diff --git a/.travis.yml b/.travis.yml index e23dec5a..bf593a69 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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: diff --git a/Makefile b/Makefile index 639e4572..930a948d 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/go.mod b/go.mod index 919e7b7c..99b3e478 100644 --- a/go.mod +++ b/go.mod @@ -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 diff --git a/go.sum b/go.sum index 935d55d7..1a5a7a68 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/scripts/gen_readme/main.go b/scripts/gen_readme/main.go index b0db3fd9..f649dfab 100644 --- a/scripts/gen_readme/main.go +++ b/scripts/gen_readme/main.go @@ -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() diff --git a/test/data.go b/test/data.go index 710e3914..e5320b3b 100644 --- a/test/data.go +++ b/test/data.go @@ -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("..", "...") diff --git a/test/run_test.go b/test/run_test.go index a191341d..0f8a7907 100644 --- a/test/run_test.go +++ b/test/run_test.go @@ -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\"`) } diff --git a/test/testshared/testshared.go b/test/testshared/testshared.go index 1ea71652..18eff223 100644 --- a/test/testshared/testshared.go +++ b/test/testshared/testshared.go @@ -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 { diff --git a/vendor/github.com/valyala/bytebufferpool/.travis.yml b/vendor/github.com/valyala/bytebufferpool/.travis.yml new file mode 100644 index 00000000..6a6ec2eb --- /dev/null +++ b/vendor/github.com/valyala/bytebufferpool/.travis.yml @@ -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 ./... diff --git a/vendor/github.com/valyala/bytebufferpool/LICENSE b/vendor/github.com/valyala/bytebufferpool/LICENSE new file mode 100644 index 00000000..f7c935c2 --- /dev/null +++ b/vendor/github.com/valyala/bytebufferpool/LICENSE @@ -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. + diff --git a/vendor/github.com/valyala/bytebufferpool/README.md b/vendor/github.com/valyala/bytebufferpool/README.md new file mode 100644 index 00000000..061357e8 --- /dev/null +++ b/vendor/github.com/valyala/bytebufferpool/README.md @@ -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) diff --git a/vendor/github.com/valyala/bytebufferpool/bytebuffer.go b/vendor/github.com/valyala/bytebufferpool/bytebuffer.go new file mode 100644 index 00000000..07a055a2 --- /dev/null +++ b/vendor/github.com/valyala/bytebufferpool/bytebuffer.go @@ -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] +} diff --git a/vendor/github.com/valyala/bytebufferpool/doc.go b/vendor/github.com/valyala/bytebufferpool/doc.go new file mode 100644 index 00000000..e511b7c5 --- /dev/null +++ b/vendor/github.com/valyala/bytebufferpool/doc.go @@ -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 diff --git a/vendor/github.com/valyala/bytebufferpool/pool.go b/vendor/github.com/valyala/bytebufferpool/pool.go new file mode 100644 index 00000000..8bb4134d --- /dev/null +++ b/vendor/github.com/valyala/bytebufferpool/pool.go @@ -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 +} diff --git a/vendor/github.com/valyala/quicktemplate/.gitignore b/vendor/github.com/valyala/quicktemplate/.gitignore new file mode 100644 index 00000000..6e92f57d --- /dev/null +++ b/vendor/github.com/valyala/quicktemplate/.gitignore @@ -0,0 +1 @@ +tags diff --git a/vendor/github.com/valyala/quicktemplate/.travis.yml b/vendor/github.com/valyala/quicktemplate/.travis.yml new file mode 100644 index 00000000..4a1c6773 --- /dev/null +++ b/vendor/github.com/valyala/quicktemplate/.travis.yml @@ -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 ./... diff --git a/vendor/github.com/valyala/quicktemplate/LICENSE b/vendor/github.com/valyala/quicktemplate/LICENSE new file mode 100644 index 00000000..f7c935c2 --- /dev/null +++ b/vendor/github.com/valyala/quicktemplate/LICENSE @@ -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. + diff --git a/vendor/github.com/valyala/quicktemplate/QuickTemplate.xml b/vendor/github.com/valyala/quicktemplate/QuickTemplate.xml new file mode 100644 index 00000000..700d55e8 --- /dev/null +++ b/vendor/github.com/valyala/quicktemplate/QuickTemplate.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/vendor/github.com/valyala/quicktemplate/README.md b/vendor/github.com/valyala/quicktemplate/README.md new file mode 100644 index 00000000..3c104f40 --- /dev/null +++ b/vendor/github.com/valyala/quicktemplate/README.md @@ -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 ``-based + XSS attacks: + + ```qtpl + {% func FailedXSS() %} + + {% 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 `<`, `>` to `>`, etc. If you don't want HTML-safe output, +then just put `=` after the tag. For example: `{%s= "

This h1 won't be escaped

" %}`. + +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 %} +
+
space between lines
+ and {%s "tags" %} +
is collapsed into a single space + unless{% newline %}or{% space %}is used
+
+ {% endcollapsespace %} + ``` + + Is converted into: + + ``` +
space between lines
and tags
is collapsed into a single space unless + or is used
+ ``` + + * `{% stripspace %}` + + ```qtpl + {% stripspace %} +
+
space between lines
+ and {%s " tags" %} +
is removed unless{% newline %}or{% space %}is used
+
+ {% endstripspace %} + ``` + + Is converted into: + + ``` +
space between lines
and tags
is removed unless + or is used
+ ``` + + * `{% 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) %} + + {%= p.Title() %} + +
{%= p.Body("foo", 42) %}
+
{%= p.Footer() %}
+ + + {% 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) %} + s={%q s %}, n={%d n %} + {% 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) %} +
+ main body: {%s mp.BodyStr %} +
+
+ base body: {%= mp.BasePage.Body(s, n) %} +
+ {% 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() %} + + {%d d.Foo %} + {%s d.Bar %} + + {% for _, r := range d.Rows %} + + {%s r.Msg %} + {%d r.N %} + + {% endfor %} + + +{% 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). diff --git a/vendor/github.com/valyala/quicktemplate/bytebuffer.go b/vendor/github.com/valyala/quicktemplate/bytebuffer.go new file mode 100644 index 00000000..47d88f78 --- /dev/null +++ b/vendor/github.com/valyala/quicktemplate/bytebuffer.go @@ -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 diff --git a/vendor/github.com/valyala/quicktemplate/doc.go b/vendor/github.com/valyala/quicktemplate/doc.go new file mode 100644 index 00000000..14cb5ffb --- /dev/null +++ b/vendor/github.com/valyala/quicktemplate/doc.go @@ -0,0 +1,6 @@ +/* +Package quicktemplate provides fast and powerful template engine. + +See https://github.com/valyala/quicktemplate for details. +*/ +package quicktemplate diff --git a/vendor/github.com/valyala/quicktemplate/go.mod b/vendor/github.com/valyala/quicktemplate/go.mod new file mode 100644 index 00000000..ab6fd16e --- /dev/null +++ b/vendor/github.com/valyala/quicktemplate/go.mod @@ -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 +) diff --git a/vendor/github.com/valyala/quicktemplate/go.sum b/vendor/github.com/valyala/quicktemplate/go.sum new file mode 100644 index 00000000..c868cd17 --- /dev/null +++ b/vendor/github.com/valyala/quicktemplate/go.sum @@ -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= diff --git a/vendor/github.com/valyala/quicktemplate/htmlescapewriter.go b/vendor/github.com/valyala/quicktemplate/htmlescapewriter.go new file mode 100644 index 00000000..77560b41 --- /dev/null +++ b/vendor/github.com/valyala/quicktemplate/htmlescapewriter.go @@ -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("<") + strGT = []byte(">") + strQuot = []byte(""") + strApos = []byte("'") + strAmp = []byte("&") +) diff --git a/vendor/github.com/valyala/quicktemplate/jsonstring.go b/vendor/github.com/valyala/quicktemplate/jsonstring.go new file mode 100644 index 00000000..dac862c8 --- /dev/null +++ b/vendor/github.com/valyala/quicktemplate/jsonstring.go @@ -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`) +) diff --git a/vendor/github.com/valyala/quicktemplate/urlencode.go b/vendor/github.com/valyala/quicktemplate/urlencode.go new file mode 100644 index 00000000..33113ba1 --- /dev/null +++ b/vendor/github.com/valyala/quicktemplate/urlencode.go @@ -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' +} diff --git a/vendor/github.com/valyala/quicktemplate/util.go b/vendor/github.com/valyala/quicktemplate/util.go new file mode 100644 index 00000000..8476ff55 --- /dev/null +++ b/vendor/github.com/valyala/quicktemplate/util.go @@ -0,0 +1,3 @@ +package quicktemplate + +//go:generate qtc -dir=testdata/templates diff --git a/vendor/github.com/valyala/quicktemplate/util_appengine.go b/vendor/github.com/valyala/quicktemplate/util_appengine.go new file mode 100644 index 00000000..7642bf7d --- /dev/null +++ b/vendor/github.com/valyala/quicktemplate/util_appengine.go @@ -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) +} diff --git a/vendor/github.com/valyala/quicktemplate/util_noappengine.go b/vendor/github.com/valyala/quicktemplate/util_noappengine.go new file mode 100644 index 00000000..166396ea --- /dev/null +++ b/vendor/github.com/valyala/quicktemplate/util_noappengine.go @@ -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)) +} diff --git a/vendor/github.com/valyala/quicktemplate/writer.go b/vendor/github.com/valyala/quicktemplate/writer.go new file mode 100644 index 00000000..0a83a43e --- /dev/null +++ b/vendor/github.com/valyala/quicktemplate/writer.go @@ -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)) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index bc15d808..fcfad9f0 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -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