github.com/epfl-dcsl/gotee@v0.0.0-20200909122901-014b35f5e5e9/src/gnet/parse.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Simple file i/o and string manipulation, to avoid 6 // depending on strconv and bufio and strings. 7 8 package gnet 9 10 import ( 11 "io" 12 "os" 13 "strings" 14 "time" 15 _ "unsafe" // For go:linkname 16 ) 17 18 type file struct { 19 file *os.File 20 data []byte 21 atEOF bool 22 } 23 24 func (f *file) close() { f.file.Close() } 25 26 func (f *file) getLineFromData() (s string, ok bool) { 27 data := f.data 28 i := 0 29 for i = 0; i < len(data); i++ { 30 if data[i] == '\n' { 31 s = string(data[0:i]) 32 ok = true 33 // move data 34 i++ 35 n := len(data) - i 36 copy(data[0:], data[i:]) 37 f.data = data[0:n] 38 return 39 } 40 } 41 if f.atEOF && len(f.data) > 0 { 42 // EOF, return all we have 43 s = string(data) 44 f.data = f.data[0:0] 45 ok = true 46 } 47 return 48 } 49 50 func (f *file) readLine() (s string, ok bool) { 51 if s, ok = f.getLineFromData(); ok { 52 return 53 } 54 if len(f.data) < cap(f.data) { 55 ln := len(f.data) 56 n, err := io.ReadFull(f.file, f.data[ln:cap(f.data)]) 57 if n >= 0 { 58 f.data = f.data[0 : ln+n] 59 } 60 if err == io.EOF || err == io.ErrUnexpectedEOF { 61 f.atEOF = true 62 } 63 } 64 s, ok = f.getLineFromData() 65 return 66 } 67 68 func open(name string) (*file, error) { 69 fd, err := os.Open(name) 70 if err != nil { 71 return nil, err 72 } 73 return &file{fd, make([]byte, 0, 64*1024), false}, nil 74 } 75 76 func stat(name string) (mtime time.Time, size int64, err error) { 77 st, err := os.Stat(name) 78 if err != nil { 79 return time.Time{}, 0, err 80 } 81 return st.ModTime(), st.Size(), nil 82 } 83 84 // byteIndex is strings.IndexByte. It returns the index of the 85 // first instance of c in s, or -1 if c is not present in s. 86 // strings.IndexByte is implemented in runtime/asm_$GOARCH.s 87 func byteIndex(s string, c byte) int { 88 //panic("TODO implement") 89 return strings.IndexByte(s, c) 90 } 91 92 // Count occurrences in s of any bytes in t. 93 func countAnyByte(s string, t string) int { 94 n := 0 95 for i := 0; i < len(s); i++ { 96 if byteIndex(t, s[i]) >= 0 { 97 n++ 98 } 99 } 100 return n 101 } 102 103 // Split s at any bytes in t. 104 func splitAtBytes(s string, t string) []string { 105 a := make([]string, 1+countAnyByte(s, t)) 106 n := 0 107 last := 0 108 for i := 0; i < len(s); i++ { 109 if byteIndex(t, s[i]) >= 0 { 110 if last < i { 111 a[n] = s[last:i] 112 n++ 113 } 114 last = i + 1 115 } 116 } 117 if last < len(s) { 118 a[n] = s[last:] 119 n++ 120 } 121 return a[0:n] 122 } 123 124 func getFields(s string) []string { return splitAtBytes(s, " \r\t\n") } 125 126 // Bigger than we need, not too big to worry about overflow 127 const big = 0xFFFFFF 128 129 // Decimal to integer. 130 // Returns number, characters consumed, success. 131 func dtoi(s string) (n int, i int, ok bool) { 132 n = 0 133 for i = 0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ { 134 n = n*10 + int(s[i]-'0') 135 if n >= big { 136 return big, i, false 137 } 138 } 139 if i == 0 { 140 return 0, 0, false 141 } 142 return n, i, true 143 } 144 145 // Hexadecimal to integer. 146 // Returns number, characters consumed, success. 147 func xtoi(s string) (n int, i int, ok bool) { 148 n = 0 149 for i = 0; i < len(s); i++ { 150 if '0' <= s[i] && s[i] <= '9' { 151 n *= 16 152 n += int(s[i] - '0') 153 } else if 'a' <= s[i] && s[i] <= 'f' { 154 n *= 16 155 n += int(s[i]-'a') + 10 156 } else if 'A' <= s[i] && s[i] <= 'F' { 157 n *= 16 158 n += int(s[i]-'A') + 10 159 } else { 160 break 161 } 162 if n >= big { 163 return 0, i, false 164 } 165 } 166 if i == 0 { 167 return 0, i, false 168 } 169 return n, i, true 170 } 171 172 // xtoi2 converts the next two hex digits of s into a byte. 173 // If s is longer than 2 bytes then the third byte must be e. 174 // If the first two bytes of s are not hex digits or the third byte 175 // does not match e, false is returned. 176 func xtoi2(s string, e byte) (byte, bool) { 177 if len(s) > 2 && s[2] != e { 178 return 0, false 179 } 180 n, ei, ok := xtoi(s[:2]) 181 return byte(n), ok && ei == 2 182 } 183 184 // Convert integer to decimal string. 185 func itoa(val int) string { 186 if val < 0 { 187 return "-" + uitoa(uint(-val)) 188 } 189 return uitoa(uint(val)) 190 } 191 192 // Convert unsigned integer to decimal string. 193 func uitoa(val uint) string { 194 if val == 0 { // avoid string allocation 195 return "0" 196 } 197 var buf [20]byte // big enough for 64bit value base 10 198 i := len(buf) - 1 199 for val >= 10 { 200 q := val / 10 201 buf[i] = byte('0' + val - q*10) 202 i-- 203 val = q 204 } 205 // val < 10 206 buf[i] = byte('0' + val) 207 return string(buf[i:]) 208 } 209 210 // Convert i to a hexadecimal string. Leading zeros are not printed. 211 func appendHex(dst []byte, i uint32) []byte { 212 if i == 0 { 213 return append(dst, '0') 214 } 215 for j := 7; j >= 0; j-- { 216 v := i >> uint(j*4) 217 if v > 0 { 218 dst = append(dst, hexDigit[v&0xf]) 219 } 220 } 221 return dst 222 } 223 224 // Number of occurrences of b in s. 225 func count(s string, b byte) int { 226 n := 0 227 for i := 0; i < len(s); i++ { 228 if s[i] == b { 229 n++ 230 } 231 } 232 return n 233 } 234 235 // Index of rightmost occurrence of b in s. 236 func last(s string, b byte) int { 237 i := len(s) 238 for i--; i >= 0; i-- { 239 if s[i] == b { 240 break 241 } 242 } 243 return i 244 } 245 246 // lowerASCIIBytes makes x ASCII lowercase in-place. 247 func lowerASCIIBytes(x []byte) { 248 for i, b := range x { 249 if 'A' <= b && b <= 'Z' { 250 x[i] += 'a' - 'A' 251 } 252 } 253 } 254 255 // lowerASCII returns the ASCII lowercase version of b. 256 func lowerASCII(b byte) byte { 257 if 'A' <= b && b <= 'Z' { 258 return b + ('a' - 'A') 259 } 260 return b 261 } 262 263 // trimSpace returns x without any leading or trailing ASCII whitespace. 264 func trimSpace(x []byte) []byte { 265 for len(x) > 0 && isSpace(x[0]) { 266 x = x[1:] 267 } 268 for len(x) > 0 && isSpace(x[len(x)-1]) { 269 x = x[:len(x)-1] 270 } 271 return x 272 } 273 274 // isSpace reports whether b is an ASCII space character. 275 func isSpace(b byte) bool { 276 return b == ' ' || b == '\t' || b == '\n' || b == '\r' 277 } 278 279 // removeComment returns line, removing any '#' byte and any following 280 // bytes. 281 func removeComment(line []byte) []byte { 282 if i := bytesIndexByte(line, '#'); i != -1 { 283 return line[:i] 284 } 285 return line 286 } 287 288 // foreachLine runs fn on each line of x. 289 // Each line (except for possibly the last) ends in '\n'. 290 // It returns the first non-nil error returned by fn. 291 func foreachLine(x []byte, fn func(line []byte) error) error { 292 for len(x) > 0 { 293 nl := bytesIndexByte(x, '\n') 294 if nl == -1 { 295 return fn(x) 296 } 297 line := x[:nl+1] 298 x = x[nl+1:] 299 if err := fn(line); err != nil { 300 return err 301 } 302 } 303 return nil 304 } 305 306 // foreachField runs fn on each non-empty run of non-space bytes in x. 307 // It returns the first non-nil error returned by fn. 308 func foreachField(x []byte, fn func(field []byte) error) error { 309 x = trimSpace(x) 310 for len(x) > 0 { 311 sp := bytesIndexByte(x, ' ') 312 if sp == -1 { 313 return fn(x) 314 } 315 if field := trimSpace(x[:sp]); len(field) > 0 { 316 if err := fn(field); err != nil { 317 return err 318 } 319 } 320 x = trimSpace(x[sp+1:]) 321 } 322 return nil 323 } 324 325 // bytesIndexByte is bytes.IndexByte. It returns the index of the 326 // first instance of c in s, or -1 if c is not present in s. 327 // bytes.IndexByte is implemented in runtime/asm_$GOARCH.s 328 func bytesIndexByte(s []byte, c byte) int { 329 panic("TODO implement") 330 return 0 331 } 332 333 // stringsHasSuffix is strings.HasSuffix. It reports whether s ends in 334 // suffix. 335 func stringsHasSuffix(s, suffix string) bool { 336 return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix 337 } 338 339 // stringsHasSuffixFold reports whether s ends in suffix, 340 // ASCII-case-insensitively. 341 func stringsHasSuffixFold(s, suffix string) bool { 342 return len(s) >= len(suffix) && stringsEqualFold(s[len(s)-len(suffix):], suffix) 343 } 344 345 // stringsHasPrefix is strings.HasPrefix. It reports whether s begins with prefix. 346 func stringsHasPrefix(s, prefix string) bool { 347 return len(s) >= len(prefix) && s[:len(prefix)] == prefix 348 } 349 350 // stringsEqualFold is strings.EqualFold, ASCII only. It reports whether s and t 351 // are equal, ASCII-case-insensitively. 352 func stringsEqualFold(s, t string) bool { 353 if len(s) != len(t) { 354 return false 355 } 356 for i := 0; i < len(s); i++ { 357 if lowerASCII(s[i]) != lowerASCII(t[i]) { 358 return false 359 } 360 } 361 return true 362 } 363 364 func readFull(r io.Reader) (all []byte, err error) { 365 buf := make([]byte, 1024) 366 for { 367 n, err := r.Read(buf) 368 all = append(all, buf[:n]...) 369 if err == io.EOF { 370 return all, nil 371 } 372 if err != nil { 373 return nil, err 374 } 375 } 376 } 377 378 // goDebugString returns the value of the named GODEBUG key. 379 // GODEBUG is of the form "key=val,key2=val2" 380 func goDebugString(key string) string { 381 s := os.Getenv("GODEBUG") 382 for i := 0; i < len(s)-len(key)-1; i++ { 383 if i > 0 && s[i-1] != ',' { 384 continue 385 } 386 afterKey := s[i+len(key):] 387 if afterKey[0] != '=' || s[i:i+len(key)] != key { 388 continue 389 } 390 val := afterKey[1:] 391 for i, b := range val { 392 if b == ',' { 393 return val[:i] 394 } 395 } 396 return val 397 } 398 return "" 399 }