func FieldsN(s []byte, n int) [][]byte {
	if n <= 0 {
		return nil
	}
	res := make([][]byte, n)
	na := 0
	fieldStart := -1
	var i int
	for ; i < len(s); i++ {
		issep := s[i] == ' ' || s[i] == '\t'
		if fieldStart < 0 && !issep {
			fieldStart = i
		}
		if fieldStart >= 0 && issep {
			if na == n-1 {
				break
			}
			res[na] = s[fieldStart:i]
			na++
			fieldStart = -1
		}
	}
	if fieldStart >= 0 {  
		res[na] = TrimSpace(s[fieldStart:])
		if len(res[na]) != 0 {  
			na++
		}
	}
	return res[:na]
}
FieldsN is simliar with bytes.Fields, but only consider space and '\t' as
space, and will include all content in the final slice with ending white
space characters trimmed. bytes.Split can't split on both space and '\t',
and considers two separator as an empty item. bytes.FieldsFunc can't
specify how much fields we need, which is required for parsing response
status line. Returns nil if n < 0.
package main
import (
	"bytes"
	"crypto/md5"
	"errors"
	"fmt"
	"io"
	"net"
	"os"
	"path"
	"runtime"
	"strconv"
	"strings"
	"github.com/cyfdecyf/bufio"
)
const isWindows = runtime.GOOS == "windows"
type notification chan byte
func newNotification() notification {
	return make(chan byte, 1)
}
func (n notification) notify() {
	n <- 1
}
func (n notification) hasNotified() bool {
	select {
	case <-n:
		return true
	default:
		return false
	}
}
func ASCIIToUpperInplace(b []byte) {
	for i := 0; i < len(b); i++ {
		if 97 <= b[i] && b[i] <= 122 {
			b[i] -= 32
		}
	}
}
func ASCIIToUpper(b []byte) []byte {
	buf := make([]byte, len(b))
	for i := 0; i < len(b); i++ {
		if 97 <= b[i] && b[i] <= 122 {
			buf[i] = b[i] - 32
		} else {
			buf[i] = b[i]
		}
	}
	return buf
}
func ASCIIToLowerInplace(b []byte) {
	for i := 0; i < len(b); i++ {
		if 65 <= b[i] && b[i] <= 90 {
			b[i] += 32
		}
	}
}
func ASCIIToLower(b []byte) []byte {
	buf := make([]byte, len(b))
	for i := 0; i < len(b); i++ {
		if 65 <= b[i] && b[i] <= 90 {
			buf[i] = b[i] + 32
		} else {
			buf[i] = b[i]
		}
	}
	return buf
}
func IsDigit(b byte) bool {
	return '0' <= b && b <= '9'
}
var spaceTbl = [256]bool{
	'\t': true,  
	'\n': true,  
	'\r': true,  
	' ':  true,  
}
func IsSpace(b byte) bool {
	return spaceTbl[b]
}
func TrimSpace(s []byte) []byte {
	st := 0
	end := len(s) - 1
	for ; st < len(s) && IsSpace(s[st]); st++ {
	}
	if st == len(s) {
		return s[:0]
	}
	for ; end >= 0 && IsSpace(s[end]); end-- {
	}
	return s[st : end+1]
}
func TrimTrailingSpace(s []byte) []byte {
	end := len(s) - 1
	for ; end >= 0 && IsSpace(s[end]); end-- {
	}
	return s[:end+1]
}