...
Run Format

Source file src/net/parse.go

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

View as plain text