//go:generate go run bytesconv_table_gen.gopackage fasthttpimport ()// AppendHTMLEscape appends html-escaped s to dst and returns the extended dst.func ( []byte, string) []byte {var (intstring )for , := 0, len(); < ; ++ { = ""switch [] {case'&': = "&"case'<': = "<"case'>': = ">"case'"': = """// """ is shorter than """.case'\'': = "'"// "'" is shorter than "'" and apos was not in HTML until HTML5. }iflen() > 0 { = append(, [:]...) = append(, ...) = + 1 } }returnappend(, [:]...)}// AppendHTMLEscapeBytes appends html-escaped s to dst and returns// the extended dst.func (, []byte) []byte {returnAppendHTMLEscape(, b2s())}// AppendIPv4 appends string representation of the given ip v4 to dst// and returns the extended dst.func ( []byte, net.IP) []byte { = .To4()if == nil {returnappend(, "non-v4 ip passed to AppendIPv4"...) } = AppendUint(, int([0]))for := 1; < 4; ++ { = append(, '.') = AppendUint(, int([])) }return}var errEmptyIPStr = errors.New("empty ip address string")// ParseIPv4 parses ip address from ipStr into dst and returns the extended dst.func ( net.IP, []byte) (net.IP, error) {iflen() == 0 {return , errEmptyIPStr }iflen() < net.IPv4len { = make([]byte, net.IPv4len) }copy(, net.IPv4zero) = .To4()if == nil {// developer sanity-checkpanic("BUG: dst must not be nil") } := for := 0; < 3; ++ { := bytes.IndexByte(, '.')if < 0 {return , fmt.Errorf("cannot find dot in ipStr %q", ) } , := ParseUint([:])if != nil {return , fmt.Errorf("cannot parse ipStr %q: %w", , ) }if > 255 {return , fmt.Errorf("cannot parse ipStr %q: ip part cannot exceed 255: parsed %d", , ) } [] = byte() = [+1:] } , := ParseUint()if != nil {return , fmt.Errorf("cannot parse ipStr %q: %w", , ) }if > 255 {return , fmt.Errorf("cannot parse ipStr %q: ip part cannot exceed 255: parsed %d", , ) } [3] = byte()return , nil}// AppendHTTPDate appends HTTP-compliant (RFC1123) representation of date// to dst and returns the extended dst.func ( []byte, time.Time) []byte { = .In(time.UTC).AppendFormat(, time.RFC1123)copy([len()-3:], strGMT)return}// ParseHTTPDate parses HTTP-compliant (RFC1123) date.func ( []byte) (time.Time, error) {returntime.Parse(time.RFC1123, b2s())}// AppendUint appends n to dst and returns the extended dst.func ( []byte, int) []byte {if < 0 {// developer sanity-checkpanic("BUG: int must be positive") }var [20]byte := [:] := len()varintfor >= 10 { -- = / 10 [] = '0' + byte(-*10) = } -- [] = '0' + byte() = append(, [:]...)return}// ParseUint parses uint from buf.func ( []byte) (int, error) { , , := parseUintBuf()if != len() {return -1, errUnexpectedTrailingChar }return , }var ( errEmptyInt = errors.New("empty integer") errUnexpectedFirstChar = errors.New("unexpected first char found. Expecting 0-9") errUnexpectedTrailingChar = errors.New("unexpected trailing char found. Expecting 0-9") errTooLongInt = errors.New("too long int"))func parseUintBuf( []byte) (int, int, error) { := len()if == 0 {return -1, 0, errEmptyInt } := 0for := 0; < ; ++ { := [] := - '0'if > 9 {if == 0 {return -1, , errUnexpectedFirstChar }return , , nil } := 10* + int()// Test for overflow.if < {return -1, , errTooLongInt } = }return , , nil}var ( errEmptyFloat = errors.New("empty float number") errDuplicateFloatPoint = errors.New("duplicate point found in float number") errUnexpectedFloatEnd = errors.New("unexpected end of float number") errInvalidFloatExponent = errors.New("invalid float number exponent") errUnexpectedFloatChar = errors.New("unexpected char found in float number"))// ParseUfloat parses unsigned float from buf.func ( []byte) (float64, error) {iflen() == 0 {return -1, errEmptyFloat } := varuint64 := 1.0varboolfor , := range {if < '0' || > '9' {if == '.' {if {return -1, errDuplicateFloatPoint } = truecontinue }if == 'e' || == 'E' {if +1 >= len() {return -1, errUnexpectedFloatEnd } = [+1:] := -1switch [0] {case'+': = [1:] = 1case'-': = [1:]default: = 1 } , := ParseUint()if != nil {return -1, errInvalidFloatExponent }returnfloat64() * * math.Pow10(*), nil }return -1, errUnexpectedFloatChar } = 10* + uint64(-'0')if { /= 10 } }returnfloat64() * , nil}var ( errEmptyHexNum = errors.New("empty hex number") errTooLargeHexNum = errors.New("too large hex number"))func readHexInt( *bufio.Reader) (int, error) {var , , intfor { , := .ReadByte()if != nil {if == io.EOF && > 0 {return , nil }return -1, } = int(hex2intTable[])if == 16 {if == 0 {return -1, errEmptyHexNum }if := .UnreadByte(); != nil {return -1, }return , nil }if >= maxHexIntChars {return -1, errTooLargeHexNum } = ( << 4) | ++ }}var hexIntBufPool sync.Poolfunc writeHexInt( *bufio.Writer, int) error {if < 0 {// developer sanity-checkpanic("BUG: int must be positive") } := hexIntBufPool.Get()if == nil { = make([]byte, maxHexIntChars+1) } := .([]byte) := len() - 1for { [] = lowerhex[&0xf] >>= 4if == 0 {break } -- } , := .Write([:])hexIntBufPool.Put()return}const ( upperhex = "0123456789ABCDEF" lowerhex = "0123456789abcdef")func lowercaseBytes( []byte) {for := 0; < len(); ++ { := &[] * = toLowerTable[*] }}// AppendUnquotedArg appends url-decoded src to dst and returns appended dst.//// dst may point to src. In this case src will be overwritten.func (, []byte) []byte {returndecodeArgAppend(, )}// AppendQuotedArg appends url-encoded src to dst and returns appended dst.func (, []byte) []byte {for , := range {switch {case == ' ': = append(, '+')casequotedArgShouldEscapeTable[int()] != 0: = append(, '%', upperhex[>>4], upperhex[&0xf])default: = append(, ) } }return}func appendQuotedPath(, []byte) []byte {// Fix issue in https://github.com/golang/go/issues/11202iflen() == 1 && [0] == '*' {returnappend(, '*') }for , := range {ifquotedPathShouldEscapeTable[int()] != 0 { = append(, '%', upperhex[>>4], upperhex[&0xf]) } else { = append(, ) } }return}
The pages are generated with Goldsv0.6.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds.