Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use 'go generate' in bytesconv.go #663

Merged
merged 3 commits into from
Sep 28, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
10 changes: 10 additions & 0 deletions bytesconv_table.go

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

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

package main

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

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

func main() {
var hex2intTable = func() [256]byte {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you change these to := declarations like hex2intTable := .... I prefer those, thanks!

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

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

var 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
a[int('-')] = 0
a[int('_')] = 0
a[int('.')] = 0
a[int('~')] = 0

return a
}()

var 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

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

return a
}()

tables := []string{"hex2intTable", "toLowerTable", "toUpperTable", "quotedArgShouldEscapeTable", "quotedPathShouldEscapeTable"}
m := map[string][256]byte{
"hex2intTable": hex2intTable,
"toLowerTable": toLowerTable,
"toUpperTable": toUpperTable,
"quotedArgShouldEscapeTable": quotedArgShouldEscapeTable,
"quotedPathShouldEscapeTable": quotedPathShouldEscapeTable,
}

w := new(bytes.Buffer)
w.WriteString(pre)
for _, k := range tables {
v := m[k]
tmp := make([]byte, 256)
for i := 0; i < 256; i++ {
tmp[i] = v[i]
}
fmt.Fprintf(w, table, k, string(tmp))
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just replace the whole above code with:

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)


out, err := format.Source(w.Bytes())
if err != nil {
log.Fatal(err)
}
erikdubbelboer marked this conversation as resolved.
Show resolved Hide resolved

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

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove empty line.

}

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

`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you move this constant to the top of the file, I prefer to have them there. Thanks.


const table = `const %s = %#v
`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one can then be removed.