libgo: update to Go 1.11
[official-gcc.git] / libgo / go / net / parse.go
bloba2d9245348cca4707190f7a962e2e81c816b3c0b
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.
5 // Simple file i/o and string manipulation, to avoid
6 // depending on strconv and bufio and strings.
8 package net
10 import (
11 "io"
12 "os"
13 "time"
14 _ "unsafe" // For go:linkname
17 type file struct {
18 file *os.File
19 data []byte
20 atEOF bool
23 func (f *file) close() { f.file.Close() }
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
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
46 return
49 func (f *file) readLine() (s string, ok bool) {
50 if s, ok = f.getLineFromData(); ok {
51 return
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]
59 if err == io.EOF || err == io.ErrUnexpectedEOF {
60 f.atEOF = true
63 s, ok = f.getLineFromData()
64 return
67 func open(name string) (*file, error) {
68 fd, err := os.Open(name)
69 if err != nil {
70 return nil, err
72 return &file{fd, make([]byte, 0, 64*1024), false}, nil
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
80 return st.ModTime(), st.Size(), nil
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 //extern strings.IndexByte
88 func byteIndex(s string, c byte) int
90 // Count occurrences in s of any bytes in t.
91 func countAnyByte(s string, t string) int {
92 n := 0
93 for i := 0; i < len(s); i++ {
94 if byteIndex(t, s[i]) >= 0 {
95 n++
98 return n
101 // Split s at any bytes in t.
102 func splitAtBytes(s string, t string) []string {
103 a := make([]string, 1+countAnyByte(s, t))
104 n := 0
105 last := 0
106 for i := 0; i < len(s); i++ {
107 if byteIndex(t, s[i]) >= 0 {
108 if last < i {
109 a[n] = s[last:i]
112 last = i + 1
115 if last < len(s) {
116 a[n] = s[last:]
119 return a[0:n]
122 func getFields(s string) []string { return splitAtBytes(s, " \r\t\n") }
124 // Bigger than we need, not too big to worry about overflow
125 const big = 0xFFFFFF
127 // Decimal to integer.
128 // Returns number, characters consumed, success.
129 func dtoi(s string) (n int, i int, ok bool) {
130 n = 0
131 for i = 0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
132 n = n*10 + int(s[i]-'0')
133 if n >= big {
134 return big, i, false
137 if i == 0 {
138 return 0, 0, false
140 return n, i, true
143 // Hexadecimal to integer.
144 // Returns number, characters consumed, success.
145 func xtoi(s string) (n int, i int, ok bool) {
146 n = 0
147 for i = 0; i < len(s); i++ {
148 if '0' <= s[i] && s[i] <= '9' {
149 n *= 16
150 n += int(s[i] - '0')
151 } else if 'a' <= s[i] && s[i] <= 'f' {
152 n *= 16
153 n += int(s[i]-'a') + 10
154 } else if 'A' <= s[i] && s[i] <= 'F' {
155 n *= 16
156 n += int(s[i]-'A') + 10
157 } else {
158 break
160 if n >= big {
161 return 0, i, false
164 if i == 0 {
165 return 0, i, false
167 return n, i, true
170 // xtoi2 converts the next two hex digits of s into a byte.
171 // If s is longer than 2 bytes then the third byte must be e.
172 // If the first two bytes of s are not hex digits or the third byte
173 // does not match e, false is returned.
174 func xtoi2(s string, e byte) (byte, bool) {
175 if len(s) > 2 && s[2] != e {
176 return 0, false
178 n, ei, ok := xtoi(s[:2])
179 return byte(n), ok && ei == 2
182 // Convert integer to decimal string.
183 func itoa(val int) string {
184 if val < 0 {
185 return "-" + uitoa(uint(-val))
187 return uitoa(uint(val))
190 // Convert unsigned integer to decimal string.
191 func uitoa(val uint) string {
192 if val == 0 { // avoid string allocation
193 return "0"
195 var buf [20]byte // big enough for 64bit value base 10
196 i := len(buf) - 1
197 for val >= 10 {
198 q := val / 10
199 buf[i] = byte('0' + val - q*10)
201 val = q
203 // val < 10
204 buf[i] = byte('0' + val)
205 return string(buf[i:])
208 // Convert i to a hexadecimal string. Leading zeros are not printed.
209 func appendHex(dst []byte, i uint32) []byte {
210 if i == 0 {
211 return append(dst, '0')
213 for j := 7; j >= 0; j-- {
214 v := i >> uint(j*4)
215 if v > 0 {
216 dst = append(dst, hexDigit[v&0xf])
219 return dst
222 // Number of occurrences of b in s.
223 func count(s string, b byte) int {
224 n := 0
225 for i := 0; i < len(s); i++ {
226 if s[i] == b {
230 return n
233 // Index of rightmost occurrence of b in s.
234 func last(s string, b byte) int {
235 i := len(s)
236 for i--; i >= 0; i-- {
237 if s[i] == b {
238 break
241 return i
244 // lowerASCIIBytes makes x ASCII lowercase in-place.
245 func lowerASCIIBytes(x []byte) {
246 for i, b := range x {
247 if 'A' <= b && b <= 'Z' {
248 x[i] += 'a' - 'A'
253 // lowerASCII returns the ASCII lowercase version of b.
254 func lowerASCII(b byte) byte {
255 if 'A' <= b && b <= 'Z' {
256 return b + ('a' - 'A')
258 return b
261 // trimSpace returns x without any leading or trailing ASCII whitespace.
262 func trimSpace(x []byte) []byte {
263 for len(x) > 0 && isSpace(x[0]) {
264 x = x[1:]
266 for len(x) > 0 && isSpace(x[len(x)-1]) {
267 x = x[:len(x)-1]
269 return x
272 // isSpace reports whether b is an ASCII space character.
273 func isSpace(b byte) bool {
274 return b == ' ' || b == '\t' || b == '\n' || b == '\r'
277 // removeComment returns line, removing any '#' byte and any following
278 // bytes.
279 func removeComment(line []byte) []byte {
280 if i := bytesIndexByte(line, '#'); i != -1 {
281 return line[:i]
283 return line
286 // foreachLine runs fn on each line of x.
287 // Each line (except for possibly the last) ends in '\n'.
288 // It returns the first non-nil error returned by fn.
289 func foreachLine(x []byte, fn func(line []byte) error) error {
290 for len(x) > 0 {
291 nl := bytesIndexByte(x, '\n')
292 if nl == -1 {
293 return fn(x)
295 line := x[:nl+1]
296 x = x[nl+1:]
297 if err := fn(line); err != nil {
298 return err
301 return nil
304 // foreachField runs fn on each non-empty run of non-space bytes in x.
305 // It returns the first non-nil error returned by fn.
306 func foreachField(x []byte, fn func(field []byte) error) error {
307 x = trimSpace(x)
308 for len(x) > 0 {
309 sp := bytesIndexByte(x, ' ')
310 if sp == -1 {
311 return fn(x)
313 if field := trimSpace(x[:sp]); len(field) > 0 {
314 if err := fn(field); err != nil {
315 return err
318 x = trimSpace(x[sp+1:])
320 return nil
323 // bytesIndexByte is bytes.IndexByte. It returns the index of the
324 // first instance of c in s, or -1 if c is not present in s.
325 // bytes.IndexByte is implemented in runtime/asm_$GOARCH.s
326 //go:linkname bytesIndexByte bytes.IndexByte
327 //extern bytes.IndexByte
328 func bytesIndexByte(s []byte, c byte) int
330 // stringsHasSuffix is strings.HasSuffix. It reports whether s ends in
331 // suffix.
332 func stringsHasSuffix(s, suffix string) bool {
333 return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
336 // stringsHasSuffixFold reports whether s ends in suffix,
337 // ASCII-case-insensitively.
338 func stringsHasSuffixFold(s, suffix string) bool {
339 return len(s) >= len(suffix) && stringsEqualFold(s[len(s)-len(suffix):], suffix)
342 // stringsHasPrefix is strings.HasPrefix. It reports whether s begins with prefix.
343 func stringsHasPrefix(s, prefix string) bool {
344 return len(s) >= len(prefix) && s[:len(prefix)] == prefix
347 // stringsEqualFold is strings.EqualFold, ASCII only. It reports whether s and t
348 // are equal, ASCII-case-insensitively.
349 func stringsEqualFold(s, t string) bool {
350 if len(s) != len(t) {
351 return false
353 for i := 0; i < len(s); i++ {
354 if lowerASCII(s[i]) != lowerASCII(t[i]) {
355 return false
358 return true
361 func readFull(r io.Reader) (all []byte, err error) {
362 buf := make([]byte, 1024)
363 for {
364 n, err := r.Read(buf)
365 all = append(all, buf[:n]...)
366 if err == io.EOF {
367 return all, nil
369 if err != nil {
370 return nil, err
375 // goDebugString returns the value of the named GODEBUG key.
376 // GODEBUG is of the form "key=val,key2=val2"
377 func goDebugString(key string) string {
378 s := os.Getenv("GODEBUG")
379 for i := 0; i < len(s)-len(key)-1; i++ {
380 if i > 0 && s[i-1] != ',' {
381 continue
383 afterKey := s[i+len(key):]
384 if afterKey[0] != '=' || s[i:i+len(key)] != key {
385 continue
387 val := afterKey[1:]
388 for i, b := range val {
389 if b == ',' {
390 return val[:i]
393 return val
395 return ""