...

Source file src/net/parse.go

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

View as plain text