Skip to content

Commit

Permalink
Use 'go generate' in bytesconv.go (#663)
Browse files Browse the repository at this point in the history
* Add bytesconv_table_gen.go
  • Loading branch information
zhangyunhao116 authored and erikdubbelboer committed Sep 28, 2019
1 parent 97d51fb commit b1ca43f
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 95 deletions.
99 changes: 4 additions & 95 deletions bytesconv.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:generate go run bytesconv_table_gen.go

package fasthttp

import (
Expand Down Expand Up @@ -308,52 +310,11 @@ func writeHexInt(w *bufio.Writer, n int) error {
return err
}

var hex2intTable = func() []byte {
b := make([]byte, 256)
for i := 0; i < 256; i++ {
c := byte(16)
if i >= '0' && i <= '9' {
c = byte(i) - '0'
} else if i >= 'a' && i <= 'f' {
c = byte(i) - 'a' + 10
} else if i >= 'A' && i <= 'F' {
c = byte(i) - 'A' + 10
}
b[i] = c
}
return b
}()

const (
toLower = 'a' - 'A'
upperhex = "0123456789ABCDEF"
lowerhex = "0123456789abcdef"
)

var toLowerTable = func() [256]byte {
var a [256]byte
for i := 0; i < 256; i++ {
c := byte(i)
if c >= 'A' && c <= 'Z' {
c += toLower
}
a[i] = c
}
return a
}()

var toUpperTable = func() [256]byte {
var a [256]byte
for i := 0; i < 256; i++ {
c := byte(i)
if c >= 'a' && c <= 'z' {
c -= toLower
}
a[i] = c
}
return a
}()

func lowercaseBytes(b []byte) {
for i := 0; i < len(b); i++ {
p := &b[i]
Expand Down Expand Up @@ -383,58 +344,6 @@ func s2b(s string) (b []byte) {
return b
}

var quotedArgShouldEscapeTable = func() [256]bool {
// According to RFC 3986 §2.3
var a [256]bool
for i := 0; i < 256; i++ {
a[i] = true
}

// ALPHA
for i := int('a'); i <= int('z'); i++ {
a[i] = false
}
for i := int('A'); i <= int('Z'); i++ {
a[i] = false
}

// DIGIT
for i := int('0'); i <= int('9'); i++ {
a[i] = false
}

// Unreserved characters
a[int('-')] = false
a[int('_')] = false
a[int('.')] = false
a[int('~')] = false

return a
}()

var quotedPathShouldEscapeTable = func() [256]bool {
// The implementation here equal to net/url shouldEscape(s, encodePath)
//
// The RFC allows : @ & = + $ but saves / ; , for assigning
// meaning to individual path segments. This package
// only manipulates the path as a whole, so we allow those
// last three as well. That leaves only ? to escape.
var a = quotedArgShouldEscapeTable

// '$', '&', '+', ',', '/', ':', ';', '=', '@'
a[int('$')] = false
a[int('&')] = false
a[int('+')] = false
a[int(',')] = false
a[int('/')] = false
a[int(':')] = false
a[int(';')] = false
a[int('=')] = false
a[int('@')] = false

return a
}()

// AppendUnquotedArg appends url-decoded src to dst and returns appended dst.
//
// dst may point to src. In this case src will be overwritten.
Expand All @@ -448,7 +357,7 @@ func AppendQuotedArg(dst, src []byte) []byte {
switch {
case c == ' ':
dst = append(dst, '+')
case quotedArgShouldEscapeTable[int(c)]:
case quotedArgShouldEscapeTable[int(c)] != 0:
dst = append(dst, '%', upperhex[c>>4], upperhex[c&0xf])
default:
dst = append(dst, c)
Expand All @@ -464,7 +373,7 @@ func appendQuotedPath(dst, src []byte) []byte {
}

for _, c := range src {
if quotedPathShouldEscapeTable[int(c)] {
if quotedPathShouldEscapeTable[int(c)] != 0 {
dst = append(dst, '%', upperhex[c>>4], upperhex[c&15])
} else {
dst = append(dst, c)
Expand Down
9 changes: 9 additions & 0 deletions bytesconv_table.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

118 changes: 118 additions & 0 deletions bytesconv_table_gen.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// +build ignore

package main

import (
"bytes"
"fmt"
"io/ioutil"
"log"
)

const (
toLower = 'a' - 'A'
)

func main() {
hex2intTable := func() [256]byte {
var b [256]byte
for i := 0; i < 256; i++ {
c := byte(16)
if i >= '0' && i <= '9' {
c = byte(i) - '0'
} else if i >= 'a' && i <= 'f' {
c = byte(i) - 'a' + 10
} else if i >= 'A' && i <= 'F' {
c = byte(i) - 'A' + 10
}
b[i] = c
}
return b
}()

toLowerTable := func() [256]byte {
var a [256]byte
for i := 0; i < 256; i++ {
c := byte(i)
if c >= 'A' && c <= 'Z' {
c += toLower
}
a[i] = c
}
return a
}()

toUpperTable := func() [256]byte {
var a [256]byte
for i := 0; i < 256; i++ {
c := byte(i)
if c >= 'a' && c <= 'z' {
c -= toLower
}
a[i] = c
}
return a
}()

quotedArgShouldEscapeTable := func() [256]byte {
// According to RFC 3986 §2.3
var a [256]byte
for i := 0; i < 256; i++ {
a[i] = 1
}

// ALPHA
for i := int('a'); i <= int('z'); i++ {
a[i] = 0
}
for i := int('A'); i <= int('Z'); i++ {
a[i] = 0
}

// DIGIT
for i := int('0'); i <= int('9'); i++ {
a[i] = 0
}

// Unreserved characters
for _, v := range `-_.~` {
a[v] = 0
}

return a
}()

quotedPathShouldEscapeTable := func() [256]byte {
// The implementation here equal to net/url shouldEscape(s, encodePath)
//
// The RFC allows : @ & = + $ but saves / ; , for assigning
// meaning to individual path segments. This package
// only manipulates the path as a whole, so we allow those
// last three as well. That leaves only ? to escape.
var a = quotedArgShouldEscapeTable

for _, v := range `$&+,/:;=@` {
a[v] = 0
}

return a
}()

w := new(bytes.Buffer)
w.WriteString(pre)
fmt.Fprintf(w, "const hex2intTable = %q\n", hex2intTable)
fmt.Fprintf(w, "const toLowerTable = %q\n", toLowerTable)
fmt.Fprintf(w, "const toUpperTable = %q\n", toUpperTable)
fmt.Fprintf(w, "const quotedArgShouldEscapeTable = %q\n", quotedArgShouldEscapeTable)
fmt.Fprintf(w, "const quotedPathShouldEscapeTable = %q\n", quotedPathShouldEscapeTable)

if err := ioutil.WriteFile("bytesconv_table.go", w.Bytes(), 0660); err != nil {
log.Fatal(err)
}
}

const pre = `// Code generated by go run bytesconv_table_gen.go; DO NOT EDIT.
// See bytesconv_table_gen.go for more information about these tables.
package fasthttp
`

0 comments on commit b1ca43f

Please sign in to comment.