a geicko-2 based round robin ranking system designed to test c++ battleship submissions battleship.dunkirk.sh
at main 5.2 kB view raw
1package logfmt 2 3import ( 4 "bytes" 5 "io" 6 "strconv" 7 "sync" 8 "unicode" 9 "unicode/utf16" 10 "unicode/utf8" 11) 12 13// Taken from Go's encoding/json and modified for use here. 14 15// Copyright 2010 The Go Authors. All rights reserved. 16// Use of this source code is governed by a BSD-style 17// license that can be found in the LICENSE file. 18 19var hex = "0123456789abcdef" 20 21var bufferPool = sync.Pool{ 22 New: func() interface{} { 23 return &bytes.Buffer{} 24 }, 25} 26 27func getBuffer() *bytes.Buffer { 28 return bufferPool.Get().(*bytes.Buffer) 29} 30 31func poolBuffer(buf *bytes.Buffer) { 32 buf.Reset() 33 bufferPool.Put(buf) 34} 35 36// NOTE: keep in sync with writeQuotedBytes below. 37func writeQuotedString(w io.Writer, s string) (int, error) { 38 buf := getBuffer() 39 buf.WriteByte('"') 40 start := 0 41 for i := 0; i < len(s); { 42 if b := s[i]; b < utf8.RuneSelf { 43 if 0x20 <= b && b != '\\' && b != '"' { 44 i++ 45 continue 46 } 47 if start < i { 48 buf.WriteString(s[start:i]) 49 } 50 switch b { 51 case '\\', '"': 52 buf.WriteByte('\\') 53 buf.WriteByte(b) 54 case '\n': 55 buf.WriteByte('\\') 56 buf.WriteByte('n') 57 case '\r': 58 buf.WriteByte('\\') 59 buf.WriteByte('r') 60 case '\t': 61 buf.WriteByte('\\') 62 buf.WriteByte('t') 63 default: 64 // This encodes bytes < 0x20 except for \n, \r, and \t. 65 buf.WriteString(`\u00`) 66 buf.WriteByte(hex[b>>4]) 67 buf.WriteByte(hex[b&0xF]) 68 } 69 i++ 70 start = i 71 continue 72 } 73 c, size := utf8.DecodeRuneInString(s[i:]) 74 if c == utf8.RuneError { 75 if start < i { 76 buf.WriteString(s[start:i]) 77 } 78 buf.WriteString(`\ufffd`) 79 i += size 80 start = i 81 continue 82 } 83 i += size 84 } 85 if start < len(s) { 86 buf.WriteString(s[start:]) 87 } 88 buf.WriteByte('"') 89 n, err := w.Write(buf.Bytes()) 90 poolBuffer(buf) 91 return n, err 92} 93 94// NOTE: keep in sync with writeQuoteString above. 95func writeQuotedBytes(w io.Writer, s []byte) (int, error) { 96 buf := getBuffer() 97 buf.WriteByte('"') 98 start := 0 99 for i := 0; i < len(s); { 100 if b := s[i]; b < utf8.RuneSelf { 101 if 0x20 <= b && b != '\\' && b != '"' { 102 i++ 103 continue 104 } 105 if start < i { 106 buf.Write(s[start:i]) 107 } 108 switch b { 109 case '\\', '"': 110 buf.WriteByte('\\') 111 buf.WriteByte(b) 112 case '\n': 113 buf.WriteByte('\\') 114 buf.WriteByte('n') 115 case '\r': 116 buf.WriteByte('\\') 117 buf.WriteByte('r') 118 case '\t': 119 buf.WriteByte('\\') 120 buf.WriteByte('t') 121 default: 122 // This encodes bytes < 0x20 except for \n, \r, and \t. 123 buf.WriteString(`\u00`) 124 buf.WriteByte(hex[b>>4]) 125 buf.WriteByte(hex[b&0xF]) 126 } 127 i++ 128 start = i 129 continue 130 } 131 c, size := utf8.DecodeRune(s[i:]) 132 if c == utf8.RuneError { 133 if start < i { 134 buf.Write(s[start:i]) 135 } 136 buf.WriteString(`\ufffd`) 137 i += size 138 start = i 139 continue 140 } 141 i += size 142 } 143 if start < len(s) { 144 buf.Write(s[start:]) 145 } 146 buf.WriteByte('"') 147 n, err := w.Write(buf.Bytes()) 148 poolBuffer(buf) 149 return n, err 150} 151 152// getu4 decodes \uXXXX from the beginning of s, returning the hex value, 153// or it returns -1. 154func getu4(s []byte) rune { 155 if len(s) < 6 || s[0] != '\\' || s[1] != 'u' { 156 return -1 157 } 158 r, err := strconv.ParseUint(string(s[2:6]), 16, 64) 159 if err != nil { 160 return -1 161 } 162 return rune(r) 163} 164 165func unquoteBytes(s []byte) (t []byte, ok bool) { 166 if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' { 167 return 168 } 169 s = s[1 : len(s)-1] 170 171 // Check for unusual characters. If there are none, 172 // then no unquoting is needed, so return a slice of the 173 // original bytes. 174 r := 0 175 for r < len(s) { 176 c := s[r] 177 if c == '\\' || c == '"' || c < ' ' { 178 break 179 } 180 if c < utf8.RuneSelf { 181 r++ 182 continue 183 } 184 rr, size := utf8.DecodeRune(s[r:]) 185 if rr == utf8.RuneError { 186 break 187 } 188 r += size 189 } 190 if r == len(s) { 191 return s, true 192 } 193 194 b := make([]byte, len(s)+2*utf8.UTFMax) 195 w := copy(b, s[0:r]) 196 for r < len(s) { 197 // Out of room? Can only happen if s is full of 198 // malformed UTF-8 and we're replacing each 199 // byte with RuneError. 200 if w >= len(b)-2*utf8.UTFMax { 201 nb := make([]byte, (len(b)+utf8.UTFMax)*2) 202 copy(nb, b[0:w]) 203 b = nb 204 } 205 switch c := s[r]; { 206 case c == '\\': 207 r++ 208 if r >= len(s) { 209 return 210 } 211 switch s[r] { 212 default: 213 return 214 case '"', '\\', '/', '\'': 215 b[w] = s[r] 216 r++ 217 w++ 218 case 'b': 219 b[w] = '\b' 220 r++ 221 w++ 222 case 'f': 223 b[w] = '\f' 224 r++ 225 w++ 226 case 'n': 227 b[w] = '\n' 228 r++ 229 w++ 230 case 'r': 231 b[w] = '\r' 232 r++ 233 w++ 234 case 't': 235 b[w] = '\t' 236 r++ 237 w++ 238 case 'u': 239 r-- 240 rr := getu4(s[r:]) 241 if rr < 0 { 242 return 243 } 244 r += 6 245 if utf16.IsSurrogate(rr) { 246 rr1 := getu4(s[r:]) 247 if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar { 248 // A valid pair; consume. 249 r += 6 250 w += utf8.EncodeRune(b[w:], dec) 251 break 252 } 253 // Invalid surrogate; fall back to replacement rune. 254 rr = unicode.ReplacementChar 255 } 256 w += utf8.EncodeRune(b[w:], rr) 257 } 258 259 // Quote, control characters are invalid. 260 case c == '"', c < ' ': 261 return 262 263 // ASCII 264 case c < utf8.RuneSelf: 265 b[w] = c 266 r++ 267 w++ 268 269 // Coerce to well-formed UTF-8. 270 default: 271 rr, size := utf8.DecodeRune(s[r:]) 272 r += size 273 w += utf8.EncodeRune(b[w:], rr) 274 } 275 } 276 return b[0:w], true 277}