a geicko-2 based round robin ranking system designed to test c++ battleship submissions battleship.dunkirk.sh
1package terminfo 2 3import ( 4 "sort" 5) 6 7const ( 8 // maxFileLength is the max file length. 9 maxFileLength = 4096 10 // magic is the file magic for terminfo files. 11 magic = 0o432 12 // magicExtended is the file magic for terminfo files with the extended 13 // number format. 14 magicExtended = 0o1036 15) 16 17// header fields. 18const ( 19 fieldMagic = iota 20 fieldNameSize 21 fieldBoolCount 22 fieldNumCount 23 fieldStringCount 24 fieldTableSize 25) 26 27// header extended fields. 28const ( 29 fieldExtBoolCount = iota 30 fieldExtNumCount 31 fieldExtStringCount 32 fieldExtOffsetCount 33 fieldExtTableSize 34) 35 36// hasInvalidCaps determines if the capabilities in h are invalid. 37func hasInvalidCaps(h []int) bool { 38 return h[fieldBoolCount] > CapCountBool || 39 h[fieldNumCount] > CapCountNum || 40 h[fieldStringCount] > CapCountString 41} 42 43// capLength returns the total length of the capabilities in bytes. 44func capLength(h []int) int { 45 return h[fieldNameSize] + 46 h[fieldBoolCount] + 47 (h[fieldNameSize]+h[fieldBoolCount])%2 + // account for word align 48 h[fieldNumCount]*2 + 49 h[fieldStringCount]*2 + 50 h[fieldTableSize] 51} 52 53// hasInvalidExtOffset determines if the extended offset field is valid. 54func hasInvalidExtOffset(h []int) bool { 55 return h[fieldExtBoolCount]+ 56 h[fieldExtNumCount]+ 57 h[fieldExtStringCount]*2 != h[fieldExtOffsetCount] 58} 59 60// extCapLength returns the total length of extended capabilities in bytes. 61func extCapLength(h []int, numWidth int) int { 62 return h[fieldExtBoolCount] + 63 h[fieldExtBoolCount]%2 + // account for word align 64 h[fieldExtNumCount]*(numWidth/8) + 65 h[fieldExtOffsetCount]*2 + 66 h[fieldExtTableSize] 67} 68 69// findNull finds the position of null in buf. 70func findNull(buf []byte, i int) int { 71 for ; i < len(buf); i++ { 72 if buf[i] == 0 { 73 return i 74 } 75 } 76 return -1 77} 78 79// readStrings decodes n strings from string data table buf using the indexes in idx. 80func readStrings(idx []int, buf []byte, n int) (map[int][]byte, int, error) { 81 var last int 82 m := make(map[int][]byte) 83 for i := 0; i < n; i++ { 84 start := idx[i] 85 if start < 0 { 86 continue 87 } 88 if end := findNull(buf, start); end != -1 { 89 m[i], last = buf[start:end], end+1 90 } else { 91 return nil, 0, ErrInvalidStringTable 92 } 93 } 94 return m, last, nil 95} 96 97// decoder holds state info while decoding a terminfo file. 98type decoder struct { 99 buf []byte 100 pos int 101 n int 102} 103 104// readBytes reads the next n bytes of buf, incrementing pos by n. 105func (d *decoder) readBytes(n int) ([]byte, error) { 106 if d.n < d.pos+n { 107 return nil, ErrUnexpectedFileEnd 108 } 109 n, d.pos = d.pos, d.pos+n 110 return d.buf[n:d.pos], nil 111} 112 113// readInts reads n number of ints with width w. 114func (d *decoder) readInts(n, w int) ([]int, error) { 115 w /= 8 116 l := n * w 117 buf, err := d.readBytes(l) 118 if err != nil { 119 return nil, err 120 } 121 // align 122 d.pos += d.pos % 2 123 z := make([]int, n) 124 for i, j := 0, 0; i < l; i, j = i+w, j+1 { 125 switch w { 126 case 1: 127 z[i] = int(buf[i]) 128 case 2: 129 z[j] = int(int16(buf[i+1])<<8 | int16(buf[i])) 130 case 4: 131 z[j] = int(buf[i+3])<<24 | int(buf[i+2])<<16 | int(buf[i+1])<<8 | int(buf[i]) 132 } 133 } 134 return z, nil 135} 136 137// readBools reads the next n bools. 138func (d *decoder) readBools(n int) (map[int]bool, map[int]bool, error) { 139 buf, err := d.readInts(n, 8) 140 if err != nil { 141 return nil, nil, err 142 } 143 // process 144 bools, boolsM := make(map[int]bool), make(map[int]bool) 145 for i, b := range buf { 146 bools[i] = b == 1 147 if int8(b) == -2 { 148 boolsM[i] = true 149 } 150 } 151 return bools, boolsM, nil 152} 153 154// readNums reads the next n nums. 155func (d *decoder) readNums(n, w int) (map[int]int, map[int]bool, error) { 156 buf, err := d.readInts(n, w) 157 if err != nil { 158 return nil, nil, err 159 } 160 // process 161 nums, numsM := make(map[int]int), make(map[int]bool) 162 for i := 0; i < n; i++ { 163 nums[i] = buf[i] 164 if buf[i] == -2 { 165 numsM[i] = true 166 } 167 } 168 return nums, numsM, nil 169} 170 171// readStringTable reads the string data for n strings and the accompanying data 172// table of length sz. 173func (d *decoder) readStringTable(n, sz int) ([][]byte, []int, error) { 174 buf, err := d.readInts(n, 16) 175 if err != nil { 176 return nil, nil, err 177 } 178 // read string data table 179 data, err := d.readBytes(sz) 180 if err != nil { 181 return nil, nil, err 182 } 183 // align 184 d.pos += d.pos % 2 185 // process 186 s := make([][]byte, n) 187 var m []int 188 for i := 0; i < n; i++ { 189 start := buf[i] 190 if start == -2 { 191 m = append(m, i) 192 } else if start >= 0 { 193 if end := findNull(data, start); end != -1 { 194 s[i] = data[start:end] 195 } else { 196 return nil, nil, ErrInvalidStringTable 197 } 198 } 199 } 200 return s, m, nil 201} 202 203// readStrings reads the next n strings and processes the string data table of 204// length sz. 205func (d *decoder) readStrings(n, sz int) (map[int][]byte, map[int]bool, error) { 206 s, m, err := d.readStringTable(n, sz) 207 if err != nil { 208 return nil, nil, err 209 } 210 strs := make(map[int][]byte) 211 for k, v := range s { 212 if k == AcsChars { 213 v = canonicalizeAscChars(v) 214 } 215 strs[k] = v 216 } 217 strsM := make(map[int]bool, len(m)) 218 for _, k := range m { 219 strsM[k] = true 220 } 221 return strs, strsM, nil 222} 223 224// canonicalizeAscChars reorders chars to be unique, in order. 225// 226// see repair_ascc in ncurses-6.3/progs/dump_entry.c 227func canonicalizeAscChars(z []byte) []byte { 228 var c []byte 229 enc := make(map[byte]byte, len(z)/2) 230 for i := 0; i < len(z); i += 2 { 231 if _, ok := enc[z[i]]; !ok { 232 a, b := z[i], z[i+1] 233 // log.Printf(">>> a: %d %c, b: %d %c", a, a, b, b) 234 c, enc[a] = append(c, b), b 235 } 236 } 237 sort.Slice(c, func(i, j int) bool { 238 return c[i] < c[j] 239 }) 240 r := make([]byte, 2*len(c)) 241 for i := 0; i < len(c); i++ { 242 r[i*2], r[i*2+1] = c[i], enc[c[i]] 243 } 244 return r 245}