// 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 ( *file) () ( time.Time,  int64,  error) {
	,  := .file.Stat()
	if  != nil {
		return time.Time{}, 0, 
	}
	return .ModTime(), .Size(), nil
}

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
}

// hasUpperCase tells whether the given string contains at least one upper-case.
func hasUpperCase( string) bool {
	for  := range  {
		if 'A' <= [] && [] <= 'Z' {
			return true
		}
	}
	return false
}

// 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( string) string {
	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( string) string {
	if  := bytealg.IndexByteString(, '#');  != -1 {
		return [:]
	}
	return 
}

// 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( string,  func( string) error) error {
	 = trimSpace()
	for len() > 0 {
		 := bytealg.IndexByteString(, ' ')
		if  == -1 {
			return ()
		}
		if  := trimSpace([:]); len() > 0 {
			if  := ();  != nil {
				return 
			}
		}
		 = trimSpace([+1:])
	}
	return nil
}

// stringsHasSuffixFold reports whether s ends in suffix,
// ASCII-case-insensitively.
func stringsHasSuffixFold(,  string) bool {
	return len() >= len() && stringsEqualFold([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
}