Makefile: Set GO111MODULE=on for consistency, adjust tests accordingly

This commit is contained in:
Luke Shumaker 2019-06-04 21:55:20 -04:00
parent b51d53e11e
commit 9ce337296b
31 changed files with 1524 additions and 20 deletions

View File

@ -4,9 +4,6 @@ go:
- 1.11.x
- 1.12.x
before_script:
- go get github.com/valyala/quicktemplate
script: make check_generated test
after_success:

View File

@ -1,3 +1,5 @@
export GO111MODULE = on
test: build
GL_TEST_RUN=1 ./golangci-lint run -v
GL_TEST_RUN=1 ./golangci-lint run --fast --no-config -v --skip-dirs 'test/testdata_etc,pkg/golinters/goanalysis/(checker|passes)'
@ -32,9 +34,9 @@ release:
curl -sL https://git.io/goreleaser | bash
update_deps:
GO111MODULE=on go mod verify
GO111MODULE=on go mod tidy
go mod verify
go mod tidy
rm -rf vendor
GO111MODULE=on go mod vendor
go mod vendor
.PHONY: test

1
go.mod
View File

@ -49,6 +49,7 @@ require (
github.com/spf13/pflag v1.0.1
github.com/spf13/viper v1.0.2
github.com/stretchr/testify v1.2.2
github.com/valyala/quicktemplate v1.1.1
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a // indirect
golang.org/x/net v0.0.0-20190313220215-9f648a60d977 // indirect
golang.org/x/sys v0.0.0-20190312061237-fead79001313 // indirect

11
go.sum
View File

@ -86,6 +86,10 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt
github.com/kisielk/gotool v0.0.0-20161130080628-0de1eaf82fa3/go.mod h1:jxZFDH7ILpTPQTk+E2s+z4CUas9lVNjIuKR4c5/zKgM=
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@ -150,12 +154,19 @@ github.com/spf13/viper v1.0.2 h1:Ncr3ZIuJn322w2k1qmzXDnkLAdQMlJqBa9kfAH+irso=
github.com/spf13/viper v1.0.2/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s=
github.com/valyala/quicktemplate v1.1.1 h1:C58y/wN0FMTi2PR0n3onltemfFabany53j7M6SDDB8k=
github.com/valyala/quicktemplate v1.1.1/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4=
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a h1:YX8ljsm6wXlHZO+aRz9Exqr0evNhKRNe5K/gi+zKh4U=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20170915142106-8351a756f30f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190313220215-9f648a60d977 h1:actzWV6iWn3GLqN8dZjzsB+CLt+gaV2+wsxroxiQI8I=
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=

View File

@ -53,18 +53,18 @@ func buildTemplateContext() (map[string]interface{}, error) {
return nil, fmt.Errorf("can't read .golangci.example.yml: %s", err)
}
if err = exec.Command("go", "install", "./cmd/...").Run(); err != nil {
if err = exec.Command("make", "build").Run(); err != nil {
return nil, fmt.Errorf("can't run go install: %s", err)
}
lintersOut, err := exec.Command("golangci-lint", "help", "linters").Output()
lintersOut, err := exec.Command("./golangci-lint", "help", "linters").Output()
if err != nil {
return nil, fmt.Errorf("can't run linters cmd: %s", err)
}
lintersOutParts := bytes.Split(lintersOut, []byte("\n\n"))
helpCmd := exec.Command("golangci-lint", "run", "-h")
helpCmd := exec.Command("./golangci-lint", "run", "-h")
helpCmd.Env = append(helpCmd.Env, os.Environ()...)
helpCmd.Env = append(helpCmd.Env, "HELP_RUN=1") // make default concurrency stable: don't depend on machine CPU number
help, err := helpCmd.Output()

View File

@ -3,7 +3,7 @@ package test
import "path/filepath"
const testdataDir = "testdata"
const binName = "golangci-lint"
const binName = "../golangci-lint"
func getProjectRoot() string {
return filepath.Join("..", "...")

View File

@ -10,6 +10,8 @@ import (
"github.com/golangci/golangci-lint/test/testshared"
"github.com/golangci/golangci-lint/pkg/exitcodes"
_ "github.com/valyala/quicktemplate"
)
func getCommonRunArgs() []string {
@ -25,13 +27,13 @@ func TestAutogeneratedNoIssues(t *testing.T) {
}
func TestEmptyDirRun(t *testing.T) {
testshared.NewLintRunner(t).Run(getTestDataDir("nogofiles")).
testshared.NewLintRunner(t, "GO111MODULE=off").Run(getTestDataDir("nogofiles")).
ExpectExitCode(exitcodes.NoGoFiles).
ExpectOutputContains(": no go files to analyze")
}
func TestNotExistingDirRun(t *testing.T) {
testshared.NewLintRunner(t).Run(getTestDataDir("no_such_dir")).
testshared.NewLintRunner(t, "GO111MODULE=off").Run(getTestDataDir("no_such_dir")).
ExpectExitCode(exitcodes.Failure).
ExpectOutputContains(`cannot find package \"./testdata/no_such_dir\"`)
}

View File

@ -4,7 +4,6 @@ import (
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"syscall"
@ -17,27 +16,26 @@ import (
type LintRunner struct {
t assert.TestingT
log logutils.Log
installed bool
env []string
}
func NewLintRunner(t assert.TestingT) *LintRunner {
func NewLintRunner(t assert.TestingT, environ ...string) *LintRunner {
log := logutils.NewStderrLog("test")
log.SetLevel(logutils.LogLevelInfo)
return &LintRunner{
t: t,
log: log,
env: environ,
}
}
func (r *LintRunner) Install() {
if r.installed {
if _, err := os.Stat("../golangci-lint"); err == nil {
return
}
cmd := exec.Command("go", "install", filepath.Join("..", "cmd", "golangci-lint"))
cmd := exec.Command("make", "-C", "..", "build")
assert.NoError(r.t, cmd.Run(), "Can't go install golangci-lint")
r.installed = true
}
type RunResult struct {
@ -82,7 +80,8 @@ func (r *LintRunner) Run(args ...string) *RunResult {
runArgs := append([]string{"run"}, args...)
r.log.Infof("golangci-lint %s", strings.Join(runArgs, " "))
cmd := exec.Command("golangci-lint", runArgs...)
cmd := exec.Command("../golangci-lint", runArgs...)
cmd.Env = append(os.Environ(), r.env...)
out, err := cmd.CombinedOutput()
if err != nil {
if exitError, ok := err.(*exec.ExitError); ok {

15
vendor/github.com/valyala/bytebufferpool/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,15 @@
language: go
go:
- 1.6
script:
# build test for supported platforms
- GOOS=linux go build
- GOOS=darwin go build
- GOOS=freebsd go build
- GOOS=windows go build
- GOARCH=386 go build
# run tests on a standard platform
- go test -v ./...

22
vendor/github.com/valyala/bytebufferpool/LICENSE generated vendored Normal file
View File

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2016 Aliaksandr Valialkin, VertaMedia
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

21
vendor/github.com/valyala/bytebufferpool/README.md generated vendored Normal file
View File

@ -0,0 +1,21 @@
[![Build Status](https://travis-ci.org/valyala/bytebufferpool.svg)](https://travis-ci.org/valyala/bytebufferpool)
[![GoDoc](https://godoc.org/github.com/valyala/bytebufferpool?status.svg)](http://godoc.org/github.com/valyala/bytebufferpool)
[![Go Report](http://goreportcard.com/badge/valyala/bytebufferpool)](http://goreportcard.com/report/valyala/bytebufferpool)
# bytebufferpool
An implementation of a pool of byte buffers with anti-memory-waste protection.
The pool may waste limited amount of memory due to fragmentation.
This amount equals to the maximum total size of the byte buffers
in concurrent use.
# Benchmark results
Currently bytebufferpool is fastest and most effective buffer pool written in Go.
You can find results [here](https://omgnull.github.io/go-benchmark/buffer/).
# bytebufferpool users
* [fasthttp](https://github.com/valyala/fasthttp)
* [quicktemplate](https://github.com/valyala/quicktemplate)

111
vendor/github.com/valyala/bytebufferpool/bytebuffer.go generated vendored Normal file
View File

@ -0,0 +1,111 @@
package bytebufferpool
import "io"
// ByteBuffer provides byte buffer, which can be used for minimizing
// memory allocations.
//
// ByteBuffer may be used with functions appending data to the given []byte
// slice. See example code for details.
//
// Use Get for obtaining an empty byte buffer.
type ByteBuffer struct {
// B is a byte buffer to use in append-like workloads.
// See example code for details.
B []byte
}
// Len returns the size of the byte buffer.
func (b *ByteBuffer) Len() int {
return len(b.B)
}
// ReadFrom implements io.ReaderFrom.
//
// The function appends all the data read from r to b.
func (b *ByteBuffer) ReadFrom(r io.Reader) (int64, error) {
p := b.B
nStart := int64(len(p))
nMax := int64(cap(p))
n := nStart
if nMax == 0 {
nMax = 64
p = make([]byte, nMax)
} else {
p = p[:nMax]
}
for {
if n == nMax {
nMax *= 2
bNew := make([]byte, nMax)
copy(bNew, p)
p = bNew
}
nn, err := r.Read(p[n:])
n += int64(nn)
if err != nil {
b.B = p[:n]
n -= nStart
if err == io.EOF {
return n, nil
}
return n, err
}
}
}
// WriteTo implements io.WriterTo.
func (b *ByteBuffer) WriteTo(w io.Writer) (int64, error) {
n, err := w.Write(b.B)
return int64(n), err
}
// Bytes returns b.B, i.e. all the bytes accumulated in the buffer.
//
// The purpose of this function is bytes.Buffer compatibility.
func (b *ByteBuffer) Bytes() []byte {
return b.B
}
// Write implements io.Writer - it appends p to ByteBuffer.B
func (b *ByteBuffer) Write(p []byte) (int, error) {
b.B = append(b.B, p...)
return len(p), nil
}
// WriteByte appends the byte c to the buffer.
//
// The purpose of this function is bytes.Buffer compatibility.
//
// The function always returns nil.
func (b *ByteBuffer) WriteByte(c byte) error {
b.B = append(b.B, c)
return nil
}
// WriteString appends s to ByteBuffer.B.
func (b *ByteBuffer) WriteString(s string) (int, error) {
b.B = append(b.B, s...)
return len(s), nil
}
// Set sets ByteBuffer.B to p.
func (b *ByteBuffer) Set(p []byte) {
b.B = append(b.B[:0], p...)
}
// SetString sets ByteBuffer.B to s.
func (b *ByteBuffer) SetString(s string) {
b.B = append(b.B[:0], s...)
}
// String returns string representation of ByteBuffer.B.
func (b *ByteBuffer) String() string {
return string(b.B)
}
// Reset makes ByteBuffer.B empty.
func (b *ByteBuffer) Reset() {
b.B = b.B[:0]
}

7
vendor/github.com/valyala/bytebufferpool/doc.go generated vendored Normal file
View File

@ -0,0 +1,7 @@
// Package bytebufferpool implements a pool of byte buffers
// with anti-fragmentation protection.
//
// The pool may waste limited amount of memory due to fragmentation.
// This amount equals to the maximum total size of the byte buffers
// in concurrent use.
package bytebufferpool

151
vendor/github.com/valyala/bytebufferpool/pool.go generated vendored Normal file
View File

@ -0,0 +1,151 @@
package bytebufferpool
import (
"sort"
"sync"
"sync/atomic"
)
const (
minBitSize = 6 // 2**6=64 is a CPU cache line size
steps = 20
minSize = 1 << minBitSize
maxSize = 1 << (minBitSize + steps - 1)
calibrateCallsThreshold = 42000
maxPercentile = 0.95
)
// Pool represents byte buffer pool.
//
// Distinct pools may be used for distinct types of byte buffers.
// Properly determined byte buffer types with their own pools may help reducing
// memory waste.
type Pool struct {
calls [steps]uint64
calibrating uint64
defaultSize uint64
maxSize uint64
pool sync.Pool
}
var defaultPool Pool
// Get returns an empty byte buffer from the pool.
//
// Got byte buffer may be returned to the pool via Put call.
// This reduces the number of memory allocations required for byte buffer
// management.
func Get() *ByteBuffer { return defaultPool.Get() }
// Get returns new byte buffer with zero length.
//
// The byte buffer may be returned to the pool via Put after the use
// in order to minimize GC overhead.
func (p *Pool) Get() *ByteBuffer {
v := p.pool.Get()
if v != nil {
return v.(*ByteBuffer)
}
return &ByteBuffer{
B: make([]byte, 0, atomic.LoadUint64(&p.defaultSize)),
}
}
// Put returns byte buffer to the pool.
//
// ByteBuffer.B mustn't be touched after returning it to the pool.
// Otherwise data races will occur.
func Put(b *ByteBuffer) { defaultPool.Put(b) }
// Put releases byte buffer obtained via Get to the pool.
//
// The buffer mustn't be accessed after returning to the pool.
func (p *Pool) Put(b *ByteBuffer) {
idx := index(len(b.B))
if atomic.AddUint64(&p.calls[idx], 1) > calibrateCallsThreshold {
p.calibrate()
}
maxSize := int(atomic.LoadUint64(&p.maxSize))
if maxSize == 0 || cap(b.B) <= maxSize {
b.Reset()
p.pool.Put(b)
}
}
func (p *Pool) calibrate() {
if !atomic.CompareAndSwapUint64(&p.calibrating, 0, 1) {
return
}
a := make(callSizes, 0, steps)
var callsSum uint64
for i := uint64(0); i < steps; i++ {
calls := atomic.SwapUint64(&p.calls[i], 0)
callsSum += calls
a = append(a, callSize{
calls: calls,
size: minSize << i,
})
}
sort.Sort(a)
defaultSize := a[0].size
maxSize := defaultSize
maxSum := uint64(float64(callsSum) * maxPercentile)
callsSum = 0
for i := 0; i < steps; i++ {
if callsSum > maxSum {
break
}
callsSum += a[i].calls
size := a[i].size
if size > maxSize {
maxSize = size
}
}
atomic.StoreUint64(&p.defaultSize, defaultSize)
atomic.StoreUint64(&p.maxSize, maxSize)
atomic.StoreUint64(&p.calibrating, 0)
}
type callSize struct {
calls uint64
size uint64
}
type callSizes []callSize
func (ci callSizes) Len() int {
return len(ci)
}
func (ci callSizes) Less(i, j int) bool {
return ci[i].calls > ci[j].calls
}
func (ci callSizes) Swap(i, j int) {
ci[i], ci[j] = ci[j], ci[i]
}
func index(n int) int {
n--
n >>= minBitSize
idx := 0
for n > 0 {
n >>= 1
idx++
}
if idx >= steps {
idx = steps - 1
}
return idx
}

1
vendor/github.com/valyala/quicktemplate/.gitignore generated vendored Normal file
View File

@ -0,0 +1 @@
tags

19
vendor/github.com/valyala/quicktemplate/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,19 @@
language: go
go:
- 1.11.x
- 1.12.x
- tip
before_install:
- go get -u github.com/valyala/quicktemplate/qtc
- go generate
script:
# build test for supported platforms
- GOOS=linux go build
- GOOS=darwin go build
- GOOS=freebsd go build
# run tests on a standard platform
- go test -v ./...

22
vendor/github.com/valyala/quicktemplate/LICENSE generated vendored Normal file
View File

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2016 Aliaksandr Valialkin, VertaMedia
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,16 @@
<filetype binary="false" description="QuickTemplate" name="QuickTemplate">
<highlighting>
<options>
<option name="LINE_COMMENT" value="//" />
<option name="COMMENT_START" value="" />
<option name="COMMENT_END" value="" />
<option name="HEX_PREFIX" value="" />
<option name="NUM_POSTFIXES" value="" />
</options>
<keywords keywords="case;cat;code;collapsespace;comment;default;else;elseif;endcollapsespace;endcomment;endfor;endfunc;endif;endplain;endstripspace;endswitch;for;func;if;import;interface;package;plain;space;stripspace;struct;switch;type" ignore_case="false" />
<keywords3 keywords="{%=;{%=h;{%=j;{%=jh;{%=q;{%=qh;{%=u;{%=uh;{%d;{%d=;{%f;{%f.;{%f.=;{%f=;{%j;{%j=;{%q;{%q=;{%s=;{%u;{%u=;{%uz;{%uz=;{%v;{%v=;{%z;{%z=" />
</highlighting>
<extensionMap>
<mapping ext="qtpl" />
</extensionMap>
</filetype>

621
vendor/github.com/valyala/quicktemplate/README.md generated vendored Normal file
View File

@ -0,0 +1,621 @@
[![Build Status](https://travis-ci.org/valyala/quicktemplate.svg)](https://travis-ci.org/valyala/quicktemplate)
[![GoDoc](https://godoc.org/github.com/valyala/quicktemplate?status.svg)](http://godoc.org/github.com/valyala/quicktemplate)
[![Go Report Card](https://goreportcard.com/badge/github.com/valyala/quicktemplate)](https://goreportcard.com/report/github.com/valyala/quicktemplate)
# quicktemplate
A fast, powerful, yet easy to use template engine for Go.
Inspired by the [Mako templates](http://www.makotemplates.org/) philosophy.
# Features
* [Extremely fast](#performance-comparison-with-htmltemplate).
Templates are converted into Go code and then compiled.
* Quicktemplate syntax is very close to Go - there is no need to learn
yet another template language before starting to use quicktemplate.
* Almost all bugs are caught during template compilation, so production
suffers less from template-related bugs.
* Easy to use. See [quickstart](#quick-start) and [examples](https://github.com/valyala/quicktemplate/tree/master/examples)
for details.
* Powerful. Arbitrary Go code may be embedded into and mixed with templates.
Be careful with this power - do not query the database and/or external resources from
templates unless you miss the PHP way in Go :) This power is mostly for
arbitrary data transformations.
* Easy to use template inheritance powered by [Go interfaces](https://golang.org/doc/effective_go.html#interfaces).
See [this example](https://github.com/valyala/quicktemplate/tree/master/examples/basicserver) for details.
* Templates are compiled into a single binary, so there is no need to copy
template files to the server.
# Drawbacks
* Templates cannot be updated on the fly on the server, since they
are compiled into a single binary.
Take a look at [fasttemplate](https://github.com/valyala/fasttemplate)
if you need a fast template engine for simple dynamically updated templates.
# Performance comparison with html/template
Quicktemplate is more than 20x faster than [html/template](https://golang.org/pkg/html/template/).
The following simple template is used in the benchmark:
* [html/template version](https://github.com/valyala/quicktemplate/blob/master/testdata/templates/bench.tpl)
* [quicktemplate version](https://github.com/valyala/quicktemplate/blob/master/testdata/templates/bench.qtpl)
Benchmark results:
```
$ go test -bench='Benchmark(Quick|HTML)Template' -benchmem github.com/valyala/quicktemplate/tests
BenchmarkQuickTemplate1-4 10000000 120 ns/op 0 B/op 0 allocs/op
BenchmarkQuickTemplate10-4 3000000 441 ns/op 0 B/op 0 allocs/op
BenchmarkQuickTemplate100-4 300000 3945 ns/op 0 B/op 0 allocs/op
BenchmarkHTMLTemplate1-4 500000 2501 ns/op 752 B/op 23 allocs/op
BenchmarkHTMLTemplate10-4 100000 12442 ns/op 3521 B/op 117 allocs/op
BenchmarkHTMLTemplate100-4 10000 123392 ns/op 34498 B/op 1152 allocs/op
```
[goTemplateBenchmark](https://github.com/SlinSo/goTemplateBenchmark) compares QuickTemplate with numerous Go templating packages. QuickTemplate performs favorably.
# Security
* All template placeholders are HTML-escaped by default.
* Template placeholders for JSON strings prevent from `</script>`-based
XSS attacks:
```qtpl
{% func FailedXSS() %}
<script>
var s = {%q= "</script><script>alert('you pwned!')" %};
</script>
{% endfunc %}
```
# Examples
See [examples](https://github.com/valyala/quicktemplate/tree/master/examples).
# Quick start
First of all, install the `quicktemplate` package
and [quicktemplate compiler](https://github.com/valyala/quicktemplate/tree/master/qtc) (`qtc`):
```
go get -u github.com/valyala/quicktemplate
go get -u github.com/valyala/quicktemplate/qtc
```
Let's start with a minimal template example:
```qtpl
All text outside function templates is treated as comments,
i.e. it is just ignored by quicktemplate compiler (`qtc`). It is for humans.
Hello is a simple template function.
{% func Hello(name string) %}
Hello, {%s name %}!
{% endfunc %}
```
Save this file into a `templates` folder under the name `hello.qtpl`
and run `qtc` inside this folder.
If everything went OK, `hello.qtpl.go` file should appear in the `templates` folder.
This file contains Go code for `hello.qtpl`. Let's use it!
Create a file main.go outside `templates` folder and put the following
code there:
```go
package main
import (
"fmt"
"./templates"
)
func main() {
fmt.Printf("%s\n", templates.Hello("Foo"))
fmt.Printf("%s\n", templates.Hello("Bar"))
}
```
Then issue `go run`. If everything went OK, you'll see something like this:
```
Hello, Foo!
Hello, Bar!
```
Let's create more a complex template which calls other template functions,
contains loops, conditions, breaks, continues and returns.
Put the following template into `templates/greetings.qtpl`:
```qtpl
Greetings greets up to 42 names.
It also greets John differently comparing to others.
{% func Greetings(names []string) %}
{% if len(names) == 0 %}
Nobody to greet :(
{% return %}
{% endif %}
{% for i, name := range names %}
{% if i == 42 %}
I'm tired to greet so many people...
{% break %}
{% elseif name == "John" %}
{%= sayHi("Mr. " + name) %}
{% continue %}
{% else %}
{%= Hello(name) %}
{% endif %}
{% endfor %}
{% endfunc %}
sayHi is unexported, since it starts with lowercase letter.
{% func sayHi(name string) %}
Hi, {%s name %}
{% endfunc %}
Note that every template file may contain an arbitrary number
of template functions. For instance, this file contains Greetings and sayHi
functions.
```
Run `qtc` inside `templates` folder. Now the folder should contain
two files with Go code: `hello.qtpl.go` and `greetings.qtpl.go`. These files
form a single `templates` Go package. Template functions and other template
stuff is shared between template files located in the same folder.
So `Hello` template function may be used inside `greetings.qtpl` while
it is defined in `hello.qtpl`.
Moreover, the folder may contain ordinary Go files, so its contents may
be used inside templates and vice versa.
The package name inside template files may be overriden
with `{% package packageName %}`.
Now put the following code into `main.go`:
```go
package main
import (
"bytes"
"fmt"
"./templates"
)
func main() {
names := []string{"Kate", "Go", "John", "Brad"}
// qtc creates Write* function for each template function.
// Such functions accept io.Writer as first parameter:
var buf bytes.Buffer
templates.WriteGreetings(&buf, names)
fmt.Printf("buf=\n%s", buf.Bytes())
}
```
Careful readers may notice different output tags were used in these
templates: `{%s name %}` and `{%= Hello(name) %}`. What's the difference?
The `{%s x %}` is used for printing HTML-safe strings, while `{%= F() %}`
is used for embedding template function calls. Quicktemplate supports also
other output tags:
* `{%d num %}` for integers.
* `{%f float %}` for float64.
Floating point precision may be set via `{%f.precision float %}`.
For example, `{%f.2 1.2345 %}` outputs `1.23`.
* `{%z bytes %}` for byte slices.
* `{%q str %}` and `{%qz bytes %}` for JSON-compatible quoted strings.
* `{%j str %}` and `{%jz bytes %}` for embedding str into a JSON string. Unlike `{%q str %}`,
it doesn't quote the string.
* `{%u str %}` and `{%uz bytes %}` for [URL encoding](https://en.wikipedia.org/wiki/Percent-encoding)
the given str.
* `{%v anything %}` is equivalent to `%v` in [printf-like functions](https://golang.org/pkg/fmt/).
All the output tags except `{%= F() %}` produce HTML-safe output, i.e. they
escape `<` to `&lt;`, `>` to `&gt;`, etc. If you don't want HTML-safe output,
then just put `=` after the tag. For example: `{%s= "<h1>This h1 won't be escaped</h1>" %}`.
As you may notice `{%= F() %}` and `{%s= F() %}` produce the same output for `{% func F() %}`.
But the first one is optimized for speed - it avoids memory allocations and copies.
It is therefore recommended to stick to it when embedding template function calls.
Additionally, the following extensions are supported for `{%= F() %}`:
* `{%=h F() %}` produces html-escaped output.
* `{%=u F() %}` produces [URL-encoded](https://en.wikipedia.org/wiki/Percent-encoding) output.
* `{%=q F() %}` produces quoted json string.
* `{%=j F() %}` produces json string without quotes.
* `{%=uh F() %}` produces html-safe URL-encoded output.
* `{%=qh F() %}` produces html-safe quoted json string.
* `{%=jh F() %}` produces html-safe json string without quotes.
All output tags except `{%= F() %}` family may contain arbitrary valid
Go expressions instead of just an identifier. For example:
```qtpl
Import fmt for fmt.Sprintf()
{% import "fmt" %}
FmtFunc uses fmt.Sprintf() inside output tag
{% func FmtFunc(s string) %}
{%s fmt.Sprintf("FmtFunc accepted %q string", s) %}
{% endfunc %}
```
There are other useful tags supported by quicktemplate:
* `{% comment %}`
```qtpl
{% comment %}
This is a comment. It won't trap into the output.
It may contain {% arbitrary tags %}. They are just ignored.
{% endcomment %}
```
* `{% plain %}`
```qtpl
{% plain %}
Tags will {% trap into %} the output {% unmodified %}.
Plain block may contain invalid and {% incomplete tags.
{% endplain %}
```
* `{% collapsespace %}`
```qtpl
{% collapsespace %}
<div>
<div>space between lines</div>
and {%s "tags" %}
<div>is collapsed into a single space
unless{% newline %}or{% space %}is used</div>
</div>
{% endcollapsespace %}
```
Is converted into:
```
<div> <div>space between lines</div> and tags <div>is collapsed into a single space unless
or is used</div> </div>
```
* `{% stripspace %}`
```qtpl
{% stripspace %}
<div>
<div>space between lines</div>
and {%s " tags" %}
<div>is removed unless{% newline %}or{% space %}is used</div>
</div>
{% endstripspace %}
```
Is converted into:
```
<div><div>space between lines</div>and tags<div>is removed unless
or is used</div></div>
```
* `{% switch %}`, `{% case %}` and `{% default %}`:
```qtpl
1 + 1 =
{% switch 1+1 %}
{% case 2 %}
2?
{% case 42 %}
42!
{% default %}
I don't know :(
{% endswitch %}
```
* `{% code %}`:
```qtpl
{% code
// arbitrary Go code may be embedded here!
type FooArg struct {
Name string
Age int
}
%}
```
* `{% package %}`:
```qtpl
Override default package name with the custom name
{% package customPackageName %}
```
* `{% import %}`:
```qtpl
Import external packages.
{% import "foo/bar" %}
{% import (
"foo"
bar "baz/baa"
) %}
```
* `{% cat "/path/to/file" %}`:
```qtpl
Cat emits the given file contents as a plaintext:
{% func passwords() %}
/etc/passwd contents:
{% cat "/etc/passwd" %}
{% endfunc %}
```
* `{% interface %}`:
```qtpl
Interfaces allow powerful templates' inheritance
{%
interface Page {
Title()
Body(s string, n int)
Footer()
}
%}
PrintPage prints Page
{% func PrintPage(p Page) %}
<html>
<head><title>{%= p.Title() %}</title></head>
<body>
<div>{%= p.Body("foo", 42) %}</div>
<div>{%= p.Footer() %}</div>
</body>
</html>
{% endfunc %}
Base page implementation
{% code
type BasePage struct {
TitleStr string
FooterStr string
}
%}
{% func (bp *BasePage) Title() %}{%s bp.TitleStr %}{% endfunc %}
{% func (bp *BasePage) Body(s string, n int) %}
<b>s={%q s %}, n={%d n %}</b>
{% endfunc %}
{% func (bp *BasePage) Footer() %}{%s bp.FooterStr %}{% endfunc %}
Main page implementation
{% code
type MainPage struct {
// inherit from BasePage
BasePage
// real body for main page
BodyStr string
}
%}
Override only Body
Title and Footer are used from BasePage.
{% func (mp *MainPage) Body(s string, n int) %}
<div>
main body: {%s mp.BodyStr %}
</div>
<div>
base body: {%= mp.BasePage.Body(s, n) %}
</div>
{% endfunc %}
```
See [basicserver example](https://github.com/valyala/quicktemplate/tree/master/examples/basicserver)
for more details.
# Performance optimization tips
* Prefer calling `WriteFoo` instead of `Foo` when generating template output
for `{% func Foo() %}`. This avoids unnesessary memory allocation and a copy
for a `string` returned from `Foo()`.
* Prefer `{%= Foo() %}` instead of `{%s= Foo() %}` when embedding
a function template `{% func Foo() %}`. Though both approaches generate
identical output, the first approach is optimized for speed.
* Prefer using existing output tags instead of passing `fmt.Sprintf`
to `{%s %}`. For instance, use `{%d num %}` instead
of `{%s fmt.Sprintf("%d", num) %}`, because the first approach is optimized
for speed.
* Prefer using specific output tags instead of generic output tag
`{%v %}`. For example, use `{%s str %}` instead of `{%v str %}`, since
specific output tags are optimized for speed.
* Prefer creating custom function templates instead of composing complex
strings by hands before passing them to `{%s %}`.
For instance, the first approach is slower than the second one:
```qtpl
{% func Foo(n int) %}
{% code
// construct complex string
complexStr := ""
for i := 0; i < n; i++ {
complexStr += fmt.Sprintf("num %d,", i)
}
%}
complex string = {%s= complexStr %}
{% endfunc %}
```
```qtpl
{% func Foo(n int) %}
complex string = {%= complexStr(n) %}
{% endfunc %}
// Wrap complexStr func into stripspace for stripping unnesessary space
// between tags and lines.
{% stripspace %}
{% func complexStr(n int) %}
{% for i := 0; i < n; i++ %}
num{% space %}{%d i %}{% newline %}
{% endfor %}
{% endfunc %}
{% endstripspace %}
```
* Make sure that the `io.Writer` passed to `Write*` functions
is [buffered](https://golang.org/pkg/bufio/#Writer).
This will minimize the number of `write`
[syscalls](https://en.wikipedia.org/wiki/System_call),
which may be quite expensive.
Note: There is no need to wrap [fasthttp.RequestCtx](https://godoc.org/github.com/valyala/fasthttp#RequestCtx)
into [bufio.Writer](https://golang.org/pkg/bufio/#Writer), since it is already buffered.
* [Profile](http://blog.golang.org/profiling-go-programs) your programs
for memory allocations and fix the most demanding functions based on
the output of `go tool pprof --alloc_objects`.
# Use cases
While the main quicktemplate purpose is generating HTML, it may be used
for generating other data too. For example, JSON and XML marshalling may
be easily implemented with quicktemplate:
```qtpl
{% code
type MarshalRow struct {
Msg string
N int
}
type MarshalData struct {
Foo int
Bar string
Rows []MarshalRow
}
%}
// JSON marshaling
{% stripspace %}
{% func (d *MarshalData) JSON() %}
{
"Foo": {%d d.Foo %},
"Bar": {%q= d.Bar %},
"Rows":[
{% for i, r := range d.Rows %}
{
"Msg": {%q= r.Msg %},
"N": {%d r.N %}
}
{% if i + 1 < len(d.Rows) %},{% endif %}
{% endfor %}
]
}
{% endfunc %}
{% endstripspace %}
// XML marshalling
{% stripspace %}
{% func (d *MarshalData) XML() %}
<MarshalData>
<Foo>{%d d.Foo %}</Foo>
<Bar>{%s d.Bar %}</Bar>
<Rows>
{% for _, r := range d.Rows %}
<Row>
<Msg>{%s r.Msg %}</Msg>
<N>{%d r.N %}</N>
</Row>
{% endfor %}
</Rows>
</MarshalData>
{% endfunc %}
{% endstripspace %}
```
Usually, marshalling built with quicktemplate works faster than the marshalling
implemented via standard [encoding/json](https://golang.org/pkg/encoding/json/)
and [encoding/xml](https://golang.org/pkg/encoding/xml/).
See the corresponding benchmark results:
```
go test -bench=Marshal -benchmem github.com/valyala/quicktemplate/tests
BenchmarkMarshalJSONStd1-4 3000000 480 ns/op 8 B/op 1 allocs/op
BenchmarkMarshalJSONStd10-4 1000000 1842 ns/op 8 B/op 1 allocs/op
BenchmarkMarshalJSONStd100-4 100000 15820 ns/op 8 B/op 1 allocs/op
BenchmarkMarshalJSONStd1000-4 10000 159327 ns/op 59 B/op 1 allocs/op
BenchmarkMarshalJSONQuickTemplate1-4 10000000 162 ns/op 0 B/op 0 allocs/op
BenchmarkMarshalJSONQuickTemplate10-4 2000000 748 ns/op 0 B/op 0 allocs/op
BenchmarkMarshalJSONQuickTemplate100-4 200000 6572 ns/op 0 B/op 0 allocs/op
BenchmarkMarshalJSONQuickTemplate1000-4 20000 66784 ns/op 29 B/op 0 allocs/op
BenchmarkMarshalXMLStd1-4 1000000 1652 ns/op 2 B/op 2 allocs/op
BenchmarkMarshalXMLStd10-4 200000 7533 ns/op 11 B/op 11 allocs/op
BenchmarkMarshalXMLStd100-4 20000 65763 ns/op 195 B/op 101 allocs/op
BenchmarkMarshalXMLStd1000-4 2000 663373 ns/op 3522 B/op 1002 allocs/op
BenchmarkMarshalXMLQuickTemplate1-4 10000000 145 ns/op 0 B/op 0 allocs/op
BenchmarkMarshalXMLQuickTemplate10-4 3000000 597 ns/op 0 B/op 0 allocs/op
BenchmarkMarshalXMLQuickTemplate100-4 300000 5833 ns/op 0 B/op 0 allocs/op
BenchmarkMarshalXMLQuickTemplate1000-4 30000 53000 ns/op 32 B/op 0 allocs/op
```
# FAQ
* *Why is the quicktemplate syntax incompatible with [html/template](https://golang.org/pkg/html/template/)?*
Because `html/template` syntax isn't expressive enough for `quicktemplate`.
* *What's the difference between quicktemplate and [ego](https://github.com/benbjohnson/ego)?*
`Ego` is similar to `quicktemplate` in the sense it converts templates into Go code.
But it misses the following stuff, which makes `quicktemplate` so powerful
and easy to use:
* Defining multiple function templates in a single template file.
* Embedding function templates inside other function templates.
* Template interfaces, inheritance and overriding.
See [this example](https://github.com/valyala/quicktemplate/tree/master/examples/basicserver)
for details.
* Top-level comments outside function templates.
* Template packages.
* Combining arbitrary Go files with template files in template packages.
* Performance optimizations.
* *What's the difference between quicktemplate and [gorazor](https://github.com/sipin/gorazor)?*
`Gorazor` is similar to `quicktemplate` in the sense it converts templates into Go code.
But it misses the following useful features:
* Clear syntax insead of hard-to-understand magic stuff related
to template arguments, template inheritance and embedding function
templates into other templates.
* Performance optimizations.
* *Is there a syntax highlighting for qtpl files?*
Yes - see [this issue](https://github.com/valyala/quicktemplate/issues/19) for details.
If you are using JetBrains products (syntax highlighting and autocomplete):
* cd [JetBrains settings directory](https://intellij-support.jetbrains.com/hc/en-us/articles/206544519-Directories-used-by-the-IDE-to-store-settings-caches-plugins-and-logs)
* mkdir -p filetypes && cd filetypes
* curl https://raw.githubusercontent.com/valyala/quicktemplate/master/QuickTemplate.xml >> QuickTemplate.xml
* Restart your IDE
* *I didn't find an answer for my question here.*
Try exploring [these questions](https://github.com/valyala/quicktemplate/issues?q=label%3Aquestion).

45
vendor/github.com/valyala/quicktemplate/bytebuffer.go generated vendored Normal file
View File

@ -0,0 +1,45 @@
package quicktemplate
import (
"github.com/valyala/bytebufferpool"
)
// ByteBuffer implements io.Writer on top of byte slice.
//
// Recycle byte buffers via AcquireByteBuffer and ReleaseByteBuffer
// in order to reduce memory allocations.
//
// Deprecated: use github.com/valyala/bytebufferpool instead.
type ByteBuffer bytebufferpool.ByteBuffer
// Write implements io.Writer.
func (b *ByteBuffer) Write(p []byte) (int, error) {
return bb(b).Write(p)
}
// Reset resets the byte buffer.
func (b *ByteBuffer) Reset() {
bb(b).Reset()
}
// AcquireByteBuffer returns new ByteBuffer from the pool.
//
// Return unneeded buffers to the pool by calling ReleaseByteBuffer
// in order to reduce memory allocations.
func AcquireByteBuffer() *ByteBuffer {
return (*ByteBuffer)(byteBufferPool.Get())
}
// ReleaseByteBuffer retruns byte buffer to the pool.
//
// Do not access byte buffer after returning it to the pool,
// otherwise data races may occur.
func ReleaseByteBuffer(b *ByteBuffer) {
byteBufferPool.Put(bb(b))
}
func bb(b *ByteBuffer) *bytebufferpool.ByteBuffer {
return (*bytebufferpool.ByteBuffer)(b)
}
var byteBufferPool bytebufferpool.Pool

6
vendor/github.com/valyala/quicktemplate/doc.go generated vendored Normal file
View File

@ -0,0 +1,6 @@
/*
Package quicktemplate provides fast and powerful template engine.
See https://github.com/valyala/quicktemplate for details.
*/
package quicktemplate

8
vendor/github.com/valyala/quicktemplate/go.mod generated vendored Normal file
View File

@ -0,0 +1,8 @@
module github.com/valyala/quicktemplate
require (
github.com/klauspost/compress v1.4.1 // indirect
github.com/klauspost/cpuid v1.2.0 // indirect
github.com/valyala/bytebufferpool v1.0.0
github.com/valyala/fasthttp v1.2.0
)

12
vendor/github.com/valyala/quicktemplate/go.sum generated vendored Normal file
View File

@ -0,0 +1,12 @@
github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.4.1 h1:8VMb5+0wMgdBykOV96DwNwKFQ+WTI4pzYURP99CcB9E=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.2.0 h1:dzZJf2IuMiclVjdw0kkT+f9u4YdrapbNyGAN47E/qnk=
github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s=
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=

View File

@ -0,0 +1,62 @@
package quicktemplate
import (
"bytes"
"io"
)
type htmlEscapeWriter struct {
w io.Writer
}
func (w *htmlEscapeWriter) Write(b []byte) (int, error) {
if bytes.IndexByte(b, '<') < 0 &&
bytes.IndexByte(b, '>') < 0 &&
bytes.IndexByte(b, '"') < 0 &&
bytes.IndexByte(b, '\'') < 0 &&
bytes.IndexByte(b, '&') < 0 {
// fast path - nothing to escape
return w.w.Write(b)
}
// slow path
write := w.w.Write
j := 0
for i, c := range b {
switch c {
case '<':
write(b[j:i])
write(strLT)
j = i + 1
case '>':
write(b[j:i])
write(strGT)
j = i + 1
case '"':
write(b[j:i])
write(strQuot)
j = i + 1
case '\'':
write(b[j:i])
write(strApos)
j = i + 1
case '&':
write(b[j:i])
write(strAmp)
j = i + 1
}
}
if n, err := write(b[j:]); err != nil {
return j + n, err
}
return len(b), nil
}
var (
strLT = []byte("&lt;")
strGT = []byte("&gt;")
strQuot = []byte("&quot;")
strApos = []byte("&#39;")
strAmp = []byte("&amp;")
)

93
vendor/github.com/valyala/quicktemplate/jsonstring.go generated vendored Normal file
View File

@ -0,0 +1,93 @@
package quicktemplate
import (
"io"
"strings"
)
func writeJSONString(w io.Writer, s string) {
if len(s) > 24 &&
strings.IndexByte(s, '"') < 0 &&
strings.IndexByte(s, '\\') < 0 &&
strings.IndexByte(s, '\n') < 0 &&
strings.IndexByte(s, '\r') < 0 &&
strings.IndexByte(s, '\t') < 0 &&
strings.IndexByte(s, '\f') < 0 &&
strings.IndexByte(s, '\b') < 0 &&
strings.IndexByte(s, '<') < 0 &&
strings.IndexByte(s, '\'') < 0 &&
strings.IndexByte(s, 0) < 0 {
// fast path - nothing to escape
w.Write(unsafeStrToBytes(s))
return
}
// slow path
write := w.Write
b := unsafeStrToBytes(s)
j := 0
n := len(b)
if n > 0 {
// Hint the compiler to remove bounds checks in the loop below.
_ = b[n-1]
}
for i := 0; i < n; i++ {
switch b[i] {
case '"':
write(b[j:i])
write(strBackslashQuote)
j = i + 1
case '\\':
write(b[j:i])
write(strBackslashBackslash)
j = i + 1
case '\n':
write(b[j:i])
write(strBackslashN)
j = i + 1
case '\r':
write(b[j:i])
write(strBackslashR)
j = i + 1
case '\t':
write(b[j:i])
write(strBackslashT)
j = i + 1
case '\f':
write(b[j:i])
write(strBackslashF)
j = i + 1
case '\b':
write(b[j:i])
write(strBackslashB)
j = i + 1
case '<':
write(b[j:i])
write(strBackslashLT)
j = i + 1
case '\'':
write(b[j:i])
write(strBackslashQ)
j = i + 1
case 0:
write(b[j:i])
write(strBackslashZero)
j = i + 1
}
}
write(b[j:])
}
var (
strBackslashQuote = []byte(`\"`)
strBackslashBackslash = []byte(`\\`)
strBackslashN = []byte(`\n`)
strBackslashR = []byte(`\r`)
strBackslashT = []byte(`\t`)
strBackslashF = []byte(`\u000c`)
strBackslashB = []byte(`\u0008`)
strBackslashLT = []byte(`\u003c`)
strBackslashQ = []byte(`\u0027`)
strBackslashZero = []byte(`\u0000`)
)

32
vendor/github.com/valyala/quicktemplate/urlencode.go generated vendored Normal file
View File

@ -0,0 +1,32 @@
package quicktemplate
func appendURLEncode(dst []byte, src string) []byte {
n := len(src)
if n > 0 {
// Hint the compiler to remove bounds checks in the loop below.
_ = src[n-1]
}
for i := 0; i < n; i++ {
c := src[i]
// See http://www.w3.org/TR/html5/forms.html#form-submission-algorithm
if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' ||
c == '-' || c == '.' || c == '_' {
dst = append(dst, c)
} else {
if c == ' ' {
dst = append(dst, '+')
} else {
dst = append(dst, '%', hexCharUpper(c>>4), hexCharUpper(c&15))
}
}
}
return dst
}
func hexCharUpper(c byte) byte {
if c < 10 {
return '0' + c
}
return c - 10 + 'A'
}

3
vendor/github.com/valyala/quicktemplate/util.go generated vendored Normal file
View File

@ -0,0 +1,3 @@
package quicktemplate
//go:generate qtc -dir=testdata/templates

View File

@ -0,0 +1,11 @@
// +build appengine appenginevm
package quicktemplate
func unsafeStrToBytes(s string) []byte {
return []byte(s)
}
func unsafeBytesToStr(z []byte) string {
return string(z)
}

View File

@ -0,0 +1,22 @@
// +build !appengine,!appenginevm
package quicktemplate
import (
"reflect"
"unsafe"
)
func unsafeStrToBytes(s string) []byte {
sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
bh := reflect.SliceHeader{
Data: sh.Data,
Len: sh.Len,
Cap: sh.Len,
}
return *(*[]byte)(unsafe.Pointer(&bh))
}
func unsafeBytesToStr(z []byte) string {
return *(*string)(unsafe.Pointer(&z))
}

188
vendor/github.com/valyala/quicktemplate/writer.go generated vendored Normal file
View File

@ -0,0 +1,188 @@
package quicktemplate
import (
"fmt"
"io"
"strconv"
"sync"
)
// Writer implements auxiliary writer used by quicktemplate functions.
//
// Use AcquireWriter for creating new writers.
type Writer struct {
e QWriter
n QWriter
}
// W returns the underlying writer passed to AcquireWriter.
func (qw *Writer) W() io.Writer {
return qw.n.w
}
// E returns QWriter with enabled html escaping.
func (qw *Writer) E() *QWriter {
return &qw.e
}
// N returns QWriter without html escaping.
func (qw *Writer) N() *QWriter {
return &qw.n
}
// AcquireWriter returns new writer from the pool.
//
// Return unneeded writer to the pool by calling ReleaseWriter
// in order to reduce memory allocations.
func AcquireWriter(w io.Writer) *Writer {
v := writerPool.Get()
if v == nil {
qw := &Writer{}
qw.e.w = &htmlEscapeWriter{}
v = qw
}
qw := v.(*Writer)
qw.e.w.(*htmlEscapeWriter).w = w
qw.n.w = w
return qw
}
// ReleaseWriter returns the writer to the pool.
//
// Do not access released writer, otherwise data races may occur.
func ReleaseWriter(qw *Writer) {
hw := qw.e.w.(*htmlEscapeWriter)
hw.w = nil
qw.e.Reset()
qw.e.w = hw
qw.n.Reset()
writerPool.Put(qw)
}
var writerPool sync.Pool
// QWriter is auxiliary writer used by Writer.
type QWriter struct {
w io.Writer
err error
b []byte
}
// Write implements io.Writer.
func (w *QWriter) Write(p []byte) (int, error) {
if w.err != nil {
return 0, w.err
}
n, err := w.w.Write(p)
if err != nil {
w.err = err
}
return n, err
}
// Reset resets QWriter to the original state.
func (w *QWriter) Reset() {
w.w = nil
w.err = nil
}
// S writes s to w.
func (w *QWriter) S(s string) {
w.Write(unsafeStrToBytes(s))
}
// Z writes z to w.
func (w *QWriter) Z(z []byte) {
w.Write(z)
}
// SZ is a synonym to Z.
func (w *QWriter) SZ(z []byte) {
w.Write(z)
}
// D writes n to w.
func (w *QWriter) D(n int) {
bb, ok := w.w.(*ByteBuffer)
if ok {
bb.B = strconv.AppendInt(bb.B, int64(n), 10)
} else {
w.b = strconv.AppendInt(w.b[:0], int64(n), 10)
w.Write(w.b)
}
}
// F writes f to w.
func (w *QWriter) F(f float64) {
n := int(f)
if float64(n) == f {
// Fast path - just int.
w.D(n)
return
}
// Slow path.
w.FPrec(f, -1)
}
// FPrec writes f to w using the given floating point precision.
func (w *QWriter) FPrec(f float64, prec int) {
bb, ok := w.w.(*ByteBuffer)
if ok {
bb.B = strconv.AppendFloat(bb.B, f, 'f', prec, 64)
} else {
w.b = strconv.AppendFloat(w.b[:0], f, 'f', prec, 64)
w.Write(w.b)
}
}
// Q writes quoted json-safe s to w.
func (w *QWriter) Q(s string) {
w.Write(strQuote)
writeJSONString(w, s)
w.Write(strQuote)
}
var strQuote = []byte(`"`)
// QZ writes quoted json-safe z to w.
func (w *QWriter) QZ(z []byte) {
w.Q(unsafeBytesToStr(z))
}
// J writes json-safe s to w.
//
// Unlike Q it doesn't qoute resulting s.
func (w *QWriter) J(s string) {
writeJSONString(w, s)
}
// JZ writes json-safe z to w.
//
// Unlike Q it doesn't qoute resulting z.
func (w *QWriter) JZ(z []byte) {
w.J(unsafeBytesToStr(z))
}
// V writes v to w.
func (w *QWriter) V(v interface{}) {
fmt.Fprintf(w, "%v", v)
}
// U writes url-encoded s to w.
func (w *QWriter) U(s string) {
bb, ok := w.w.(*ByteBuffer)
if ok {
bb.B = appendURLEncode(bb.B, s)
} else {
w.b = appendURLEncode(w.b[:0], s)
w.Write(w.b)
}
}
// UZ writes url-encoded z to w.
func (w *QWriter) UZ(z []byte) {
w.U(unsafeBytesToStr(z))
}

4
vendor/modules.txt vendored
View File

@ -179,6 +179,10 @@ github.com/spf13/viper
# github.com/stretchr/testify v1.2.2
github.com/stretchr/testify/assert
github.com/stretchr/testify/require
# github.com/valyala/bytebufferpool v1.0.0
github.com/valyala/bytebufferpool
# github.com/valyala/quicktemplate v1.1.1
github.com/valyala/quicktemplate
# golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a
golang.org/x/crypto/ssh/terminal
# golang.org/x/net v0.0.0-20190313220215-9f648a60d977