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
8package net
9
10import (
11	"internal/bytealg"
12	"io"
13	"os"
14	"time"
15)
16
17type file struct {
18	file  *os.File
19	data  []byte
20	atEOF bool
21}
22
23func (f *file) close() { f.file.Close() }
24
25func (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
49func (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
67func 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
75func 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.
84func 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.
95func 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
115func getFields(s string) []string { return splitAtBytes(s, " \r\t\n") }
116
117// Bigger than we need, not too big to worry about overflow
118const big = 0xFFFFFF
119
120// Decimal to integer.
121// Returns number, characters consumed, success.
122func 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.
138func 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.
167func 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 integer to decimal string.
176func itoa(val int) string {
177	if val < 0 {
178		return "-" + uitoa(uint(-val))
179	}
180	return uitoa(uint(val))
181}
182
183// Convert unsigned integer to decimal string.
184func uitoa(val uint) string {
185	if val == 0 { // avoid string allocation
186		return "0"
187	}
188	var buf [20]byte // big enough for 64bit value base 10
189	i := len(buf) - 1
190	for val >= 10 {
191		q := val / 10
192		buf[i] = byte('0' + val - q*10)
193		i--
194		val = q
195	}
196	// val < 10
197	buf[i] = byte('0' + val)
198	return string(buf[i:])
199}
200
201// Convert i to a hexadecimal string. Leading zeros are not printed.
202func appendHex(dst []byte, i uint32) []byte {
203	if i == 0 {
204		return append(dst, '0')
205	}
206	for j := 7; j >= 0; j-- {
207		v := i >> uint(j*4)
208		if v > 0 {
209			dst = append(dst, hexDigit[v&0xf])
210		}
211	}
212	return dst
213}
214
215// Number of occurrences of b in s.
216func count(s string, b byte) int {
217	n := 0
218	for i := 0; i < len(s); i++ {
219		if s[i] == b {
220			n++
221		}
222	}
223	return n
224}
225
226// Index of rightmost occurrence of b in s.
227func last(s string, b byte) int {
228	i := len(s)
229	for i--; i >= 0; i-- {
230		if s[i] == b {
231			break
232		}
233	}
234	return i
235}
236
237// lowerASCIIBytes makes x ASCII lowercase in-place.
238func lowerASCIIBytes(x []byte) {
239	for i, b := range x {
240		if 'A' <= b && b <= 'Z' {
241			x[i] += 'a' - 'A'
242		}
243	}
244}
245
246// lowerASCII returns the ASCII lowercase version of b.
247func lowerASCII(b byte) byte {
248	if 'A' <= b && b <= 'Z' {
249		return b + ('a' - 'A')
250	}
251	return b
252}
253
254// trimSpace returns x without any leading or trailing ASCII whitespace.
255func trimSpace(x []byte) []byte {
256	for len(x) > 0 && isSpace(x[0]) {
257		x = x[1:]
258	}
259	for len(x) > 0 && isSpace(x[len(x)-1]) {
260		x = x[:len(x)-1]
261	}
262	return x
263}
264
265// isSpace reports whether b is an ASCII space character.
266func isSpace(b byte) bool {
267	return b == ' ' || b == '\t' || b == '\n' || b == '\r'
268}
269
270// removeComment returns line, removing any '#' byte and any following
271// bytes.
272func removeComment(line []byte) []byte {
273	if i := bytealg.IndexByte(line, '#'); i != -1 {
274		return line[:i]
275	}
276	return line
277}
278
279// foreachLine runs fn on each line of x.
280// Each line (except for possibly the last) ends in '\n'.
281// It returns the first non-nil error returned by fn.
282func foreachLine(x []byte, fn func(line []byte) error) error {
283	for len(x) > 0 {
284		nl := bytealg.IndexByte(x, '\n')
285		if nl == -1 {
286			return fn(x)
287		}
288		line := x[:nl+1]
289		x = x[nl+1:]
290		if err := fn(line); err != nil {
291			return err
292		}
293	}
294	return nil
295}
296
297// foreachField runs fn on each non-empty run of non-space bytes in x.
298// It returns the first non-nil error returned by fn.
299func foreachField(x []byte, fn func(field []byte) error) error {
300	x = trimSpace(x)
301	for len(x) > 0 {
302		sp := bytealg.IndexByte(x, ' ')
303		if sp == -1 {
304			return fn(x)
305		}
306		if field := trimSpace(x[:sp]); len(field) > 0 {
307			if err := fn(field); err != nil {
308				return err
309			}
310		}
311		x = trimSpace(x[sp+1:])
312	}
313	return nil
314}
315
316// stringsHasSuffix is strings.HasSuffix. It reports whether s ends in
317// suffix.
318func stringsHasSuffix(s, suffix string) bool {
319	return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
320}
321
322// stringsHasSuffixFold reports whether s ends in suffix,
323// ASCII-case-insensitively.
324func stringsHasSuffixFold(s, suffix string) bool {
325	return len(s) >= len(suffix) && stringsEqualFold(s[len(s)-len(suffix):], suffix)
326}
327
328// stringsHasPrefix is strings.HasPrefix. It reports whether s begins with prefix.
329func stringsHasPrefix(s, prefix string) bool {
330	return len(s) >= len(prefix) && s[:len(prefix)] == prefix
331}
332
333// stringsEqualFold is strings.EqualFold, ASCII only. It reports whether s and t
334// are equal, ASCII-case-insensitively.
335func stringsEqualFold(s, t string) bool {
336	if len(s) != len(t) {
337		return false
338	}
339	for i := 0; i < len(s); i++ {
340		if lowerASCII(s[i]) != lowerASCII(t[i]) {
341			return false
342		}
343	}
344	return true
345}
346
347func readFull(r io.Reader) (all []byte, err error) {
348	buf := make([]byte, 1024)
349	for {
350		n, err := r.Read(buf)
351		all = append(all, buf[:n]...)
352		if err == io.EOF {
353			return all, nil
354		}
355		if err != nil {
356			return nil, err
357		}
358	}
359}
360
361// goDebugString returns the value of the named GODEBUG key.
362// GODEBUG is of the form "key=val,key2=val2"
363func goDebugString(key string) string {
364	s := os.Getenv("GODEBUG")
365	for i := 0; i < len(s)-len(key)-1; i++ {
366		if i > 0 && s[i-1] != ',' {
367			continue
368		}
369		afterKey := s[i+len(key):]
370		if afterKey[0] != '=' || s[i:i+len(key)] != key {
371			continue
372		}
373		val := afterKey[1:]
374		for i, b := range val {
375			if b == ',' {
376				return val[:i]
377			}
378		}
379		return val
380	}
381	return ""
382}
383