summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/skip2/go-qrcode
diff options
context:
space:
mode:
authorWim <wim@42.be>2022-03-20 02:20:54 +0100
committerWim <wim@42.be>2022-03-20 14:57:48 +0100
commit496d5b4ec7f5f4afae6199f928675d14d18de015 (patch)
tree3a649c80a76f0ffc33e6b3a63c0e65e892169cde /vendor/github.com/skip2/go-qrcode
parent2623a412c42a81104b97ae8c81a5f66760fee4b6 (diff)
downloadmatterbridge-msglm-496d5b4ec7f5f4afae6199f928675d14d18de015.tar.gz
matterbridge-msglm-496d5b4ec7f5f4afae6199f928675d14d18de015.tar.bz2
matterbridge-msglm-496d5b4ec7f5f4afae6199f928675d14d18de015.zip
Add whatsappmulti buildflag for whatsapp with multidevice support (whatsapp)
Diffstat (limited to 'vendor/github.com/skip2/go-qrcode')
-rw-r--r--vendor/github.com/skip2/go-qrcode/.gitignore4
-rw-r--r--vendor/github.com/skip2/go-qrcode/.travis.yml8
-rw-r--r--vendor/github.com/skip2/go-qrcode/LICENSE19
-rw-r--r--vendor/github.com/skip2/go-qrcode/README.md80
-rw-r--r--vendor/github.com/skip2/go-qrcode/bitset/bitset.go273
-rw-r--r--vendor/github.com/skip2/go-qrcode/encoder.go455
-rw-r--r--vendor/github.com/skip2/go-qrcode/qrcode.go589
-rw-r--r--vendor/github.com/skip2/go-qrcode/reedsolomon/gf2_8.go387
-rw-r--r--vendor/github.com/skip2/go-qrcode/reedsolomon/gf_poly.go216
-rw-r--r--vendor/github.com/skip2/go-qrcode/reedsolomon/reed_solomon.go73
-rw-r--r--vendor/github.com/skip2/go-qrcode/regular_symbol.go309
-rw-r--r--vendor/github.com/skip2/go-qrcode/symbol.go309
-rw-r--r--vendor/github.com/skip2/go-qrcode/version.go3050
13 files changed, 5772 insertions, 0 deletions
diff --git a/vendor/github.com/skip2/go-qrcode/.gitignore b/vendor/github.com/skip2/go-qrcode/.gitignore
new file mode 100644
index 00000000..bc1be2bb
--- /dev/null
+++ b/vendor/github.com/skip2/go-qrcode/.gitignore
@@ -0,0 +1,4 @@
+*.sw*
+*.png
+*.directory
+qrcode/qrcode
diff --git a/vendor/github.com/skip2/go-qrcode/.travis.yml b/vendor/github.com/skip2/go-qrcode/.travis.yml
new file mode 100644
index 00000000..7ced8fb1
--- /dev/null
+++ b/vendor/github.com/skip2/go-qrcode/.travis.yml
@@ -0,0 +1,8 @@
+language: go
+
+go:
+ - 1.7
+
+script:
+ - go test -v ./...
+
diff --git a/vendor/github.com/skip2/go-qrcode/LICENSE b/vendor/github.com/skip2/go-qrcode/LICENSE
new file mode 100644
index 00000000..342c5e5a
--- /dev/null
+++ b/vendor/github.com/skip2/go-qrcode/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2014 Tom Harwood
+
+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/skip2/go-qrcode/README.md b/vendor/github.com/skip2/go-qrcode/README.md
new file mode 100644
index 00000000..8281ed3e
--- /dev/null
+++ b/vendor/github.com/skip2/go-qrcode/README.md
@@ -0,0 +1,80 @@
+# go-qrcode #
+
+<img src='https://skip.org/img/nyancat-youtube-qr.png' align='right'>
+
+Package qrcode implements a QR Code encoder. [![Build Status](https://travis-ci.org/skip2/go-qrcode.svg?branch=master)](https://travis-ci.org/skip2/go-qrcode)
+
+A QR Code is a matrix (two-dimensional) barcode. Arbitrary content may be encoded, with URLs being a popular choice :)
+
+Each QR Code contains error recovery information to aid reading damaged or obscured codes. There are four levels of error recovery: Low, medium, high and highest. QR Codes with a higher recovery level are more robust to damage, at the cost of being physically larger.
+
+## Install
+
+ go get -u github.com/skip2/go-qrcode/...
+
+A command-line tool `qrcode` will be built into `$GOPATH/bin/`.
+
+## Usage
+
+ import qrcode "github.com/skip2/go-qrcode"
+
+- **Create a PNG image:**
+
+ var png []byte
+ png, err := qrcode.Encode("https://example.org", qrcode.Medium, 256)
+
+- **Create a PNG image and write to a file:**
+
+ err := qrcode.WriteFile("https://example.org", qrcode.Medium, 256, "qr.png")
+
+- **Create a PNG image with custom colors and write to file:**
+
+ err := qrcode.WriteColorFile("https://example.org", qrcode.Medium, 256, color.Black, color.White, "qr.png")
+
+All examples use the qrcode.Medium error Recovery Level and create a fixed
+256x256px size QR Code. The last function creates a white on black instead of black
+on white QR Code.
+
+The maximum capacity of a QR Code varies according to the content encoded and
+the error recovery level. The maximum capacity is 2,953 bytes, 4,296
+alphanumeric characters, 7,089 numeric digits, or a combination of these.
+
+## Documentation
+
+[![godoc](https://godoc.org/github.com/skip2/go-qrcode?status.png)](https://godoc.org/github.com/skip2/go-qrcode)
+
+## Demoapp
+
+[http://go-qrcode.appspot.com](http://go-qrcode.appspot.com)
+
+## CLI
+
+A command-line tool `qrcode` will be built into `$GOPATH/bin/`.
+
+```
+qrcode -- QR Code encoder in Go
+https://github.com/skip2/go-qrcode
+
+Flags:
+ -o string
+ out PNG file prefix, empty for stdout
+ -s int
+ image size (pixel) (default 256)
+
+Usage:
+ 1. Arguments except for flags are joined by " " and used to generate QR code.
+ Default output is STDOUT, pipe to imagemagick command "display" to display
+ on any X server.
+
+ qrcode hello word | display
+
+ 2. Save to file if "display" not available:
+
+ qrcode "homepage: https://github.com/skip2/go-qrcode" > out.png
+```
+
+## Links
+
+- [http://en.wikipedia.org/wiki/QR_code](http://en.wikipedia.org/wiki/QR_code)
+- [ISO/IEC 18004:2006](http://www.iso.org/iso/catalogue_detail.htm?csnumber=43655) - Main QR Code specification (approx CHF 198,00)<br>
+- [https://github.com/qpliu/qrencode-go/](https://github.com/qpliu/qrencode-go/) - alternative Go QR encoding library based on [ZXing](https://github.com/zxing/zxing)
diff --git a/vendor/github.com/skip2/go-qrcode/bitset/bitset.go b/vendor/github.com/skip2/go-qrcode/bitset/bitset.go
new file mode 100644
index 00000000..fba3bf4d
--- /dev/null
+++ b/vendor/github.com/skip2/go-qrcode/bitset/bitset.go
@@ -0,0 +1,273 @@
+// go-qrcode
+// Copyright 2014 Tom Harwood
+
+// Package bitset implements an append only bit array.
+//
+// To create a Bitset and append some bits:
+// // Bitset Contents
+// b := bitset.New() // {}
+// b.AppendBools(true, true, false) // {1, 1, 0}
+// b.AppendBools(true) // {1, 1, 0, 1}
+// b.AppendValue(0x02, 4) // {1, 1, 0, 1, 0, 0, 1, 0}
+//
+// To read values:
+//
+// len := b.Len() // 8
+// v := b.At(0) // 1
+// v = b.At(1) // 1
+// v = b.At(2) // 0
+// v = b.At(8) // 0
+package bitset
+
+import (
+ "bytes"
+ "fmt"
+ "log"
+)
+
+const (
+ b0 = false
+ b1 = true
+)
+
+// Bitset stores an array of bits.
+type Bitset struct {
+ // The number of bits stored.
+ numBits int
+
+ // Storage for individual bits.
+ bits []byte
+}
+
+// New returns an initialised Bitset with optional initial bits v.
+func New(v ...bool) *Bitset {
+ b := &Bitset{numBits: 0, bits: make([]byte, 0)}
+ b.AppendBools(v...)
+
+ return b
+}
+
+// Clone returns a copy.
+func Clone(from *Bitset) *Bitset {
+ return &Bitset{numBits: from.numBits, bits: from.bits[:]}
+}
+
+// Substr returns a substring, consisting of the bits from indexes start to end.
+func (b *Bitset) Substr(start int, end int) *Bitset {
+ if start > end || end > b.numBits {
+ log.Panicf("Out of range start=%d end=%d numBits=%d", start, end, b.numBits)
+ }
+
+ result := New()
+ result.ensureCapacity(end - start)
+
+ for i := start; i < end; i++ {
+ if b.At(i) {
+ result.bits[result.numBits/8] |= 0x80 >> uint(result.numBits%8)
+ }
+ result.numBits++
+ }
+
+ return result
+}
+
+// NewFromBase2String constructs and returns a Bitset from a string. The string
+// consists of '1', '0' or ' ' characters, e.g. "1010 0101". The '1' and '0'
+// characters represent true/false bits respectively, and ' ' characters are
+// ignored.
+//
+// The function panics if the input string contains other characters.
+func NewFromBase2String(b2string string) *Bitset {
+ b := &Bitset{numBits: 0, bits: make([]byte, 0)}
+
+ for _, c := range b2string {
+ switch c {
+ case '1':
+ b.AppendBools(true)
+ case '0':
+ b.AppendBools(false)
+ case ' ':
+ default:
+ log.Panicf("Invalid char %c in NewFromBase2String", c)
+ }
+ }
+
+ return b
+}
+
+// AppendBytes appends a list of whole bytes.
+func (b *Bitset) AppendBytes(data []byte) {
+ for _, d := range data {
+ b.AppendByte(d, 8)
+ }
+}
+
+// AppendByte appends the numBits least significant bits from value.
+func (b *Bitset) AppendByte(value byte, numBits int) {
+ b.ensureCapacity(numBits)
+
+ if numBits > 8 {
+ log.Panicf("numBits %d out of range 0-8", numBits)
+ }
+
+ for i := numBits - 1; i >= 0; i-- {
+ if value&(1<<uint(i)) != 0 {
+ b.bits[b.numBits/8] |= 0x80 >> uint(b.numBits%8)
+ }
+
+ b.numBits++
+ }
+}
+
+// AppendUint32 appends the numBits least significant bits from value.
+func (b *Bitset) AppendUint32(value uint32, numBits int) {
+ b.ensureCapacity(numBits)
+
+ if numBits > 32 {
+ log.Panicf("numBits %d out of range 0-32", numBits)
+ }
+
+ for i := numBits - 1; i >= 0; i-- {
+ if value&(1<<uint(i)) != 0 {
+ b.bits[b.numBits/8] |= 0x80 >> uint(b.numBits%8)
+ }
+
+ b.numBits++
+ }
+}
+
+// ensureCapacity ensures the Bitset can store an additional |numBits|.
+//
+// The underlying array is expanded if necessary. To prevent frequent
+// reallocation, expanding the underlying array at least doubles its capacity.
+func (b *Bitset) ensureCapacity(numBits int) {
+ numBits += b.numBits
+
+ newNumBytes := numBits / 8
+ if numBits%8 != 0 {
+ newNumBytes++
+ }
+
+ if len(b.bits) >= newNumBytes {
+ return
+ }
+
+ b.bits = append(b.bits, make([]byte, newNumBytes+2*len(b.bits))...)
+}
+
+// Append bits copied from |other|.
+//
+// The new length is b.Len() + other.Len().
+func (b *Bitset) Append(other *Bitset) {
+ b.ensureCapacity(other.numBits)
+
+ for i := 0; i < other.numBits; i++ {
+ if other.At(i) {
+ b.bits[b.numBits/8] |= 0x80 >> uint(b.numBits%8)
+ }
+ b.numBits++
+ }
+}
+
+// AppendBools appends bits to the Bitset.
+func (b *Bitset) AppendBools(bits ...bool) {
+ b.ensureCapacity(len(bits))
+
+ for _, v := range bits {
+ if v {
+ b.bits[b.numBits/8] |= 0x80 >> uint(b.numBits%8)
+ }
+ b.numBits++
+ }
+}
+
+// AppendNumBools appends num bits of value value.
+func (b *Bitset) AppendNumBools(num int, value bool) {
+ for i := 0; i < num; i++ {
+ b.AppendBools(value)
+ }
+}
+
+// String returns a human readable representation of the Bitset's contents.
+func (b *Bitset) String() string {
+ var bitString string
+ for i := 0; i < b.numBits; i++ {
+ if (i % 8) == 0 {
+ bitString += " "
+ }
+
+ if (b.bits[i/8] & (0x80 >> byte(i%8))) != 0 {
+ bitString += "1"
+ } else {
+ bitString += "0"
+ }
+ }
+
+ return fmt.Sprintf("numBits=%d, bits=%s", b.numBits, bitString)
+}
+
+// Len returns the length of the Bitset in bits.
+func (b *Bitset) Len() int {
+ return b.numBits
+}
+
+// Bits returns the contents of the Bitset.
+func (b *Bitset) Bits() []bool {
+ result := make([]bool, b.numBits)
+
+ var i int
+ for i = 0; i < b.numBits; i++ {
+ result[i] = (b.bits[i/8] & (0x80 >> byte(i%8))) != 0
+ }
+
+ return result
+}
+
+// At returns the value of the bit at |index|.
+func (b *Bitset) At(index int) bool {
+ if index >= b.numBits {
+ log.Panicf("Index %d out of range", index)
+ }
+
+ return (b.bits[index/8] & (0x80 >> byte(index%8))) != 0
+}
+
+// Equals returns true if the Bitset equals other.
+func (b *Bitset) Equals(other *Bitset) bool {
+ if b.numBits != other.numBits {
+ return false
+ }
+
+ if !bytes.Equal(b.bits[0:b.numBits/8], other.bits[0:b.numBits/8]) {
+ return false
+ }
+
+ for i := 8 * (b.numBits / 8); i < b.numBits; i++ {
+ a := (b.bits[i/8] & (0x80 >> byte(i%8)))
+ b := (other.bits[i/8] & (0x80 >> byte(i%8)))
+
+ if a != b {
+ return false
+ }
+ }
+
+ return true
+}
+
+// ByteAt returns a byte consisting of upto 8 bits starting at index.
+func (b *Bitset) ByteAt(index int) byte {
+ if index < 0 || index >= b.numBits {
+ log.Panicf("Index %d out of range", index)
+ }
+
+ var result byte
+
+ for i := index; i < index+8 && i < b.numBits; i++ {
+ result <<= 1
+ if b.At(i) {
+ result |= 1
+ }
+ }
+
+ return result
+}
diff --git a/vendor/github.com/skip2/go-qrcode/encoder.go b/vendor/github.com/skip2/go-qrcode/encoder.go
new file mode 100644
index 00000000..713378c0
--- /dev/null
+++ b/vendor/github.com/skip2/go-qrcode/encoder.go
@@ -0,0 +1,455 @@
+// go-qrcode
+// Copyright 2014 Tom Harwood
+
+package qrcode
+
+import (
+ "errors"
+ "log"
+
+ bitset "github.com/skip2/go-qrcode/bitset"
+)
+
+// Data encoding.
+//
+// The main data portion of a QR Code consists of one or more segments of data.
+// A segment consists of:
+//
+// - The segment Data Mode: numeric, alphanumeric, or byte.
+// - The length of segment in bits.
+// - Encoded data.
+//
+// For example, the string "123ZZ#!#!" may be represented as:
+//
+// [numeric, 3, "123"] [alphanumeric, 2, "ZZ"] [byte, 4, "#!#!"]
+//
+// Multiple data modes exist to minimise the size of encoded data. For example,
+// 8-bit bytes require 8 bits to encode each, but base 10 numeric data can be
+// encoded at a higher density of 3 numbers (e.g. 123) per 10 bits.
+//
+// Some data can be represented in multiple modes. Numeric data can be
+// represented in all three modes, whereas alphanumeric data (e.g. 'A') can be
+// represented in alphanumeric and byte mode.
+//
+// Starting a new segment (to use a different Data Mode) has a cost, the bits to
+// state the new segment Data Mode and length. To minimise each QR Code's symbol
+// size, an optimisation routine coalesces segment types where possible, to
+// reduce the encoded data length.
+//
+// There are several other data modes available (e.g. Kanji mode) which are not
+// implemented here.
+
+// A segment encoding mode.
+type dataMode uint8
+
+const (
+ // Each dataMode is a subset of the subsequent dataMode:
+ // dataModeNone < dataModeNumeric < dataModeAlphanumeric < dataModeByte
+ //
+ // This ordering is important for determining which data modes a character can
+ // be encoded with. E.g. 'E' can be encoded in both dataModeAlphanumeric and
+ // dataModeByte.
+ dataModeNone dataMode = 1 << iota
+ dataModeNumeric
+ dataModeAlphanumeric
+ dataModeByte
+)
+
+// dataModeString returns d as a short printable string.
+func dataModeString(d dataMode) string {
+ switch d {
+ case dataModeNone:
+ return "none"
+ case dataModeNumeric:
+ return "numeric"
+ case dataModeAlphanumeric:
+ return "alphanumeric"
+ case dataModeByte:
+ return "byte"
+ }
+
+ return "unknown"
+}
+
+type dataEncoderType uint8
+
+const (
+ dataEncoderType1To9 dataEncoderType = iota
+ dataEncoderType10To26
+ dataEncoderType27To40
+)
+
+// segment is a single segment of data.
+type segment struct {
+ // Data Mode (e.g. numeric).
+ dataMode dataMode
+
+ // segment data (e.g. "abc").
+ data []byte
+}
+
+// A dataEncoder encodes data for a particular QR Code version.
+type dataEncoder struct {
+ // Minimum & maximum versions supported.
+ minVersion int
+ maxVersion int
+
+ // Mode indicator bit sequences.
+ numericModeIndicator *bitset.Bitset
+ alphanumericModeIndicator *bitset.Bitset
+ byteModeIndicator *bitset.Bitset
+
+ // Character count lengths.
+ numNumericCharCountBits int
+ numAlphanumericCharCountBits int
+ numByteCharCountBits int
+
+ // The raw input data.
+ data []byte
+
+ // The data classified into unoptimised segments.
+ actual []segment
+
+ // The data classified into optimised segments.
+ optimised []segment
+}
+
+// newDataEncoder constructs a dataEncoder.
+func newDataEncoder(t dataEncoderType) *dataEncoder {
+ d := &dataEncoder{}
+
+ switch t {
+ case dataEncoderType1To9:
+ d = &dataEncoder{
+ minVersion: 1,
+ maxVersion: 9,
+ numericModeIndicator: bitset.New(b0, b0, b0, b1),
+ alphanumericModeIndicator: bitset.New(b0, b0, b1, b0),
+ byteModeIndicator: bitset.New(b0, b1, b0, b0),
+ numNumericCharCountBits: 10,
+ numAlphanumericCharCountBits: 9,
+ numByteCharCountBits: 8,
+ }
+ case dataEncoderType10To26:
+ d = &dataEncoder{
+ minVersion: 10,
+ maxVersion: 26,
+ numericModeIndicator: bitset.New(b0, b0, b0, b1),
+ alphanumericModeIndicator: bitset.New(b0, b0, b1, b0),
+ byteModeIndicator: bitset.New(b0, b1, b0, b0),
+ numNumericCharCountBits: 12,
+ numAlphanumericCharCountBits: 11,
+ numByteCharCountBits: 16,
+ }
+ case dataEncoderType27To40:
+ d = &dataEncoder{
+ minVersion: 27,
+ maxVersion: 40,
+ numericModeIndicator: bitset.New(b0, b0, b0, b1),
+ alphanumericModeIndicator: bitset.New(b0, b0, b1, b0),
+ byteModeIndicator: bitset.New(b0, b1, b0, b0),
+ numNumericCharCountBits: 14,
+ numAlphanumericCharCountBits: 13,
+ numByteCharCountBits: 16,
+ }
+ default:
+ log.Panic("Unknown dataEncoderType")
+ }
+
+ return d
+}
+
+// encode data as one or more segments and return the encoded data.
+//
+// The returned data does not include the terminator bit sequence.
+func (d *dataEncoder) encode(data []byte) (*bitset.Bitset, error) {
+ d.data = data
+ d.actual = nil
+ d.optimised = nil
+
+ if len(data) == 0 {
+ return nil, errors.New("no data to encode")
+ }
+
+ // Classify data into unoptimised segments.
+ d.classifyDataModes()
+
+ // Optimise segments.
+ err := d.optimiseDataModes()
+ if err != nil {
+ return nil, err
+ }
+
+ // Encode data.
+ encoded := bitset.New()
+ for _, s := range d.optimised {
+ d.encodeDataRaw(s.data, s.dataMode, encoded)
+ }
+
+ return encoded, nil
+}
+
+// classifyDataModes classifies the raw data into unoptimised segments.
+// e.g. "123ZZ#!#!" =>
+// [numeric, 3, "123"] [alphanumeric, 2, "ZZ"] [byte, 4, "#!#!"].
+func (d *dataEncoder) classifyDataModes() {
+ var start int
+ mode := dataModeNone
+
+ for i, v := range d.data {
+ newMode := dataModeNone
+ switch {
+ case v >= 0x30 && v <= 0x39:
+ newMode = dataModeNumeric
+ case v == 0x20 || v == 0x24 || v == 0x25 || v == 0x2a || v == 0x2b || v ==
+ 0x2d || v == 0x2e || v == 0x2f || v == 0x3a || (v >= 0x41 && v <= 0x5a):
+ newMode = dataModeAlphanumeric
+ default:
+ newMode = dataModeByte
+ }
+
+ if newMode != mode {
+ if i > 0 {
+ d.actual = append(d.actual, segment{dataMode: mode, data: d.data[start:i]})
+
+ start = i
+ }
+
+ mode = newMode
+ }
+ }
+
+ d.actual = append(d.actual, segment{dataMode: mode, data: d.data[start:len(d.data)]})
+}
+
+// optimiseDataModes optimises the list of segments to reduce the overall output
+// encoded data length.
+//
+// The algorithm coalesces adjacent segments. segments are only coalesced when
+// the Data Modes are compatible, and when the coalesced segment has a shorter
+// encoded length than separate segments.
+//
+// Multiple segments may be coalesced. For example a string of alternating
+// alphanumeric/numeric segments ANANANANA can be optimised to just A.
+func (d *dataEncoder) optimiseDataModes() error {
+ for i := 0; i < len(d.actual); {
+ mode := d.actual[i].dataMode
+ numChars := len(d.actual[i].data)
+
+ j := i + 1
+ for j < len(d.actual) {
+ nextNumChars := len(d.actual[j].data)
+ nextMode := d.actual[j].dataMode
+
+ if nextMode > mode {
+ break
+ }
+
+ coalescedLength, err := d.encodedLength(mode, numChars+nextNumChars)
+
+ if err != nil {
+ return err
+ }
+
+ seperateLength1, err := d.encodedLength(mode, numChars)
+
+ if err != nil {
+ return err
+ }
+
+ seperateLength2, err := d.encodedLength(nextMode, nextNumChars)
+
+ if err != nil {
+ return err
+ }
+
+ if coalescedLength < seperateLength1+seperateLength2 {
+ j++
+ numChars += nextNumChars
+ } else {
+ break
+ }
+ }
+
+ optimised := segment{dataMode: mode,
+ data: make([]byte, 0, numChars)}
+
+ for k := i; k < j; k++ {
+ optimised.data = append(optimised.data, d.actual[k].data...)
+ }
+
+ d.optimised = append(d.optimised, optimised)
+
+ i = j
+ }
+
+ return nil
+}
+
+// encodeDataRaw encodes data in dataMode. The encoded data is appended to
+// encoded.
+func (d *dataEncoder) encodeDataRaw(data []byte, dataMode dataMode, encoded *bitset.Bitset) {
+ modeIndicator := d.modeIndicator(dataMode)
+ charCountBits := d.charCountBits(dataMode)
+
+ // Append mode indicator.
+ encoded.Append(modeIndicator)
+
+ // Append character count.
+ encoded.AppendUint32(uint32(len(data)), charCountBits)
+
+ // Append data.
+ switch dataMode {
+ case dataModeNumeric:
+ for i := 0; i < len(data); i += 3 {
+ charsRemaining := len(data) - i
+
+ var value uint32
+ bitsUsed := 1
+
+ for j := 0; j < charsRemaining && j < 3; j++ {
+ value *= 10
+ value += uint32(data[i+j] - 0x30)
+ bitsUsed += 3
+ }
+ encoded.AppendUint32(value, bitsUsed)
+ }
+ case dataModeAlphanumeric:
+ for i := 0; i < len(data); i += 2 {
+ charsRemaining := len(data) - i
+
+ var value uint32
+ for j := 0; j < charsRemaining && j < 2; j++ {
+ value *= 45
+ value += encodeAlphanumericCharacter(data[i+j])
+ }
+
+ bitsUsed := 6
+ if charsRemaining > 1 {
+ bitsUsed = 11
+ }
+
+ encoded.AppendUint32(value, bitsUsed)
+ }
+ case dataModeByte:
+ for _, b := range data {
+ encoded.AppendByte(b, 8)
+ }
+ }
+}
+
+// modeIndicator returns the segment header bits for a segment of type dataMode.
+func (d *dataEncoder) modeIndicator(dataMode dataMode) *bitset.Bitset {
+ switch dataMode {
+ case dataModeNumeric:
+ return d.numericModeIndicator
+ case dataModeAlphanumeric:
+ return d.alphanumericModeIndicator
+ case dataModeByte:
+ return d.byteModeIndicator
+ default:
+ log.Panic("Unknown data mode")
+ }
+
+ return nil
+}
+
+// charCountBits returns the number of bits used to encode the length of a data
+// segment of type dataMode.
+func (d *dataEncoder) charCountBits(dataMode dataMode) int {
+ switch dataMode {
+ case dataModeNumeric:
+ return d.numNumericCharCountBits
+ case dataModeAlphanumeric:
+ return d.numAlphanumericCharCountBits
+ case dataModeByte:
+ return d.numByteCharCountBits
+ default:
+ log.Panic("Unknown data mode")
+ }
+
+ return 0
+}
+
+// encodedLength returns the number of bits required to encode n symbols in
+// dataMode.
+//
+// The number of bits required is affected by:
+// - QR code type - Mode Indicator length.
+// - Data mode - number of bits used to represent data length.
+// - Data mode - how the data is encoded.
+// - Number of symbols encoded.
+//
+// An error is returned if the mode is not supported, or the length requested is
+// too long to be represented.
+func (d *dataEncoder) encodedLength(dataMode dataMode, n int) (int, error) {
+ modeIndicator := d.modeIndicator(dataMode)
+ charCountBits := d.charCountBits(dataMode)
+
+ if modeIndicator == nil {
+ return 0, errors.New("mode not supported")
+ }
+
+ maxLength := (1 << uint8(charCountBits)) - 1
+
+ if n > maxLength {
+ return 0, errors.New("length too long to be represented")
+ }
+
+ length := modeIndicator.Len() + charCountBits
+
+ switch dataMode {
+ case dataModeNumeric:
+ length += 10 * (n / 3)
+
+ if n%3 != 0 {
+ length += 1 + 3*(n%3)
+ }
+ case dataModeAlphanumeric:
+ length += 11 * (n / 2)
+ length += 6 * (n % 2)
+ case dataModeByte:
+ length += 8 * n
+ }
+
+ return length, nil
+}
+
+// encodeAlphanumericChar returns the QR Code encoded value of v.
+//
+// v must be a QR Code defined alphanumeric character: 0-9, A-Z, SP, $%*+-./ or
+// :. The characters are mapped to values in the range 0-44 respectively.
+func encodeAlphanumericCharacter(v byte) uint32 {
+ c := uint32(v)
+
+ switch {
+ case c >= '0' && c <= '9':
+ // 0-9 encoded as 0-9.
+ return c - '0'
+ case c >= 'A' && c <= 'Z':
+ // A-Z encoded as 10-35.
+ return c - 'A' + 10
+ case c == ' ':
+ return 36
+ case c == '$':
+ return 37
+ case c == '%':
+ return 38
+ case c == '*':
+ return 39
+ case c == '+':
+ return 40
+ case c == '-':
+ return 41
+ case c == '.':
+ return 42
+ case c == '/':
+ return 43
+ case c == ':':
+ return 44
+ default:
+ log.Panicf("encodeAlphanumericCharacter() with non alphanumeric char %v.", v)
+ }
+
+ return 0
+}
diff --git a/vendor/github.com/skip2/go-qrcode/qrcode.go b/vendor/github.com/skip2/go-qrcode/qrcode.go
new file mode 100644
index 00000000..9428d863
--- /dev/null
+++ b/vendor/github.com/skip2/go-qrcode/qrcode.go
@@ -0,0 +1,589 @@
+// go-qrcode
+// Copyright 2014 Tom Harwood
+
+/*
+Package qrcode implements a QR Code encoder.
+
+A QR Code is a matrix (two-dimensional) barcode. Arbitrary content may be
+encoded.
+
+A QR Code contains error recovery information to aid reading damaged or
+obscured codes. There are four levels of error recovery: qrcode.{Low, Medium,
+High, Highest}. QR Codes with a higher recovery level are more robust to damage,
+at the cost of being physically larger.
+
+Three functions cover most use cases:
+
+- Create a PNG image:
+
+ var png []byte
+ png, err := qrcode.Encode("https://example.org", qrcode.Medium, 256)
+
+- Create a PNG image and write to a file:
+
+ err := qrcode.WriteFile("https://example.org", qrcode.Medium, 256, "qr.png")
+
+- Create a PNG image with custom colors and write to file:
+
+ err := qrcode.WriteColorFile("https://example.org", qrcode.Medium, 256, color.Black, color.White, "qr.png")
+
+All examples use the qrcode.Medium error Recovery Level and create a fixed
+256x256px size QR Code. The last function creates a white on black instead of black
+on white QR Code.
+
+To generate a variable sized image instead, specify a negative size (in place of
+the 256 above), such as -4 or -5. Larger negative numbers create larger images:
+A size of -5 sets each module (QR Code "pixel") to be 5px wide/high.
+
+- Create a PNG image (variable size, with minimum white padding) and write to a file:
+
+ err := qrcode.WriteFile("https://example.org", qrcode.Medium, -5, "qr.png")
+
+The maximum capacity of a QR Code varies according to the content encoded and
+the error recovery level. The maximum capacity is 2,953 bytes, 4,296
+alphanumeric characters, 7,089 numeric digits, or a combination of these.
+
+This package implements a subset of QR Code 2005, as defined in ISO/IEC
+18004:2006.
+*/
+package qrcode
+
+import (
+ "bytes"
+ "errors"
+ "image"
+ "image/color"
+ "image/png"
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+
+ bitset "github.com/skip2/go-qrcode/bitset"
+ reedsolomon "github.com/skip2/go-qrcode/reedsolomon"
+)
+
+// Encode a QR Code and return a raw PNG image.
+//
+// size is both the image width and height in pixels. If size is too small then
+// a larger image is silently returned. Negative values for size cause a
+// variable sized image to be returned: See the documentation for Image().
+//
+// To serve over HTTP, remember to send a Content-Type: image/png header.
+func Encode(content string, level RecoveryLevel, size int) ([]byte, error) {
+ var q *QRCode
+
+ q, err := New(content, level)
+
+ if err != nil {
+ return nil, err
+ }
+
+ return q.PNG(size)
+}
+
+// WriteFile encodes, then writes a QR Code to the given filename in PNG format.
+//
+// size is both the image width and height in pixels. If size is too small then
+// a larger image is silently written. Negative values for size cause a variable
+// sized image to be written: See the documentation for Image().
+func WriteFile(content string, level RecoveryLevel, size int, filename string) error {
+ var q *QRCode
+
+ q, err := New(content, level)
+
+ if err != nil {
+ return err
+ }
+
+ return q.WriteFile(size, filename)
+}
+
+// WriteColorFile encodes, then writes a QR Code to the given filename in PNG format.
+// With WriteColorFile you can also specify the colors you want to use.
+//
+// size is both the image width and height in pixels. If size is too small then
+// a larger image is silently written. Negative values for size cause a variable
+// sized image to be written: See the documentation for Image().
+func WriteColorFile(content string, level RecoveryLevel, size int, background,
+ foreground color.Color, filename string) error {
+
+ var q *QRCode
+
+ q, err := New(content, level)
+
+ q.BackgroundColor = background
+ q.ForegroundColor = foreground
+
+ if err != nil {
+ return err
+ }
+
+ return q.WriteFile(size, filename)
+}
+
+// A QRCode represents a valid encoded QRCode.
+type QRCode struct {
+ // Original content encoded.
+ Content string
+
+ // QR Code type.
+ Level RecoveryLevel
+ VersionNumber int
+
+ // User settable drawing options.
+ ForegroundColor color.Color
+ BackgroundColor color.Color
+
+ encoder *dataEncoder
+ version qrCodeVersion
+
+ data *bitset.Bitset
+ symbol *symbol
+ mask int
+}
+
+// New constructs a QRCode.
+//
+// var q *qrcode.QRCode
+// q, err := qrcode.New("my content", qrcode.Medium)
+//
+// An error occurs if the content is too long.
+func New(content string, level RecoveryLevel) (*QRCode, error) {
+ encoders := []dataEncoderType{dataEncoderType1To9, dataEncoderType10To26,
+ dataEncoderType27To40}
+
+ var encoder *dataEncoder
+ var encoded *bitset.Bitset
+ var chosenVersion *qrCodeVersion
+ var err error
+
+ for _, t := range encoders {
+ encoder = newDataEncoder(t)
+ encoded, err = encoder.encode([]byte(content))
+
+ if err != nil {
+ continue
+ }
+
+ chosenVersion = chooseQRCodeVersion(level, encoder, encoded.Len())
+
+ if chosenVersion != nil {
+ break
+ }
+ }
+
+ if err != nil {
+ return nil, err
+ } else if chosenVersion == nil {
+ return nil, errors.New("content too long to encode")
+ }
+
+ q := &QRCode{
+ Content: content,
+
+ Level: level,
+ VersionNumber: chosenVersion.version,
+
+ ForegroundColor: color.Black,
+ BackgroundColor: color.White,
+
+ encoder: encoder,
+ data: encoded,
+ version: *chosenVersion,
+ }
+
+ q.encode(chosenVersion.numTerminatorBitsRequired(encoded.Len()))
+
+ return q, nil
+}
+
+func newWithForcedVersion(content string, version int, level RecoveryLevel) (*QRCode, error) {
+ var encoder *dataEncoder
+
+ switch {
+ case version >= 1 && version <= 9:
+ encoder = newDataEncoder(dataEncoderType1To9)
+ case version >= 10 && version <= 26:
+ encoder = newDataEncoder(dataEncoderType10To26)
+ case version >= 27 && version <= 40:
+ encoder = newDataEncoder(dataEncoderType27To40)
+ default:
+ log.Fatalf("Invalid version %d (expected 1-40 inclusive)", version)
+ }
+
+ var encoded *bitset.Bitset
+ encoded, err := encoder.encode([]byte(content))
+
+ if err != nil {
+ return nil, err
+ }
+
+ chosenVersion := getQRCodeVersion(level, version)
+
+ if chosenVersion == nil {
+ return nil, errors.New("cannot find QR Code version")
+ }
+
+ q := &QRCode{
+ Content: content,
+
+ Level: level,
+ VersionNumber: chosenVersion.version,
+
+ ForegroundColor: color.Black,
+ BackgroundColor: color.White,
+
+ encoder: encoder,
+ data: encoded,
+ version: *chosenVersion,
+ }
+
+ q.encode(chosenVersion.numTerminatorBitsRequired(encoded.Len()))
+
+ return q, nil
+}
+
+// Bitmap returns the QR Code as a 2D array of 1-bit pixels.
+//
+// bitmap[y][x] is true if the pixel at (x, y) is set.
+//
+// The bitmap includes the required "quiet zone" around the QR Code to aid
+// decoding.
+func (q *QRCode) Bitmap() [][]bool {
+ return q.symbol.bitmap()
+}
+
+// Image returns the QR Code as an image.Image.
+//
+// A positive size sets a fixed image width and height (e.g. 256 yields an
+// 256x256px image).
+//
+// Depending on the amount of data encoded, fixed size images can have different
+// amounts of padding (white space around the QR Code). As an alternative, a
+// variable sized image can be generated instead:
+//
+// A negative size causes a variable sized image to be returned. The image
+// returned is the minimum size required for the QR Code. Choose a larger
+// negative number to increase the scale of the image. e.g. a size of -5 causes
+// each module (QR Code "pixel") to be 5px in size.
+func (q *QRCode) Image(size int) image.Image {
+ // Minimum pixels (both width and height) required.
+ realSize := q.symbol.size
+
+ // Variable size support.
+ if size < 0 {
+ size = size * -1 * realSize
+ }
+
+ // Actual pixels available to draw the symbol. Automatically increase the
+ // image size if it's not large enough.
+ if size < realSize {
+ size = realSize
+ }
+
+ // Size of each module drawn.
+ pixelsPerModule := size / realSize
+
+ // Center the symbol within the image.
+ offset := (size - realSize*pixelsPerModule) / 2
+
+ rect := image.Rectangle{Min: image.Point{0, 0}, Max: image.Point{size, size}}
+
+ // Saves a few bytes to have them in this order
+ p := color.Palette([]color.Color{q.BackgroundColor, q.ForegroundColor})
+ img := image.NewPaletted(rect, p)
+ fgClr := uint8(img.Palette.Index(q.ForegroundColor))
+
+ bitmap := q.symbol.bitmap()
+ for y, row := range bitmap {
+ for x, v := range row {
+ if v {
+ startX := x*pixelsPerModule + offset
+ startY := y*pixelsPerModule + offset
+ for i := startX; i < startX+pixelsPerModule; i++ {
+ for j := startY; j < startY+pixelsPerModule; j++ {
+ pos := img.PixOffset(i, j)
+ img.Pix[pos] = fgClr
+ }
+ }
+ }
+ }
+ }
+
+ return img
+}
+
+// PNG returns the QR Code as a PNG image.
+//
+// size is both the image width and height in pixels. If size is too small then
+// a larger image is silently returned. Negative values for size cause a
+// variable sized image to be returned: See the documentation for Image().
+func (q *QRCode) PNG(size int) ([]byte, error) {
+ img := q.Image(size)
+
+ encoder := png.Encoder{CompressionLevel: png.BestCompression}
+
+ var b bytes.Buffer
+ err := encoder.Encode(&b, img)
+
+ if err != nil {
+ return nil, err
+ }
+
+ return b.Bytes(), nil
+}
+
+// Write writes the QR Code as a PNG image to io.Writer.
+//
+// size is both the image width and height in pixels. If size is too small then
+// a larger image is silently written. Negative values for size cause a
+// variable sized image to be written: See the documentation for Image().
+func (q *QRCode) Write(size int, out io.Writer) error {
+ var png []byte
+
+ png, err := q.PNG(size)
+
+ if err != nil {
+ return err
+ }
+ _, err = out.Write(png)
+ return err
+}
+
+// WriteFile writes the QR Code as a PNG image to the specified file.
+//
+// size is both the image width and height in pixels. If size is too small then
+// a larger image is silently written. Negative values for size cause a
+// variable sized image to be written: See the documentation for Image().
+func (q *QRCode) WriteFile(size int, filename string) error {
+ var png []byte
+
+ png, err := q.PNG(size)
+
+ if err != nil {
+ return err
+ }
+
+ return ioutil.WriteFile(filename, png, os.FileMode(0644))
+}
+
+// encode completes the steps required to encode the QR Code. These include
+// adding the terminator bits and padding, splitting the data into blocks and
+// applying the error correction, and selecting the best data mask.
+func (q *QRCode) encode(numTerminatorBits int) {
+ q.addTerminatorBits(numTerminatorBits)
+ q.addPadding()
+
+ encoded := q.encodeBlocks()
+
+ const numMasks int = 8
+ penalty := 0
+
+ for mask := 0; mask < numMasks; mask++ {
+ var s *symbol
+ var err error
+
+ s, err = buildRegularSymbol(q.version, mask, encoded)
+
+ if err != nil {
+ log.Panic(err.Error())
+ }
+
+ numEmptyModules := s.numEmptyModules()
+ if numEmptyModules != 0 {
+ log.Panicf("bug: numEmptyModules is %d (expected 0) (version=%d)",
+ numEmptyModules, q.VersionNumber)
+ }
+
+ p := s.penaltyScore()
+
+ //log.Printf("mask=%d p=%3d p1=%3d p2=%3d p3=%3d p4=%d\n", mask, p, s.penalty1(), s.penalty2(), s.penalty3(), s.penalty4())
+
+ if q.symbol == nil || p < penalty {
+ q.symbol = s
+ q.mask = mask
+ penalty = p
+ }
+ }
+}
+
+// addTerminatorBits adds final terminator bits to the encoded data.
+//
+// The number of terminator bits required is determined when the QR Code version
+// is chosen (which itself depends on the length of the data encoded). The
+// terminator bits are thus added after the QR Code version
+// is chosen, rather than at the data encoding stage.
+func (q *QRCode) addTerminatorBits(numTerminatorBits int) {
+ q.data.AppendNumBools(numTerminatorBits, false)
+}
+
+// encodeBlocks takes the completed (terminated & padded) encoded data, splits
+// the data into blocks (as specified by the QR Code version), applies error
+// correction to each block, then interleaves the blocks together.
+//
+// The QR Code's final data sequence is returned.
+func (q *QRCode) encodeBlocks() *bitset.Bitset {
+ // Split into blocks.
+ type dataBlock struct {
+ data *bitset.Bitset
+ ecStartOffset int
+ }
+
+ block := make([]dataBlock, q.version.numBlocks())
+
+ start := 0
+ end := 0
+ blockID := 0
+
+ for _, b := range q.version.block {
+ for j := 0; j < b.numBlocks; j++ {
+ start = end
+ end = start + b.numDataCodewords*8
+
+ // Apply error correction to each block.
+ numErrorCodewords := b.numCodewords - b.numDataCodewords
+ block[blockID].data = reedsolomon.Encode(q.data.Substr(start, end), numErrorCodewords)
+ block[blockID].ecStartOffset = end - start
+
+ blockID++
+ }
+ }
+
+ // Interleave the blocks.
+
+ result := bitset.New()
+
+ // Combine data blocks.
+ working := true
+ for i := 0; working; i += 8 {
+ working = false
+
+ for j, b := range block {
+ if i >= block[j].ecStartOffset {
+ continue
+ }
+
+ result.Append(b.data.Substr(i, i+8))
+
+ working = true
+ }
+ }
+
+ // Combine error correction blocks.
+ working = true
+ for i := 0; working; i += 8 {
+ working = false
+
+ for j, b := range block {
+ offset := i + block[j].ecStartOffset
+ if offset >= block[j].data.Len() {
+ continue
+ }
+
+ result.Append(b.data.Substr(offset, offset+8))
+
+ working = true
+ }
+ }
+
+ // Append remainder bits.
+ result.AppendNumBools(q.version.numRemainderBits, false)
+
+ return result
+}
+
+// max returns the maximum of a and b.
+func max(a int, b int) int {
+ if a > b {
+ return a
+ }
+
+ return b
+}
+
+// addPadding pads the encoded data upto the full length required.
+func (q *QRCode) addPadding() {
+ numDataBits := q.version.numDataBits()
+
+ if q.data.Len() == numDataBits {
+ return
+ }
+
+ // Pad to the nearest codeword boundary.
+ q.data.AppendNumBools(q.version.numBitsToPadToCodeword(q.data.Len()), false)
+
+ // Pad codewords 0b11101100 and 0b00010001.
+ padding := [2]*bitset.Bitset{
+ bitset.New(true, true, true, false, true, true, false, false),
+ bitset.New(false, false, false, true, false, false, false, true),
+ }
+
+ // Insert pad codewords alternately.
+ i := 0
+ for numDataBits-q.data.Len() >= 8 {
+ q.data.Append(padding[i])
+
+ i = 1 - i // Alternate between 0 and 1.
+ }
+
+ if q.data.Len() != numDataBits {
+ log.Panicf("BUG: got len %d, expected %d", q.data.Len(), numDataBits)
+ }
+}
+
+// ToString produces a multi-line string that forms a QR-code image.
+func (q *QRCode) ToString(inverseColor bool) string {
+ bits := q.Bitmap()
+ var buf bytes.Buffer
+ for y := range bits {
+ for x := range bits[y] {
+ if bits[y][x] != inverseColor {
+ buf.WriteString(" ")
+ } else {
+ buf.WriteString("██")
+ }
+ }
+ buf.WriteString("\n")
+ }
+ return buf.String()
+}
+
+// ToSmallString produces a multi-line string that forms a QR-code image, a
+// factor two smaller in x and y then ToString.
+func (q *QRCode) ToSmallString(inverseColor bool) string {
+ bits := q.Bitmap()
+ var buf bytes.Buffer
+ // if there is an odd number of rows, the last one needs special treatment
+ for y := 0; y < len(bits)-1; y += 2 {
+ for x := range bits[y] {
+ if bits[y][x] == bits[y+1][x] {
+ if bits[y][x] != inverseColor {
+ buf.WriteString(" ")
+ } else {
+ buf.WriteString("â–ˆ")
+ }
+ } else {
+ if bits[y][x] != inverseColor {
+ buf.WriteString("â–„")
+ } else {
+ buf.WriteString("â–€")
+ }
+ }
+ }
+ buf.WriteString("\n")
+ }
+ // special treatment for the last row if odd
+ if len(bits)%2 == 1 {
+ y := len(bits) - 1
+ for x := range bits[y] {
+ if bits[y][x] != inverseColor {
+ buf.WriteString(" ")
+ } else {
+ buf.WriteString("â–€")
+ }
+ }
+ buf.WriteString("\n")
+ }
+ return buf.String()
+}
diff --git a/vendor/github.com/skip2/go-qrcode/reedsolomon/gf2_8.go b/vendor/github.com/skip2/go-qrcode/reedsolomon/gf2_8.go
new file mode 100644
index 00000000..6a7003f7
--- /dev/null
+++ b/vendor/github.com/skip2/go-qrcode/reedsolomon/gf2_8.go
@@ -0,0 +1,387 @@
+// go-qrcode
+// Copyright 2014 Tom Harwood
+
+package reedsolomon
+
+// Addition, subtraction, multiplication, and division in GF(2^8).
+// Operations are performed modulo x^8 + x^4 + x^3 + x^2 + 1.
+
+// http://en.wikipedia.org/wiki/Finite_field_arithmetic
+
+import "log"
+
+const (
+ gfZero = gfElement(0)
+ gfOne = gfElement(1)
+)
+
+var (
+ gfExpTable = [256]gfElement{
+ /* 0 - 9 */ 1, 2, 4, 8, 16, 32, 64, 128, 29, 58,
+ /* 10 - 19 */ 116, 232, 205, 135, 19, 38, 76, 152, 45, 90,
+ /* 20 - 29 */ 180, 117, 234, 201, 143, 3, 6, 12, 24, 48,
+ /* 30 - 39 */ 96, 192, 157, 39, 78, 156, 37, 74, 148, 53,
+ /* 40 - 49 */ 106, 212, 181, 119, 238, 193, 159, 35, 70, 140,
+ /* 50 - 59 */ 5, 10, 20, 40, 80, 160, 93, 186, 105, 210,
+ /* 60 - 69 */ 185, 111, 222, 161, 95, 190, 97, 194, 153, 47,
+ /* 70 - 79 */ 94, 188, 101, 202, 137, 15, 30, 60, 120, 240,
+ /* 80 - 89 */ 253, 231, 211, 187, 107, 214, 177, 127, 254, 225,
+ /* 90 - 99 */ 223, 163, 91, 182, 113, 226, 217, 175, 67, 134,
+ /* 100 - 109 */ 17, 34, 68, 136, 13, 26, 52, 104, 208, 189,
+ /* 110 - 119 */ 103, 206, 129, 31, 62, 124, 248, 237, 199, 147,
+ /* 120 - 129 */ 59, 118, 236, 197, 151, 51, 102, 204, 133, 23,
+ /* 130 - 139 */ 46, 92, 184, 109, 218, 169, 79, 158, 33, 66,
+ /* 140 - 149 */ 132, 21, 42, 84, 168, 77, 154, 41, 82, 164,
+ /* 150 - 159 */ 85, 170, 73, 146, 57, 114, 228, 213, 183, 115,
+ /* 160 - 169 */ 230, 209, 191, 99, 198, 145, 63, 126, 252, 229,
+ /* 170 - 179 */ 215, 179, 123, 246, 241, 255, 227, 219, 171, 75,
+ /* 180 - 189 */ 150, 49, 98, 196, 149, 55, 110, 220, 165, 87,
+ /* 190 - 199 */ 174, 65, 130, 25, 50, 100, 200, 141, 7, 14,
+ /* 200 - 209 */ 28, 56, 112, 224, 221, 167, 83, 166, 81, 162,
+ /* 210 - 219 */ 89, 178, 121, 242, 249, 239, 195, 155, 43, 86,
+ /* 220 - 229 */ 172, 69, 138, 9, 18, 36, 72, 144, 61, 122,
+ /* 230 - 239 */ 244, 245, 247, 243, 251, 235, 203, 139, 11, 22,
+ /* 240 - 249 */ 44, 88, 176, 125, 250, 233, 207, 131, 27, 54,
+ /* 250 - 255 */ 108, 216, 173, 71, 142, 1}
+
+ gfLogTable = [256]int{
+ /* 0 - 9 */ -1, 0, 1, 25, 2, 50, 26, 198, 3, 223,
+ /* 10 - 19 */ 51, 238, 27, 104, 199, 75, 4, 100, 224, 14,
+ /* 20 - 29 */ 52, 141, 239, 129, 28, 193, 105, 248, 200, 8,
+ /* 30 - 39 */ 76, 113, 5, 138, 101, 47, 225, 36, 15, 33,
+ /* 40 - 49 */ 53, 147, 142, 218, 240, 18, 130, 69, 29, 181,
+ /* 50 - 59 */ 194, 125, 106, 39, 249, 185, 201, 154, 9, 120,
+ /* 60 - 69 */ 77, 228, 114, 166, 6, 191, 139, 98, 102, 221,
+ /* 70 - 79 */ 48, 253, 226, 152, 37, 179, 16, 145, 34, 136,
+ /* 80 - 89 */ 54, 208, 148, 206, 143, 150, 219, 189, 241, 210,
+ /* 90 - 99 */ 19, 92, 131, 56, 70, 64, 30, 66, 182, 163,
+ /* 100 - 109 */ 195, 72, 126, 110, 107, 58, 40, 84, 250, 133,
+ /* 110 - 119 */ 186, 61, 202, 94, 155, 159, 10, 21, 121, 43,
+ /* 120 - 129 */ 78, 212, 229, 172, 115, 243, 167, 87, 7, 112,
+ /* 130 - 139 */ 192, 247, 140, 128, 99, 13, 103, 74, 222, 237,
+ /* 140 - 149 */ 49, 197, 254, 24, 227, 165, 153, 119, 38, 184,
+ /* 150 - 159 */ 180, 124, 17, 68, 146, 217, 35, 32, 137, 46,
+ /* 160 - 169 */ 55, 63, 209, 91, 149, 188, 207, 205, 144, 135,
+ /* 170 - 179 */ 151, 178, 220, 252, 190, 97, 242, 86, 211, 171,
+ /* 180 - 189 */ 20, 42, 93, 158, 132, 60, 57, 83, 71, 109,
+ /* 190 - 199 */ 65, 162, 31, 45, 67, 216, 183, 123, 164, 118,
+ /* 200 - 209 */ 196, 23, 73, 236, 127, 12, 111, 246, 108, 161,
+ /* 210 - 219 */ 59, 82, 41, 157, 85, 170, 251, 96, 134, 177,
+ /* 220 - 229 */ 187, 204, 62, 90, 203, 89, 95, 176, 156, 169,
+ /* 230 - 239 */ 160, 81, 11, 245, 22, 235, 122, 117, 44, 215,
+ /* 240 - 249 */ 79, 174, 213, 233, 230, 231, 173, 232, 116, 214,
+ /* 250 - 255 */ 244, 234, 168, 80, 88, 175}
+)
+
+// gfElement is an element in GF(2^8).
+type gfElement uint8
+
+// newGFElement creates and returns a new gfElement.
+func newGFElement(data byte) gfElement {
+ return gfElement(data)
+}
+
+// gfAdd returns a + b.
+func gfAdd(a, b gfElement) gfElement {
+ return a ^ b
+}
+
+// gfSub returns a - b.
+//
+// Note addition is equivalent to subtraction in GF(2).
+func gfSub(a, b gfElement) gfElement {
+ return a ^ b
+}
+
+// gfMultiply returns a * b.
+func gfMultiply(a, b gfElement) gfElement {
+ if a == gfZero || b == gfZero {
+ return gfZero
+ }
+
+ return gfExpTable[(gfLogTable[a]+gfLogTable[b])%255]
+}
+
+// gfDivide returns a / b.
+//
+// Divide by zero results in a panic.
+func gfDivide(a, b gfElement) gfElement {
+ if a == gfZero {
+ return gfZero
+ } else if b == gfZero {
+ log.Panicln("Divide by zero")
+ }
+
+ return gfMultiply(a, gfInverse(b))
+}
+
+// gfInverse returns the multiplicative inverse of a, a^-1.
+//
+// a * a^-1 = 1
+func gfInverse(a gfElement) gfElement {
+ if a == gfZero {
+ log.Panicln("No multiplicative inverse of 0")
+ }
+
+ return gfExpTable[255-gfLogTable[a]]
+}
+
+// a^i | bits | polynomial | decimal
+// --------------------------------------------------------------------------
+// 0 | 000000000 | 0x^8 0x^7 0x^6 0x^5 0x^4 0x^3 0x^2 0x^1 0x^0 | 0
+// a^0 | 000000001 | 0x^8 0x^7 0x^6 0x^5 0x^4 0x^3 0x^2 0x^1 1x^0 | 1
+// a^1 | 000000010 | 0x^8 0x^7 0x^6 0x^5 0x^4 0x^3 0x^2 1x^1 0x^0 | 2
+// a^2 | 000000100 | 0x^8 0x^7 0x^6 0x^5 0x^4 0x^3 1x^2 0x^1 0x^0 | 4
+// a^3 | 000001000 | 0x^8 0x^7 0x^6 0x^5 0x^4 1x^3 0x^2 0x^1 0x^0 | 8
+// a^4 | 000010000 | 0x^8 0x^7 0x^6 0x^5 1x^4 0x^3 0x^2 0x^1 0x^0 | 16
+// a^5 | 000100000 | 0x^8 0x^7 0x^6 1x^5 0x^4 0x^3 0x^2 0x^1 0x^0 | 32
+// a^6 | 001000000 | 0x^8 0x^7 1x^6 0x^5 0x^4 0x^3 0x^2 0x^1 0x^0 | 64
+// a^7 | 010000000 | 0x^8 1x^7 0x^6 0x^5 0x^4 0x^3 0x^2 0x^1 0x^0 | 128
+// a^8 | 000011101 | 0x^8 0x^7 0x^6 0x^5 1x^4 1x^3 1x^2 0x^1 1x^0 | 29
+// a^9 | 000111010 | 0x^8 0x^7 0x^6 1x^5 1x^4 1x^3 0x^2 1x^1 0x^0 | 58
+// a^10 | 001110100 | 0x^8 0x^7 1x^6 1x^5 1x^4 0x^3 1x^2 0x^1 0x^0 | 116
+// a^11 | 011101000 | 0x^8 1x^7 1x^6 1x^5 0x^4 1x^3 0x^2 0x^1 0x^0 | 232
+// a^12 | 011001101 | 0x^8 1x^7 1x^6 0x^5 0x^4 1x^3 1x^2 0x^1 1x^0 | 205
+// a^13 | 010000111 | 0x^8 1x^7 0x^6 0x^5 0x^4 0x^3 1x^2 1x^1 1x^0 | 135
+// a^14 | 000010011 | 0x^8 0x^7 0x^6 0x^5 1x^4 0x^3 0x^2 1x^1 1x^0 | 19
+// a^15 | 000100110 | 0x^8 0x^7 0x^6 1x^5 0x^4 0x^3 1x^2 1x^1 0x^0 | 38
+// a^16 | 001001100 | 0x^8 0x^7 1x^6 0x^5 0x^4 1x^3 1x^2 0x^1 0x^0 | 76
+// a^17 | 010011000 | 0x^8 1x^7 0x^6 0x^5 1x^4 1x^3 0x^2 0x^1 0x^0 | 152
+// a^18 | 000101101 | 0x^8 0x^7 0x^6 1x^5 0x^4 1x^3 1x^2 0x^1 1x^0 | 45
+// a^19 | 001011010 | 0x^8 0x^7 1x^6 0x^5 1x^4 1x^3 0x^2 1x^1 0x^0 | 90
+// a^20 | 010110100 | 0x^8 1x^7 0x^6 1x^5 1x^4 0x^3 1x^2 0x^1 0x^0 | 180
+// a^21 | 001110101 | 0x^8 0x^7 1x^6 1x^5 1x^4 0x^3 1x^2 0x^1 1x^0 | 117
+// a^22 | 011101010 | 0x^8 1x^7 1x^6 1x^5 0x^4 1x^3 0x^2 1x^1 0x^0 | 234
+// a^23 | 011001001 | 0x^8 1x^7 1x^6 0x^5 0x^4 1x^3 0x^2 0x^1 1x^0 | 201
+// a^24 | 010001111 | 0x^8 1x^7 0x^6 0x^5 0x^4 1x^3 1x^2 1x^1 1x^0 | 143
+// a^25 | 000000011 | 0x^8 0x^7 0x^6 0x^5 0x^4 0x^3 0x^2 1x^1 1x^0 | 3
+// a^26 | 000000110 | 0x^8 0x^7 0x^6 0x^5 0x^4 0x^3 1x^2 1x^1 0x^0 | 6
+// a^27 | 000001100 | 0x^8 0x^7 0x^6 0x^5 0x^4 1x^3 1x^2 0x^1 0x^0 | 12
+// a^28 | 000011000 | 0x^8 0x^7 0x^6 0x^5 1x^4 1x^3 0x^2 0x^1 0x^0 | 24
+// a^29 | 000110000 | 0x^8 0x^7 0x^6 1x^5 1x^4 0x^3 0x^2 0x^1 0x^0 | 48
+// a^30 | 001100000 | 0x^8 0x^7 1x^6 1x^5 0x^4 0x^3 0x^2 0x^1 0x^0 | 96
+// a^31 | 011000000 | 0x^8 1x^7 1x^6 0x^5 0x^4 0x^3 0x^2 0x^1 0x^0 | 192
+// a^32 | 010011101 | 0x^8 1x^7 0x^6 0x^5 1x^4 1x^3 1x^2 0x^1 1x^0 | 157
+// a^33 | 000100111 | 0x^8 0x^7 0x^6 1x^5 0x^4 0x^3 1x^2 1x^1 1x^0 | 39
+// a^34 | 001001110 | 0x^8 0x^7 1x^6 0x^5 0x^4 1x^3 1x^2 1x^1 0x^0 | 78
+// a^35 | 010011100 | 0x^8 1x^7 0x^6 0x^5 1x^4 1x^3 1x^2 0x^1 0x^0 | 156
+// a^36 | 000100101 | 0x^8 0x^7 0x^6 1x^5 0x^4 0x^3 1x^2 0x^1 1x^0 | 37
+// a^37 | 001001010 | 0x^8 0x^7 1x^6 0x^5 0x^4 1x^3 0x^2 1x^1 0x^0 | 74
+// a^38 | 010010100 | 0x^8 1x^7 0x^6 0x^5 1x^4 0x^3 1x^2 0x^1 0x^0 | 148
+// a^39 | 000110101 | 0x^8 0x^7 0x^6 1x^5 1x^4 0x^3 1x^2 0x^1 1x^0 | 53
+// a^40 | 001101010 | 0x^8 0x^7 1x^6 1x^5 0x^4 1x^3 0x^2 1x^1 0x^0 | 106
+// a^41 | 011010100 | 0x^8 1x^7 1x^6 0x^5 1x^4 0x^3 1x^2 0x^1 0x^0 | 212
+// a^42 | 010110101 | 0x^8 1x^7 0x^6 1x^5 1x^4 0x^3 1x^2 0x^1 1x^0 | 181
+// a^43 | 001110111 | 0x^8 0x^7 1x^6 1x^5 1x^4 0x^3 1x^2 1x^1 1x^0 | 119
+// a^44 | 011101110 | 0x^8 1x^7 1x^6 1x^5 0x^4 1x^3 1x^2 1x^1 0x^0 | 238
+// a^45 | 011000001 | 0x^8 1x^7 1x^6 0x^5 0x^4 0x^3 0x^2 0x^1 1x^0 | 193
+// a^46 | 010011111 | 0x^8 1x^7 0x^6 0x^5 1x^4 1x^3 1x^2 1x^1 1x^0 | 159
+// a^47 | 000100011 | 0x^8 0x^7 0x^6 1x^5 0x^4 0x^3 0x^2 1x^1 1x^0 | 35
+// a^48 | 001000110 | 0x^8 0x^7 1x^6 0x^5 0x^4 0x^3 1x^2 1x^1 0x^0 | 70
+// a^49 | 010001100 | 0x^8 1x^7 0x^6 0x^5 0x^4 1x^3 1x^2 0x^1 0x^0 | 140
+// a^50 | 000000101 | 0x^8 0x^7 0x^6 0x^5 0x^4 0x^3 1x^2 0x^1 1x^0 | 5
+// a^51 | 000001010 | 0x^8 0x^7 0x^6 0x^5 0x^4 1x^3 0x^2 1x^1 0x^0 | 10
+// a^52 | 000010100 | 0x^8 0x^7 0x^6 0x^5 1x^4 0x^3 1x^2 0x^1 0x^0 | 20
+// a^53 | 000101000 | 0x^8 0x^7 0x^6 1x^5 0x^4 1x^3 0x^2 0x^1 0x^0 | 40
+// a^54 | 001010000 | 0x^8 0x^7 1x^6 0x^5 1x^4 0x^3 0x^2 0x^1 0x^0 | 80
+// a^55 | 010100000 | 0x^8 1x^7 0x^6 1x^5 0x^4 0x^3 0x^2 0x^1 0x^0 | 160
+// a^56 | 001011101 | 0x^8 0x^7 1x^6 0x^5 1x^4 1x^3 1x^2 0x^1 1x^0 | 93
+// a^57 | 010111010 | 0x^8 1x^7 0x^6 1x^5 1x^4 1x^3 0x^2 1x^1 0x^0 | 186
+// a^58 | 001101001 | 0x^8 0x^7 1x^6 1x^5 0x^4 1x^3 0x^2 0x^1 1x^0 | 105
+// a^59 | 011010010 | 0x^8 1x^7 1x^6 0x^5 1x^4 0x^3 0x^2 1x^1 0x^0 | 210
+// a^60 | 010111001 | 0x^8 1x^7 0x^6 1x^5 1x^4 1x^3 0x^2 0x^1 1x^0 | 185
+// a^61 | 001101111 | 0x^8 0x^7 1x^6 1x^5 0x^4 1x^3 1x^2 1x^1 1x^0 | 111
+// a^62 | 011011110 | 0x^8 1x^7 1x^6 0x^5 1x^4 1x^3 1x^2 1x^1 0x^0 | 222
+// a^63 | 010100001 | 0x^8 1x^7 0x^6 1x^5 0x^4 0x^3 0x^2 0x^1 1x^0 | 161
+// a^64 | 001011111 | 0x^8 0x^7 1x^6 0x^5 1x^4 1x^3 1x^2 1x^1 1x^0 | 95
+// a^65 | 010111110 | 0x^8 1x^7 0x^6 1x^5 1x^4 1x^3 1x^2 1x^1 0x^0 | 190
+// a^66 | 001100001 | 0x^8 0x^7 1x^6 1x^5 0x^4 0x^3 0x^2 0x^1 1x^0 | 97
+// a^67 | 011000010 | 0x^8 1x^7 1x^6 0x^5 0x^4 0x^3 0x^2 1x^1 0x^0 | 194
+// a^68 | 010011001 | 0x^8 1x^7 0x^6 0x^5 1x^4 1x^3 0x^2 0x^1 1x^0 | 153
+// a^69 | 000101111 | 0x^8 0x^7 0x^6 1x^5 0x^4 1x^3 1x^2 1x^1 1x^0 | 47
+// a^70 | 001011110 | 0x^8 0x^7 1x^6 0x^5 1x^4 1x^3 1x^2 1x^1 0x^0 | 94
+// a^71 | 010111100 | 0x^8 1x^7 0x^6 1x^5 1x^4 1x^3 1x^2 0x^1 0x^0 | 188
+// a^72 | 001100101 | 0x^8 0x^7 1x^6 1x^5 0x^4 0x^3 1x^2 0x^1 1x^0 | 101
+// a^73 | 011001010 | 0x^8 1x^7 1x^6 0x^5 0x^4 1x^3 0x^2 1x^1 0x^0 | 202
+// a^74 | 010001001 | 0x^8 1x^7 0x^6 0x^5 0x^4 1x^3 0x^2 0x^1 1x^0 | 137
+// a^75 | 000001111 | 0x^8 0x^7 0x^6 0x^5 0x^4 1x^3 1x^2 1x^1 1x^0 | 15
+// a^76 | 000011110 | 0x^8 0x^7 0x^6 0x^5 1x^4 1x^3 1x^2 1x^1 0x^0 | 30
+// a^77 | 000111100 | 0x^8 0x^7 0x^6 1x^5 1x^4 1x^3 1x^2 0x^1 0x^0 | 60
+// a^78 | 001111000 | 0x^8 0x^7 1x^6 1x^5 1x^4 1x^3 0x^2 0x^1 0x^0 | 120
+// a^79 | 011110000 | 0x^8 1x^7 1x^6 1x^5 1x^4 0x^3 0x^2 0x^1 0x^0 | 240
+// a^80 | 011111101 | 0x^8 1x^7 1x^6 1x^5 1x^4 1x^3 1x^2 0x^1 1x^0 | 253
+// a^81 | 011100111 | 0x^8 1x^7 1x^6 1x^5 0x^4 0x^3 1x^2 1x^1 1x^0 | 231
+// a^82 | 011010011 | 0x^8 1x^7 1x^6 0x^5 1x^4 0x^3 0x^2 1x^1 1x^0 | 211
+// a^83 | 010111011 | 0x^8 1x^7 0x^6 1x^5 1x^4 1x^3 0x^2 1x^1 1x^0 | 187
+// a^84 | 001101011 | 0x^8 0x^7 1x^6 1x^5 0x^4 1x^3 0x^2 1x^1 1x^0 | 107
+// a^85 | 011010110 | 0x^8 1x^7 1x^6 0x^5 1x^4 0x^3 1x^2 1x^1 0x^0 | 214
+// a^86 | 010110001 | 0x^8 1x^7 0x^6 1x^5 1x^4 0x^3 0x^2 0x^1 1x^0 | 177
+// a^87 | 001111111 | 0x^8 0x^7 1x^6 1x^5 1x^4 1x^3 1x^2 1x^1 1x^0 | 127
+// a^88 | 011111110 | 0x^8 1x^7 1x^6 1x^5 1x^4 1x^3 1x^2 1x^1 0x^0 | 254
+// a^89 | 011100001 | 0x^8 1x^7 1x^6 1x^5 0x^4 0x^3 0x^2 0x^1 1x^0 | 225
+// a^90 | 011011111 | 0x^8 1x^7 1x^6 0x^5 1x^4 1x^3 1x^2 1x^1 1x^0 | 223
+// a^91 | 010100011 | 0x^8 1x^7 0x^6 1x^5 0x^4 0x^3 0x^2 1x^1 1x^0 | 163
+// a^92 | 001011011 | 0x^8 0x^7 1x^6 0x^5 1x^4 1x^3 0x^2 1x^1 1x^0 | 91
+// a^93 | 010110110 | 0x^8 1x^7 0x^6 1x^5 1x^4 0x^3 1x^2 1x^1 0x^0 | 182
+// a^94 | 001110001 | 0x^8 0x^7 1x^6 1x^5 1x^4 0x^3 0x^2 0x^1 1x^0 | 113
+// a^95 | 011100010 | 0x^8 1x^7 1x^6 1x^5 0x^4 0x^3 0x^2 1x^1 0x^0 | 226
+// a^96 | 011011001 | 0x^8 1x^7 1x^6 0x^5 1x^4 1x^3 0x^2 0x^1 1x^0 | 217
+// a^97 | 010101111 | 0x^8 1x^7 0x^6 1x^5 0x^4 1x^3 1x^2 1x^1 1x^0 | 175
+// a^98 | 001000011 | 0x^8 0x^7 1x^6 0x^5 0x^4 0x^3 0x^2 1x^1 1x^0 | 67
+// a^99 | 010000110 | 0x^8 1x^7 0x^6 0x^5 0x^4 0x^3 1x^2 1x^1 0x^0 | 134
+// a^100 | 000010001 | 0x^8 0x^7 0x^6 0x^5 1x^4 0x^3 0x^2 0x^1 1x^0 | 17
+// a^101 | 000100010 | 0x^8 0x^7 0x^6 1x^5 0x^4 0x^3 0x^2 1x^1 0x^0 | 34
+// a^102 | 001000100 | 0x^8 0x^7 1x^6 0x^5 0x^4 0x^3 1x^2 0x^1 0x^0 | 68
+// a^103 | 010001000 | 0x^8 1x^7 0x^6 0x^5 0x^4 1x^3 0x^2 0x^1 0x^0 | 136
+// a^104 | 000001101 | 0x^8 0x^7 0x^6 0x^5 0x^4 1x^3 1x^2 0x^1 1x^0 | 13
+// a^105 | 000011010 | 0x^8 0x^7 0x^6 0x^5 1x^4 1x^3 0x^2 1x^1 0x^0 | 26
+// a^106 | 000110100 | 0x^8 0x^7 0x^6 1x^5 1x^4 0x^3 1x^2 0x^1 0x^0 | 52
+// a^107 | 001101000 | 0x^8 0x^7 1x^6 1x^5 0x^4 1x^3 0x^2 0x^1 0x^0 | 104
+// a^108 | 011010000 | 0x^8 1x^7 1x^6 0x^5 1x^4 0x^3 0x^2 0x^1 0x^0 | 208
+// a^109 | 010111101 | 0x^8 1x^7 0x^6 1x^5 1x^4 1x^3 1x^2 0x^1 1x^0 | 189
+// a^110 | 001100111 | 0x^8 0x^7 1x^6 1x^5 0x^4 0x^3 1x^2 1x^1 1x^0 | 103
+// a^111 | 011001110 | 0x^8 1x^7 1x^6 0x^5 0x^4 1x^3 1x^2 1x^1 0x^0 | 206
+// a^112 | 010000001 | 0x^8 1x^7 0x^6 0x^5 0x^4 0x^3 0x^2 0x^1 1x^0 | 129
+// a^113 | 000011111 | 0x^8 0x^7 0x^6 0x^5 1x^4 1x^3 1x^2 1x^1 1x^0 | 31
+// a^114 | 000111110 | 0x^8 0x^7 0x^6 1x^5 1x^4 1x^3 1x^2 1x^1 0x^0 | 62
+// a^115 | 001111100 | 0x^8 0x^7 1x^6 1x^5 1x^4 1x^3 1x^2 0x^1 0x^0 | 124
+// a^116 | 011111000 | 0x^8 1x^7 1x^6 1x^5 1x^4 1x^3 0x^2 0x^1 0x^0 | 248
+// a^117 | 011101101 | 0x^8 1x^7 1x^6 1x^5 0x^4 1x^3 1x^2 0x^1 1x^0 | 237
+// a^118 | 011000111 | 0x^8 1x^7 1x^6 0x^5 0x^4 0x^3 1x^2 1x^1 1x^0 | 199
+// a^119 | 010010011 | 0x^8 1x^7 0x^6 0x^5 1x^4 0x^3 0x^2 1x^1 1x^0 | 147
+// a^120 | 000111011 | 0x^8 0x^7 0x^6 1x^5 1x^4 1x^3 0x^2 1x^1 1x^0 | 59
+// a^121 | 001110110 | 0x^8 0x^7 1x^6 1x^5 1x^4 0x^3 1x^2 1x^1 0x^0 | 118
+// a^122 | 011101100 | 0x^8 1x^7 1x^6 1x^5 0x^4 1x^3 1x^2 0x^1 0x^0 | 236
+// a^123 | 011000101 | 0x^8 1x^7 1x^6 0x^5 0x^4 0x^3 1x^2 0x^1 1x^0 | 197
+// a^124 | 010010111 | 0x^8 1x^7 0x^6 0x^5 1x^4 0x^3 1x^2 1x^1 1x^0 | 151
+// a^125 | 000110011 | 0x^8 0x^7 0x^6 1x^5 1x^4 0x^3 0x^2 1x^1 1x^0 | 51
+// a^126 | 001100110 | 0x^8 0x^7 1x^6 1x^5 0x^4 0x^3 1x^2 1x^1 0x^0 | 102
+// a^127 | 011001100 | 0x^8 1x^7 1x^6 0x^5 0x^4 1x^3 1x^2 0x^1 0x^0 | 204
+// a^128 | 010000101 | 0x^8 1x^7 0x^6 0x^5 0x^4 0x^3 1x^2 0x^1 1x^0 | 133
+// a^129 | 000010111 | 0x^8 0x^7 0x^6 0x^5 1x^4 0x^3 1x^2 1x^1 1x^0 | 23
+// a^130 | 000101110 | 0x^8 0x^7 0x^6 1x^5 0x^4 1x^3 1x^2 1x^1 0x^0 | 46
+// a^131 | 001011100 | 0x^8 0x^7 1x^6 0x^5 1x^4 1x^3 1x^2 0x^1 0x^0 | 92
+// a^132 | 010111000 | 0x^8 1x^7 0x^6 1x^5 1x^4 1x^3 0x^2 0x^1 0x^0 | 184
+// a^133 | 001101101 | 0x^8 0x^7 1x^6 1x^5 0x^4 1x^3 1x^2 0x^1 1x^0 | 109
+// a^134 | 011011010 | 0x^8 1x^7 1x^6 0x^5 1x^4 1x^3 0x^2 1x^1 0x^0 | 218
+// a^135 | 010101001 | 0x^8 1x^7 0x^6 1x^5 0x^4 1x^3 0x^2 0x^1 1x^0 | 169
+// a^136 | 001001111 | 0x^8 0x^7 1x^6 0x^5 0x^4 1x^3 1x^2 1x^1 1x^0 | 79
+// a^137 | 010011110 | 0x^8 1x^7 0x^6 0x^5 1x^4 1x^3 1x^2 1x^1 0x^0 | 158
+// a^138 | 000100001 | 0x^8 0x^7 0x^6 1x^5 0x^4 0x^3 0x^2 0x^1 1x^0 | 33
+// a^139 | 001000010 | 0x^8 0x^7 1x^6 0x^5 0x^4 0x^3 0x^2 1x^1 0x^0 | 66
+// a^140 | 010000100 | 0x^8 1x^7 0x^6 0x^5 0x^4 0x^3 1x^2 0x^1 0x^0 | 132
+// a^141 | 000010101 | 0x^8 0x^7 0x^6 0x^5 1x^4 0x^3 1x^2 0x^1 1x^0 | 21
+// a^142 | 000101010 | 0x^8 0x^7 0x^6 1x^5 0x^4 1x^3 0x^2 1x^1 0x^0 | 42
+// a^143 | 001010100 | 0x^8 0x^7 1x^6 0x^5 1x^4 0x^3 1x^2 0x^1 0x^0 | 84
+// a^144 | 010101000 | 0x^8 1x^7 0x^6 1x^5 0x^4 1x^3 0x^2 0x^1 0x^0 | 168
+// a^145 | 001001101 | 0x^8 0x^7 1x^6 0x^5 0x^4 1x^3 1x^2 0x^1 1x^0 | 77
+// a^146 | 010011010 | 0x^8 1x^7 0x^6 0x^5 1x^4 1x^3 0x^2 1x^1 0x^0 | 154
+// a^147 | 000101001 | 0x^8 0x^7 0x^6 1x^5 0x^4 1x^3 0x^2 0x^1 1x^0 | 41
+// a^148 | 001010010 | 0x^8 0x^7 1x^6 0x^5 1x^4 0x^3 0x^2 1x^1 0x^0 | 82
+// a^149 | 010100100 | 0x^8 1x^7 0x^6 1x^5 0x^4 0x^3 1x^2 0x^1 0x^0 | 164
+// a^150 | 001010101 | 0x^8 0x^7 1x^6 0x^5 1x^4 0x^3 1x^2 0x^1 1x^0 | 85
+// a^151 | 010101010 | 0x^8 1x^7 0x^6 1x^5 0x^4 1x^3 0x^2 1x^1 0x^0 | 170
+// a^152 | 001001001 | 0x^8 0x^7 1x^6 0x^5 0x^4 1x^3 0x^2 0x^1 1x^0 | 73
+// a^153 | 010010010 | 0x^8 1x^7 0x^6 0x^5 1x^4 0x^3 0x^2 1x^1 0x^0 | 146
+// a^154 | 000111001 | 0x^8 0x^7 0x^6 1x^5 1x^4 1x^3 0x^2 0x^1 1x^0 | 57
+// a^155 | 001110010 | 0x^8 0x^7 1x^6 1x^5 1x^4 0x^3 0x^2 1x^1 0x^0 | 114
+// a^156 | 011100100 | 0x^8 1x^7 1x^6 1x^5 0x^4 0x^3 1x^2 0x^1 0x^0 | 228
+// a^157 | 011010101 | 0x^8 1x^7 1x^6 0x^5 1x^4 0x^3 1x^2 0x^1 1x^0 | 213
+// a^158 | 010110111 | 0x^8 1x^7 0x^6 1x^5 1x^4 0x^3 1x^2 1x^1 1x^0 | 183
+// a^159 | 001110011 | 0x^8 0x^7 1x^6 1x^5 1x^4 0x^3 0x^2 1x^1 1x^0 | 115
+// a^160 | 011100110 | 0x^8 1x^7 1x^6 1x^5 0x^4 0x^3 1x^2 1x^1 0x^0 | 230
+// a^161 | 011010001 | 0x^8 1x^7 1x^6 0x^5 1x^4 0x^3 0x^2 0x^1 1x^0 | 209
+// a^162 | 010111111 | 0x^8 1x^7 0x^6 1x^5 1x^4 1x^3 1x^2 1x^1 1x^0 | 191
+// a^163 | 001100011 | 0x^8 0x^7 1x^6 1x^5 0x^4 0x^3 0x^2 1x^1 1x^0 | 99
+// a^164 | 011000110 | 0x^8 1x^7 1x^6 0x^5 0x^4 0x^3 1x^2 1x^1 0x^0 | 198
+// a^165 | 010010001 | 0x^8 1x^7 0x^6 0x^5 1x^4 0x^3 0x^2 0x^1 1x^0 | 145
+// a^166 | 000111111 | 0x^8 0x^7 0x^6 1x^5 1x^4 1x^3 1x^2 1x^1 1x^0 | 63
+// a^167 | 001111110 | 0x^8 0x^7 1x^6 1x^5 1x^4 1x^3 1x^2 1x^1 0x^0 | 126
+// a^168 | 011111100 | 0x^8 1x^7 1x^6 1x^5 1x^4 1x^3 1x^2 0x^1 0x^0 | 252
+// a^169 | 011100101 | 0x^8 1x^7 1x^6 1x^5 0x^4 0x^3 1x^2 0x^1 1x^0 | 229
+// a^170 | 011010111 | 0x^8 1x^7 1x^6 0x^5 1x^4 0x^3 1x^2 1x^1 1x^0 | 215
+// a^171 | 010110011 | 0x^8 1x^7 0x^6 1x^5 1x^4 0x^3 0x^2 1x^1 1x^0 | 179
+// a^172 | 001111011 | 0x^8 0x^7 1x^6 1x^5 1x^4 1x^3 0x^2 1x^1 1x^0 | 123
+// a^173 | 011110110 | 0x^8 1x^7 1x^6 1x^5 1x^4 0x^3 1x^2 1x^1 0x^0 | 246
+// a^174 | 011110001 | 0x^8 1x^7 1x^6 1x^5 1x^4 0x^3 0x^2 0x^1 1x^0 | 241
+// a^175 | 011111111 | 0x^8 1x^7 1x^6 1x^5 1x^4 1x^3 1x^2 1x^1 1x^0 | 255
+// a^176 | 011100011 | 0x^8 1x^7 1x^6 1x^5 0x^4 0x^3 0x^2 1x^1 1x^0 | 227
+// a^177 | 011011011 | 0x^8 1x^7 1x^6 0x^5 1x^4 1x^3 0x^2 1x^1 1x^0 | 219
+// a^178 | 010101011 | 0x^8 1x^7 0x^6 1x^5 0x^4 1x^3 0x^2 1x^1 1x^0 | 171
+// a^179 | 001001011 | 0x^8 0x^7 1x^6 0x^5 0x^4 1x^3 0x^2 1x^1 1x^0 | 75
+// a^180 | 010010110 | 0x^8 1x^7 0x^6 0x^5 1x^4 0x^3 1x^2 1x^1 0x^0 | 150
+// a^181 | 000110001 | 0x^8 0x^7 0x^6 1x^5 1x^4 0x^3 0x^2 0x^1 1x^0 | 49
+// a^182 | 001100010 | 0x^8 0x^7 1x^6 1x^5 0x^4 0x^3 0x^2 1x^1 0x^0 | 98
+// a^183 | 011000100 | 0x^8 1x^7 1x^6 0x^5 0x^4 0x^3 1x^2 0x^1 0x^0 | 196
+// a^184 | 010010101 | 0x^8 1x^7 0x^6 0x^5 1x^4 0x^3 1x^2 0x^1 1x^0 | 149
+// a^185 | 000110111 | 0x^8 0x^7 0x^6 1x^5 1x^4 0x^3 1x^2 1x^1 1x^0 | 55
+// a^186 | 001101110 | 0x^8 0x^7 1x^6 1x^5 0x^4 1x^3 1x^2 1x^1 0x^0 | 110
+// a^187 | 011011100 | 0x^8 1x^7 1x^6 0x^5 1x^4 1x^3 1x^2 0x^1 0x^0 | 220
+// a^188 | 010100101 | 0x^8 1x^7 0x^6 1x^5 0x^4 0x^3 1x^2 0x^1 1x^0 | 165
+// a^189 | 001010111 | 0x^8 0x^7 1x^6 0x^5 1x^4 0x^3 1x^2 1x^1 1x^0 | 87
+// a^190 | 010101110 | 0x^8 1x^7 0x^6 1x^5 0x^4 1x^3 1x^2 1x^1 0x^0 | 174
+// a^191 | 001000001 | 0x^8 0x^7 1x^6 0x^5 0x^4 0x^3 0x^2 0x^1 1x^0 | 65
+// a^192 | 010000010 | 0x^8 1x^7 0x^6 0x^5 0x^4 0x^3 0x^2 1x^1 0x^0 | 130
+// a^193 | 000011001 | 0x^8 0x^7 0x^6 0x^5 1x^4 1x^3 0x^2 0x^1 1x^0 | 25
+// a^194 | 000110010 | 0x^8 0x^7 0x^6 1x^5 1x^4 0x^3 0x^2 1x^1 0x^0 | 50
+// a^195 | 001100100 | 0x^8 0x^7 1x^6 1x^5 0x^4 0x^3 1x^2 0x^1 0x^0 | 100
+// a^196 | 011001000 | 0x^8 1x^7 1x^6 0x^5 0x^4 1x^3 0x^2 0x^1 0x^0 | 200
+// a^197 | 010001101 | 0x^8 1x^7 0x^6 0x^5 0x^4 1x^3 1x^2 0x^1 1x^0 | 141
+// a^198 | 000000111 | 0x^8 0x^7 0x^6 0x^5 0x^4 0x^3 1x^2 1x^1 1x^0 | 7
+// a^199 | 000001110 | 0x^8 0x^7 0x^6 0x^5 0x^4 1x^3 1x^2 1x^1 0x^0 | 14
+// a^200 | 000011100 | 0x^8 0x^7 0x^6 0x^5 1x^4 1x^3 1x^2 0x^1 0x^0 | 28
+// a^201 | 000111000 | 0x^8 0x^7 0x^6 1x^5 1x^4 1x^3 0x^2 0x^1 0x^0 | 56
+// a^202 | 001110000 | 0x^8 0x^7 1x^6 1x^5 1x^4 0x^3 0x^2 0x^1 0x^0 | 112
+// a^203 | 011100000 | 0x^8 1x^7 1x^6 1x^5 0x^4 0x^3 0x^2 0x^1 0x^0 | 224
+// a^204 | 011011101 | 0x^8 1x^7 1x^6 0x^5 1x^4 1x^3 1x^2 0x^1 1x^0 | 221
+// a^205 | 010100111 | 0x^8 1x^7 0x^6 1x^5 0x^4 0x^3 1x^2 1x^1 1x^0 | 167
+// a^206 | 001010011 | 0x^8 0x^7 1x^6 0x^5 1x^4 0x^3 0x^2 1x^1 1x^0 | 83
+// a^207 | 010100110 | 0x^8 1x^7 0x^6 1x^5 0x^4 0x^3 1x^2 1x^1 0x^0 | 166
+// a^208 | 001010001 | 0x^8 0x^7 1x^6 0x^5 1x^4 0x^3 0x^2 0x^1 1x^0 | 81
+// a^209 | 010100010 | 0x^8 1x^7 0x^6 1x^5 0x^4 0x^3 0x^2 1x^1 0x^0 | 162
+// a^210 | 001011001 | 0x^8 0x^7 1x^6 0x^5 1x^4 1x^3 0x^2 0x^1 1x^0 | 89
+// a^211 | 010110010 | 0x^8 1x^7 0x^6 1x^5 1x^4 0x^3 0x^2 1x^1 0x^0 | 178
+// a^212 | 001111001 | 0x^8 0x^7 1x^6 1x^5 1x^4 1x^3 0x^2 0x^1 1x^0 | 121
+// a^213 | 011110010 | 0x^8 1x^7 1x^6 1x^5 1x^4 0x^3 0x^2 1x^1 0x^0 | 242
+// a^214 | 011111001 | 0x^8 1x^7 1x^6 1x^5 1x^4 1x^3 0x^2 0x^1 1x^0 | 249
+// a^215 | 011101111 | 0x^8 1x^7 1x^6 1x^5 0x^4 1x^3 1x^2 1x^1 1x^0 | 239
+// a^216 | 011000011 | 0x^8 1x^7 1x^6 0x^5 0x^4 0x^3 0x^2 1x^1 1x^0 | 195
+// a^217 | 010011011 | 0x^8 1x^7 0x^6 0x^5 1x^4 1x^3 0x^2 1x^1 1x^0 | 155
+// a^218 | 000101011 | 0x^8 0x^7 0x^6 1x^5 0x^4 1x^3 0x^2 1x^1 1x^0 | 43
+// a^219 | 001010110 | 0x^8 0x^7 1x^6 0x^5 1x^4 0x^3 1x^2 1x^1 0x^0 | 86
+// a^220 | 010101100 | 0x^8 1x^7 0x^6 1x^5 0x^4 1x^3 1x^2 0x^1 0x^0 | 172
+// a^221 | 001000101 | 0x^8 0x^7 1x^6 0x^5 0x^4 0x^3 1x^2 0x^1 1x^0 | 69
+// a^222 | 010001010 | 0x^8 1x^7 0x^6 0x^5 0x^4 1x^3 0x^2 1x^1 0x^0 | 138
+// a^223 | 000001001 | 0x^8 0x^7 0x^6 0x^5 0x^4 1x^3 0x^2 0x^1 1x^0 | 9
+// a^224 | 000010010 | 0x^8 0x^7 0x^6 0x^5 1x^4 0x^3 0x^2 1x^1 0x^0 | 18
+// a^225 | 000100100 | 0x^8 0x^7 0x^6 1x^5 0x^4 0x^3 1x^2 0x^1 0x^0 | 36
+// a^226 | 001001000 | 0x^8 0x^7 1x^6 0x^5 0x^4 1x^3 0x^2 0x^1 0x^0 | 72
+// a^227 | 010010000 | 0x^8 1x^7 0x^6 0x^5 1x^4 0x^3 0x^2 0x^1 0x^0 | 144
+// a^228 | 000111101 | 0x^8 0x^7 0x^6 1x^5 1x^4 1x^3 1x^2 0x^1 1x^0 | 61
+// a^229 | 001111010 | 0x^8 0x^7 1x^6 1x^5 1x^4 1x^3 0x^2 1x^1 0x^0 | 122
+// a^230 | 011110100 | 0x^8 1x^7 1x^6 1x^5 1x^4 0x^3 1x^2 0x^1 0x^0 | 244
+// a^231 | 011110101 | 0x^8 1x^7 1x^6 1x^5 1x^4 0x^3 1x^2 0x^1 1x^0 | 245
+// a^232 | 011110111 | 0x^8 1x^7 1x^6 1x^5 1x^4 0x^3 1x^2 1x^1 1x^0 | 247
+// a^233 | 011110011 | 0x^8 1x^7 1x^6 1x^5 1x^4 0x^3 0x^2 1x^1 1x^0 | 243
+// a^234 | 011111011 | 0x^8 1x^7 1x^6 1x^5 1x^4 1x^3 0x^2 1x^1 1x^0 | 251
+// a^235 | 011101011 | 0x^8 1x^7 1x^6 1x^5 0x^4 1x^3 0x^2 1x^1 1x^0 | 235
+// a^236 | 011001011 | 0x^8 1x^7 1x^6 0x^5 0x^4 1x^3 0x^2 1x^1 1x^0 | 203
+// a^237 | 010001011 | 0x^8 1x^7 0x^6 0x^5 0x^4 1x^3 0x^2 1x^1 1x^0 | 139
+// a^238 | 000001011 | 0x^8 0x^7 0x^6 0x^5 0x^4 1x^3 0x^2 1x^1 1x^0 | 11
+// a^239 | 000010110 | 0x^8 0x^7 0x^6 0x^5 1x^4 0x^3 1x^2 1x^1 0x^0 | 22
+// a^240 | 000101100 | 0x^8 0x^7 0x^6 1x^5 0x^4 1x^3 1x^2 0x^1 0x^0 | 44
+// a^241 | 001011000 | 0x^8 0x^7 1x^6 0x^5 1x^4 1x^3 0x^2 0x^1 0x^0 | 88
+// a^242 | 010110000 | 0x^8 1x^7 0x^6 1x^5 1x^4 0x^3 0x^2 0x^1 0x^0 | 176
+// a^243 | 001111101 | 0x^8 0x^7 1x^6 1x^5 1x^4 1x^3 1x^2 0x^1 1x^0 | 125
+// a^244 | 011111010 | 0x^8 1x^7 1x^6 1x^5 1x^4 1x^3 0x^2 1x^1 0x^0 | 250
+// a^245 | 011101001 | 0x^8 1x^7 1x^6 1x^5 0x^4 1x^3 0x^2 0x^1 1x^0 | 233
+// a^246 | 011001111 | 0x^8 1x^7 1x^6 0x^5 0x^4 1x^3 1x^2 1x^1 1x^0 | 207
+// a^247 | 010000011 | 0x^8 1x^7 0x^6 0x^5 0x^4 0x^3 0x^2 1x^1 1x^0 | 131
+// a^248 | 000011011 | 0x^8 0x^7 0x^6 0x^5 1x^4 1x^3 0x^2 1x^1 1x^0 | 27
+// a^249 | 000110110 | 0x^8 0x^7 0x^6 1x^5 1x^4 0x^3 1x^2 1x^1 0x^0 | 54
+// a^250 | 001101100 | 0x^8 0x^7 1x^6 1x^5 0x^4 1x^3 1x^2 0x^1 0x^0 | 108
+// a^251 | 011011000 | 0x^8 1x^7 1x^6 0x^5 1x^4 1x^3 0x^2 0x^1 0x^0 | 216
+// a^252 | 010101101 | 0x^8 1x^7 0x^6 1x^5 0x^4 1x^3 1x^2 0x^1 1x^0 | 173
+// a^253 | 001000111 | 0x^8 0x^7 1x^6 0x^5 0x^4 0x^3 1x^2 1x^1 1x^0 | 71
+// a^254 | 010001110 | 0x^8 1x^7 0x^6 0x^5 0x^4 1x^3 1x^2 1x^1 0x^0 | 142
+// a^255 | 000000001 | 0x^8 0x^7 0x^6 0x^5 0x^4 0x^3 0x^2 0x^1 1x^0 | 1
diff --git a/vendor/github.com/skip2/go-qrcode/reedsolomon/gf_poly.go b/vendor/github.com/skip2/go-qrcode/reedsolomon/gf_poly.go
new file mode 100644
index 00000000..962f5454
--- /dev/null
+++ b/vendor/github.com/skip2/go-qrcode/reedsolomon/gf_poly.go
@@ -0,0 +1,216 @@
+// go-qrcode
+// Copyright 2014 Tom Harwood
+
+package reedsolomon
+
+import (
+ "fmt"
+ "log"
+
+ bitset "github.com/skip2/go-qrcode/bitset"
+)
+
+// gfPoly is a polynomial over GF(2^8).
+type gfPoly struct {
+ // The ith value is the coefficient of the ith degree of x.
+ // term[0]*(x^0) + term[1]*(x^1) + term[2]*(x^2) ...
+ term []gfElement
+}
+
+// newGFPolyFromData returns |data| as a polynomial over GF(2^8).
+//
+// Each data byte becomes the coefficient of an x term.
+//
+// For an n byte input the polynomial is:
+// data[n-1]*(x^n-1) + data[n-2]*(x^n-2) ... + data[0]*(x^0).
+func newGFPolyFromData(data *bitset.Bitset) gfPoly {
+ numTotalBytes := data.Len() / 8
+ if data.Len()%8 != 0 {
+ numTotalBytes++
+ }
+
+ result := gfPoly{term: make([]gfElement, numTotalBytes)}
+
+ i := numTotalBytes - 1
+ for j := 0; j < data.Len(); j += 8 {
+ result.term[i] = gfElement(data.ByteAt(j))
+ i--
+ }
+
+ return result
+}
+
+// newGFPolyMonomial returns term*(x^degree).
+func newGFPolyMonomial(term gfElement, degree int) gfPoly {
+ if term == gfZero {
+ return gfPoly{}
+ }
+
+ result := gfPoly{term: make([]gfElement, degree+1)}
+ result.term[degree] = term
+
+ return result
+}
+
+func (e gfPoly) data(numTerms int) []byte {
+ result := make([]byte, numTerms)
+
+ i := numTerms - len(e.term)
+ for j := len(e.term) - 1; j >= 0; j-- {
+ result[i] = byte(e.term[j])
+ i++
+ }
+
+ return result
+}
+
+// numTerms returns the number of
+func (e gfPoly) numTerms() int {
+ return len(e.term)
+}
+
+// gfPolyMultiply returns a * b.
+func gfPolyMultiply(a, b gfPoly) gfPoly {
+ numATerms := a.numTerms()
+ numBTerms := b.numTerms()
+
+ result := gfPoly{term: make([]gfElement, numATerms+numBTerms)}
+
+ for i := 0; i < numATerms; i++ {
+ for j := 0; j < numBTerms; j++ {
+ if a.term[i] != 0 && b.term[j] != 0 {
+ monomial := gfPoly{term: make([]gfElement, i+j+1)}
+ monomial.term[i+j] = gfMultiply(a.term[i], b.term[j])
+
+ result = gfPolyAdd(result, monomial)
+ }
+ }
+ }
+
+ return result.normalised()
+}
+
+// gfPolyRemainder return the remainder of numerator / denominator.
+func gfPolyRemainder(numerator, denominator gfPoly) gfPoly {
+ if denominator.equals(gfPoly{}) {
+ log.Panicln("Remainder by zero")
+ }
+
+ remainder := numerator
+
+ for remainder.numTerms() >= denominator.numTerms() {
+ degree := remainder.numTerms() - denominator.numTerms()
+ coefficient := gfDivide(remainder.term[remainder.numTerms()-1],
+ denominator.term[denominator.numTerms()-1])
+
+ divisor := gfPolyMultiply(denominator,
+ newGFPolyMonomial(coefficient, degree))
+
+ remainder = gfPolyAdd(remainder, divisor)
+ }
+
+ return remainder.normalised()
+}
+
+// gfPolyAdd returns a + b.
+func gfPolyAdd(a, b gfPoly) gfPoly {
+ numATerms := a.numTerms()
+ numBTerms := b.numTerms()
+
+ numTerms := numATerms
+ if numBTerms > numTerms {
+ numTerms = numBTerms
+ }
+
+ result := gfPoly{term: make([]gfElement, numTerms)}
+
+ for i := 0; i < numTerms; i++ {
+ switch {
+ case numATerms > i && numBTerms > i:
+ result.term[i] = gfAdd(a.term[i], b.term[i])
+ case numATerms > i:
+ result.term[i] = a.term[i]
+ default:
+ result.term[i] = b.term[i]
+ }
+ }
+
+ return result.normalised()
+}
+
+func (e gfPoly) normalised() gfPoly {
+ numTerms := e.numTerms()
+ maxNonzeroTerm := numTerms - 1
+
+ for i := numTerms - 1; i >= 0; i-- {
+ if e.term[i] != 0 {
+ break
+ }
+
+ maxNonzeroTerm = i - 1
+ }
+
+ if maxNonzeroTerm < 0 {
+ return gfPoly{}
+ } else if maxNonzeroTerm < numTerms-1 {
+ e.term = e.term[0 : maxNonzeroTerm+1]
+ }
+
+ return e
+}
+
+func (e gfPoly) string(useIndexForm bool) string {
+ var str string
+ numTerms := e.numTerms()
+
+ for i := numTerms - 1; i >= 0; i-- {
+ if e.term[i] > 0 {
+ if len(str) > 0 {
+ str += " + "
+ }
+
+ if !useIndexForm {
+ str += fmt.Sprintf("%dx^%d", e.term[i], i)
+ } else {
+ str += fmt.Sprintf("a^%dx^%d", gfLogTable[e.term[i]], i)
+ }
+ }
+ }
+
+ if len(str) == 0 {
+ str = "0"
+ }
+
+ return str
+}
+
+// equals returns true if e == other.
+func (e gfPoly) equals(other gfPoly) bool {
+ var minecPoly *gfPoly
+ var maxecPoly *gfPoly
+
+ if e.numTerms() > other.numTerms() {
+ minecPoly = &other
+ maxecPoly = &e
+ } else {
+ minecPoly = &e
+ maxecPoly = &other
+ }
+
+ numMinTerms := minecPoly.numTerms()
+ numMaxTerms := maxecPoly.numTerms()
+
+ for i := 0; i < numMinTerms; i++ {
+ if e.term[i] != other.term[i] {
+ return false
+ }
+ }
+
+ for i := numMinTerms; i < numMaxTerms; i++ {
+ if maxecPoly.term[i] != 0 {
+ return false
+ }
+ }
+
+ return true
+}
diff --git a/vendor/github.com/skip2/go-qrcode/reedsolomon/reed_solomon.go b/vendor/github.com/skip2/go-qrcode/reedsolomon/reed_solomon.go
new file mode 100644
index 00000000..561697b4
--- /dev/null
+++ b/vendor/github.com/skip2/go-qrcode/reedsolomon/reed_solomon.go
@@ -0,0 +1,73 @@
+// go-qrcode
+// Copyright 2014 Tom Harwood
+
+// Package reedsolomon provides error correction encoding for QR Code 2005.
+//
+// QR Code 2005 uses a Reed-Solomon error correcting code to detect and correct
+// errors encountered during decoding.
+//
+// The generated RS codes are systematic, and consist of the input data with
+// error correction bytes appended.
+package reedsolomon
+
+import (
+ "log"
+
+ bitset "github.com/skip2/go-qrcode/bitset"
+)
+
+// Encode data for QR Code 2005 using the appropriate Reed-Solomon code.
+//
+// numECBytes is the number of error correction bytes to append, and is
+// determined by the target QR Code's version and error correction level.
+//
+// ISO/IEC 18004 table 9 specifies the numECBytes required. e.g. a 1-L code has
+// numECBytes=7.
+func Encode(data *bitset.Bitset, numECBytes int) *bitset.Bitset {
+ // Create a polynomial representing |data|.
+ //
+ // The bytes are interpreted as the sequence of coefficients of a polynomial.
+ // The last byte's value becomes the x^0 coefficient, the second to last
+ // becomes the x^1 coefficient and so on.
+ ecpoly := newGFPolyFromData(data)
+ ecpoly = gfPolyMultiply(ecpoly, newGFPolyMonomial(gfOne, numECBytes))
+
+ // Pick the generator polynomial.
+ generator := rsGeneratorPoly(numECBytes)
+
+ // Generate the error correction bytes.
+ remainder := gfPolyRemainder(ecpoly, generator)
+
+ // Combine the data & error correcting bytes.
+ // The mathematically correct answer is:
+ //
+ // result := gfPolyAdd(ecpoly, remainder).
+ //
+ // The encoding used by QR Code 2005 is slightly different this result: To
+ // preserve the original |data| bit sequence exactly, the data and remainder
+ // are combined manually below. This ensures any most significant zero bits
+ // are preserved (and not optimised away).
+ result := bitset.Clone(data)
+ result.AppendBytes(remainder.data(numECBytes))
+
+ return result
+}
+
+// rsGeneratorPoly returns the Reed-Solomon generator polynomial with |degree|.
+//
+// The generator polynomial is calculated as:
+// (x + a^0)(x + a^1)...(x + a^degree-1)
+func rsGeneratorPoly(degree int) gfPoly {
+ if degree < 2 {
+ log.Panic("degree < 2")
+ }
+
+ generator := gfPoly{term: []gfElement{1}}
+
+ for i := 0; i < degree; i++ {
+ nextPoly := gfPoly{term: []gfElement{gfExpTable[i], 1}}
+ generator = gfPolyMultiply(generator, nextPoly)
+ }
+
+ return generator
+}
diff --git a/vendor/github.com/skip2/go-qrcode/regular_symbol.go b/vendor/github.com/skip2/go-qrcode/regular_symbol.go
new file mode 100644
index 00000000..134be18e
--- /dev/null
+++ b/vendor/github.com/skip2/go-qrcode/regular_symbol.go
@@ -0,0 +1,309 @@
+// go-qrcode
+// Copyright 2014 Tom Harwood
+
+package qrcode
+
+import (
+ bitset "github.com/skip2/go-qrcode/bitset"
+)
+
+type regularSymbol struct {
+ version qrCodeVersion
+ mask int
+
+ data *bitset.Bitset
+
+ symbol *symbol
+ size int
+}
+
+// Abbreviated true/false.
+const (
+ b0 = false
+ b1 = true
+)
+
+var (
+ alignmentPatternCenter = [][]int{
+ {}, // Version 0 doesn't exist.
+ {}, // Version 1 doesn't use alignment patterns.
+ {6, 18},
+ {6, 22},
+ {6, 26},
+ {6, 30},
+ {6, 34},
+ {6, 22, 38},
+ {6, 24, 42},
+ {6, 26, 46},
+ {6, 28, 50},
+ {6, 30, 54},
+ {6, 32, 58},
+ {6, 34, 62},
+ {6, 26, 46, 66},
+ {6, 26, 48, 70},
+ {6, 26, 50, 74},
+ {6, 30, 54, 78},
+ {6, 30, 56, 82},
+ {6, 30, 58, 86},
+ {6, 34, 62, 90},
+ {6, 28, 50, 72, 94},
+ {6, 26, 50, 74, 98},
+ {6, 30, 54, 78, 102},
+ {6, 28, 54, 80, 106},
+ {6, 32, 58, 84, 110},
+ {6, 30, 58, 86, 114},
+ {6, 34, 62, 90, 118},
+ {6, 26, 50, 74, 98, 122},
+ {6, 30, 54, 78, 102, 126},
+ {6, 26, 52, 78, 104, 130},
+ {6, 30, 56, 82, 108, 134},
+ {6, 34, 60, 86, 112, 138},
+ {6, 30, 58, 86, 114, 142},
+ {6, 34, 62, 90, 118, 146},
+ {6, 30, 54, 78, 102, 126, 150},
+ {6, 24, 50, 76, 102, 128, 154},
+ {6, 28, 54, 80, 106, 132, 158},
+ {6, 32, 58, 84, 110, 136, 162},
+ {6, 26, 54, 82, 110, 138, 166},
+ {6, 30, 58, 86, 114, 142, 170},
+ }
+
+ finderPattern = [][]bool{
+ {b1, b1, b1, b1, b1, b1, b1},
+ {b1, b0, b0, b0, b0, b0, b1},
+ {b1, b0, b1, b1, b1, b0, b1},
+ {b1, b0, b1, b1, b1, b0, b1},
+ {b1, b0, b1, b1, b1, b0, b1},
+ {b1, b0, b0, b0, b0, b0, b1},
+ {b1, b1, b1, b1, b1, b1, b1},
+ }
+
+ finderPatternSize = 7
+
+ finderPatternHorizontalBorder = [][]bool{
+ {b0, b0, b0, b0, b0, b0, b0, b0},
+ }
+
+ finderPatternVerticalBorder = [][]bool{
+ {b0},
+ {b0},
+ {b0},
+ {b0},
+ {b0},
+ {b0},
+ {b0},
+ {b0},
+ }
+
+ alignmentPattern = [][]bool{
+ {b1, b1, b1, b1, b1},
+ {b1, b0, b0, b0, b1},
+ {b1, b0, b1, b0, b1},
+ {b1, b0, b0, b0, b1},
+ {b1, b1, b1, b1, b1},
+ }
+)
+
+func buildRegularSymbol(version qrCodeVersion, mask int,
+ data *bitset.Bitset) (*symbol, error) {
+ m := &regularSymbol{
+ version: version,
+ mask: mask,
+ data: data,
+
+ symbol: newSymbol(version.symbolSize(), version.quietZoneSize()),
+ size: version.symbolSize(),
+ }
+
+ m.addFinderPatterns()
+ m.addAlignmentPatterns()
+ m.addTimingPatterns()
+ m.addFormatInfo()
+ m.addVersionInfo()
+
+ ok, err := m.addData()
+ if !ok {
+ return nil, err
+ }
+
+ return m.symbol, nil
+}
+
+func (m *regularSymbol) addFinderPatterns() {
+ fpSize := finderPatternSize
+ fp := finderPattern
+ fpHBorder := finderPatternHorizontalBorder
+ fpVBorder := finderPatternVerticalBorder
+
+ // Top left Finder Pattern.
+ m.symbol.set2dPattern(0, 0, fp)
+ m.symbol.set2dPattern(0, fpSize, fpHBorder)
+ m.symbol.set2dPattern(fpSize, 0, fpVBorder)
+
+ // Top right Finder Pattern.
+ m.symbol.set2dPattern(m.size-fpSize, 0, fp)
+ m.symbol.set2dPattern(m.size-fpSize-1, fpSize, fpHBorder)
+ m.symbol.set2dPattern(m.size-fpSize-1, 0, fpVBorder)
+
+ // Bottom left Finder Pattern.
+ m.symbol.set2dPattern(0, m.size-fpSize, fp)
+ m.symbol.set2dPattern(0, m.size-fpSize-1, fpHBorder)
+ m.symbol.set2dPattern(fpSize, m.size-fpSize-1, fpVBorder)
+}
+
+func (m *regularSymbol) addAlignmentPatterns() {
+ for _, x := range alignmentPatternCenter[m.version.version] {
+ for _, y := range alignmentPatternCenter[m.version.version] {
+ if !m.symbol.empty(x, y) {
+ continue
+ }
+
+ m.symbol.set2dPattern(x-2, y-2, alignmentPattern)
+ }
+ }
+}
+
+func (m *regularSymbol) addTimingPatterns() {
+ value := true
+
+ for i := finderPatternSize + 1; i < m.size-finderPatternSize; i++ {
+ m.symbol.set(i, finderPatternSize-1, value)
+ m.symbol.set(finderPatternSize-1, i, value)
+
+ value = !value
+ }
+}
+
+func (m *regularSymbol) addFormatInfo() {
+ fpSize := finderPatternSize
+ l := formatInfoLengthBits - 1
+
+ f := m.version.formatInfo(m.mask)
+
+ // Bits 0-7, under the top right finder pattern.
+ for i := 0; i <= 7; i++ {
+ m.symbol.set(m.size-i-1, fpSize+1, f.At(l-i))
+ }
+
+ // Bits 0-5, right of the top left finder pattern.
+ for i := 0; i <= 5; i++ {
+ m.symbol.set(fpSize+1, i, f.At(l-i))
+ }
+
+ // Bits 6-8 on the corner of the top left finder pattern.
+ m.symbol.set(fpSize+1, fpSize, f.At(l-6))
+ m.symbol.set(fpSize+1, fpSize+1, f.At(l-7))
+ m.symbol.set(fpSize, fpSize+1, f.At(l-8))
+
+ // Bits 9-14 on the underside of the top left finder pattern.
+ for i := 9; i <= 14; i++ {
+ m.symbol.set(14-i, fpSize+1, f.At(l-i))
+ }
+
+ // Bits 8-14 on the right side of the bottom left finder pattern.
+ for i := 8; i <= 14; i++ {
+ m.symbol.set(fpSize+1, m.size-fpSize+i-8, f.At(l-i))
+ }
+
+ // Always dark symbol.
+ m.symbol.set(fpSize+1, m.size-fpSize-1, true)
+}
+
+func (m *regularSymbol) addVersionInfo() {
+ fpSize := finderPatternSize
+
+ v := m.version.versionInfo()
+ l := versionInfoLengthBits - 1
+
+ if v == nil {
+ return
+ }
+
+ for i := 0; i < v.Len(); i++ {
+ // Above the bottom left finder pattern.
+ m.symbol.set(i/3, m.size-fpSize-4+i%3, v.At(l-i))
+
+ // Left of the top right finder pattern.
+ m.symbol.set(m.size-fpSize-4+i%3, i/3, v.At(l-i))
+ }
+}
+
+type direction uint8
+
+const (
+ up direction = iota
+ down
+)
+
+func (m *regularSymbol) addData() (bool, error) {
+ xOffset := 1
+ dir := up
+
+ x := m.size - 2
+ y := m.size - 1
+
+ for i := 0; i < m.data.Len(); i++ {
+ var mask bool
+ switch m.mask {
+ case 0:
+ mask = (y+x+xOffset)%2 == 0
+ case 1:
+ mask = y%2 == 0
+ case 2:
+ mask = (x+xOffset)%3 == 0
+ case 3:
+ mask = (y+x+xOffset)%3 == 0
+ case 4:
+ mask = (y/2+(x+xOffset)/3)%2 == 0
+ case 5:
+ mask = (y*(x+xOffset))%2+(y*(x+xOffset))%3 == 0
+ case 6:
+ mask = ((y*(x+xOffset))%2+((y*(x+xOffset))%3))%2 == 0
+ case 7:
+ mask = ((y+x+xOffset)%2+((y*(x+xOffset))%3))%2 == 0
+ }
+
+ // != is equivalent to XOR.
+ m.symbol.set(x+xOffset, y, mask != m.data.At(i))
+
+ if i == m.data.Len()-1 {
+ break
+ }
+
+ // Find next free bit in the symbol.
+ for {
+ if xOffset == 1 {
+ xOffset = 0
+ } else {
+ xOffset = 1
+
+ if dir == up {
+ if y > 0 {
+ y--
+ } else {
+ dir = down
+ x -= 2
+ }
+ } else {
+ if y < m.size-1 {
+ y++
+ } else {
+ dir = up
+ x -= 2
+ }
+ }
+ }
+
+ // Skip over the vertical timing pattern entirely.
+ if x == 5 {
+ x--
+ }
+
+ if m.symbol.empty(x+xOffset, y) {
+ break
+ }
+ }
+ }
+
+ return true, nil
+}
diff --git a/vendor/github.com/skip2/go-qrcode/symbol.go b/vendor/github.com/skip2/go-qrcode/symbol.go
new file mode 100644
index 00000000..0cb1327c
--- /dev/null
+++ b/vendor/github.com/skip2/go-qrcode/symbol.go
@@ -0,0 +1,309 @@
+// go-qrcode
+// Copyright 2014 Tom Harwood
+
+package qrcode
+
+// symbol is a 2D array of bits representing a QR Code symbol.
+//
+// A symbol consists of size*size modules, with each module normally drawn as a
+// black or white square. The symbol also has a border of quietZoneSize modules.
+//
+// A (fictional) size=2, quietZoneSize=1 QR Code looks like:
+//
+// +----+
+// | |
+// | ab |
+// | cd |
+// | |
+// +----+
+//
+// For ease of implementation, the functions to set/get bits ignore the border,
+// so (0,0)=a, (0,1)=b, (1,0)=c, and (1,1)=d. The entire symbol (including the
+// border) is returned by bitmap().
+//
+type symbol struct {
+ // Value of module at [y][x]. True is set.
+ module [][]bool
+
+ // True if the module at [y][x] is used (to either true or false).
+ // Used to identify unused modules.
+ isUsed [][]bool
+
+ // Combined width/height of the symbol and quiet zones.
+ //
+ // size = symbolSize + 2*quietZoneSize.
+ size int
+
+ // Width/height of the symbol only.
+ symbolSize int
+
+ // Width/height of a single quiet zone.
+ quietZoneSize int
+}
+
+// newSymbol constructs a symbol of size size*size, with a border of
+// quietZoneSize.
+func newSymbol(size int, quietZoneSize int) *symbol {
+ var m symbol
+
+ m.module = make([][]bool, size+2*quietZoneSize)
+ m.isUsed = make([][]bool, size+2*quietZoneSize)
+
+ for i := range m.module {
+ m.module[i] = make([]bool, size+2*quietZoneSize)
+ m.isUsed[i] = make([]bool, size+2*quietZoneSize)
+ }
+
+ m.size = size + 2*quietZoneSize
+ m.symbolSize = size
+ m.quietZoneSize = quietZoneSize
+
+ return &m
+}
+
+// get returns the module value at (x, y).
+func (m *symbol) get(x int, y int) (v bool) {
+ v = m.module[y+m.quietZoneSize][x+m.quietZoneSize]
+ return
+}
+
+// empty returns true if the module at (x, y) has not been set (to either true
+// or false).
+func (m *symbol) empty(x int, y int) bool {
+ return !m.isUsed[y+m.quietZoneSize][x+m.quietZoneSize]
+}
+
+// numEmptyModules returns the number of empty modules.
+//
+// Initially numEmptyModules is symbolSize * symbolSize. After every module has
+// been set (to either true or false), the number of empty modules is zero.
+func (m *symbol) numEmptyModules() int {
+ var count int
+ for y := 0; y < m.symbolSize; y++ {
+ for x := 0; x < m.symbolSize; x++ {
+ if !m.isUsed[y+m.quietZoneSize][x+m.quietZoneSize] {
+ count++
+ }
+ }
+ }
+
+ return count
+}
+
+// set sets the module at (x, y) to v.
+func (m *symbol) set(x int, y int, v bool) {
+ m.module[y+m.quietZoneSize][x+m.quietZoneSize] = v
+ m.isUsed[y+m.quietZoneSize][x+m.quietZoneSize] = true
+}
+
+// set2dPattern sets a 2D array of modules, starting at (x, y).
+func (m *symbol) set2dPattern(x int, y int, v [][]bool) {
+ for j, row := range v {
+ for i, value := range row {
+ m.set(x+i, y+j, value)
+ }
+ }
+}
+
+// bitmap returns the entire symbol, including the quiet zone.
+func (m *symbol) bitmap() [][]bool {
+ module := make([][]bool, len(m.module))
+
+ for i := range m.module {
+ module[i] = m.module[i][:]
+ }
+
+ return module
+}
+
+// string returns a pictorial representation of the symbol, suitable for
+// printing in a TTY.
+func (m *symbol) string() string {
+ var result string
+
+ for _, row := range m.module {
+ for _, value := range row {
+ switch value {
+ case true:
+ result += " "
+ case false:
+ // Unicode 'FULL BLOCK' (U+2588).
+ result += "██"
+ }
+ }
+ result += "\n"
+ }
+
+ return result
+}
+
+// Constants used to weight penalty calculations. Specified by ISO/IEC
+// 18004:2006.
+const (
+ penaltyWeight1 = 3
+ penaltyWeight2 = 3
+ penaltyWeight3 = 40
+ penaltyWeight4 = 10
+)
+
+// penaltyScore returns the penalty score of the symbol. The penalty score
+// consists of the sum of the four individual penalty types.
+func (m *symbol) penaltyScore() int {
+ return m.penalty1() + m.penalty2() + m.penalty3() + m.penalty4()
+}
+
+// penalty1 returns the penalty score for "adjacent modules in row/column with
+// same colour".
+//
+// The numbers of adjacent matching modules and scores are:
+// 0-5: score = 0
+// 6+ : score = penaltyWeight1 + (numAdjacentModules - 5)
+func (m *symbol) penalty1() int {
+ penalty := 0
+
+ for x := 0; x < m.symbolSize; x++ {
+ lastValue := m.get(x, 0)
+ count := 1
+
+ for y := 1; y < m.symbolSize; y++ {
+ v := m.get(x, y)
+
+ if v != lastValue {
+ count = 1
+ lastValue = v
+ } else {
+ count++
+ if count == 6 {
+ penalty += penaltyWeight1 + 1
+ } else if count > 6 {
+ penalty++
+ }
+ }
+ }
+ }
+
+ for y := 0; y < m.symbolSize; y++ {
+ lastValue := m.get(0, y)
+ count := 1
+
+ for x := 1; x < m.symbolSize; x++ {
+ v := m.get(x, y)
+
+ if v != lastValue {
+ count = 1
+ lastValue = v
+ } else {
+ count++
+ if count == 6 {
+ penalty += penaltyWeight1 + 1
+ } else if count > 6 {
+ penalty++
+ }
+ }
+ }
+ }
+
+ return penalty
+}
+
+// penalty2 returns the penalty score for "block of modules in the same colour".
+//
+// m*n: score = penaltyWeight2 * (m-1) * (n-1).
+func (m *symbol) penalty2() int {
+ penalty := 0
+
+ for y := 1; y < m.symbolSize; y++ {
+ for x := 1; x < m.symbolSize; x++ {
+ topLeft := m.get(x-1, y-1)
+ above := m.get(x, y-1)
+ left := m.get(x-1, y)
+ current := m.get(x, y)
+
+ if current == left && current == above && current == topLeft {
+ penalty++
+ }
+ }
+ }
+
+ return penalty * penaltyWeight2
+}
+
+// penalty3 returns the penalty score for "1:1:3:1:1 ratio
+// (dark:light:dark:light:dark) pattern in row/column, preceded or followed by
+// light area 4 modules wide".
+//
+// Existence of the pattern scores penaltyWeight3.
+func (m *symbol) penalty3() int {
+ penalty := 0
+
+ for y := 0; y < m.symbolSize; y++ {
+ var bitBuffer int16 = 0x00
+
+ for x := 0; x < m.symbolSize; x++ {
+ bitBuffer <<= 1
+ if v := m.get(x, y); v {
+ bitBuffer |= 1
+ }
+
+ switch bitBuffer & 0x7ff {
+ // 0b000 0101 1101 or 0b10111010000
+ // 0x05d or 0x5d0
+ case 0x05d, 0x5d0:
+ penalty += penaltyWeight3
+ bitBuffer = 0xFF
+ default:
+ if x == m.symbolSize-1 && (bitBuffer&0x7f) == 0x5d {
+ penalty += penaltyWeight3
+ bitBuffer = 0xFF
+ }
+ }
+ }
+ }
+
+ for x := 0; x < m.symbolSize; x++ {
+ var bitBuffer int16 = 0x00
+
+ for y := 0; y < m.symbolSize; y++ {
+ bitBuffer <<= 1
+ if v := m.get(x, y); v {
+ bitBuffer |= 1
+ }
+
+ switch bitBuffer & 0x7ff {
+ // 0b000 0101 1101 or 0b10111010000
+ // 0x05d or 0x5d0
+ case 0x05d, 0x5d0:
+ penalty += penaltyWeight3
+ bitBuffer = 0xFF
+ default:
+ if y == m.symbolSize-1 && (bitBuffer&0x7f) == 0x5d {
+ penalty += penaltyWeight3
+ bitBuffer = 0xFF
+ }
+ }
+ }
+ }
+
+ return penalty
+}
+
+// penalty4 returns the penalty score...
+func (m *symbol) penalty4() int {
+ numModules := m.symbolSize * m.symbolSize
+ numDarkModules := 0
+
+ for x := 0; x < m.symbolSize; x++ {
+ for y := 0; y < m.symbolSize; y++ {
+ if v := m.get(x, y); v {
+ numDarkModules++
+ }
+ }
+ }
+
+ numDarkModuleDeviation := numModules/2 - numDarkModules
+ if numDarkModuleDeviation < 0 {
+ numDarkModuleDeviation *= -1
+ }
+
+ return penaltyWeight4 * (numDarkModuleDeviation / (numModules / 20))
+}
diff --git a/vendor/github.com/skip2/go-qrcode/version.go b/vendor/github.com/skip2/go-qrcode/version.go
new file mode 100644
index 00000000..738cf3d3
--- /dev/null
+++ b/vendor/github.com/skip2/go-qrcode/version.go
@@ -0,0 +1,3050 @@
+// go-qrcode
+// Copyright 2014 Tom Harwood
+
+package qrcode
+
+import (
+ "log"
+
+ bitset "github.com/skip2/go-qrcode/bitset"
+)
+
+// Error detection/recovery capacity.
+//
+// There are several levels of error detection/recovery capacity. Higher levels
+// of error recovery are able to correct more errors, with the trade-off of
+// increased symbol size.
+type RecoveryLevel int
+
+const (
+ // Level L: 7% error recovery.
+ Low RecoveryLevel = iota
+
+ // Level M: 15% error recovery. Good default choice.
+ Medium
+
+ // Level Q: 25% error recovery.
+ High
+
+ // Level H: 30% error recovery.
+ Highest
+)
+
+// qrCodeVersion describes the data length and encoding order of a single QR
+// Code version. There are 40 versions numbers x 4 recovery levels == 160
+// possible qrCodeVersion structures.
+type qrCodeVersion struct {
+ // Version number (1-40 inclusive).
+ version int
+
+ // Error recovery level.
+ level RecoveryLevel
+
+ dataEncoderType dataEncoderType
+
+ // Encoded data can be split into multiple blocks. Each block contains data
+ // and error recovery bytes.
+ //
+ // Larger QR Codes contain more blocks.
+ block []block
+
+ // Number of bits required to pad the combined data & error correction bit
+ // stream up to the symbol's full capacity.
+ numRemainderBits int
+}
+
+type block struct {
+ numBlocks int
+
+ // Total codewords (numCodewords == numErrorCodewords+numDataCodewords).
+ numCodewords int
+
+ // Number of data codewords.
+ numDataCodewords int
+}
+
+var (
+ versions = []qrCodeVersion{
+ {
+ 1,
+ Low,
+ dataEncoderType1To9,
+ []block{
+ {
+ 1,
+ 26,
+ 19,
+ },
+ },
+ 0,
+ },
+ {
+ 1,
+ Medium,
+ dataEncoderType1To9,
+ []block{
+ {
+ 1,
+ 26,
+ 16,
+ },
+ },
+ 0,
+ },
+ {
+ 1,
+ High,
+ dataEncoderType1To9,
+ []block{
+ {
+ 1,
+ 26,
+ 13,
+ },
+ },
+ 0,
+ },
+ {
+ 1,
+ Highest,
+ dataEncoderType1To9,
+ []block{
+ {
+ 1,
+ 26,
+ 9,
+ },
+ },
+ 0,
+ },
+ {
+ 2,
+ Low,
+ dataEncoderType1To9,
+ []block{
+ {
+ 1,
+ 44,
+ 34,
+ },
+ },
+ 7,
+ },
+ {
+ 2,
+ Medium,
+ dataEncoderType1To9,
+ []block{
+ {
+ 1,
+ 44,
+ 28,
+ },
+ },
+ 7,
+ },
+ {
+ 2,
+ High,
+ dataEncoderType1To9,
+ []block{
+ {
+ 1,
+ 44,
+ 22,
+ },
+ },
+ 7,
+ },
+ {
+ 2,
+ Highest,
+ dataEncoderType1To9,
+ []block{
+ {
+ 1,
+ 44,
+ 16,
+ },
+ },
+ 7,
+ },
+ {
+ 3,
+ Low,
+ dataEncoderType1To9,
+ []block{
+ {
+ 1,
+ 70,
+ 55,
+ },
+ },
+ 7,
+ },
+ {
+ 3,
+ Medium,
+ dataEncoderType1To9,
+ []block{
+ {
+ 1,
+ 70,
+ 44,
+ },
+ },
+ 7,
+ },
+ {
+ 3,
+ High,
+ dataEncoderType1To9,
+ []block{
+ {
+ 2,
+ 35,
+ 17,
+ },
+ },
+ 7,
+ },
+ {
+ 3,
+ Highest,
+ dataEncoderType1To9,
+ []block{
+ {
+ 2,
+ 35,
+ 13,
+ },
+ },
+ 7,
+ },
+ {
+ 4,
+ Low,
+ dataEncoderType1To9,
+ []block{
+ {
+ 1,
+ 100,
+ 80,
+ },
+ },
+ 7,
+ },
+ {
+ 4,
+ Medium,
+ dataEncoderType1To9,
+ []block{
+ {
+ 2,
+ 50,
+ 32,
+ },
+ },
+ 7,
+ },
+ {
+ 4,
+ High,
+ dataEncoderType1To9,
+ []block{
+ {
+ 2,
+ 50,
+ 24,
+ },
+ },
+ 7,
+ },
+ {
+ 4,
+ Highest,
+ dataEncoderType1To9,
+ []block{
+ {
+ 4,
+ 25,
+ 9,
+ },
+ },
+ 7,
+ },
+ {
+ 5,
+ Low,
+ dataEncoderType1To9,
+ []block{
+ {
+ 1,
+ 134,
+ 108,
+ },
+ },
+ 7,
+ },
+ {
+ 5,
+ Medium,
+ dataEncoderType1To9,
+ []block{
+ {
+ 2,
+ 67,
+ 43,
+ },
+ },
+ 7,
+ },
+ {
+ 5,
+ High,
+ dataEncoderType1To9,
+ []block{
+ {
+ 2,
+ 33,
+ 15,
+ },
+ {
+ 2,
+ 34,
+ 16,
+ },
+ },
+ 7,
+ },
+ {
+ 5,
+ Highest,
+ dataEncoderType1To9,
+ []block{
+ {
+ 2,
+ 33,
+ 11,
+ },
+ {
+ 2,
+ 34,
+ 12,
+ },
+ },
+ 7,
+ },
+ {
+ 6,
+ Low,
+ dataEncoderType1To9,
+ []block{
+ {
+ 2,
+ 86,
+ 68,
+ },
+ },
+ 7,
+ },
+ {
+ 6,
+ Medium,
+ dataEncoderType1To9,
+ []block{
+ {
+ 4,
+ 43,
+ 27,
+ },
+ },
+ 7,
+ },
+ {
+ 6,
+ High,
+ dataEncoderType1To9,
+ []block{
+ {
+ 4,
+ 43,
+ 19,
+ },
+ },
+ 7,
+ },
+ {
+ 6,
+ Highest,
+ dataEncoderType1To9,
+ []block{
+ {
+ 4,
+ 43,
+ 15,
+ },
+ },
+ 7,
+ },
+ {
+ 7,
+ Low,
+ dataEncoderType1To9,
+ []block{
+ {
+ 2,
+ 98,
+ 78,
+ },
+ },
+ 0,
+ },
+ {
+ 7,
+ Medium,
+ dataEncoderType1To9,
+ []block{
+ {
+ 4,
+ 49,
+ 31,
+ },
+ },
+ 0,
+ },
+ {
+ 7,
+ High,
+ dataEncoderType1To9,
+ []block{
+ {
+ 2,
+ 32,
+ 14,
+ },
+ {
+ 4,
+ 33,
+ 15,
+ },
+ },
+ 0,
+ },
+ {
+ 7,
+ Highest,
+ dataEncoderType1To9,
+ []block{
+ {
+ 4,
+ 39,
+ 13,
+ },
+ {
+ 1,
+ 40,
+ 14,
+ },
+ },
+ 0,
+ },
+ {
+ 8,
+ Low,
+ dataEncoderType1To9,
+ []block{
+ {
+ 2,
+ 121,
+ 97,
+ },
+ },
+ 0,
+ },
+ {
+ 8,
+ Medium,
+ dataEncoderType1To9,
+ []block{
+ {
+ 2,
+ 60,
+ 38,
+ },
+ {
+ 2,
+ 61,
+ 39,
+ },
+ },
+ 0,
+ },
+ {
+ 8,
+ High,
+ dataEncoderType1To9,
+ []block{
+ {
+ 4,
+ 40,
+ 18,
+ },
+ {
+ 2,
+ 41,
+ 19,
+ },
+ },
+ 0,
+ },
+ {
+ 8,
+ Highest,
+ dataEncoderType1To9,
+ []block{
+ {
+ 4,
+ 40,
+ 14,
+ },
+ {
+ 2,
+ 41,
+ 15,
+ },
+ },
+ 0,
+ },
+ {
+ 9,
+ Low,
+ dataEncoderType1To9,
+ []block{
+ {
+ 2,
+ 146,
+ 116,
+ },
+ },
+ 0,
+ },
+ {
+ 9,
+ Medium,
+ dataEncoderType1To9,
+ []block{
+ {
+ 3,
+ 58,
+ 36,
+ },
+ {
+ 2,
+ 59,
+ 37,
+ },
+ },
+ 0,
+ },
+ {
+ 9,
+ High,
+ dataEncoderType1To9,
+ []block{
+ {
+ 4,
+ 36,
+ 16,
+ },
+ {
+ 4,
+ 37,
+ 17,
+ },
+ },
+ 0,
+ },
+ {
+ 9,
+ Highest,
+ dataEncoderType1To9,
+ []block{
+ {
+ 4,
+ 36,
+ 12,
+ },
+ {
+ 4,
+ 37,
+ 13,
+ },
+ },
+ 0,
+ },
+ {
+ 10,
+ Low,
+ dataEncoderType10To26,
+ []block{
+ {
+ 2,
+ 86,
+ 68,
+ },
+ {
+ 2,
+ 87,
+ 69,
+ },
+ },
+ 0,
+ },
+ {
+ 10,
+ Medium,
+ dataEncoderType10To26,
+ []block{
+ {
+ 4,
+ 69,
+ 43,
+ },
+ {
+ 1,
+ 70,
+ 44,
+ },
+ },
+ 0,
+ },
+ {
+ 10,
+ High,
+ dataEncoderType10To26,
+ []block{
+ {
+ 6,
+ 43,
+ 19,
+ },
+ {
+ 2,
+ 44,
+ 20,
+ },
+ },
+ 0,
+ },
+ {
+ 10,
+ Highest,
+ dataEncoderType10To26,
+ []block{
+ {
+ 6,
+ 43,
+ 15,
+ },
+ {
+ 2,
+ 44,
+ 16,
+ },
+ },
+ 0,
+ },
+ {
+ 11,
+ Low,
+ dataEncoderType10To26,
+ []block{
+ {
+ 4,
+ 101,
+ 81,
+ },
+ },
+ 0,
+ },
+ {
+ 11,
+ Medium,
+ dataEncoderType10To26,
+ []block{
+ {
+ 1,
+ 80,
+ 50,
+ },
+ {
+ 4,
+ 81,
+ 51,
+ },
+ },
+ 0,
+ },
+ {
+ 11,
+ High,
+ dataEncoderType10To26,
+ []block{
+ {
+ 4,
+ 50,
+ 22,
+ },
+ {
+ 4,
+ 51,
+ 23,
+ },
+ },
+ 0,
+ },
+ {
+ 11,
+ Highest,
+ dataEncoderType10To26,
+ []block{
+ {
+ 3,
+ 36,
+ 12,
+ },
+ {
+ 8,
+ 37,
+ 13,
+ },
+ },
+ 0,
+ },
+ {
+ 12,
+ Low,
+ dataEncoderType10To26,
+ []block{
+ {
+ 2,
+ 116,
+ 92,
+ },
+ {
+ 2,
+ 117,
+ 93,
+ },
+ },
+ 0,
+ },
+ {
+ 12,
+ Medium,
+ dataEncoderType10To26,
+ []block{
+ {
+ 6,
+ 58,
+ 36,
+ },
+ {
+ 2,
+ 59,
+ 37,
+ },
+ },
+ 0,
+ },
+ {
+ 12,
+ High,
+ dataEncoderType10To26,
+ []block{
+ {
+ 4,
+ 46,
+ 20,
+ },
+ {
+ 6,
+ 47,
+ 21,
+ },
+ },
+ 0,
+ },
+ {
+ 12,
+ Highest,
+ dataEncoderType10To26,
+ []block{
+ {
+ 7,
+ 42,
+ 14,
+ },
+ {
+ 4,
+ 43,
+ 15,
+ },
+ },
+ 0,
+ },
+ {
+ 13,
+ Low,
+ dataEncoderType10To26,
+ []block{
+ {
+ 4,
+ 133,
+ 107,
+ },
+ },
+ 0,
+ },
+ {
+ 13,
+ Medium,
+ dataEncoderType10To26,
+ []block{
+ {
+ 8,
+ 59,
+ 37,
+ },
+ {
+ 1,
+ 60,
+ 38,
+ },
+ },
+ 0,
+ },
+ {
+ 13,
+ High,
+ dataEncoderType10To26,
+ []block{
+ {
+ 8,
+ 44,
+ 20,
+ },
+ {
+ 4,
+ 45,
+ 21,
+ },
+ },
+ 0,
+ },
+ {
+ 13,
+ Highest,
+ dataEncoderType10To26,
+ []block{
+ {
+ 12,
+ 33,
+ 11,
+ },
+ {
+ 4,
+ 34,
+ 12,
+ },
+ },
+ 0,
+ },
+ {
+ 14,
+ Low,
+ dataEncoderType10To26,
+ []block{
+ {
+ 3,
+ 145,
+ 115,
+ },
+ {
+ 1,
+ 146,
+ 116,
+ },
+ },
+ 3,
+ },
+ {
+ 14,
+ Medium,
+ dataEncoderType10To26,
+ []block{
+ {
+ 4,
+ 64,
+ 40,
+ },
+ {
+ 5,
+ 65,
+ 41,
+ },
+ },
+ 3,
+ },
+ {
+ 14,
+ High,
+ dataEncoderType10To26,
+ []block{
+ {
+ 11,
+ 36,
+ 16,
+ },
+ {
+ 5,
+ 37,
+ 17,
+ },
+ },
+ 3,
+ },
+ {
+ 14,
+ Highest,
+ dataEncoderType10To26,
+ []block{
+ {
+ 11,
+ 36,
+ 12,
+ },
+ {
+ 5,
+ 37,
+ 13,
+ },
+ },
+ 3,
+ },
+ {
+ 15,
+ Low,
+ dataEncoderType10To26,
+ []block{
+ {
+ 5,
+ 109,
+ 87,
+ },
+ {
+ 1,
+ 110,
+ 88,
+ },
+ },
+ 3,
+ },
+ {
+ 15,
+ Medium,
+ dataEncoderType10To26,
+ []block{
+ {
+ 5,
+ 65,
+ 41,
+ },
+ {
+ 5,
+ 66,
+ 42,
+ },
+ },
+ 3,
+ },
+ {
+ 15,
+ High,
+ dataEncoderType10To26,
+ []block{
+ {
+ 5,
+ 54,
+ 24,
+ },
+ {
+ 7,
+ 55,
+ 25,
+ },
+ },
+ 3,
+ },
+ {
+ 15,
+ Highest,
+ dataEncoderType10To26,
+ []block{
+ {
+ 11,
+ 36,
+ 12,
+ },
+ {
+ 7,
+ 37,
+ 13,
+ },
+ },
+ 3,
+ },
+ {
+ 16,
+ Low,
+ dataEncoderType10To26,
+ []block{
+ {
+ 5,
+ 122,
+ 98,
+ },
+ {
+ 1,
+ 123,
+ 99,
+ },
+ },
+ 3,
+ },
+ {
+ 16,
+ Medium,
+ dataEncoderType10To26,
+ []block{
+ {
+ 7,
+ 73,
+ 45,
+ },
+ {
+ 3,
+ 74,
+ 46,
+ },
+ },
+ 3,
+ },
+ {
+ 16,
+ High,
+ dataEncoderType10To26,
+ []block{
+ {
+ 15,
+ 43,
+ 19,
+ },
+ {
+ 2,
+ 44,
+ 20,
+ },
+ },
+ 3,
+ },
+ {
+ 16,
+ Highest,
+ dataEncoderType10To26,
+ []block{
+ {
+ 3,
+ 45,
+ 15,
+ },
+ {
+ 13,
+ 46,
+ 16,
+ },
+ },
+ 3,
+ },
+ {
+ 17,
+ Low,
+ dataEncoderType10To26,
+ []block{
+ {
+ 1,
+ 135,
+ 107,
+ },
+ {
+ 5,
+ 136,
+ 108,
+ },
+ },
+ 3,
+ },
+ {
+ 17,
+ Medium,
+ dataEncoderType10To26,
+ []block{
+ {
+ 10,
+ 74,
+ 46,
+ },
+ {
+ 1,
+ 75,
+ 47,
+ },
+ },
+ 3,
+ },
+ {
+ 17,
+ High,
+ dataEncoderType10To26,
+ []block{
+ {
+ 1,
+ 50,
+ 22,
+ },
+ {
+ 15,
+ 51,
+ 23,
+ },
+ },
+ 3,
+ },
+ {
+ 17,
+ Highest,
+ dataEncoderType10To26,
+ []block{
+ {
+ 2,
+ 42,
+ 14,
+ },
+ {
+ 17,
+ 43,
+ 15,
+ },
+ },
+ 3,
+ },
+ {
+ 18,
+ Low,
+ dataEncoderType10To26,
+ []block{
+ {
+ 5,
+ 150,
+ 120,
+ },
+ {
+ 1,
+ 151,
+ 121,
+ },
+ },
+ 3,
+ },
+ {
+ 18,
+ Medium,
+ dataEncoderType10To26,
+ []block{
+ {
+ 9,
+ 69,
+ 43,
+ },
+ {
+ 4,
+ 70,
+ 44,
+ },
+ },
+ 3,
+ },
+ {
+ 18,
+ High,
+ dataEncoderType10To26,
+ []block{
+ {
+ 17,
+ 50,
+ 22,
+ },
+ {
+ 1,
+ 51,
+ 23,
+ },
+ },
+ 3,
+ },
+ {
+ 18,
+ Highest,
+ dataEncoderType10To26,
+ []block{
+ {
+ 2,
+ 42,
+ 14,
+ },
+ {
+ 19,
+ 43,
+ 15,
+ },
+ },
+ 3,
+ },
+ {
+ 19,
+ Low,
+ dataEncoderType10To26,
+ []block{
+ {
+ 3,
+ 141,
+ 113,
+ },
+ {
+ 4,
+ 142,
+ 114,
+ },
+ },
+ 3,
+ },
+ {
+ 19,
+ Medium,
+ dataEncoderType10To26,
+ []block{
+ {
+ 3,
+ 70,
+ 44,
+ },
+ {
+ 11,
+ 71,
+ 45,
+ },
+ },
+ 3,
+ },
+ {
+ 19,
+ High,
+ dataEncoderType10To26,
+ []block{
+ {
+ 17,
+ 47,
+ 21,
+ },
+ {
+ 4,
+ 48,
+ 22,
+ },
+ },
+ 3,
+ },
+ {
+ 19,
+ Highest,
+ dataEncoderType10To26,
+ []block{
+ {
+ 9,
+ 39,
+ 13,
+ },
+ {
+ 16,
+ 40,
+ 14,
+ },
+ },
+ 3,
+ },
+ {
+ 20,
+ Low,
+ dataEncoderType10To26,
+ []block{
+ {
+ 3,
+ 135,
+ 107,
+ },
+ {
+ 5,
+ 136,
+ 108,
+ },
+ },
+ 3,
+ },
+ {
+ 20,
+ Medium,
+ dataEncoderType10To26,
+ []block{
+ {
+ 3,
+ 67,
+ 41,
+ },
+ {
+ 13,
+ 68,
+ 42,
+ },
+ },
+ 3,
+ },
+ {
+ 20,
+ High,
+ dataEncoderType10To26,
+ []block{
+ {
+ 15,
+ 54,
+ 24,
+ },
+ {
+ 5,
+ 55,
+ 25,
+ },
+ },
+ 3,
+ },
+ {
+ 20,
+ Highest,
+ dataEncoderType10To26,
+ []block{
+ {
+ 15,
+ 43,
+ 15,
+ },
+ {
+ 10,
+ 44,
+ 16,
+ },
+ },
+ 3,
+ },
+ {
+ 21,
+ Low,
+ dataEncoderType10To26,
+ []block{
+ {
+ 4,
+ 144,
+ 116,
+ },
+ {
+ 4,
+ 145,
+ 117,
+ },
+ },
+ 4,
+ },
+ {
+ 21,
+ Medium,
+ dataEncoderType10To26,
+ []block{
+ {
+ 17,
+ 68,
+ 42,
+ },
+ },
+ 4,
+ },
+ {
+ 21,
+ High,
+ dataEncoderType10To26,
+ []block{
+ {
+ 17,
+ 50,
+ 22,
+ },
+ {
+ 6,
+ 51,
+ 23,
+ },
+ },
+ 4,
+ },
+ {
+ 21,
+ Highest,
+ dataEncoderType10To26,
+ []block{
+ {
+ 19,
+ 46,
+ 16,
+ },
+ {
+ 6,
+ 47,
+ 17,
+ },
+ },
+ 4,
+ },
+ {
+ 22,
+ Low,
+ dataEncoderType10To26,
+ []block{
+ {
+ 2,
+ 139,
+ 111,
+ },
+ {
+ 7,
+ 140,
+ 112,
+ },
+ },
+ 4,
+ },
+ {
+ 22,
+ Medium,
+ dataEncoderType10To26,
+ []block{
+ {
+ 17,
+ 74,
+ 46,
+ },
+ },
+ 4,
+ },
+ {
+ 22,
+ High,
+ dataEncoderType10To26,
+ []block{
+ {
+ 7,
+ 54,
+ 24,
+ },
+ {
+ 16,
+ 55,
+ 25,
+ },
+ },
+ 4,
+ },
+ {
+ 22,
+ Highest,
+ dataEncoderType10To26,
+ []block{
+ {
+ 34,
+ 37,
+ 13,
+ },
+ },
+ 4,
+ },
+ {
+ 23,
+ Low,
+ dataEncoderType10To26,
+ []block{
+ {
+ 4,
+ 151,
+ 121,
+ },
+ {
+ 5,
+ 152,
+ 122,
+ },
+ },
+ 4,
+ },
+ {
+ 23,
+ Medium,
+ dataEncoderType10To26,
+ []block{
+ {
+ 4,
+ 75,
+ 47,
+ },
+ {
+ 14,
+ 76,
+ 48,
+ },
+ },
+ 4,
+ },
+ {
+ 23,
+ High,
+ dataEncoderType10To26,
+ []block{
+ {
+ 11,
+ 54,
+ 24,
+ },
+ {
+ 14,
+ 55,
+ 25,
+ },
+ },
+ 4,
+ },
+ {
+ 23,
+ Highest,
+ dataEncoderType10To26,
+ []block{
+ {
+ 16,
+ 45,
+ 15,
+ },
+ {
+ 14,
+ 46,
+ 16,
+ },
+ },
+ 4,
+ },
+ {
+ 24,
+ Low,
+ dataEncoderType10To26,
+ []block{
+ {
+ 6,
+ 147,
+ 117,
+ },
+ {
+ 4,
+ 148,
+ 118,
+ },
+ },
+ 4,
+ },
+ {
+ 24,
+ Medium,
+ dataEncoderType10To26,
+ []block{
+ {
+ 6,
+ 73,
+ 45,
+ },
+ {
+ 14,
+ 74,
+ 46,
+ },
+ },
+ 4,
+ },
+ {
+ 24,
+ High,
+ dataEncoderType10To26,
+ []block{
+ {
+ 11,
+ 54,
+ 24,
+ },
+ {
+ 16,
+ 55,
+ 25,
+ },
+ },
+ 4,
+ },
+ {
+ 24,
+ Highest,
+ dataEncoderType10To26,
+ []block{
+ {
+ 30,
+ 46,
+ 16,
+ },
+ {
+ 2,
+ 47,
+ 17,
+ },
+ },
+ 4,
+ },
+ {
+ 25,
+ Low,
+ dataEncoderType10To26,
+ []block{
+ {
+ 8,
+ 132,
+ 106,
+ },
+ {
+ 4,
+ 133,
+ 107,
+ },
+ },
+ 4,
+ },
+ {
+ 25,
+ Medium,
+ dataEncoderType10To26,
+ []block{
+ {
+ 8,
+ 75,
+ 47,
+ },
+ {
+ 13,
+ 76,
+ 48,
+ },
+ },
+ 4,
+ },
+ {
+ 25,
+ High,
+ dataEncoderType10To26,
+ []block{
+ {
+ 7,
+ 54,
+ 24,
+ },
+ {
+ 22,
+ 55,
+ 25,
+ },
+ },
+ 4,
+ },
+ {
+ 25,
+ Highest,
+ dataEncoderType10To26,
+ []block{
+ {
+ 22,
+ 45,
+ 15,
+ },
+ {
+ 13,
+ 46,
+ 16,
+ },
+ },
+ 4,
+ },
+ {
+ 26,
+ Low,
+ dataEncoderType10To26,
+ []block{
+ {
+ 10,
+ 142,
+ 114,
+ },
+ {
+ 2,
+ 143,
+ 115,
+ },
+ },
+ 4,
+ },
+ {
+ 26,
+ Medium,
+ dataEncoderType10To26,
+ []block{
+ {
+ 19,
+ 74,
+ 46,
+ },
+ {
+ 4,
+ 75,
+ 47,
+ },
+ },
+ 4,
+ },
+ {
+ 26,
+ High,
+ dataEncoderType10To26,
+ []block{
+ {
+ 28,
+ 50,
+ 22,
+ },
+ {
+ 6,
+ 51,
+ 23,
+ },
+ },
+ 4,
+ },
+ {
+ 26,
+ Highest,
+ dataEncoderType10To26,
+ []block{
+ {
+ 33,
+ 46,
+ 16,
+ },
+ {
+ 4,
+ 47,
+ 17,
+ },
+ },
+ 4,
+ },
+ {
+ 27,
+ Low,
+ dataEncoderType27To40,
+ []block{
+ {
+ 8,
+ 152,
+ 122,
+ },
+ {
+ 4,
+ 153,
+ 123,
+ },
+ },
+ 4,
+ },
+ {
+ 27,
+ Medium,
+ dataEncoderType27To40,
+ []block{
+ {
+ 22,
+ 73,
+ 45,
+ },
+ {
+ 3,
+ 74,
+ 46,
+ },
+ },
+ 4,
+ },
+ {
+ 27,
+ High,
+ dataEncoderType27To40,
+ []block{
+ {
+ 8,
+ 53,
+ 23,
+ },
+ {
+ 26,
+ 54,
+ 24,
+ },
+ },
+ 4,
+ },
+ {
+ 27,
+ Highest,
+ dataEncoderType27To40,
+ []block{
+ {
+ 12,
+ 45,
+ 15,
+ },
+ {
+ 28,
+ 46,
+ 16,
+ },
+ },
+ 4,
+ },
+ {
+ 28,
+ Low,
+ dataEncoderType27To40,
+ []block{
+ {
+ 3,
+ 147,
+ 117,
+ },
+ {
+ 10,
+ 148,
+ 118,
+ },
+ },
+ 3,
+ },
+ {
+ 28,
+ Medium,
+ dataEncoderType27To40,
+ []block{
+ {
+ 3,
+ 73,
+ 45,
+ },
+ {
+ 23,
+ 74,
+ 46,
+ },
+ },
+ 3,
+ },
+ {
+ 28,
+ High,
+ dataEncoderType27To40,
+ []block{
+ {
+ 4,
+ 54,
+ 24,
+ },
+ {
+ 31,
+ 55,
+ 25,
+ },
+ },
+ 3,
+ },
+ {
+ 28,
+ Highest,
+ dataEncoderType27To40,
+ []block{
+ {
+ 11,
+ 45,
+ 15,
+ },
+ {
+ 31,
+ 46,
+ 16,
+ },
+ },
+ 3,
+ },
+ {
+ 29,
+ Low,
+ dataEncoderType27To40,
+ []block{
+ {
+ 7,
+ 146,
+ 116,
+ },
+ {
+ 7,
+ 147,
+ 117,
+ },
+ },
+ 3,
+ },
+ {
+ 29,
+ Medium,
+ dataEncoderType27To40,
+ []block{
+ {
+ 21,
+ 73,
+ 45,
+ },
+ {
+ 7,
+ 74,
+ 46,
+ },
+ },
+ 3,
+ },
+ {
+ 29,
+ High,
+ dataEncoderType27To40,
+ []block{
+ {
+ 1,
+ 53,
+ 23,
+ },
+ {
+ 37,
+ 54,
+ 24,
+ },
+ },
+ 3,
+ },
+ {
+ 29,
+ Highest,
+ dataEncoderType27To40,
+ []block{
+ {
+ 19,
+ 45,
+ 15,
+ },
+ {
+ 26,
+ 46,
+ 16,
+ },
+ },
+ 3,
+ },
+ {
+ 30,
+ Low,
+ dataEncoderType27To40,
+ []block{
+ {
+ 5,
+ 145,
+ 115,
+ },
+ {
+ 10,
+ 146,
+ 116,
+ },
+ },
+ 3,
+ },
+ {
+ 30,
+ Medium,
+ dataEncoderType27To40,
+ []block{
+ {
+ 19,
+ 75,
+ 47,
+ },
+ {
+ 10,
+ 76,
+ 48,
+ },
+ },
+ 3,
+ },
+ {
+ 30,
+ High,
+ dataEncoderType27To40,
+ []block{
+ {
+ 15,
+ 54,
+ 24,
+ },
+ {
+ 25,
+ 55,
+ 25,
+ },
+ },
+ 3,
+ },
+ {
+ 30,
+ Highest,
+ dataEncoderType27To40,
+ []block{
+ {
+ 23,
+ 45,
+ 15,
+ },
+ {
+ 25,
+ 46,
+ 16,
+ },
+ },
+ 3,
+ },
+ {
+ 31,
+ Low,
+ dataEncoderType27To40,
+ []block{
+ {
+ 13,
+ 145,
+ 115,
+ },
+ {
+ 3,
+ 146,
+ 116,
+ },
+ },
+ 3,
+ },
+ {
+ 31,
+ Medium,
+ dataEncoderType27To40,
+ []block{
+ {
+ 2,
+ 74,
+ 46,
+ },
+ {
+ 29,
+ 75,
+ 47,
+ },
+ },
+ 3,
+ },
+ {
+ 31,
+ High,
+ dataEncoderType27To40,
+ []block{
+ {
+ 42,
+ 54,
+ 24,
+ },
+ {
+ 1,
+ 55,
+ 25,
+ },
+ },
+ 3,
+ },
+ {
+ 31,
+ Highest,
+ dataEncoderType27To40,
+ []block{
+ {
+ 23,
+ 45,
+ 15,
+ },
+ {
+ 28,
+ 46,
+ 16,
+ },
+ },
+ 3,
+ },
+ {
+ 32,
+ Low,
+ dataEncoderType27To40,
+ []block{
+ {
+ 17,
+ 145,
+ 115,
+ },
+ },
+ 3,
+ },
+ {
+ 32,
+ Medium,
+ dataEncoderType27To40,
+ []block{
+ {
+ 10,
+ 74,
+ 46,
+ },
+ {
+ 23,
+ 75,
+ 47,
+ },
+ },
+ 3,
+ },
+ {
+ 32,
+ High,
+ dataEncoderType27To40,
+ []block{
+ {
+ 10,
+ 54,
+ 24,
+ },
+ {
+ 35,
+ 55,
+ 25,
+ },
+ },
+ 3,
+ },
+ {
+ 32,
+ Highest,
+ dataEncoderType27To40,
+ []block{
+ {
+ 19,
+ 45,
+ 15,
+ },
+ {
+ 35,
+ 46,
+ 16,
+ },
+ },
+ 3,
+ },
+ {
+ 33,
+ Low,
+ dataEncoderType27To40,
+ []block{
+ {
+ 17,
+ 145,
+ 115,
+ },
+ {
+ 1,
+ 146,
+ 116,
+ },
+ },
+ 3,
+ },
+ {
+ 33,
+ Medium,
+ dataEncoderType27To40,
+ []block{
+ {
+ 14,
+ 74,
+ 46,
+ },
+ {
+ 21,
+ 75,
+ 47,
+ },
+ },
+ 3,
+ },
+ {
+ 33,
+ High,
+ dataEncoderType27To40,
+ []block{
+ {
+ 29,
+ 54,
+ 24,
+ },
+ {
+ 19,
+ 55,
+ 25,
+ },
+ },
+ 3,
+ },
+ {
+ 33,
+ Highest,
+ dataEncoderType27To40,
+ []block{
+ {
+ 11,
+ 45,
+ 15,
+ },
+ {
+ 46,
+ 46,
+ 16,
+ },
+ },
+ 3,
+ },
+ {
+ 34,
+ Low,
+ dataEncoderType27To40,
+ []block{
+ {
+ 13,
+ 145,
+ 115,
+ },
+ {
+ 6,
+ 146,
+ 116,
+ },
+ },
+ 3,
+ },
+ {
+ 34,
+ Medium,
+ dataEncoderType27To40,
+ []block{
+ {
+ 14,
+ 74,
+ 46,
+ },
+ {
+ 23,
+ 75,
+ 47,
+ },
+ },
+ 3,
+ },
+ {
+ 34,
+ High,
+ dataEncoderType27To40,
+ []block{
+ {
+ 44,
+ 54,
+ 24,
+ },
+ {
+ 7,
+ 55,
+ 25,
+ },
+ },
+ 3,
+ },
+ {
+ 34,
+ Highest,
+ dataEncoderType27To40,
+ []block{
+ {
+ 59,
+ 46,
+ 16,
+ },
+ {
+ 1,
+ 47,
+ 17,
+ },
+ },
+ 3,
+ },
+ {
+ 35,
+ Low,
+ dataEncoderType27To40,
+ []block{
+ {
+ 12,
+ 151,
+ 121,
+ },
+ {
+ 7,
+ 152,
+ 122,
+ },
+ },
+ 0,
+ },
+ {
+ 35,
+ Medium,
+ dataEncoderType27To40,
+ []block{
+ {
+ 12,
+ 75,
+ 47,
+ },
+ {
+ 26,
+ 76,
+ 48,
+ },
+ },
+ 0,
+ },
+ {
+ 35,
+ High,
+ dataEncoderType27To40,
+ []block{
+ {
+ 39,
+ 54,
+ 24,
+ },
+ {
+ 14,
+ 55,
+ 25,
+ },
+ },
+ 0,
+ },
+ {
+ 35,
+ Highest,
+ dataEncoderType27To40,
+ []block{
+ {
+ 22,
+ 45,
+ 15,
+ },
+ {
+ 41,
+ 46,
+ 16,
+ },
+ },
+ 0,
+ },
+ {
+ 36,
+ Low,
+ dataEncoderType27To40,
+ []block{
+ {
+ 6,
+ 151,
+ 121,
+ },
+ {
+ 14,
+ 152,
+ 122,
+ },
+ },
+ 0,
+ },
+ {
+ 36,
+ Medium,
+ dataEncoderType27To40,
+ []block{
+ {
+ 6,
+ 75,
+ 47,
+ },
+ {
+ 34,
+ 76,
+ 48,
+ },
+ },
+ 0,
+ },
+ {
+ 36,
+ High,
+ dataEncoderType27To40,
+ []block{
+ {
+ 46,
+ 54,
+ 24,
+ },
+ {
+ 10,
+ 55,
+ 25,
+ },
+ },
+ 0,
+ },
+ {
+ 36,
+ Highest,
+ dataEncoderType27To40,
+ []block{
+ {
+ 2,
+ 45,
+ 15,
+ },
+ {
+ 64,
+ 46,
+ 16,
+ },
+ },
+ 0,
+ },
+ {
+ 37,
+ Low,
+ dataEncoderType27To40,
+ []block{
+ {
+ 17,
+ 152,
+ 122,
+ },
+ {
+ 4,
+ 153,
+ 123,
+ },
+ },
+ 0,
+ },
+ {
+ 37,
+ Medium,
+ dataEncoderType27To40,
+ []block{
+ {
+ 29,
+ 74,
+ 46,
+ },
+ {
+ 14,
+ 75,
+ 47,
+ },
+ },
+ 0,
+ },
+ {
+ 37,
+ High,
+ dataEncoderType27To40,
+ []block{
+ {
+ 49,
+ 54,
+ 24,
+ },
+ {
+ 10,
+ 55,
+ 25,
+ },
+ },
+ 0,
+ },
+ {
+ 37,
+ Highest,
+ dataEncoderType27To40,
+ []block{
+ {
+ 24,
+ 45,
+ 15,
+ },
+ {
+ 46,
+ 46,
+ 16,
+ },
+ },
+ 0,
+ },
+ {
+ 38,
+ Low,
+ dataEncoderType27To40,
+ []block{
+ {
+ 4,
+ 152,
+ 122,
+ },
+ {
+ 18,
+ 153,
+ 123,
+ },
+ },
+ 0,
+ },
+ {
+ 38,
+ Medium,
+ dataEncoderType27To40,
+ []block{
+ {
+ 13,
+ 74,
+ 46,
+ },
+ {
+ 32,
+ 75,
+ 47,
+ },
+ },
+ 0,
+ },
+ {
+ 38,
+ High,
+ dataEncoderType27To40,
+ []block{
+ {
+ 48,
+ 54,
+ 24,
+ },
+ {
+ 14,
+ 55,
+ 25,
+ },
+ },
+ 0,
+ },
+ {
+ 38,
+ Highest,
+ dataEncoderType27To40,
+ []block{
+ {
+ 42,
+ 45,
+ 15,
+ },
+ {
+ 32,
+ 46,
+ 16,
+ },
+ },
+ 0,
+ },
+ {
+ 39,
+ Low,
+ dataEncoderType27To40,
+ []block{
+ {
+ 20,
+ 147,
+ 117,
+ },
+ {
+ 4,
+ 148,
+ 118,
+ },
+ },
+ 0,
+ },
+ {
+ 39,
+ Medium,
+ dataEncoderType27To40,
+ []block{
+ {
+ 40,
+ 75,
+ 47,
+ },
+ {
+ 7,
+ 76,
+ 48,
+ },
+ },
+ 0,
+ },
+ {
+ 39,
+ High,
+ dataEncoderType27To40,
+ []block{
+ {
+ 43,
+ 54,
+ 24,
+ },
+ {
+ 22,
+ 55,
+ 25,
+ },
+ },
+ 0,
+ },
+ {
+ 39,
+ Highest,
+ dataEncoderType27To40,
+ []block{
+ {
+ 10,
+ 45,
+ 15,
+ },
+ {
+ 67,
+ 46,
+ 16,
+ },
+ },
+ 0,
+ },
+ {
+ 40,
+ Low,
+ dataEncoderType27To40,
+ []block{
+ {
+ 19,
+ 148,
+ 118,
+ },
+ {
+ 6,
+ 149,
+ 119,
+ },
+ },
+ 0,
+ },
+ {
+ 40,
+ Medium,
+ dataEncoderType27To40,
+ []block{
+ {
+ 18,
+ 75,
+ 47,
+ },
+ {
+ 31,
+ 76,
+ 48,
+ },
+ },
+ 0,
+ },
+ {
+ 40,
+ High,
+ dataEncoderType27To40,
+ []block{
+ {
+ 34,
+ 54,
+ 24,
+ },
+ {
+ 34,
+ 55,
+ 25,
+ },
+ },
+ 0,
+ },
+ {
+ 40,
+ Highest,
+ dataEncoderType27To40,
+ []block{
+ {
+ 20,
+ 45,
+ 15,
+ },
+ {
+ 61,
+ 46,
+ 16,
+ },
+ },
+ 0,
+ },
+ }
+)
+
+var (
+ // Each QR Code contains a 15-bit Format Information value. The 15 bits
+ // consist of 5 data bits concatenated with 10 error correction bits.
+ //
+ // The 5 data bits consist of:
+ // - 2 bits for the error correction level (L=01, M=00, G=11, H=10).
+ // - 3 bits for the data mask pattern identifier.
+ //
+ // formatBitSequence is a mapping from the 5 data bits to the completed 15-bit
+ // Format Information value.
+ //
+ // For example, a QR Code using error correction level L, and data mask
+ // pattern identifier 001:
+ //
+ // 01 | 001 = 01001 = 0x9
+ // formatBitSequence[0x9].qrCode = 0x72f3 = 111001011110011
+ formatBitSequence = []struct {
+ regular uint32
+ micro uint32
+ }{
+ {0x5412, 0x4445},
+ {0x5125, 0x4172},
+ {0x5e7c, 0x4e2b},
+ {0x5b4b, 0x4b1c},
+ {0x45f9, 0x55ae},
+ {0x40ce, 0x5099},
+ {0x4f97, 0x5fc0},
+ {0x4aa0, 0x5af7},
+ {0x77c4, 0x6793},
+ {0x72f3, 0x62a4},
+ {0x7daa, 0x6dfd},
+ {0x789d, 0x68ca},
+ {0x662f, 0x7678},
+ {0x6318, 0x734f},
+ {0x6c41, 0x7c16},
+ {0x6976, 0x7921},
+ {0x1689, 0x06de},
+ {0x13be, 0x03e9},
+ {0x1ce7, 0x0cb0},
+ {0x19d0, 0x0987},
+ {0x0762, 0x1735},
+ {0x0255, 0x1202},
+ {0x0d0c, 0x1d5b},
+ {0x083b, 0x186c},
+ {0x355f, 0x2508},
+ {0x3068, 0x203f},
+ {0x3f31, 0x2f66},
+ {0x3a06, 0x2a51},
+ {0x24b4, 0x34e3},
+ {0x2183, 0x31d4},
+ {0x2eda, 0x3e8d},
+ {0x2bed, 0x3bba},
+ }
+
+ // QR Codes version 7 and higher contain an 18-bit Version Information value,
+ // consisting of a 6 data bits and 12 error correction bits.
+ //
+ // versionBitSequence is a mapping from QR Code version to the completed
+ // 18-bit Version Information value.
+ //
+ // For example, a QR code of version 7:
+ // versionBitSequence[0x7] = 0x07c94 = 000111110010010100
+ versionBitSequence = []uint32{
+ 0x00000,
+ 0x00000,
+ 0x00000,
+ 0x00000,
+ 0x00000,
+ 0x00000,
+ 0x00000,
+ 0x07c94,
+ 0x085bc,
+ 0x09a99,
+ 0x0a4d3,
+ 0x0bbf6,
+ 0x0c762,
+ 0x0d847,
+ 0x0e60d,
+ 0x0f928,
+ 0x10b78,
+ 0x1145d,
+ 0x12a17,
+ 0x13532,
+ 0x149a6,
+ 0x15683,
+ 0x168c9,
+ 0x177ec,
+ 0x18ec4,
+ 0x191e1,
+ 0x1afab,
+ 0x1b08e,
+ 0x1cc1a,
+ 0x1d33f,
+ 0x1ed75,
+ 0x1f250,
+ 0x209d5,
+ 0x216f0,
+ 0x228ba,
+ 0x2379f,
+ 0x24b0b,
+ 0x2542e,
+ 0x26a64,
+ 0x27541,
+ 0x28c69,
+ }
+)
+
+const (
+ formatInfoLengthBits = 15
+ versionInfoLengthBits = 18
+)
+
+// formatInfo returns the 15-bit Format Information value for a QR
+// code.
+func (v qrCodeVersion) formatInfo(maskPattern int) *bitset.Bitset {
+ formatID := 0
+
+ switch v.level {
+ case Low:
+ formatID = 0x08 // 0b01000
+ case Medium:
+ formatID = 0x00 // 0b00000
+ case High:
+ formatID = 0x18 // 0b11000
+ case Highest:
+ formatID = 0x10 // 0b10000
+ default:
+ log.Panicf("Invalid level %d", v.level)
+ }
+
+ if maskPattern < 0 || maskPattern > 7 {
+ log.Panicf("Invalid maskPattern %d", maskPattern)
+ }
+
+ formatID |= maskPattern & 0x7
+
+ result := bitset.New()
+
+ result.AppendUint32(formatBitSequence[formatID].regular, formatInfoLengthBits)
+
+ return result
+}
+
+// versionInfo returns the 18-bit Version Information value for a QR Code.
+//
+// Version Information is applicable only to QR Codes versions 7-40 inclusive.
+// nil is returned if Version Information is not required.
+func (v qrCodeVersion) versionInfo() *bitset.Bitset {
+ if v.version < 7 {
+ return nil
+ }
+
+ result := bitset.New()
+ result.AppendUint32(versionBitSequence[v.version], 18)
+
+ return result
+}
+
+// numDataBits returns the data capacity in bits.
+func (v qrCodeVersion) numDataBits() int {
+ numDataBits := 0
+ for _, b := range v.block {
+ numDataBits += 8 * b.numBlocks * b.numDataCodewords // 8 bits in a byte
+ }
+
+ return numDataBits
+}
+
+// chooseQRCodeVersion chooses the most suitable QR Code version for a stated
+// data length in bits, the error recovery level required, and the data encoder
+// used.
+//
+// The chosen QR Code version is the smallest version able to fit numDataBits
+// and the optional terminator bits required by the specified encoder.
+//
+// On success the chosen QR Code version is returned.
+func chooseQRCodeVersion(level RecoveryLevel, encoder *dataEncoder, numDataBits int) *qrCodeVersion {
+ var chosenVersion *qrCodeVersion
+
+ for _, v := range versions {
+ if v.level != level {
+ continue
+ } else if v.version < encoder.minVersion {
+ continue
+ } else if v.version > encoder.maxVersion {
+ break
+ }
+
+ numFreeBits := v.numDataBits() - numDataBits
+
+ if numFreeBits >= 0 {
+ chosenVersion = &v
+ break
+ }
+ }
+
+ return chosenVersion
+}
+
+func (v qrCodeVersion) numTerminatorBitsRequired(numDataBits int) int {
+ numFreeBits := v.numDataBits() - numDataBits
+
+ var numTerminatorBits int
+
+ switch {
+ case numFreeBits >= 4:
+ numTerminatorBits = 4
+ default:
+ numTerminatorBits = numFreeBits
+ }
+
+ return numTerminatorBits
+}
+
+// numBlocks returns the number of blocks.
+func (v qrCodeVersion) numBlocks() int {
+ numBlocks := 0
+
+ for _, b := range v.block {
+ numBlocks += b.numBlocks
+ }
+
+ return numBlocks
+}
+
+// numBitsToPadToCodeword returns the number of bits required to pad data of
+// length numDataBits upto the nearest codeword size.
+func (v qrCodeVersion) numBitsToPadToCodeword(numDataBits int) int {
+ if numDataBits == v.numDataBits() {
+ return 0
+ }
+
+ return (8 - numDataBits%8) % 8
+}
+
+// symbolSize returns the size of the QR Code symbol in number of modules (which
+// is both the width and height, since QR codes are square). The QR Code has
+// size symbolSize() x symbolSize() pixels. This does not include the quiet
+// zone.
+func (v qrCodeVersion) symbolSize() int {
+ return 21 + (v.version-1)*4
+}
+
+// quietZoneSize returns the number of pixels of border space on each side of
+// the QR Code. The quiet space assists with decoding.
+func (v qrCodeVersion) quietZoneSize() int {
+ return 4
+}
+
+// getQRCodeVersion returns the QR Code version by version number and recovery
+// level. Returns nil if the requested combination is not defined.
+func getQRCodeVersion(level RecoveryLevel, version int) *qrCodeVersion {
+ for _, v := range versions {
+ if v.level == level && v.version == version {
+ return &v
+ }
+ }
+
+ return nil
+}