2008-12-18 16:42:39 -07:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
// Simple file i/o and string manipulation, to avoid
|
2009-11-01 12:15:34 -07:00
|
|
|
// depending on strconv and bufio and strings.
|
2008-12-18 16:42:39 -07:00
|
|
|
|
|
|
|
package net
|
|
|
|
|
|
|
|
import (
|
2009-12-15 16:35:38 -07:00
|
|
|
"io"
|
|
|
|
"os"
|
2008-12-18 16:42:39 -07:00
|
|
|
)
|
|
|
|
|
2009-02-15 15:18:39 -07:00
|
|
|
type file struct {
|
2009-12-15 16:35:38 -07:00
|
|
|
file *os.File
|
|
|
|
data []byte
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
|
|
|
|
2009-12-15 16:35:38 -07:00
|
|
|
func (f *file) close() { f.file.Close() }
|
2008-12-18 16:42:39 -07:00
|
|
|
|
2009-02-15 15:18:39 -07:00
|
|
|
func (f *file) getLineFromData() (s string, ok bool) {
|
2009-12-15 16:35:38 -07:00
|
|
|
data := f.data
|
2008-12-18 16:42:39 -07:00
|
|
|
for i := 0; i < len(data); i++ {
|
|
|
|
if data[i] == '\n' {
|
2009-12-15 16:35:38 -07:00
|
|
|
s = string(data[0:i])
|
|
|
|
ok = true
|
2008-12-18 16:42:39 -07:00
|
|
|
// move data
|
2009-12-15 16:35:38 -07:00
|
|
|
i++
|
|
|
|
n := len(data) - i
|
2008-12-18 16:42:39 -07:00
|
|
|
for j := 0; j < n; j++ {
|
2009-11-09 13:07:39 -07:00
|
|
|
data[j] = data[i+j]
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
f.data = data[0:n]
|
|
|
|
return
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
return
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
|
|
|
|
2009-02-15 15:18:39 -07:00
|
|
|
func (f *file) readLine() (s string, ok bool) {
|
|
|
|
if s, ok = f.getLineFromData(); ok {
|
2009-11-09 13:07:39 -07:00
|
|
|
return
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
|
|
|
if len(f.data) < cap(f.data) {
|
2009-12-15 16:35:38 -07:00
|
|
|
ln := len(f.data)
|
|
|
|
n, _ := io.ReadFull(f.file, f.data[ln:cap(f.data)])
|
2008-12-18 16:42:39 -07:00
|
|
|
if n >= 0 {
|
2009-11-09 13:07:39 -07:00
|
|
|
f.data = f.data[0 : ln+n]
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
s, ok = f.getLineFromData()
|
|
|
|
return
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
|
|
|
|
2009-04-17 01:08:24 -06:00
|
|
|
func open(name string) (*file, os.Error) {
|
2009-12-15 16:35:38 -07:00
|
|
|
fd, err := os.Open(name, os.O_RDONLY, 0)
|
2008-12-18 16:42:39 -07:00
|
|
|
if err != nil {
|
2009-11-09 13:07:39 -07:00
|
|
|
return nil, err
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
return &file{fd, make([]byte, 1024)[0:0]}, nil
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
|
|
|
|
2009-02-15 15:18:39 -07:00
|
|
|
func byteIndex(s string, c byte) int {
|
2008-12-18 16:42:39 -07:00
|
|
|
for i := 0; i < len(s); i++ {
|
|
|
|
if s[i] == c {
|
2009-11-09 13:07:39 -07:00
|
|
|
return i
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
return -1
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Count occurrences in s of any bytes in t.
|
2009-02-15 15:18:39 -07:00
|
|
|
func countAnyByte(s string, t string) int {
|
2009-12-15 16:35:38 -07:00
|
|
|
n := 0
|
2008-12-18 16:42:39 -07:00
|
|
|
for i := 0; i < len(s); i++ {
|
2009-02-15 15:18:39 -07:00
|
|
|
if byteIndex(t, s[i]) >= 0 {
|
2009-11-09 13:07:39 -07:00
|
|
|
n++
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
return n
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Split s at any bytes in t.
|
2009-02-15 15:18:39 -07:00
|
|
|
func splitAtBytes(s string, t string) []string {
|
2009-12-15 16:35:38 -07:00
|
|
|
a := make([]string, 1+countAnyByte(s, t))
|
|
|
|
n := 0
|
|
|
|
last := 0
|
2008-12-18 16:42:39 -07:00
|
|
|
for i := 0; i < len(s); i++ {
|
2009-02-15 15:18:39 -07:00
|
|
|
if byteIndex(t, s[i]) >= 0 {
|
2008-12-18 16:42:39 -07:00
|
|
|
if last < i {
|
2009-12-15 16:35:38 -07:00
|
|
|
a[n] = string(s[last:i])
|
|
|
|
n++
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
last = i + 1
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if last < len(s) {
|
2009-12-15 16:35:38 -07:00
|
|
|
a[n] = string(s[last:])
|
|
|
|
n++
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
return a[0:n]
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
|
|
|
|
2009-12-15 16:35:38 -07:00
|
|
|
func getFields(s string) []string { return splitAtBytes(s, " \r\t\n") }
|
2008-12-18 16:42:39 -07:00
|
|
|
|
|
|
|
// Bigger than we need, not too big to worry about overflow
|
2009-02-15 15:18:39 -07:00
|
|
|
const big = 0xFFFFFF
|
2008-12-18 16:42:39 -07:00
|
|
|
|
|
|
|
// Decimal to integer starting at &s[i0].
|
|
|
|
// Returns number, new offset, success.
|
2009-02-15 15:18:39 -07:00
|
|
|
func dtoi(s string, i0 int) (n int, i int, ok bool) {
|
2009-12-15 16:35:38 -07:00
|
|
|
n = 0
|
2008-12-18 16:42:39 -07:00
|
|
|
for i = i0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
|
2009-12-15 16:35:38 -07:00
|
|
|
n = n*10 + int(s[i]-'0')
|
2009-02-15 15:18:39 -07:00
|
|
|
if n >= big {
|
2009-11-09 13:07:39 -07:00
|
|
|
return 0, i, false
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if i == i0 {
|
2009-11-09 13:07:39 -07:00
|
|
|
return 0, i, false
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
return n, i, true
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Hexadecimal to integer starting at &s[i0].
|
|
|
|
// Returns number, new offset, success.
|
2009-02-15 15:18:39 -07:00
|
|
|
func xtoi(s string, i0 int) (n int, i int, ok bool) {
|
2009-12-15 16:35:38 -07:00
|
|
|
n = 0
|
2008-12-18 16:42:39 -07:00
|
|
|
for i = i0; i < len(s); i++ {
|
|
|
|
if '0' <= s[i] && s[i] <= '9' {
|
2009-12-15 16:35:38 -07:00
|
|
|
n *= 16
|
|
|
|
n += int(s[i] - '0')
|
2008-12-18 16:42:39 -07:00
|
|
|
} else if 'a' <= s[i] && s[i] <= 'f' {
|
2009-12-15 16:35:38 -07:00
|
|
|
n *= 16
|
|
|
|
n += int(s[i]-'a') + 10
|
2008-12-18 16:42:39 -07:00
|
|
|
} else if 'A' <= s[i] && s[i] <= 'F' {
|
2009-12-15 16:35:38 -07:00
|
|
|
n *= 16
|
|
|
|
n += int(s[i]-'A') + 10
|
2008-12-18 16:42:39 -07:00
|
|
|
} else {
|
2009-11-09 13:07:39 -07:00
|
|
|
break
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
2009-02-15 15:18:39 -07:00
|
|
|
if n >= big {
|
2009-11-09 13:07:39 -07:00
|
|
|
return 0, i, false
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if i == i0 {
|
2009-11-09 13:07:39 -07:00
|
|
|
return 0, i, false
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
return n, i, true
|
2008-12-18 16:42:39 -07:00
|
|
|
}
|
|
|
|
|
2009-11-01 12:15:34 -07:00
|
|
|
// Integer to decimal.
|
|
|
|
func itoa(i int) string {
|
2009-12-15 16:35:38 -07:00
|
|
|
var buf [30]byte
|
|
|
|
n := len(buf)
|
|
|
|
neg := false
|
2009-11-01 12:15:34 -07:00
|
|
|
if i < 0 {
|
2009-12-15 16:35:38 -07:00
|
|
|
i = -i
|
|
|
|
neg = true
|
2009-11-01 12:15:34 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
ui := uint(i)
|
2009-11-01 12:15:34 -07:00
|
|
|
for ui > 0 || n == len(buf) {
|
2009-12-15 16:35:38 -07:00
|
|
|
n--
|
|
|
|
buf[n] = byte('0' + ui%10)
|
|
|
|
ui /= 10
|
2009-11-01 12:15:34 -07:00
|
|
|
}
|
|
|
|
if neg {
|
2009-12-15 16:35:38 -07:00
|
|
|
n--
|
|
|
|
buf[n] = '-'
|
2009-11-01 12:15:34 -07:00
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
return string(buf[n:])
|
2009-11-01 12:15:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Number of occurrences of b in s.
|
|
|
|
func count(s string, b byte) int {
|
2009-12-15 16:35:38 -07:00
|
|
|
n := 0
|
2009-11-01 12:15:34 -07:00
|
|
|
for i := 0; i < len(s); i++ {
|
|
|
|
if s[i] == b {
|
2009-11-09 13:07:39 -07:00
|
|
|
n++
|
2009-11-01 12:15:34 -07:00
|
|
|
}
|
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
return n
|
2009-11-01 12:15:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Index of rightmost occurrence of b in s.
|
|
|
|
func last(s string, b byte) int {
|
2009-12-15 16:35:38 -07:00
|
|
|
i := len(s)
|
2009-11-01 12:15:34 -07:00
|
|
|
for i--; i >= 0; i-- {
|
|
|
|
if s[i] == b {
|
2009-11-09 13:07:39 -07:00
|
|
|
break
|
2009-11-01 12:15:34 -07:00
|
|
|
}
|
|
|
|
}
|
2009-12-15 16:35:38 -07:00
|
|
|
return i
|
2009-11-01 12:15:34 -07:00
|
|
|
}
|