// 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 (
	
	
	
	
)

type file struct {
	file  *os.File
	data  []byte
	atEOF bool
}

func ( *file) () { .file.Close() }

func ( *file) () ( string,  bool) {
	 := .data
	 := 0
	for  = 0;  < len(); ++ {
		if [] == '\n' {
			 = string([0:])
			 = true
			// move data
			++
			 := len() - 
			copy([0:], [:])
			.data = [0:]
			return
		}
	}
	if .atEOF && len(.data) > 0 {
		// EOF, return all we have
		 = string()
		.data = .data[0:0]
		 = true
	}
	return
}

func ( *file) () ( string,  bool) {
	if ,  = .getLineFromData();  {
		return
	}
	if len(.data) < cap(.data) {
		 := len(.data)
		,  := io.ReadFull(.file, .data[:cap(.data)])
		if  >= 0 {
			.data = .data[0 : +]
		}
		if  == io.EOF ||  == io.ErrUnexpectedEOF {
			.atEOF = true
		}
	}
	,  = .getLineFromData()
	return
}

func open( string) (*file, error) {
	,  := os.Open()
	if  != nil {
		return nil, 
	}
	return &file{, make([]byte, 0, 64*1024), false}, nil
}

func stat( string) ( time.Time,  int64,  error) {
	,  := os.Stat()
	if  != nil {
		return time.Time{}, 0, 
	}
	return .ModTime(), .Size(), nil
}

// Count occurrences in s of any bytes in t.
func countAnyByte( string,  string) int {
	 := 0
	for  := 0;  < len(); ++ {
		if bytealg.IndexByteString(, []) >= 0 {
			++
		}
	}
	return 
}

// Split s at any bytes in t.
func splitAtBytes( string,  string) []string {
	 := make([]string, 1+countAnyByte(, ))
	 := 0
	 := 0
	for  := 0;  < len(); ++ {
		if bytealg.IndexByteString(, []) >= 0 {
			if  <  {
				[] = [:]
				++
			}
			 =  + 1
		}
	}
	if  < len() {
		[] = [:]
		++
	}
	return [0:]
}

func getFields( string) []string { return splitAtBytes(, " \r\t\n") }

// Bigger than we need, not too big to worry about overflow
const big = 0xFFFFFF

// Decimal to integer.
// Returns number, characters consumed, success.
func dtoi( string) ( int,  int,  bool) {
	 = 0
	for  = 0;  < len() && '0' <= [] && [] <= '9'; ++ {
		 = *10 + int([]-'0')
		if  >= big {
			return big, , false
		}
	}
	if  == 0 {
		return 0, 0, false
	}
	return , , true
}

// Hexadecimal to integer.
// Returns number, characters consumed, success.
func xtoi( string) ( int,  int,  bool) {
	 = 0
	for  = 0;  < len(); ++ {
		if '0' <= [] && [] <= '9' {
			 *= 16
			 += int([] - '0')
		} else if 'a' <= [] && [] <= 'f' {
			 *= 16
			 += int([]-'a') + 10
		} else if 'A' <= [] && [] <= 'F' {
			 *= 16
			 += int([]-'A') + 10
		} else {
			break
		}
		if  >= big {
			return 0, , false
		}
	}
	if  == 0 {
		return 0, , false
	}
	return , , 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( string,  byte) (byte, bool) {
	if len() > 2 && [2] !=  {
		return 0, false
	}
	, ,  := xtoi([:2])
	return byte(),  &&  == 2
}

// Convert integer to decimal string.
func itoa( int) string {
	if  < 0 {
		return "-" + uitoa(uint(-))
	}
	return uitoa(uint())
}

// Convert unsigned integer to decimal string.
func uitoa( uint) string {
	if  == 0 { // avoid string allocation
		return "0"
	}
	var  [20]byte // big enough for 64bit value base 10
	 := len() - 1
	for  >= 10 {
		 :=  / 10
		[] = byte('0' +  - *10)
		--
		 = 
	}
	// val < 10
	[] = byte('0' + )
	return string([:])
}

// Convert i to a hexadecimal string. Leading zeros are not printed.
func appendHex( []byte,  uint32) []byte {
	if  == 0 {
		return append(, '0')
	}
	for  := 7;  >= 0; -- {
		 :=  >> uint(*4)
		if  > 0 {
			 = append(, hexDigit[&0xf])
		}
	}
	return 
}

// Number of occurrences of b in s.
func count( string,  byte) int {
	 := 0
	for  := 0;  < len(); ++ {
		if [] ==  {
			++
		}
	}
	return 
}

// Index of rightmost occurrence of b in s.
func last( string,  byte) int {
	 := len()
	for --;  >= 0; -- {
		if [] ==  {
			break
		}
	}
	return 
}

// lowerASCIIBytes makes x ASCII lowercase in-place.
func lowerASCIIBytes( []byte) {
	for ,  := range  {
		if 'A' <=  &&  <= 'Z' {
			[] += 'a' - 'A'
		}
	}
}

// lowerASCII returns the ASCII lowercase version of b.
func lowerASCII( byte) byte {
	if 'A' <=  &&  <= 'Z' {
		return  + ('a' - 'A')
	}
	return 
}

// trimSpace returns x without any leading or trailing ASCII whitespace.
func trimSpace( []byte) []byte {
	for len() > 0 && isSpace([0]) {
		 = [1:]
	}
	for len() > 0 && isSpace([len()-1]) {
		 = [:len()-1]
	}
	return 
}

// isSpace reports whether b is an ASCII space character.
func isSpace( byte) bool {
	return  == ' ' ||  == '\t' ||  == '\n' ||  == '\r'
}

// removeComment returns line, removing any '#' byte and any following
// bytes.
func removeComment( []byte) []byte {
	if  := bytealg.IndexByte(, '#');  != -1 {
		return [:]
	}
	return 
}

// foreachLine runs fn on each line of x.
// Each line (except for possibly the last) ends in '\n'.
// It returns the first non-nil error returned by fn.
func foreachLine( []byte,  func( []byte) error) error {
	for len() > 0 {
		 := bytealg.IndexByte(, '\n')
		if  == -1 {
			return ()
		}
		 := [:+1]
		 = [+1:]
		if  := ();  != nil {
			return 
		}
	}
	return nil
}

// foreachField runs fn on each non-empty run of non-space bytes in x.
// It returns the first non-nil error returned by fn.
func foreachField( []byte,  func( []byte) error) error {
	 = trimSpace()
	for len() > 0 {
		 := bytealg.IndexByte(, ' ')
		if  == -1 {
			return ()
		}
		if  := trimSpace([:]); len() > 0 {
			if  := ();  != nil {
				return 
			}
		}
		 = trimSpace([+1:])
	}
	return nil
}

// stringsHasSuffix is strings.HasSuffix. It reports whether s ends in
// suffix.
func stringsHasSuffix(,  string) bool {
	return len() >= len() && [len()-len():] == 
}

// stringsHasSuffixFold reports whether s ends in suffix,
// ASCII-case-insensitively.
func stringsHasSuffixFold(,  string) bool {
	return len() >= len() && stringsEqualFold([len()-len():], )
}

// stringsHasPrefix is strings.HasPrefix. It reports whether s begins with prefix.
func stringsHasPrefix(,  string) bool {
	return len() >= len() && [:len()] == 
}

// stringsEqualFold is strings.EqualFold, ASCII only. It reports whether s and t
// are equal, ASCII-case-insensitively.
func stringsEqualFold(,  string) bool {
	if len() != len() {
		return false
	}
	for  := 0;  < len(); ++ {
		if lowerASCII([]) != lowerASCII([]) {
			return false
		}
	}
	return true
}

func readFull( io.Reader) ( []byte,  error) {
	 := make([]byte, 1024)
	for {
		,  := .Read()
		 = append(, [:]...)
		if  == io.EOF {
			return , nil
		}
		if  != nil {
			return nil, 
		}
	}
}

// goDebugString returns the value of the named GODEBUG key.
// GODEBUG is of the form "key=val,key2=val2"
func goDebugString( string) string {
	 := os.Getenv("GODEBUG")
	for  := 0;  < len()-len()-1; ++ {
		if  > 0 && [-1] != ',' {
			continue
		}
		 := [+len():]
		if [0] != '=' || [:+len()] !=  {
			continue
		}
		 := [1:]
		for ,  := range  {
			if  == ',' {
				return [:]
			}
		}
		return 
	}
	return ""
}