// 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 // depending on strconv and bufio and strings. package net import ( "io" "os" ) type file struct { file *os.File data []byte atEOF bool } func (f *file) close() { f.file.Close() } func (f *file) getLineFromData() (s string, ok bool) { data := f.data i := 0 for i = 0; i < len(data); i++ { if data[i] == '\n' { s = string(data[0:i]) ok = true // move data i++ n := len(data) - i copy(data[0:], data[i:]) f.data = data[0:n] return } } if f.atEOF && len(f.data) > 0 { // EOF, return all we have s = string(data) f.data = f.data[0:0] ok = true } return } func (f *file) readLine() (s string, ok bool) { if s, ok = f.getLineFromData(); ok { return } if len(f.data) < cap(f.data) { ln := len(f.data) n, err := io.ReadFull(f.file, f.data[ln:cap(f.data)]) if n >= 0 { f.data = f.data[0 : ln+n] } if err == io.EOF { f.atEOF = true } } s, ok = f.getLineFromData() return } func open(name string) (*file, error) { fd, err := os.Open(name) if err != nil { return nil, err } return &file{fd, make([]byte, os.Getpagesize())[0:0], false}, nil } func byteIndex(s string, c byte) int { for i := 0; i < len(s); i++ { if s[i] == c { return i } } return -1 } // Count occurrences in s of any bytes in t. func countAnyByte(s string, t string) int { n := 0 for i := 0; i < len(s); i++ { if byteIndex(t, s[i]) >= 0 { n++ } } return n } // Split s at any bytes in t. func splitAtBytes(s string, t string) []string { a := make([]string, 1+countAnyByte(s, t)) n := 0 last := 0 for i := 0; i < len(s); i++ { if byteIndex(t, s[i]) >= 0 { if last < i { a[n] = string(s[last:i]) n++ } last = i + 1 } } if last < len(s) { a[n] = string(s[last:]) n++ } return a[0:n] } func getFields(s string) []string { return splitAtBytes(s, " \r\t\n") } // Bigger than we need, not too big to worry about overflow const big = 0xFFFFFF // Decimal to integer starting at &s[i0]. // Returns number, new offset, success. func dtoi(s string, i0 int) (n int, i int, ok bool) { n = 0 for i = i0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ { n = n*10 + int(s[i]-'0') if n >= big { return 0, i, false } } if i == i0 { return 0, i, false } return n, i, true } // Hexadecimal to integer starting at &s[i0]. // Returns number, new offset, success. func xtoi(s string, i0 int) (n int, i int, ok bool) { n = 0 for i = i0; i < len(s); i++ { if '0' <= s[i] && s[i] <= '9' { n *= 16 n += int(s[i] - '0') } else if 'a' <= s[i] && s[i] <= 'f' { n *= 16 n += int(s[i]-'a') + 10 } else if 'A' <= s[i] && s[i] <= 'F' { n *= 16 n += int(s[i]-'A') + 10 } else { break } if n >= big { return 0, i, false } } if i == i0 { return 0, i, false } return n, i, true } // xtoi2 converts the next two hex digits of s into a byte. // If s is longer than 2 bytes then the third byte must be e. // If the first two bytes of s are not hex digits or the third byte // does not match e, false is returned. func xtoi2(s string, e byte) (byte, bool) { if len(s) > 2 && s[2] != e { return 0, false } n, ei, ok := xtoi(s[:2], 0) return byte(n), ok && ei == 2 } // Integer to decimal. func itoa(i int) string { var buf [30]byte n := len(buf) neg := false if i < 0 { i = -i neg = true } ui := uint(i) for ui > 0 || n == len(buf) { n-- buf[n] = byte('0' + ui%10) ui /= 10 } if neg { n-- buf[n] = '-' } return string(buf[n:]) } // Convert i to decimal string. func itod(i uint) string { if i == 0 { return "0" } // Assemble decimal in reverse order. var b [32]byte bp := len(b) for ; i > 0; i /= 10 { bp-- b[bp] = byte(i%10) + '0' } return string(b[bp:]) } // Convert i to hexadecimal string. func itox(i uint, min int) string { // Assemble hexadecimal in reverse order. var b [32]byte bp := len(b) for ; i > 0 || min > 0; i /= 16 { bp-- b[bp] = "0123456789abcdef"[byte(i%16)] min-- } return string(b[bp:]) } // Number of occurrences of b in s. func count(s string, b byte) int { n := 0 for i := 0; i < len(s); i++ { if s[i] == b { n++ } } return n } // Index of rightmost occurrence of b in s. func last(s string, b byte) int { i := len(s) for i--; i >= 0; i-- { if s[i] == b { break } } return i }