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