Source file src/pkg/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 )
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 {
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, os.Getpagesize())[0:0], 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 // Integer to decimal.
175 func itoa(i int) string {
176 var buf [30]byte
177 n := len(buf)
178 neg := false
179 if i < 0 {
180 i = -i
181 neg = true
182 }
183 ui := uint(i)
184 for ui > 0 || n == len(buf) {
185 n--
186 buf[n] = byte('0' + ui%10)
187 ui /= 10
188 }
189 if neg {
190 n--
191 buf[n] = '-'
192 }
193 return string(buf[n:])
194 }
195
196 // Convert i to decimal string.
197 func itod(i uint) string {
198 if i == 0 {
199 return "0"
200 }
201
202 // Assemble decimal in reverse order.
203 var b [32]byte
204 bp := len(b)
205 for ; i > 0; i /= 10 {
206 bp--
207 b[bp] = byte(i%10) + '0'
208 }
209
210 return string(b[bp:])
211 }
212
213 // Convert i to hexadecimal string.
214 func itox(i uint, min int) string {
215 // Assemble hexadecimal in reverse order.
216 var b [32]byte
217 bp := len(b)
218 for ; i > 0 || min > 0; i /= 16 {
219 bp--
220 b[bp] = "0123456789abcdef"[byte(i%16)]
221 min--
222 }
223
224 return string(b[bp:])
225 }
226
227 // Number of occurrences of b in s.
228 func count(s string, b byte) int {
229 n := 0
230 for i := 0; i < len(s); i++ {
231 if s[i] == b {
232 n++
233 }
234 }
235 return n
236 }
237
238 // Index of rightmost occurrence of b in s.
239 func last(s string, b byte) int {
240 i := len(s)
241 for i--; i >= 0; i-- {
242 if s[i] == b {
243 break
244 }
245 }
246 return i
247 }