mirror of
https://github.com/dutchcoders/transfer.sh.git
synced 2020-11-18 19:53:40 -08:00
QR code, html5 player
This commit is contained in:
parent
b31e6acd71
commit
99bb2a6118
@ -58,6 +58,9 @@ import (
|
||||
web "github.com/dutchcoders/transfer.sh-web"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/russross/blackfriday"
|
||||
|
||||
qrcode "github.com/skip2/go-qrcode"
|
||||
"encoding/base64"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -147,6 +150,15 @@ func (s *Server) previewHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
var png []byte
|
||||
png, err = qrcode.Encode(resolveUrl(r, getURL(r).ResolveReference(r.URL), true), qrcode.High, 150)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
qrCode := base64.StdEncoding.EncodeToString(png)
|
||||
|
||||
data := struct {
|
||||
ContentType string
|
||||
Content html_template.HTML
|
||||
@ -155,6 +167,7 @@ func (s *Server) previewHandler(w http.ResponseWriter, r *http.Request) {
|
||||
ContentLength uint64
|
||||
GAKey string
|
||||
UserVoiceKey string
|
||||
QRCode string
|
||||
}{
|
||||
contentType,
|
||||
content,
|
||||
@ -163,6 +176,7 @@ func (s *Server) previewHandler(w http.ResponseWriter, r *http.Request) {
|
||||
contentLength,
|
||||
s.gaKey,
|
||||
s.userVoiceKey,
|
||||
qrCode,
|
||||
}
|
||||
|
||||
if err := htmlTemplates.ExecuteTemplate(w, templatePath, data); err != nil {
|
||||
|
2996
vendor/github.com/dutchcoders/transfer.sh-web/bindata_gen.go
generated
vendored
2996
vendor/github.com/dutchcoders/transfer.sh-web/bindata_gen.go
generated
vendored
File diff suppressed because it is too large
Load Diff
4
vendor/github.com/skip2/go-qrcode/.gitignore
generated
vendored
Normal file
4
vendor/github.com/skip2/go-qrcode/.gitignore
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
*.sw*
|
||||
*.png
|
||||
*.directory
|
||||
qrcode/qrcode
|
8
vendor/github.com/skip2/go-qrcode/.travis.yml
generated
vendored
Normal file
8
vendor/github.com/skip2/go-qrcode/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.7
|
||||
|
||||
script:
|
||||
- go test -v ./...
|
||||
|
19
vendor/github.com/skip2/go-qrcode/LICENSE
generated
vendored
Normal file
19
vendor/github.com/skip2/go-qrcode/LICENSE
generated
vendored
Normal file
@ -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.
|
80
vendor/github.com/skip2/go-qrcode/README.md
generated
vendored
Normal file
80
vendor/github.com/skip2/go-qrcode/README.md
generated
vendored
Normal file
@ -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. [](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
|
||||
|
||||
[](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)
|
273
vendor/github.com/skip2/go-qrcode/bitset/bitset.go
generated
vendored
Normal file
273
vendor/github.com/skip2/go-qrcode/bitset/bitset.go
generated
vendored
Normal file
@ -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
|
||||
}
|
321
vendor/github.com/skip2/go-qrcode/bitset/bitset_test.go
generated
vendored
Normal file
321
vendor/github.com/skip2/go-qrcode/bitset/bitset_test.go
generated
vendored
Normal file
@ -0,0 +1,321 @@
|
||||
// go-qrcode
|
||||
// Copyright 2014 Tom Harwood
|
||||
|
||||
package bitset
|
||||
|
||||
import (
|
||||
rand "math/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewBitset(t *testing.T) {
|
||||
tests := [][]bool{
|
||||
{},
|
||||
{b1},
|
||||
{b0},
|
||||
{b1, b0},
|
||||
{b1, b0, b1},
|
||||
{b0, b0, b1},
|
||||
}
|
||||
|
||||
for _, v := range tests {
|
||||
result := New(v...)
|
||||
|
||||
if !equal(result.Bits(), v) {
|
||||
t.Errorf("%s", result.String())
|
||||
t.Errorf("%v => %v, want %v", v, result.Bits(), v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppend(t *testing.T) {
|
||||
randomBools := make([]bool, 128)
|
||||
|
||||
rng := rand.New(rand.NewSource(1))
|
||||
|
||||
for i := 0; i < len(randomBools); i++ {
|
||||
randomBools[i] = rng.Intn(2) == 1
|
||||
}
|
||||
|
||||
for i := 0; i < len(randomBools)-1; i++ {
|
||||
a := New(randomBools[0:i]...)
|
||||
b := New(randomBools[i:]...)
|
||||
|
||||
a.Append(b)
|
||||
|
||||
if !equal(a.Bits(), randomBools) {
|
||||
t.Errorf("got %v, want %v", a.Bits(), randomBools)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendByte(t *testing.T) {
|
||||
tests := []struct {
|
||||
initial *Bitset
|
||||
value byte
|
||||
numBits int
|
||||
expected *Bitset
|
||||
}{
|
||||
{
|
||||
New(),
|
||||
0x01,
|
||||
1,
|
||||
New(b1),
|
||||
},
|
||||
{
|
||||
New(b1),
|
||||
0x01,
|
||||
1,
|
||||
New(b1, b1),
|
||||
},
|
||||
{
|
||||
New(b0),
|
||||
0x01,
|
||||
1,
|
||||
New(b0, b1),
|
||||
},
|
||||
{
|
||||
New(b1, b0, b1, b0, b1, b0, b1),
|
||||
0xAA, // 0b10101010
|
||||
2,
|
||||
New(b1, b0, b1, b0, b1, b0, b1, b1, b0),
|
||||
},
|
||||
{
|
||||
New(b1, b0, b1, b0, b1, b0, b1),
|
||||
0xAA, // 0b10101010
|
||||
8,
|
||||
New(b1, b0, b1, b0, b1, b0, b1, b1, b0, b1, b0, b1, b0, b1, b0),
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
test.initial.AppendByte(test.value, test.numBits)
|
||||
if !equal(test.initial.Bits(), test.expected.Bits()) {
|
||||
t.Errorf("Got %v, expected %v", test.initial.Bits(),
|
||||
test.expected.Bits())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendUint32(t *testing.T) {
|
||||
tests := []struct {
|
||||
initial *Bitset
|
||||
value uint32
|
||||
numBits int
|
||||
expected *Bitset
|
||||
}{
|
||||
{
|
||||
New(),
|
||||
0xAAAAAAAF,
|
||||
4,
|
||||
New(b1, b1, b1, b1),
|
||||
},
|
||||
{
|
||||
New(),
|
||||
0xFFFFFFFF,
|
||||
32,
|
||||
New(b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1,
|
||||
b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1),
|
||||
},
|
||||
{
|
||||
New(),
|
||||
0x0,
|
||||
32,
|
||||
New(b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0,
|
||||
b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0),
|
||||
},
|
||||
{
|
||||
New(),
|
||||
0xAAAAAAAA,
|
||||
32,
|
||||
New(b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1,
|
||||
b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0),
|
||||
},
|
||||
{
|
||||
New(),
|
||||
0xAAAAAAAA,
|
||||
31,
|
||||
New(b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1,
|
||||
b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0),
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
test.initial.AppendUint32(test.value, test.numBits)
|
||||
if !equal(test.initial.Bits(), test.expected.Bits()) {
|
||||
t.Errorf("Got %v, expected %v", test.initial.Bits(),
|
||||
test.expected.Bits())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendBools(t *testing.T) {
|
||||
randomBools := make([]bool, 128)
|
||||
|
||||
rng := rand.New(rand.NewSource(1))
|
||||
|
||||
for i := 0; i < len(randomBools); i++ {
|
||||
randomBools[i] = rng.Intn(2) == 1
|
||||
}
|
||||
|
||||
for i := 0; i < len(randomBools)-1; i++ {
|
||||
result := New(randomBools[0:i]...)
|
||||
result.AppendBools(randomBools[i:]...)
|
||||
|
||||
if !equal(result.Bits(), randomBools) {
|
||||
t.Errorf("got %v, want %v", result.Bits(), randomBools)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkShortAppend(b *testing.B) {
|
||||
bitset := New()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
bitset.AppendBools(b0, b1, b0, b1, b0, b1, b0)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLen(t *testing.T) {
|
||||
randomBools := make([]bool, 128)
|
||||
|
||||
rng := rand.New(rand.NewSource(1))
|
||||
|
||||
for i := 0; i < len(randomBools); i++ {
|
||||
randomBools[i] = rng.Intn(2) == 1
|
||||
}
|
||||
|
||||
for i := 0; i < len(randomBools)-1; i++ {
|
||||
result := New(randomBools[0:i]...)
|
||||
|
||||
if result.Len() != i {
|
||||
t.Errorf("Len = %d, want %d", result.Len(), i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAt(t *testing.T) {
|
||||
test := []bool{b0, b1, b0, b1, b0, b1, b1, b0, b1}
|
||||
|
||||
bitset := New(test...)
|
||||
for i, v := range test {
|
||||
result := bitset.At(i)
|
||||
|
||||
if result != test[i] {
|
||||
t.Errorf("bitset[%d] => %t, want %t", i, result, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func equal(a []bool, b []bool) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := 0; i < len(a); i++ {
|
||||
if a[i] != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func TestExample(t *testing.T) {
|
||||
b := New() // {}
|
||||
b.AppendBools(true, true, false) // {1, 1, 0}
|
||||
b.AppendBools(true) // {1, 1, 0, 1}
|
||||
b.AppendByte(0x02, 4) // {1, 1, 0, 1, 0, 0, 1, 0}
|
||||
|
||||
expected := []bool{b1, b1, b0, b1, b0, b0, b1, b0}
|
||||
|
||||
if !equal(b.Bits(), expected) {
|
||||
t.Errorf("Got %v, expected %v", b.Bits(), expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestByteAt(t *testing.T) {
|
||||
data := []bool{b0, b1, b0, b1, b0, b1, b1, b0, b1}
|
||||
|
||||
tests := []struct {
|
||||
index int
|
||||
expected byte
|
||||
}{
|
||||
{
|
||||
0,
|
||||
0x56,
|
||||
},
|
||||
{
|
||||
1,
|
||||
0xad,
|
||||
},
|
||||
{
|
||||
2,
|
||||
0x2d,
|
||||
},
|
||||
{
|
||||
5,
|
||||
0x0d,
|
||||
},
|
||||
{
|
||||
8,
|
||||
0x01,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
b := New()
|
||||
b.AppendBools(data...)
|
||||
|
||||
result := b.ByteAt(test.index)
|
||||
|
||||
if result != test.expected {
|
||||
t.Errorf("Got %#x, expected %#x", result, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubstr(t *testing.T) {
|
||||
data := []bool{b0, b1, b0, b1, b0, b1, b1, b0}
|
||||
|
||||
tests := []struct {
|
||||
start int
|
||||
end int
|
||||
expected []bool
|
||||
}{
|
||||
{
|
||||
0,
|
||||
8,
|
||||
[]bool{b0, b1, b0, b1, b0, b1, b1, b0},
|
||||
},
|
||||
{
|
||||
0,
|
||||
0,
|
||||
[]bool{},
|
||||
},
|
||||
{
|
||||
0,
|
||||
1,
|
||||
[]bool{b0},
|
||||
},
|
||||
{
|
||||
2,
|
||||
4,
|
||||
[]bool{b0, b1},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
b := New()
|
||||
b.AppendBools(data...)
|
||||
|
||||
result := b.Substr(test.start, test.end)
|
||||
|
||||
expected := New()
|
||||
expected.AppendBools(test.expected...)
|
||||
|
||||
if !result.Equals(expected) {
|
||||
t.Errorf("Got %s, expected %s", result.String(), expected.String())
|
||||
}
|
||||
}
|
||||
}
|
455
vendor/github.com/skip2/go-qrcode/encoder.go
generated
vendored
Normal file
455
vendor/github.com/skip2/go-qrcode/encoder.go
generated
vendored
Normal file
@ -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
|
||||
}
|
328
vendor/github.com/skip2/go-qrcode/encoder_test.go
generated
vendored
Normal file
328
vendor/github.com/skip2/go-qrcode/encoder_test.go
generated
vendored
Normal file
@ -0,0 +1,328 @@
|
||||
// go-qrcode
|
||||
// Copyright 2014 Tom Harwood
|
||||
|
||||
package qrcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
bitset "github.com/skip2/go-qrcode/bitset"
|
||||
)
|
||||
|
||||
func TestClassifyDataMode(t *testing.T) {
|
||||
type Test struct {
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
data []byte
|
||||
actual []segment
|
||||
}{
|
||||
{
|
||||
[]byte{0x30},
|
||||
[]segment{
|
||||
{
|
||||
dataModeNumeric,
|
||||
[]byte{0x30},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
[]byte{0x30, 0x41, 0x42, 0x43, 0x20, 0x00, 0xf0, 0xf1, 0xf2, 0x31},
|
||||
[]segment{
|
||||
{
|
||||
dataModeNumeric,
|
||||
[]byte{0x30},
|
||||
},
|
||||
{
|
||||
dataModeAlphanumeric,
|
||||
[]byte{0x41, 0x42, 0x43, 0x20},
|
||||
},
|
||||
{
|
||||
dataModeByte,
|
||||
[]byte{0x00, 0xf0, 0xf1, 0xf2},
|
||||
},
|
||||
{
|
||||
dataModeNumeric,
|
||||
[]byte{0x31},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
encoder := newDataEncoder(dataEncoderType1To9)
|
||||
encoder.encode(test.data)
|
||||
|
||||
if !reflect.DeepEqual(test.actual, encoder.actual) {
|
||||
t.Errorf("Got %v, expected %v", encoder.actual, test.actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestByteModeLengthCalculations(t *testing.T) {
|
||||
tests := []struct {
|
||||
dataEncoderType dataEncoderType
|
||||
dataMode dataMode
|
||||
numSymbols int
|
||||
expectedLength int
|
||||
}{}
|
||||
|
||||
for i, test := range tests {
|
||||
encoder := newDataEncoder(test.dataEncoderType)
|
||||
var resultLength int
|
||||
|
||||
resultLength, err := encoder.encodedLength(test.dataMode, test.numSymbols)
|
||||
|
||||
if test.expectedLength == -1 {
|
||||
if err == nil {
|
||||
t.Errorf("Test %d: got length %d, expected error", i, resultLength)
|
||||
}
|
||||
} else if resultLength != test.expectedLength {
|
||||
t.Errorf("Test %d: got length %d, expected length %d", i, resultLength,
|
||||
test.expectedLength)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSingleModeEncodings(t *testing.T) {
|
||||
tests := []struct {
|
||||
dataEncoderType dataEncoderType
|
||||
dataMode dataMode
|
||||
data string
|
||||
expected *bitset.Bitset
|
||||
}{
|
||||
{
|
||||
dataEncoderType1To9,
|
||||
dataModeNumeric,
|
||||
"01234567",
|
||||
bitset.NewFromBase2String("0001 0000001000 0000001100 0101011001 1000011"),
|
||||
},
|
||||
{
|
||||
dataEncoderType1To9,
|
||||
dataModeAlphanumeric,
|
||||
"AC-42",
|
||||
bitset.NewFromBase2String("0010 000000101 00111001110 11100111001 000010"),
|
||||
},
|
||||
{
|
||||
dataEncoderType1To9,
|
||||
dataModeByte,
|
||||
"123",
|
||||
bitset.NewFromBase2String("0100 00000011 00110001 00110010 00110011"),
|
||||
},
|
||||
{
|
||||
dataEncoderType10To26,
|
||||
dataModeByte,
|
||||
"123",
|
||||
bitset.NewFromBase2String("0100 00000000 00000011 00110001 00110010 00110011"),
|
||||
},
|
||||
{
|
||||
dataEncoderType27To40,
|
||||
dataModeByte,
|
||||
"123",
|
||||
bitset.NewFromBase2String("0100 00000000 00000011 00110001 00110010 00110011"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
encoder := newDataEncoder(test.dataEncoderType)
|
||||
encoded := bitset.New()
|
||||
|
||||
encoder.encodeDataRaw([]byte(test.data), test.dataMode, encoded)
|
||||
|
||||
if !test.expected.Equals(encoded) {
|
||||
t.Errorf("For %s got %s, expected %s", test.data, encoded.String(),
|
||||
test.expected.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type testModeSegment struct {
|
||||
dataMode dataMode
|
||||
numChars int
|
||||
}
|
||||
|
||||
func TestOptimiseEncoding(t *testing.T) {
|
||||
tests := []struct {
|
||||
dataEncoderType dataEncoderType
|
||||
actual []testModeSegment
|
||||
optimised []testModeSegment
|
||||
}{
|
||||
// Coalescing multiple segments.
|
||||
{
|
||||
dataEncoderType1To9,
|
||||
[]testModeSegment{
|
||||
{dataModeAlphanumeric, 1}, // length = 4 + 9 + 6 = 19 bits
|
||||
{dataModeNumeric, 1}, // length = 4 + 10 + 4 = 18 bits
|
||||
{dataModeAlphanumeric, 1}, // 19 bits.
|
||||
{dataModeNumeric, 1}, // 18 bits.
|
||||
{dataModeAlphanumeric, 1}, // 19 bits.
|
||||
// total = 93 bits.
|
||||
},
|
||||
[]testModeSegment{
|
||||
{dataModeAlphanumeric, 5}, // length = 4 + 9 + 22 + 6 = 41.
|
||||
},
|
||||
},
|
||||
// Coalesing not necessary.
|
||||
{
|
||||
dataEncoderType1To9,
|
||||
[]testModeSegment{
|
||||
{dataModeAlphanumeric, 1},
|
||||
{dataModeNumeric, 20},
|
||||
},
|
||||
[]testModeSegment{
|
||||
{dataModeAlphanumeric, 1},
|
||||
{dataModeNumeric, 20},
|
||||
},
|
||||
},
|
||||
// Switch to more general dataMode.
|
||||
{
|
||||
dataEncoderType1To9,
|
||||
[]testModeSegment{
|
||||
{dataModeAlphanumeric, 1},
|
||||
{dataModeByte, 1},
|
||||
{dataModeNumeric, 1},
|
||||
},
|
||||
[]testModeSegment{
|
||||
{dataModeAlphanumeric, 1},
|
||||
{dataModeByte, 2},
|
||||
},
|
||||
},
|
||||
// https://www.google.com/123
|
||||
// BBBBBAAABBBABBBBBBABBBANNN
|
||||
{
|
||||
dataEncoderType1To9,
|
||||
[]testModeSegment{
|
||||
{dataModeByte, 5},
|
||||
{dataModeAlphanumeric, 3},
|
||||
{dataModeByte, 3},
|
||||
{dataModeAlphanumeric, 1},
|
||||
{dataModeByte, 6},
|
||||
{dataModeAlphanumeric, 1},
|
||||
{dataModeAlphanumeric, 4},
|
||||
{dataModeNumeric, 3},
|
||||
},
|
||||
[]testModeSegment{
|
||||
{dataModeByte, 23},
|
||||
{dataModeNumeric, 3},
|
||||
},
|
||||
},
|
||||
// HTTPS://WWW.GOOGLE.COM/123
|
||||
// AAAAAAAAAAAAAAAAAAAAAAANNN
|
||||
{
|
||||
dataEncoderType1To9,
|
||||
[]testModeSegment{
|
||||
{dataModeAlphanumeric, 23},
|
||||
{dataModeNumeric, 3},
|
||||
},
|
||||
[]testModeSegment{
|
||||
{dataModeAlphanumeric, 26},
|
||||
},
|
||||
},
|
||||
{
|
||||
dataEncoderType27To40,
|
||||
[]testModeSegment{
|
||||
{dataModeByte, 1},
|
||||
{dataModeNumeric, 1},
|
||||
{dataModeByte, 1},
|
||||
{dataModeNumeric, 1},
|
||||
{dataModeByte, 1},
|
||||
{dataModeNumeric, 1},
|
||||
{dataModeByte, 1},
|
||||
{dataModeNumeric, 1},
|
||||
},
|
||||
[]testModeSegment{
|
||||
{dataModeByte, 8},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
numTotalChars := 0
|
||||
for _, v := range test.actual {
|
||||
numTotalChars += v.numChars
|
||||
}
|
||||
|
||||
data := make([]byte, numTotalChars)
|
||||
|
||||
i := 0
|
||||
for _, v := range test.actual {
|
||||
for j := 0; j < v.numChars; j++ {
|
||||
switch v.dataMode {
|
||||
case dataModeNumeric:
|
||||
data[i] = '1'
|
||||
case dataModeAlphanumeric:
|
||||
data[i] = 'A'
|
||||
case dataModeByte:
|
||||
data[i] = '#'
|
||||
default:
|
||||
t.Fatal("Unrecognised data mode")
|
||||
}
|
||||
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
encoder := newDataEncoder(test.dataEncoderType)
|
||||
|
||||
_, err := encoder.encode(data)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Got %s, expected valid encoding", err.Error())
|
||||
} else {
|
||||
ok := true
|
||||
|
||||
if len(encoder.optimised) != len(test.optimised) {
|
||||
ok = false
|
||||
} else {
|
||||
for i, s := range test.optimised {
|
||||
if encoder.optimised[i].dataMode != s.dataMode ||
|
||||
len(encoder.optimised[i].data) != s.numChars {
|
||||
ok = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !ok {
|
||||
t.Errorf("got %s, expected %s", segmentsString(encoder.optimised),
|
||||
testModeSegmentsString(test.optimised))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testModeSegmentsString(segments []testModeSegment) string {
|
||||
result := "["
|
||||
|
||||
for i, segment := range segments {
|
||||
if i > 0 {
|
||||
result += ", "
|
||||
}
|
||||
|
||||
result += fmt.Sprintf("%d*%s", segment.numChars,
|
||||
dataModeString(segment.dataMode))
|
||||
}
|
||||
|
||||
result += "]"
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func segmentsString(segments []segment) string {
|
||||
result := "["
|
||||
|
||||
for i, segment := range segments {
|
||||
if i > 0 {
|
||||
result += ", "
|
||||
}
|
||||
|
||||
result += fmt.Sprintf("%d*%s", len(segment.data),
|
||||
dataModeString(segment.dataMode))
|
||||
}
|
||||
|
||||
result += "]"
|
||||
|
||||
return result
|
||||
}
|
31
vendor/github.com/skip2/go-qrcode/example_test.go
generated
vendored
Normal file
31
vendor/github.com/skip2/go-qrcode/example_test.go
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
// go-qrcode
|
||||
// Copyright 2014 Tom Harwood
|
||||
/*
|
||||
Amendments Thu, 2017-December-14:
|
||||
- test integration (go test -v)
|
||||
- idiomatic go code
|
||||
*/
|
||||
package qrcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestExampleEncode(t *testing.T) {
|
||||
if png, err := Encode("https://example.org", Medium, 256); err != nil {
|
||||
t.Errorf("Error: %s", err.Error())
|
||||
} else {
|
||||
fmt.Printf("PNG is %d bytes long", len(png))
|
||||
}
|
||||
}
|
||||
|
||||
func TestExampleWriteFile(t *testing.T) {
|
||||
filename := "example.png"
|
||||
if err := WriteFile("https://example.org", Medium, 256, filename); err != nil {
|
||||
if err = os.Remove(filename); err != nil {
|
||||
t.Errorf("Error: %s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
554
vendor/github.com/skip2/go-qrcode/qrcode.go
generated
vendored
Normal file
554
vendor/github.com/skip2/go-qrcode/qrcode.go
generated
vendored
Normal file
@ -0,0 +1,554 @@
|
||||
// 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)
|
||||
|
||||
for i := 0; i < size; i++ {
|
||||
for j := 0; j < size; j++ {
|
||||
img.Set(i, j, q.BackgroundColor)
|
||||
}
|
||||
}
|
||||
|
||||
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++ {
|
||||
img.Set(i, j, q.ForegroundColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
85
vendor/github.com/skip2/go-qrcode/qrcode/main.go
generated
vendored
Normal file
85
vendor/github.com/skip2/go-qrcode/qrcode/main.go
generated
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
// go-qrcode
|
||||
// Copyright 2014 Tom Harwood
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
qrcode "github.com/skip2/go-qrcode"
|
||||
)
|
||||
|
||||
func main() {
|
||||
outFile := flag.String("o", "", "out PNG file prefix, empty for stdout")
|
||||
size := flag.Int("s", 256, "image size (pixel)")
|
||||
textArt := flag.Bool("t", false, "print as text-art on stdout")
|
||||
negative := flag.Bool("i", false, "invert black and white")
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintf(os.Stderr, `qrcode -- QR Code encoder in Go
|
||||
https://github.com/skip2/go-qrcode
|
||||
|
||||
Flags:
|
||||
`)
|
||||
flag.PrintDefaults()
|
||||
fmt.Fprintf(os.Stderr, `
|
||||
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
|
||||
|
||||
`)
|
||||
}
|
||||
flag.Parse()
|
||||
|
||||
if len(flag.Args()) == 0 {
|
||||
flag.Usage()
|
||||
checkError(fmt.Errorf("Error: no content given"))
|
||||
}
|
||||
|
||||
content := strings.Join(flag.Args(), " ")
|
||||
|
||||
var err error
|
||||
var q *qrcode.QRCode
|
||||
q, err = qrcode.New(content, qrcode.Highest)
|
||||
checkError(err)
|
||||
|
||||
if *textArt {
|
||||
art := q.ToString(*negative)
|
||||
fmt.Println(art)
|
||||
return
|
||||
}
|
||||
|
||||
if *negative {
|
||||
q.ForegroundColor, q.BackgroundColor = q.BackgroundColor, q.ForegroundColor
|
||||
}
|
||||
|
||||
var png []byte
|
||||
png, err = q.PNG(*size)
|
||||
checkError(err)
|
||||
|
||||
if *outFile == "" {
|
||||
os.Stdout.Write(png)
|
||||
} else {
|
||||
var fh *os.File
|
||||
fh, err = os.Create(*outFile + ".png")
|
||||
checkError(err)
|
||||
defer fh.Close()
|
||||
fh.Write(png)
|
||||
}
|
||||
}
|
||||
|
||||
func checkError(err error) {
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
232
vendor/github.com/skip2/go-qrcode/qrcode_decode_test.go
generated
vendored
Normal file
232
vendor/github.com/skip2/go-qrcode/qrcode_decode_test.go
generated
vendored
Normal file
@ -0,0 +1,232 @@
|
||||
// go-qrcode
|
||||
// Copyright 2014 Tom Harwood
|
||||
|
||||
package qrcode
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// These tests use zbarimg to decode generated QR Codes to ensure they are
|
||||
// readable. sudo apt-get install zbar-tools, or download from
|
||||
// http://zbar.sourceforge.net.
|
||||
//
|
||||
// By default these tests are disabled to avoid a dependency on zbarimg if
|
||||
// you're not running the tests. Use the -test-decode flag (go test
|
||||
// -test-decode) to enable.
|
||||
|
||||
var testDecode *bool = flag.Bool("test-decode",
|
||||
false,
|
||||
"Enable decode tests. Requires zbarimg installed.")
|
||||
|
||||
var testDecodeFuzz *bool = flag.Bool("test-decode-fuzz",
|
||||
false,
|
||||
"Enable decode fuzz tests. Requires zbarimg installed.")
|
||||
|
||||
func TestDecodeBasic(t *testing.T) {
|
||||
if !*testDecode {
|
||||
t.Skip("Decode tests not enabled")
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
content string
|
||||
numRepetitions int
|
||||
level RecoveryLevel
|
||||
}{
|
||||
{
|
||||
"A",
|
||||
1,
|
||||
Low,
|
||||
},
|
||||
{
|
||||
"A",
|
||||
1,
|
||||
Medium,
|
||||
},
|
||||
{
|
||||
"A",
|
||||
1,
|
||||
High,
|
||||
},
|
||||
{
|
||||
"A",
|
||||
1,
|
||||
Highest,
|
||||
},
|
||||
{
|
||||
"01234567",
|
||||
1,
|
||||
Medium,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
content := strings.Repeat(test.content, test.numRepetitions)
|
||||
|
||||
q, err := New(content, test.level)
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
|
||||
err = zbarimgCheck(q)
|
||||
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeAllVersionLevels(t *testing.T) {
|
||||
if !*testDecode {
|
||||
t.Skip("Decode tests not enabled")
|
||||
}
|
||||
|
||||
for version := 1; version <= 40; version++ {
|
||||
for _, level := range []RecoveryLevel{Low, Medium, High, Highest} {
|
||||
t.Logf("Version=%d Level=%d",
|
||||
version,
|
||||
level)
|
||||
|
||||
q, err := newWithForcedVersion(
|
||||
fmt.Sprintf("v-%d l-%d", version, level), version, level)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = zbarimgCheck(q)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Version=%d Level=%d, err=%s, expected success",
|
||||
version,
|
||||
level,
|
||||
err.Error())
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeAllCharacters(t *testing.T) {
|
||||
if !*testDecode {
|
||||
t.Skip("Decode tests not enabled")
|
||||
}
|
||||
|
||||
var content string
|
||||
|
||||
// zbarimg has trouble with null bytes, hence start from ASCII 1.
|
||||
for i := 1; i < 256; i++ {
|
||||
content += string(i)
|
||||
}
|
||||
|
||||
q, err := New(content, Low)
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
|
||||
err = zbarimgCheck(q)
|
||||
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeFuzz(t *testing.T) {
|
||||
if !*testDecodeFuzz {
|
||||
t.Skip("Decode fuzz tests not enabled")
|
||||
}
|
||||
|
||||
r := rand.New(rand.NewSource(0))
|
||||
|
||||
const iterations int = 32
|
||||
const maxLength int = 128
|
||||
|
||||
for i := 0; i < iterations; i++ {
|
||||
len := r.Intn(maxLength-1) + 1
|
||||
|
||||
var content string
|
||||
for j := 0; j < len; j++ {
|
||||
// zbarimg seems to have trouble with special characters, test printable
|
||||
// characters only for now.
|
||||
content += string(32 + r.Intn(94))
|
||||
}
|
||||
|
||||
for _, level := range []RecoveryLevel{Low, Medium, High, Highest} {
|
||||
q, err := New(content, level)
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
|
||||
err = zbarimgCheck(q)
|
||||
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func zbarimgCheck(q *QRCode) error {
|
||||
s, err := zbarimgDecode(q)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if s != q.Content {
|
||||
q.WriteFile(256, fmt.Sprintf("%x.png", q.Content))
|
||||
return fmt.Errorf("got '%s' (%x) expected '%s' (%x)", s, s, q.Content, q.Content)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func zbarimgDecode(q *QRCode) (string, error) {
|
||||
var png []byte
|
||||
|
||||
// 512x512px
|
||||
png, err := q.PNG(512)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
cmd := exec.Command("zbarimg", "--quiet", "-Sdisable",
|
||||
"-Sqrcode.enable", "/dev/stdin")
|
||||
|
||||
var out bytes.Buffer
|
||||
|
||||
cmd.Stdin = bytes.NewBuffer(png)
|
||||
cmd.Stdout = &out
|
||||
|
||||
err = cmd.Run()
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return strings.TrimSuffix(strings.TrimPrefix(out.String(), "QR-Code:"), "\n"), nil
|
||||
}
|
||||
|
||||
func BenchmarkDecodeTest(b *testing.B) {
|
||||
if !*testDecode {
|
||||
b.Skip("Decode benchmarks not enabled")
|
||||
}
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
q, err := New("content", Medium)
|
||||
if err != nil {
|
||||
b.Error(err.Error())
|
||||
}
|
||||
|
||||
err = zbarimgCheck(q)
|
||||
|
||||
if err != nil {
|
||||
b.Error(err.Error())
|
||||
}
|
||||
}
|
||||
}
|
173
vendor/github.com/skip2/go-qrcode/qrcode_test.go
generated
vendored
Normal file
173
vendor/github.com/skip2/go-qrcode/qrcode_test.go
generated
vendored
Normal file
@ -0,0 +1,173 @@
|
||||
// go-qrcode
|
||||
// Copyright 2014 Tom Harwood
|
||||
|
||||
package qrcode
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestQRCodeMaxCapacity(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skipping TestQRCodeCapacity")
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
string string
|
||||
numRepetitions int
|
||||
}{
|
||||
{
|
||||
"0",
|
||||
7089,
|
||||
},
|
||||
{
|
||||
"A",
|
||||
4296,
|
||||
},
|
||||
{
|
||||
"#",
|
||||
2953,
|
||||
},
|
||||
// Alternate byte/numeric data types. Optimises to 2,952 bytes.
|
||||
{
|
||||
"#1",
|
||||
1476,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
_, err := New(strings.Repeat(test.string, test.numRepetitions), Low)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("%d x '%s' got %s expected success", test.numRepetitions,
|
||||
test.string, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
_, err := New(strings.Repeat(test.string, test.numRepetitions+1), Low)
|
||||
|
||||
if err == nil {
|
||||
t.Errorf("%d x '%s' chars encodable, expected not encodable",
|
||||
test.numRepetitions+1, test.string)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestQRCodeVersionCapacity(t *testing.T) {
|
||||
tests := []struct {
|
||||
version int
|
||||
level RecoveryLevel
|
||||
maxNumeric int
|
||||
maxAlphanumeric int
|
||||
maxByte int
|
||||
}{
|
||||
{
|
||||
1,
|
||||
Low,
|
||||
41,
|
||||
25,
|
||||
17,
|
||||
},
|
||||
{
|
||||
2,
|
||||
Low,
|
||||
77,
|
||||
47,
|
||||
32,
|
||||
},
|
||||
{
|
||||
2,
|
||||
Highest,
|
||||
34,
|
||||
20,
|
||||
14,
|
||||
},
|
||||
{
|
||||
40,
|
||||
Low,
|
||||
7089,
|
||||
4296,
|
||||
2953,
|
||||
},
|
||||
{
|
||||
40,
|
||||
Highest,
|
||||
3057,
|
||||
1852,
|
||||
1273,
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
numericData := strings.Repeat("1", test.maxNumeric)
|
||||
alphanumericData := strings.Repeat("A", test.maxAlphanumeric)
|
||||
byteData := strings.Repeat("#", test.maxByte)
|
||||
|
||||
var n *QRCode
|
||||
var a *QRCode
|
||||
var b *QRCode
|
||||
var err error
|
||||
|
||||
n, err = New(numericData, test.level)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
a, err = New(alphanumericData, test.level)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
b, err = New(byteData, test.level)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if n.VersionNumber != test.version {
|
||||
t.Fatalf("Test #%d numeric has version #%d, expected #%d", i,
|
||||
n.VersionNumber, test.version)
|
||||
}
|
||||
|
||||
if a.VersionNumber != test.version {
|
||||
t.Fatalf("Test #%d alphanumeric has version #%d, expected #%d", i,
|
||||
a.VersionNumber, test.version)
|
||||
}
|
||||
|
||||
if b.VersionNumber != test.version {
|
||||
t.Fatalf("Test #%d byte has version #%d, expected #%d", i,
|
||||
b.VersionNumber, test.version)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestQRCodeISOAnnexIExample(t *testing.T) {
|
||||
var q *QRCode
|
||||
q, err := New("01234567", Medium)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Error producing ISO Annex I Example: %s, expected success",
|
||||
err.Error())
|
||||
}
|
||||
|
||||
const expectedMask int = 2
|
||||
|
||||
if q.mask != 2 {
|
||||
t.Errorf("ISO Annex I example mask got %d, expected %d\n", q.mask,
|
||||
expectedMask)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkQRCodeURLSize(b *testing.B) {
|
||||
for n := 0; n < b.N; n++ {
|
||||
New("http://www.example.org", Medium)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkQRCodeMaximumSize(b *testing.B) {
|
||||
for n := 0; n < b.N; n++ {
|
||||
// 7089 is the maximum encodable number of numeric digits.
|
||||
New(strings.Repeat("0", 7089), Low)
|
||||
}
|
||||
}
|
387
vendor/github.com/skip2/go-qrcode/reedsolomon/gf2_8.go
generated
vendored
Normal file
387
vendor/github.com/skip2/go-qrcode/reedsolomon/gf2_8.go
generated
vendored
Normal file
@ -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
|
83
vendor/github.com/skip2/go-qrcode/reedsolomon/gf2_8_test.go
generated
vendored
Normal file
83
vendor/github.com/skip2/go-qrcode/reedsolomon/gf2_8_test.go
generated
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
// go-qrcode
|
||||
// Copyright 2014 Tom Harwood
|
||||
|
||||
package reedsolomon
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestGFMultiplicationIdentities(t *testing.T) {
|
||||
for i := 0; i < 256; i++ {
|
||||
value := gfElement(i)
|
||||
if gfMultiply(gfZero, value) != gfZero {
|
||||
t.Errorf("0 . %d != 0", value)
|
||||
}
|
||||
|
||||
if gfMultiply(value, gfOne) != value {
|
||||
t.Errorf("%d . 1 == %d, want %d", value, gfMultiply(value, gfOne), value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGFMultiplicationAndDivision(t *testing.T) {
|
||||
// a * b == result
|
||||
var tests = []struct {
|
||||
a gfElement
|
||||
b gfElement
|
||||
result gfElement
|
||||
}{
|
||||
{0, 29, 0},
|
||||
{1, 1, 1},
|
||||
{1, 32, 32},
|
||||
{2, 4, 8},
|
||||
{16, 128, 232},
|
||||
{17, 17, 28},
|
||||
{27, 9, 195},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
result := gfMultiply(test.a, test.b)
|
||||
|
||||
if result != test.result {
|
||||
t.Errorf("%d * %d = %d, want %d", test.a, test.b, result, test.result)
|
||||
}
|
||||
|
||||
if test.b != gfZero && test.result != gfZero {
|
||||
b := gfDivide(test.result, test.a)
|
||||
|
||||
if b != test.b {
|
||||
t.Errorf("%d / %d = %d, want %d", test.result, test.a, b, test.b)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGFInverse(t *testing.T) {
|
||||
for i := 1; i < 256; i++ {
|
||||
a := gfElement(i)
|
||||
inverse := gfInverse(a)
|
||||
|
||||
result := gfMultiply(a, inverse)
|
||||
|
||||
if result != gfOne {
|
||||
t.Errorf("%d * %d^-1 == %d, want %d", a, inverse, result, gfOne)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGFDivide(t *testing.T) {
|
||||
for i := 1; i < 256; i++ {
|
||||
for j := 1; j < 256; j++ {
|
||||
// a * b == product
|
||||
a := gfElement(i)
|
||||
b := gfElement(j)
|
||||
product := gfMultiply(a, b)
|
||||
|
||||
// product / b == a
|
||||
result := gfDivide(product, b)
|
||||
|
||||
if result != a {
|
||||
t.Errorf("%d / %d == %d, want %d", product, b, result, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
216
vendor/github.com/skip2/go-qrcode/reedsolomon/gf_poly.go
generated
vendored
Normal file
216
vendor/github.com/skip2/go-qrcode/reedsolomon/gf_poly.go
generated
vendored
Normal file
@ -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
|
||||
}
|
182
vendor/github.com/skip2/go-qrcode/reedsolomon/gf_poly_test.go
generated
vendored
Normal file
182
vendor/github.com/skip2/go-qrcode/reedsolomon/gf_poly_test.go
generated
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
// go-qrcode
|
||||
// Copyright 2014 Tom Harwood
|
||||
|
||||
package reedsolomon
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGFPolyAdd(t *testing.T) {
|
||||
// a + b == result
|
||||
var tests = []struct {
|
||||
a gfPoly
|
||||
b gfPoly
|
||||
result gfPoly
|
||||
}{
|
||||
{
|
||||
gfPoly{[]gfElement{0, 0, 0}},
|
||||
gfPoly{[]gfElement{0}},
|
||||
gfPoly{[]gfElement{}},
|
||||
},
|
||||
{
|
||||
gfPoly{[]gfElement{1, 0}},
|
||||
gfPoly{[]gfElement{1, 0}},
|
||||
gfPoly{[]gfElement{0, 0}},
|
||||
},
|
||||
{
|
||||
gfPoly{[]gfElement{0xA0, 0x80, 0xFF, 0x00}},
|
||||
gfPoly{[]gfElement{0x0A, 0x82}},
|
||||
gfPoly{[]gfElement{0xAA, 0x02, 0xFF}},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
result := gfPolyAdd(test.a, test.b)
|
||||
|
||||
if !test.result.equals(result) {
|
||||
t.Errorf("%s * %s != %s (got %s)\n", test.a.string(false), test.b.string(false),
|
||||
test.result.string(false), result.string(false))
|
||||
}
|
||||
|
||||
if len(result.term) > 0 && result.term[len(result.term)-1] == 0 {
|
||||
t.Errorf("Result's maximum term coefficient is zero")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGFPolyequals(t *testing.T) {
|
||||
// a == b if isEqual
|
||||
var tests = []struct {
|
||||
a gfPoly
|
||||
b gfPoly
|
||||
isEqual bool
|
||||
}{
|
||||
{
|
||||
gfPoly{[]gfElement{0}},
|
||||
gfPoly{[]gfElement{0}},
|
||||
true,
|
||||
},
|
||||
{
|
||||
gfPoly{[]gfElement{1}},
|
||||
gfPoly{[]gfElement{0}},
|
||||
false,
|
||||
},
|
||||
{
|
||||
gfPoly{[]gfElement{1, 0, 1, 0, 1}},
|
||||
gfPoly{[]gfElement{1, 0, 1, 0, 1}},
|
||||
true,
|
||||
},
|
||||
{
|
||||
gfPoly{[]gfElement{1, 0, 1}},
|
||||
gfPoly{[]gfElement{1, 0, 1, 0, 0}},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
isEqual := test.a.equals(test.b)
|
||||
|
||||
if isEqual != test.isEqual {
|
||||
t.Errorf("%s and %s equality is %t (got %t)\n", test.a.string(false), test.b.string(false),
|
||||
test.isEqual, isEqual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGFPolyMultiply(t *testing.T) {
|
||||
// a * b == result
|
||||
var tests = []struct {
|
||||
a gfPoly
|
||||
b gfPoly
|
||||
result gfPoly
|
||||
}{
|
||||
{
|
||||
gfPoly{[]gfElement{0, 0, 1}},
|
||||
gfPoly{[]gfElement{9}},
|
||||
gfPoly{[]gfElement{0, 0, 9}},
|
||||
},
|
||||
{
|
||||
gfPoly{[]gfElement{0, 16, 1}},
|
||||
gfPoly{[]gfElement{128, 2}},
|
||||
gfPoly{[]gfElement{0, 232, 160, 2}},
|
||||
},
|
||||
{
|
||||
gfPoly{[]gfElement{254, 120, 88, 44, 11, 1}},
|
||||
gfPoly{[]gfElement{16, 2, 0, 51, 44}},
|
||||
gfPoly{[]gfElement{91, 50, 25, 184, 194, 105, 45, 244, 58, 44}},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
result := gfPolyMultiply(test.a, test.b)
|
||||
|
||||
if !test.result.equals(result) {
|
||||
t.Errorf("%s * %s = %s (got %s)\n",
|
||||
test.a.string(false),
|
||||
test.b.string(false),
|
||||
test.result.string(false),
|
||||
result.string(false))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGFPolyRemainder(t *testing.T) {
|
||||
// numerator / denominator == quotient + remainder.
|
||||
var tests = []struct {
|
||||
numerator gfPoly
|
||||
denominator gfPoly
|
||||
remainder gfPoly
|
||||
}{
|
||||
{
|
||||
gfPoly{[]gfElement{1}},
|
||||
gfPoly{[]gfElement{1}},
|
||||
gfPoly{[]gfElement{0}},
|
||||
},
|
||||
{
|
||||
gfPoly{[]gfElement{1, 0}},
|
||||
gfPoly{[]gfElement{1}},
|
||||
gfPoly{[]gfElement{0}},
|
||||
},
|
||||
{
|
||||
gfPoly{[]gfElement{1}},
|
||||
gfPoly{[]gfElement{1, 0}},
|
||||
gfPoly{[]gfElement{1}},
|
||||
},
|
||||
{
|
||||
gfPoly{[]gfElement{1, 0, 1}},
|
||||
gfPoly{[]gfElement{0, 1}},
|
||||
gfPoly{[]gfElement{1}},
|
||||
},
|
||||
// (x^12 + x^10) / (x^10 + x^8 + x^5 + x^4 + x^2 + x^1 + x^0) =
|
||||
// (x^10 + x^8 + x^5 + x^4 + x^2 + x^1 + x^0) * x^2 +
|
||||
// (x^7 + x^6 + x^4 + x^3 + x^2) (the remainder)
|
||||
{
|
||||
gfPoly{[]gfElement{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1}},
|
||||
gfPoly{[]gfElement{1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1}},
|
||||
gfPoly{[]gfElement{0, 0, 1, 1, 1, 0, 1, 1}},
|
||||
},
|
||||
{
|
||||
gfPoly{[]gfElement{91, 50, 25, 184, 194, 105, 45, 244, 58, 44}},
|
||||
gfPoly{[]gfElement{254, 120, 88, 44, 11, 1}},
|
||||
gfPoly{[]gfElement{}},
|
||||
},
|
||||
{
|
||||
gfPoly{[]gfElement{0, 0, 0, 0, 0, 0, 195, 172, 24, 64}},
|
||||
gfPoly{[]gfElement{116, 147, 63, 198, 31, 1}},
|
||||
gfPoly{[]gfElement{48, 174, 34, 13, 134}},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
remainder := gfPolyRemainder(test.numerator, test.denominator)
|
||||
|
||||
if !test.remainder.equals(remainder) {
|
||||
t.Errorf("%s / %s, remainder = %s (got %s)\n",
|
||||
test.numerator.string(false),
|
||||
test.denominator.string(false),
|
||||
test.remainder.string(false),
|
||||
remainder.string(false))
|
||||
}
|
||||
}
|
||||
}
|
73
vendor/github.com/skip2/go-qrcode/reedsolomon/reed_solomon.go
generated
vendored
Normal file
73
vendor/github.com/skip2/go-qrcode/reedsolomon/reed_solomon.go
generated
vendored
Normal file
@ -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
|
||||
}
|
89
vendor/github.com/skip2/go-qrcode/reedsolomon/reed_solomon_test.go
generated
vendored
Normal file
89
vendor/github.com/skip2/go-qrcode/reedsolomon/reed_solomon_test.go
generated
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
// go-qrcode
|
||||
// Copyright 2014 Tom Harwood
|
||||
|
||||
package reedsolomon
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
bitset "github.com/skip2/go-qrcode/bitset"
|
||||
)
|
||||
|
||||
func TestGeneratorPoly(t *testing.T) {
|
||||
var tests = []struct {
|
||||
degree int
|
||||
generator gfPoly
|
||||
}{
|
||||
// x^2 + 3x^1 + 2x^0 (the shortest generator poly)
|
||||
{
|
||||
2,
|
||||
gfPoly{term: []gfElement{2, 3, 1}},
|
||||
},
|
||||
// x^5 + 31x^4 + 198x^3 + 63x^2 + 147x^1 + 116x^0
|
||||
{
|
||||
5,
|
||||
gfPoly{term: []gfElement{116, 147, 63, 198, 31, 1}},
|
||||
},
|
||||
// x^68 + 131x^67 + 115x^66 + 9x^65 + 39x^64 + 18x^63 + 182x^62 + 60x^61 +
|
||||
// 94x^60 + 223x^59 + 230x^58 + 157x^57 + 142x^56 + 119x^55 + 85x^54 +
|
||||
// 107x^53 + 34x^52 + 174x^51 + 167x^50 + 109x^49 + 20x^48 + 185x^47 +
|
||||
// 112x^46 + 145x^45 + 172x^44 + 224x^43 + 170x^42 + 182x^41 + 107x^40 +
|
||||
// 38x^39 + 107x^38 + 71x^37 + 246x^36 + 230x^35 + 225x^34 + 144x^33 +
|
||||
// 20x^32 + 14x^31 + 175x^30 + 226x^29 + 245x^28 + 20x^27 + 219x^26 +
|
||||
// 212x^25 + 51x^24 + 158x^23 + 88x^22 + 63x^21 + 36x^20 + 199x^19 + 4x^18 +
|
||||
// 80x^17 + 157x^16 + 211x^15 + 239x^14 + 255x^13 + 7x^12 + 119x^11 + 11x^10
|
||||
// + 235x^9 + 12x^8 + 34x^7 + 149x^6 + 204x^5 + 8x^4 + 32x^3 + 29x^2 + 99x^1
|
||||
// + 11x^0 (the longest generator poly)
|
||||
{
|
||||
68,
|
||||
gfPoly{term: []gfElement{11, 99, 29, 32, 8, 204, 149, 34, 12,
|
||||
235, 11, 119, 7, 255, 239, 211, 157, 80, 4, 199, 36, 63, 88, 158, 51, 212,
|
||||
219, 20, 245, 226, 175, 14, 20, 144, 225, 230, 246, 71, 107, 38, 107, 182,
|
||||
170, 224, 172, 145, 112, 185, 20, 109, 167, 174, 34, 107, 85, 119, 142,
|
||||
157, 230, 223, 94, 60, 182, 18, 39, 9, 115, 131, 1}},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
generator := rsGeneratorPoly(test.degree)
|
||||
|
||||
if !generator.equals(test.generator) {
|
||||
t.Errorf("degree=%d generator=%s, want %s", test.degree,
|
||||
generator.string(true), test.generator.string(true))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncode(t *testing.T) {
|
||||
var tests = []struct {
|
||||
numECBytes int
|
||||
data string
|
||||
rsCode string
|
||||
}{
|
||||
{
|
||||
5,
|
||||
"01000000 00011000 10101100 11000011 00000000",
|
||||
"01000000 00011000 10101100 11000011 00000000 10000110 00001101 00100010 10101110 00110000",
|
||||
},
|
||||
{
|
||||
10,
|
||||
"00010000 00100000 00001100 01010110 01100001 10000000 11101100 00010001 11101100 00010001 11101100 00010001 11101100 00010001 11101100 00010001",
|
||||
"00010000 00100000 00001100 01010110 01100001 10000000 11101100 00010001 11101100 00010001 11101100 00010001 11101100 00010001 11101100 00010001 10100101 00100100 11010100 11000001 11101101 00110110 11000111 10000111 00101100 01010101",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
data := bitset.NewFromBase2String(test.data)
|
||||
rsCode := bitset.NewFromBase2String(test.rsCode)
|
||||
|
||||
result := Encode(data, test.numECBytes)
|
||||
|
||||
if !rsCode.Equals(result) {
|
||||
t.Errorf("data=%s, numECBytes=%d, encoded=%s, want %s",
|
||||
data.String(),
|
||||
test.numECBytes,
|
||||
result.String(),
|
||||
rsCode)
|
||||
}
|
||||
}
|
||||
}
|
309
vendor/github.com/skip2/go-qrcode/regular_symbol.go
generated
vendored
Normal file
309
vendor/github.com/skip2/go-qrcode/regular_symbol.go
generated
vendored
Normal file
@ -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 := ®ularSymbol{
|
||||
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
|
||||
}
|
31
vendor/github.com/skip2/go-qrcode/regular_symbol_test.go
generated
vendored
Normal file
31
vendor/github.com/skip2/go-qrcode/regular_symbol_test.go
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
// go-qrcode
|
||||
// Copyright 2014 Tom Harwood
|
||||
|
||||
package qrcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
bitset "github.com/skip2/go-qrcode/bitset"
|
||||
)
|
||||
|
||||
func TestBuildRegularSymbol(t *testing.T) {
|
||||
for k := 0; k <= 7; k++ {
|
||||
v := getQRCodeVersion(Low, 1)
|
||||
|
||||
data := bitset.New()
|
||||
for i := 0; i < 26; i++ {
|
||||
data.AppendNumBools(8, false)
|
||||
}
|
||||
|
||||
s, err := buildRegularSymbol(*v, k, data)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
} else {
|
||||
_ = s
|
||||
//fmt.Print(m.string())
|
||||
}
|
||||
}
|
||||
}
|
309
vendor/github.com/skip2/go-qrcode/symbol.go
generated
vendored
Normal file
309
vendor/github.com/skip2/go-qrcode/symbol.go
generated
vendored
Normal file
@ -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))
|
||||
}
|
334
vendor/github.com/skip2/go-qrcode/symbol_test.go
generated
vendored
Normal file
334
vendor/github.com/skip2/go-qrcode/symbol_test.go
generated
vendored
Normal file
@ -0,0 +1,334 @@
|
||||
// go-qrcode
|
||||
// Copyright 2014 Tom Harwood
|
||||
|
||||
package qrcode
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestSymbolBasic(t *testing.T) {
|
||||
size := 10
|
||||
quietZoneSize := 4
|
||||
|
||||
m := newSymbol(size, quietZoneSize)
|
||||
|
||||
if m.size != size+quietZoneSize*2 {
|
||||
t.Errorf("Symbol size is %d, expected %d", m.size, size+quietZoneSize*2)
|
||||
}
|
||||
|
||||
for i := 0; i < size; i++ {
|
||||
for j := 0; j < size; j++ {
|
||||
|
||||
v := m.get(i, j)
|
||||
|
||||
if v != false {
|
||||
t.Errorf("New symbol not empty")
|
||||
}
|
||||
|
||||
if !m.empty(i, j) {
|
||||
t.Errorf("New symbol is not empty")
|
||||
}
|
||||
|
||||
value := i*j%2 == 0
|
||||
m.set(i, j, value)
|
||||
|
||||
v = m.get(i, j)
|
||||
|
||||
if v != value {
|
||||
t.Errorf("Symbol ignores set bits")
|
||||
}
|
||||
|
||||
if m.empty(i, j) {
|
||||
t.Errorf("Symbol ignores set bits")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSymbolPenalties(t *testing.T) {
|
||||
tests := []struct {
|
||||
pattern [][]bool
|
||||
expectedPenalty1 int
|
||||
expectedPenalty2 int
|
||||
expectedPenalty3 int
|
||||
expectedPenalty4 int
|
||||
}{
|
||||
{
|
||||
[][]bool{
|
||||
{b0, b1, b0, b1, b0, b1},
|
||||
{b1, b0, b1, b0, b1, b0},
|
||||
{b0, b1, b0, b1, b0, b1},
|
||||
{b1, b0, b1, b0, b1, b0},
|
||||
{b0, b1, b0, b1, b0, b1},
|
||||
{b1, b0, b1, b0, b1, b0},
|
||||
},
|
||||
0, // No adjacent modules of same color.
|
||||
0, // No 2x2+ sized blocks.
|
||||
0, // No 1:1:3:1:1 pattern.
|
||||
-1,
|
||||
},
|
||||
{
|
||||
[][]bool{
|
||||
{b0, b0, b0, b1, b0, b1},
|
||||
{b1, b0, b1, b0, b1, b0},
|
||||
{b0, b1, b0, b1, b0, b1},
|
||||
{b1, b0, b1, b0, b1, b0},
|
||||
{b0, b1, b0, b1, b0, b1},
|
||||
{b1, b0, b1, b0, b1, b0},
|
||||
},
|
||||
0, // 5 adjacent modules of same colour, score = 0.
|
||||
0, // No 2x2+ sized blocks.
|
||||
0, // No 1:1:3:1:1 pattern.
|
||||
-1,
|
||||
},
|
||||
{
|
||||
[][]bool{
|
||||
{b0, b0, b0, b0, b0, b0},
|
||||
{b1, b0, b1, b0, b1, b0},
|
||||
{b0, b1, b0, b1, b0, b1},
|
||||
{b1, b0, b1, b0, b1, b0},
|
||||
{b0, b1, b0, b1, b0, b1},
|
||||
{b1, b0, b1, b0, b1, b0},
|
||||
},
|
||||
4, // 6 adjacent modules of same colour, score = 3 + (6-5)
|
||||
0, // No 2x2+ sized blocks.
|
||||
0, // No 1:1:3:1:1 pattern.
|
||||
-1,
|
||||
},
|
||||
{
|
||||
[][]bool{
|
||||
{b0, b0, b0, b0, b0, b0, b0},
|
||||
{b1, b0, b1, b0, b1, b0, b1},
|
||||
{b1, b0, b0, b0, b0, b0, b1},
|
||||
{b1, b0, b1, b0, b1, b0, b1},
|
||||
{b1, b0, b0, b0, b0, b0, b1},
|
||||
{b1, b0, b1, b0, b1, b0, b1},
|
||||
{b1, b0, b0, b0, b0, b0, b0},
|
||||
},
|
||||
28, // 3+(7-5) + 3+(6-5) + 3+(6-5) + 3+(6-5) + 3+(7-5) + 3+(7-5) = 28
|
||||
0, // No 2x2+ sized blocks.
|
||||
0, // No 1:1:3:1:1 pattern.
|
||||
-1,
|
||||
},
|
||||
{
|
||||
[][]bool{
|
||||
{b0, b0, b0, b1, b0, b1},
|
||||
{b0, b0, b1, b0, b1, b0},
|
||||
{b0, b1, b0, b1, b0, b1},
|
||||
{b1, b0, b1, b1, b1, b0},
|
||||
{b0, b1, b1, b1, b0, b1},
|
||||
{b1, b0, b1, b0, b1, b0},
|
||||
},
|
||||
-1,
|
||||
6, // 3*(2-1)*(2-1) + 3(2-1)*(2-1)
|
||||
0, // No 1:1:3:1:1 pattern.
|
||||
-1,
|
||||
},
|
||||
{
|
||||
[][]bool{
|
||||
{b0, b0, b0, b0, b0, b1},
|
||||
{b0, b0, b0, b0, b0, b1},
|
||||
{b0, b0, b0, b0, b0, b1},
|
||||
{b0, b0, b0, b0, b0, b1},
|
||||
{b0, b0, b0, b0, b0, b1},
|
||||
{b0, b0, b0, b0, b0, b1},
|
||||
},
|
||||
-1,
|
||||
60, // 3 * (5-1) * (6-1)
|
||||
0, // No 1:1:3:1:1 pattern.
|
||||
-1,
|
||||
},
|
||||
{
|
||||
[][]bool{
|
||||
{b0, b0, b0, b0, b0, b1},
|
||||
{b0, b0, b0, b0, b0, b1},
|
||||
{b1, b1, b0, b1, b0, b1},
|
||||
{b1, b1, b0, b1, b0, b1},
|
||||
{b1, b1, b0, b1, b0, b1},
|
||||
{b1, b1, b0, b1, b0, b1},
|
||||
},
|
||||
-1,
|
||||
21, // 3*(5-1)*(2-1) + 3*(2-1)*(4-1) = 3*4 + 3*3
|
||||
0, // No 1:1:3:1:1 pattern.
|
||||
-1,
|
||||
},
|
||||
{
|
||||
[][]bool{
|
||||
{b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0},
|
||||
{b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0},
|
||||
{b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0},
|
||||
{b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0},
|
||||
{b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0},
|
||||
{b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0},
|
||||
{b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0},
|
||||
{b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0},
|
||||
{b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0},
|
||||
{b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0},
|
||||
{b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0},
|
||||
{b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0},
|
||||
},
|
||||
-1,
|
||||
-1,
|
||||
480, // 12* 1:1:3:1:1 patterns, 12 * 40.
|
||||
-1,
|
||||
},
|
||||
{
|
||||
[][]bool{
|
||||
{b1, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b1, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b1, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b1, b1, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b1, b1, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b1, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b1, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b1, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
},
|
||||
-1,
|
||||
-1,
|
||||
80, // 2* 1:1:3:1:1 patterns, 2 * 40.
|
||||
-1,
|
||||
},
|
||||
{
|
||||
[][]bool{
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
},
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
100, // 10 * (10 steps of 5% deviation from 50% black/white).
|
||||
},
|
||||
{
|
||||
[][]bool{
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
},
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
100, // 10 * (10 steps of 5% deviation from 50% black/white).
|
||||
},
|
||||
{
|
||||
[][]bool{
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
},
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
0, // Exactly 50%/50% black/white.
|
||||
},
|
||||
{
|
||||
[][]bool{
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
},
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
20, // 10 * (2 steps of 5% deviation towards white).
|
||||
},
|
||||
{
|
||||
[][]bool{
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b1, b1, b1, b1},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
},
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
30, // 10 * (3 steps of 5% deviation towards white).
|
||||
},
|
||||
{
|
||||
[][]bool{
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b0},
|
||||
{b0, b0, b0, b0, b0, b0, b0, b0, b0, b1},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
{b1, b1, b1, b1, b1, b1, b1, b1, b1, b1},
|
||||
},
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
30, // 10 * (3 steps of 5% deviation towards white).
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
s := newSymbol(len(test.pattern[0]), 4)
|
||||
s.set2dPattern(0, 0, test.pattern)
|
||||
|
||||
penalty1 := s.penalty1()
|
||||
penalty2 := s.penalty2()
|
||||
penalty3 := s.penalty3()
|
||||
penalty4 := s.penalty4()
|
||||
|
||||
ok := true
|
||||
|
||||
if test.expectedPenalty1 != -1 && test.expectedPenalty1 != penalty1 {
|
||||
ok = false
|
||||
}
|
||||
if test.expectedPenalty2 != -1 && test.expectedPenalty2 != penalty2 {
|
||||
ok = false
|
||||
}
|
||||
if test.expectedPenalty3 != -1 && test.expectedPenalty3 != penalty3 {
|
||||
ok = false
|
||||
}
|
||||
if test.expectedPenalty4 != -1 && test.expectedPenalty4 != penalty4 {
|
||||
ok = false
|
||||
}
|
||||
|
||||
if !ok {
|
||||
t.Fatalf("Penalty test #%d p1=%d, p2=%d, p3=%d, p4=%d (expected p1=%d, p2=%d, p3=%d, p4=%d)", i, penalty1, penalty2, penalty3, penalty4,
|
||||
test.expectedPenalty1, test.expectedPenalty2, test.expectedPenalty3,
|
||||
test.expectedPenalty4)
|
||||
}
|
||||
}
|
||||
}
|
3050
vendor/github.com/skip2/go-qrcode/version.go
generated
vendored
Normal file
3050
vendor/github.com/skip2/go-qrcode/version.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
158
vendor/github.com/skip2/go-qrcode/version_test.go
generated
vendored
Normal file
158
vendor/github.com/skip2/go-qrcode/version_test.go
generated
vendored
Normal file
@ -0,0 +1,158 @@
|
||||
// go-qrcode
|
||||
// Copyright 2014 Tom Harwood
|
||||
|
||||
package qrcode
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
bitset "github.com/skip2/go-qrcode/bitset"
|
||||
)
|
||||
|
||||
func TestFormatInfo(t *testing.T) {
|
||||
tests := []struct {
|
||||
level RecoveryLevel
|
||||
maskPattern int
|
||||
|
||||
expected uint32
|
||||
}{
|
||||
{ // L=01 M=00 Q=11 H=10
|
||||
Low,
|
||||
1,
|
||||
0x72f3,
|
||||
},
|
||||
{
|
||||
Medium,
|
||||
2,
|
||||
0x5e7c,
|
||||
},
|
||||
{
|
||||
High,
|
||||
3,
|
||||
0x3a06,
|
||||
},
|
||||
{
|
||||
Highest,
|
||||
4,
|
||||
0x0762,
|
||||
},
|
||||
{
|
||||
Low,
|
||||
5,
|
||||
0x6318,
|
||||
},
|
||||
{
|
||||
Medium,
|
||||
6,
|
||||
0x4f97,
|
||||
},
|
||||
{
|
||||
High,
|
||||
7,
|
||||
0x2bed,
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
v := getQRCodeVersion(test.level, 1)
|
||||
|
||||
result := v.formatInfo(test.maskPattern)
|
||||
|
||||
expected := bitset.New()
|
||||
expected.AppendUint32(test.expected, formatInfoLengthBits)
|
||||
|
||||
if !expected.Equals(result) {
|
||||
t.Errorf("formatInfo test #%d got %s, expected %s", i, result.String(),
|
||||
expected.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestVersionInfo(t *testing.T) {
|
||||
tests := []struct {
|
||||
version int
|
||||
expected uint32
|
||||
}{
|
||||
{
|
||||
7,
|
||||
0x007c94,
|
||||
},
|
||||
{
|
||||
10,
|
||||
0x00a4d3,
|
||||
},
|
||||
{
|
||||
20,
|
||||
0x0149a6,
|
||||
},
|
||||
{
|
||||
30,
|
||||
0x01ed75,
|
||||
},
|
||||
{
|
||||
40,
|
||||
0x028c69,
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
var v *qrCodeVersion
|
||||
|
||||
v = getQRCodeVersion(Low, test.version)
|
||||
|
||||
result := v.versionInfo()
|
||||
|
||||
expected := bitset.New()
|
||||
expected.AppendUint32(test.expected, versionInfoLengthBits)
|
||||
|
||||
if !expected.Equals(result) {
|
||||
t.Errorf("versionInfo test #%d got %s, expected %s", i, result.String(),
|
||||
expected.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNumBitsToPadToCodeoword(t *testing.T) {
|
||||
tests := []struct {
|
||||
level RecoveryLevel
|
||||
version int
|
||||
|
||||
numDataBits int
|
||||
expected int
|
||||
}{
|
||||
{
|
||||
Low,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
}, {
|
||||
Low,
|
||||
1,
|
||||
1,
|
||||
7,
|
||||
}, {
|
||||
Low,
|
||||
1,
|
||||
7,
|
||||
1,
|
||||
}, {
|
||||
Low,
|
||||
1,
|
||||
8,
|
||||
0,
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
var v *qrCodeVersion
|
||||
|
||||
v = getQRCodeVersion(test.level, test.version)
|
||||
|
||||
result := v.numBitsToPadToCodeword(test.numDataBits)
|
||||
|
||||
if result != test.expected {
|
||||
t.Errorf("numBitsToPadToCodeword test %d (version=%d numDataBits=%d), got %d, expected %d",
|
||||
i, test.version, test.numDataBits, result, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user