aboutsummaryrefslogtreecommitdiff
path: root/vendor/golang.org
diff options
context:
space:
mode:
authorTulir Asokan <tulir@maunium.net>2018-04-22 21:25:06 +0300
committerTulir Asokan <tulir@maunium.net>2018-04-22 21:25:51 +0300
commit64fa922ec013079f8f0c90fc9e93c56db3611d30 (patch)
tree7bb9b40f57b8368ef0f5eeccea02d80e54796927 /vendor/golang.org
parentbfb5f0dd457be326b1ae7638a64d2e79cbace371 (diff)
Switch to dep
Diffstat (limited to 'vendor/golang.org')
-rw-r--r--vendor/golang.org/x/image/AUTHORS3
-rw-r--r--vendor/golang.org/x/image/CONTRIBUTORS3
-rw-r--r--vendor/golang.org/x/image/LICENSE27
-rw-r--r--vendor/golang.org/x/image/PATENTS22
-rw-r--r--vendor/golang.org/x/image/bmp/reader.go199
-rw-r--r--vendor/golang.org/x/image/bmp/writer.go166
-rw-r--r--vendor/golang.org/x/image/riff/riff.go193
-rw-r--r--vendor/golang.org/x/image/tiff/buffer.go69
-rw-r--r--vendor/golang.org/x/image/tiff/compress.go58
-rw-r--r--vendor/golang.org/x/image/tiff/consts.go133
-rw-r--r--vendor/golang.org/x/image/tiff/lzw/reader.go272
-rw-r--r--vendor/golang.org/x/image/tiff/reader.go684
-rw-r--r--vendor/golang.org/x/image/tiff/writer.go438
-rw-r--r--vendor/golang.org/x/image/vp8/decode.go403
-rw-r--r--vendor/golang.org/x/image/vp8/filter.go273
-rw-r--r--vendor/golang.org/x/image/vp8/idct.go98
-rw-r--r--vendor/golang.org/x/image/vp8/partition.go129
-rw-r--r--vendor/golang.org/x/image/vp8/pred.go201
-rw-r--r--vendor/golang.org/x/image/vp8/predfunc.go553
-rw-r--r--vendor/golang.org/x/image/vp8/quant.go98
-rw-r--r--vendor/golang.org/x/image/vp8/reconstruct.go442
-rw-r--r--vendor/golang.org/x/image/vp8/token.go381
-rw-r--r--vendor/golang.org/x/image/vp8l/decode.go603
-rw-r--r--vendor/golang.org/x/image/vp8l/huffman.go245
-rw-r--r--vendor/golang.org/x/image/vp8l/transform.go299
-rw-r--r--vendor/golang.org/x/image/webp/decode.go272
-rw-r--r--vendor/golang.org/x/image/webp/webp.go30
-rw-r--r--vendor/golang.org/x/net/AUTHORS3
-rw-r--r--vendor/golang.org/x/net/CONTRIBUTORS3
-rw-r--r--vendor/golang.org/x/net/LICENSE27
-rw-r--r--vendor/golang.org/x/net/PATENTS22
-rw-r--r--vendor/golang.org/x/net/html/atom/atom.go78
-rw-r--r--vendor/golang.org/x/net/html/atom/gen.go712
-rw-r--r--vendor/golang.org/x/net/html/atom/table.go783
-rw-r--r--vendor/golang.org/x/net/html/const.go104
-rw-r--r--vendor/golang.org/x/net/html/doc.go106
-rw-r--r--vendor/golang.org/x/net/html/doctype.go156
-rw-r--r--vendor/golang.org/x/net/html/entity.go2253
-rw-r--r--vendor/golang.org/x/net/html/escape.go258
-rw-r--r--vendor/golang.org/x/net/html/foreign.go226
-rw-r--r--vendor/golang.org/x/net/html/node.go220
-rw-r--r--vendor/golang.org/x/net/html/parse.go2305
-rw-r--r--vendor/golang.org/x/net/html/render.go271
-rw-r--r--vendor/golang.org/x/net/html/token.go1219
-rw-r--r--vendor/golang.org/x/text/AUTHORS3
-rw-r--r--vendor/golang.org/x/text/CONTRIBUTORS3
-rw-r--r--vendor/golang.org/x/text/LICENSE27
-rw-r--r--vendor/golang.org/x/text/PATENTS22
-rw-r--r--vendor/golang.org/x/text/encoding/encoding.go335
-rw-r--r--vendor/golang.org/x/text/encoding/internal/identifier/gen.go137
-rw-r--r--vendor/golang.org/x/text/encoding/internal/identifier/identifier.go81
-rw-r--r--vendor/golang.org/x/text/encoding/internal/identifier/mib.go1621
-rw-r--r--vendor/golang.org/x/text/internal/gen/code.go369
-rw-r--r--vendor/golang.org/x/text/internal/gen/gen.go333
-rw-r--r--vendor/golang.org/x/text/transform/transform.go705
-rw-r--r--vendor/golang.org/x/text/unicode/cldr/base.go105
-rw-r--r--vendor/golang.org/x/text/unicode/cldr/cldr.go130
-rw-r--r--vendor/golang.org/x/text/unicode/cldr/collate.go359
-rw-r--r--vendor/golang.org/x/text/unicode/cldr/decode.go171
-rw-r--r--vendor/golang.org/x/text/unicode/cldr/makexml.go400
-rw-r--r--vendor/golang.org/x/text/unicode/cldr/resolve.go602
-rw-r--r--vendor/golang.org/x/text/unicode/cldr/slice.go144
-rw-r--r--vendor/golang.org/x/text/unicode/cldr/xml.go1494
63 files changed, 22081 insertions, 0 deletions
diff --git a/vendor/golang.org/x/image/AUTHORS b/vendor/golang.org/x/image/AUTHORS
new file mode 100644
index 0000000..15167cd
--- /dev/null
+++ b/vendor/golang.org/x/image/AUTHORS
@@ -0,0 +1,3 @@
+# This source code refers to The Go Authors for copyright purposes.
+# The master list of authors is in the main Go distribution,
+# visible at http://tip.golang.org/AUTHORS.
diff --git a/vendor/golang.org/x/image/CONTRIBUTORS b/vendor/golang.org/x/image/CONTRIBUTORS
new file mode 100644
index 0000000..1c4577e
--- /dev/null
+++ b/vendor/golang.org/x/image/CONTRIBUTORS
@@ -0,0 +1,3 @@
+# This source code was written by the Go contributors.
+# The master list of contributors is in the main Go distribution,
+# visible at http://tip.golang.org/CONTRIBUTORS.
diff --git a/vendor/golang.org/x/image/LICENSE b/vendor/golang.org/x/image/LICENSE
new file mode 100644
index 0000000..6a66aea
--- /dev/null
+++ b/vendor/golang.org/x/image/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/golang.org/x/image/PATENTS b/vendor/golang.org/x/image/PATENTS
new file mode 100644
index 0000000..7330990
--- /dev/null
+++ b/vendor/golang.org/x/image/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go. This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation. If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
diff --git a/vendor/golang.org/x/image/bmp/reader.go b/vendor/golang.org/x/image/bmp/reader.go
new file mode 100644
index 0000000..a0f2715
--- /dev/null
+++ b/vendor/golang.org/x/image/bmp/reader.go
@@ -0,0 +1,199 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package bmp implements a BMP image decoder and encoder.
+//
+// The BMP specification is at http://www.digicamsoft.com/bmp/bmp.html.
+package bmp // import "golang.org/x/image/bmp"
+
+import (
+ "errors"
+ "image"
+ "image/color"
+ "io"
+)
+
+// ErrUnsupported means that the input BMP image uses a valid but unsupported
+// feature.
+var ErrUnsupported = errors.New("bmp: unsupported BMP image")
+
+func readUint16(b []byte) uint16 {
+ return uint16(b[0]) | uint16(b[1])<<8
+}
+
+func readUint32(b []byte) uint32 {
+ return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
+}
+
+// decodePaletted reads an 8 bit-per-pixel BMP image from r.
+// If topDown is false, the image rows will be read bottom-up.
+func decodePaletted(r io.Reader, c image.Config, topDown bool) (image.Image, error) {
+ paletted := image.NewPaletted(image.Rect(0, 0, c.Width, c.Height), c.ColorModel.(color.Palette))
+ if c.Width == 0 || c.Height == 0 {
+ return paletted, nil
+ }
+ var tmp [4]byte
+ y0, y1, yDelta := c.Height-1, -1, -1
+ if topDown {
+ y0, y1, yDelta = 0, c.Height, +1
+ }
+ for y := y0; y != y1; y += yDelta {
+ p := paletted.Pix[y*paletted.Stride : y*paletted.Stride+c.Width]
+ if _, err := io.ReadFull(r, p); err != nil {
+ return nil, err
+ }
+ // Each row is 4-byte aligned.
+ if c.Width%4 != 0 {
+ _, err := io.ReadFull(r, tmp[:4-c.Width%4])
+ if err != nil {
+ return nil, err
+ }
+ }
+ }
+ return paletted, nil
+}
+
+// decodeRGB reads a 24 bit-per-pixel BMP image from r.
+// If topDown is false, the image rows will be read bottom-up.
+func decodeRGB(r io.Reader, c image.Config, topDown bool) (image.Image, error) {
+ rgba := image.NewRGBA(image.Rect(0, 0, c.Width, c.Height))
+ if c.Width == 0 || c.Height == 0 {
+ return rgba, nil
+ }
+ // There are 3 bytes per pixel, and each row is 4-byte aligned.
+ b := make([]byte, (3*c.Width+3)&^3)
+ y0, y1, yDelta := c.Height-1, -1, -1
+ if topDown {
+ y0, y1, yDelta = 0, c.Height, +1
+ }
+ for y := y0; y != y1; y += yDelta {
+ if _, err := io.ReadFull(r, b); err != nil {
+ return nil, err
+ }
+ p := rgba.Pix[y*rgba.Stride : y*rgba.Stride+c.Width*4]
+ for i, j := 0, 0; i < len(p); i, j = i+4, j+3 {
+ // BMP images are stored in BGR order rather than RGB order.
+ p[i+0] = b[j+2]
+ p[i+1] = b[j+1]
+ p[i+2] = b[j+0]
+ p[i+3] = 0xFF
+ }
+ }
+ return rgba, nil
+}
+
+// decodeNRGBA reads a 32 bit-per-pixel BMP image from r.
+// If topDown is false, the image rows will be read bottom-up.
+func decodeNRGBA(r io.Reader, c image.Config, topDown bool) (image.Image, error) {
+ rgba := image.NewNRGBA(image.Rect(0, 0, c.Width, c.Height))
+ if c.Width == 0 || c.Height == 0 {
+ return rgba, nil
+ }
+ y0, y1, yDelta := c.Height-1, -1, -1
+ if topDown {
+ y0, y1, yDelta = 0, c.Height, +1
+ }
+ for y := y0; y != y1; y += yDelta {
+ p := rgba.Pix[y*rgba.Stride : y*rgba.Stride+c.Width*4]
+ if _, err := io.ReadFull(r, p); err != nil {
+ return nil, err
+ }
+ for i := 0; i < len(p); i += 4 {
+ // BMP images are stored in BGRA order rather than RGBA order.
+ p[i+0], p[i+2] = p[i+2], p[i+0]
+ }
+ }
+ return rgba, nil
+}
+
+// Decode reads a BMP image from r and returns it as an image.Image.
+// Limitation: The file must be 8, 24 or 32 bits per pixel.
+func Decode(r io.Reader) (image.Image, error) {
+ c, bpp, topDown, err := decodeConfig(r)
+ if err != nil {
+ return nil, err
+ }
+ switch bpp {
+ case 8:
+ return decodePaletted(r, c, topDown)
+ case 24:
+ return decodeRGB(r, c, topDown)
+ case 32:
+ return decodeNRGBA(r, c, topDown)
+ }
+ panic("unreachable")
+}
+
+// DecodeConfig returns the color model and dimensions of a BMP image without
+// decoding the entire image.
+// Limitation: The file must be 8, 24 or 32 bits per pixel.
+func DecodeConfig(r io.Reader) (image.Config, error) {
+ config, _, _, err := decodeConfig(r)
+ return config, err
+}
+
+func decodeConfig(r io.Reader) (config image.Config, bitsPerPixel int, topDown bool, err error) {
+ // We only support those BMP images that are a BITMAPFILEHEADER
+ // immediately followed by a BITMAPINFOHEADER.
+ const (
+ fileHeaderLen = 14
+ infoHeaderLen = 40
+ )
+ var b [1024]byte
+ if _, err := io.ReadFull(r, b[:fileHeaderLen+infoHeaderLen]); err != nil {
+ return image.Config{}, 0, false, err
+ }
+ if string(b[:2]) != "BM" {
+ return image.Config{}, 0, false, errors.New("bmp: invalid format")
+ }
+ offset := readUint32(b[10:14])
+ if readUint32(b[14:18]) != infoHeaderLen {
+ return image.Config{}, 0, false, ErrUnsupported
+ }
+ width := int(int32(readUint32(b[18:22])))
+ height := int(int32(readUint32(b[22:26])))
+ if height < 0 {
+ height, topDown = -height, true
+ }
+ if width < 0 || height < 0 {
+ return image.Config{}, 0, false, ErrUnsupported
+ }
+ // We only support 1 plane, 8 or 24 bits per pixel and no compression.
+ planes, bpp, compression := readUint16(b[26:28]), readUint16(b[28:30]), readUint32(b[30:34])
+ if planes != 1 || compression != 0 {
+ return image.Config{}, 0, false, ErrUnsupported
+ }
+ switch bpp {
+ case 8:
+ if offset != fileHeaderLen+infoHeaderLen+256*4 {
+ return image.Config{}, 0, false, ErrUnsupported
+ }
+ _, err = io.ReadFull(r, b[:256*4])
+ if err != nil {
+ return image.Config{}, 0, false, err
+ }
+ pcm := make(color.Palette, 256)
+ for i := range pcm {
+ // BMP images are stored in BGR order rather than RGB order.
+ // Every 4th byte is padding.
+ pcm[i] = color.RGBA{b[4*i+2], b[4*i+1], b[4*i+0], 0xFF}
+ }
+ return image.Config{ColorModel: pcm, Width: width, Height: height}, 8, topDown, nil
+ case 24:
+ if offset != fileHeaderLen+infoHeaderLen {
+ return image.Config{}, 0, false, ErrUnsupported
+ }
+ return image.Config{ColorModel: color.RGBAModel, Width: width, Height: height}, 24, topDown, nil
+ case 32:
+ if offset != fileHeaderLen+infoHeaderLen {
+ return image.Config{}, 0, false, ErrUnsupported
+ }
+ return image.Config{ColorModel: color.RGBAModel, Width: width, Height: height}, 32, topDown, nil
+ }
+ return image.Config{}, 0, false, ErrUnsupported
+}
+
+func init() {
+ image.RegisterFormat("bmp", "BM????\x00\x00\x00\x00", Decode, DecodeConfig)
+}
diff --git a/vendor/golang.org/x/image/bmp/writer.go b/vendor/golang.org/x/image/bmp/writer.go
new file mode 100644
index 0000000..6947968
--- /dev/null
+++ b/vendor/golang.org/x/image/bmp/writer.go
@@ -0,0 +1,166 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bmp
+
+import (
+ "encoding/binary"
+ "errors"
+ "image"
+ "io"
+)
+
+type header struct {
+ sigBM [2]byte
+ fileSize uint32
+ resverved [2]uint16
+ pixOffset uint32
+ dibHeaderSize uint32
+ width uint32
+ height uint32
+ colorPlane uint16
+ bpp uint16
+ compression uint32
+ imageSize uint32
+ xPixelsPerMeter uint32
+ yPixelsPerMeter uint32
+ colorUse uint32
+ colorImportant uint32
+}
+
+func encodePaletted(w io.Writer, pix []uint8, dx, dy, stride, step int) error {
+ var padding []byte
+ if dx < step {
+ padding = make([]byte, step-dx)
+ }
+ for y := dy - 1; y >= 0; y-- {
+ min := y*stride + 0
+ max := y*stride + dx
+ if _, err := w.Write(pix[min:max]); err != nil {
+ return err
+ }
+ if padding != nil {
+ if _, err := w.Write(padding); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+func encodeRGBA(w io.Writer, pix []uint8, dx, dy, stride, step int) error {
+ buf := make([]byte, step)
+ for y := dy - 1; y >= 0; y-- {
+ min := y*stride + 0
+ max := y*stride + dx*4
+ off := 0
+ for i := min; i < max; i += 4 {
+ buf[off+2] = pix[i+0]
+ buf[off+1] = pix[i+1]
+ buf[off+0] = pix[i+2]
+ off += 3
+ }
+ if _, err := w.Write(buf); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func encode(w io.Writer, m image.Image, step int) error {
+ b := m.Bounds()
+ buf := make([]byte, step)
+ for y := b.Max.Y - 1; y >= b.Min.Y; y-- {
+ off := 0
+ for x := b.Min.X; x < b.Max.X; x++ {
+ r, g, b, _ := m.At(x, y).RGBA()
+ buf[off+2] = byte(r >> 8)
+ buf[off+1] = byte(g >> 8)
+ buf[off+0] = byte(b >> 8)
+ off += 3
+ }
+ if _, err := w.Write(buf); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// Encode writes the image m to w in BMP format.
+func Encode(w io.Writer, m image.Image) error {
+ d := m.Bounds().Size()
+ if d.X < 0 || d.Y < 0 {
+ return errors.New("bmp: negative bounds")
+ }
+ h := &header{
+ sigBM: [2]byte{'B', 'M'},
+ fileSize: 14 + 40,
+ pixOffset: 14 + 40,
+ dibHeaderSize: 40,
+ width: uint32(d.X),
+ height: uint32(d.Y),
+ colorPlane: 1,
+ }
+
+ var step int
+ var palette []byte
+ switch m := m.(type) {
+ case *image.Gray:
+ step = (d.X + 3) &^ 3
+ palette = make([]byte, 1024)
+ for i := 0; i < 256; i++ {
+ palette[i*4+0] = uint8(i)
+ palette[i*4+1] = uint8(i)
+ palette[i*4+2] = uint8(i)
+ palette[i*4+3] = 0xFF
+ }
+ h.imageSize = uint32(d.Y * step)
+ h.fileSize += uint32(len(palette)) + h.imageSize
+ h.pixOffset += uint32(len(palette))
+ h.bpp = 8
+
+ case *image.Paletted:
+ step = (d.X + 3) &^ 3
+ palette = make([]byte, 1024)
+ for i := 0; i < len(m.Palette) && i < 256; i++ {
+ r, g, b, _ := m.Palette[i].RGBA()
+ palette[i*4+0] = uint8(b >> 8)
+ palette[i*4+1] = uint8(g >> 8)
+ palette[i*4+2] = uint8(r >> 8)
+ palette[i*4+3] = 0xFF
+ }
+ h.imageSize = uint32(d.Y * step)
+ h.fileSize += uint32(len(palette)) + h.imageSize
+ h.pixOffset += uint32(len(palette))
+ h.bpp = 8
+ default:
+ step = (3*d.X + 3) &^ 3
+ h.imageSize = uint32(d.Y * step)
+ h.fileSize += h.imageSize
+ h.bpp = 24
+ }
+
+ if err := binary.Write(w, binary.LittleEndian, h); err != nil {
+ return err
+ }
+ if palette != nil {
+ if err := binary.Write(w, binary.LittleEndian, palette); err != nil {
+ return err
+ }
+ }
+
+ if d.X == 0 || d.Y == 0 {
+ return nil
+ }
+
+ switch m := m.(type) {
+ case *image.Gray:
+ return encodePaletted(w, m.Pix, d.X, d.Y, m.Stride, step)
+ case *image.Paletted:
+ return encodePaletted(w, m.Pix, d.X, d.Y, m.Stride, step)
+ case *image.RGBA:
+ return encodeRGBA(w, m.Pix, d.X, d.Y, m.Stride, step)
+ }
+ return encode(w, m, step)
+}
diff --git a/vendor/golang.org/x/image/riff/riff.go b/vendor/golang.org/x/image/riff/riff.go
new file mode 100644
index 0000000..38dc0e5
--- /dev/null
+++ b/vendor/golang.org/x/image/riff/riff.go
@@ -0,0 +1,193 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package riff implements the Resource Interchange File Format, used by media
+// formats such as AVI, WAVE and WEBP.
+//
+// A RIFF stream contains a sequence of chunks. Each chunk consists of an 8-byte
+// header (containing a 4-byte chunk type and a 4-byte chunk length), the chunk
+// data (presented as an io.Reader), and some padding bytes.
+//
+// A detailed description of the format is at
+// http://www.tactilemedia.com/info/MCI_Control_Info.html
+package riff // import "golang.org/x/image/riff"
+
+import (
+ "errors"
+ "io"
+ "io/ioutil"
+ "math"
+)
+
+var (
+ errMissingPaddingByte = errors.New("riff: missing padding byte")
+ errMissingRIFFChunkHeader = errors.New("riff: missing RIFF chunk header")
+ errListSubchunkTooLong = errors.New("riff: list subchunk too long")
+ errShortChunkData = errors.New("riff: short chunk data")
+ errShortChunkHeader = errors.New("riff: short chunk header")
+ errStaleReader = errors.New("riff: stale reader")
+)
+
+// u32 decodes the first four bytes of b as a little-endian integer.
+func u32(b []byte) uint32 {
+ return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
+}
+
+const chunkHeaderSize = 8
+
+// FourCC is a four character code.
+type FourCC [4]byte
+
+// LIST is the "LIST" FourCC.
+var LIST = FourCC{'L', 'I', 'S', 'T'}
+
+// NewReader returns the RIFF stream's form type, such as "AVI " or "WAVE", and
+// its chunks as a *Reader.
+func NewReader(r io.Reader) (formType FourCC, data *Reader, err error) {
+ var buf [chunkHeaderSize]byte
+ if _, err := io.ReadFull(r, buf[:]); err != nil {
+ if err == io.EOF || err == io.ErrUnexpectedEOF {
+ err = errMissingRIFFChunkHeader
+ }
+ return FourCC{}, nil, err
+ }
+ if buf[0] != 'R' || buf[1] != 'I' || buf[2] != 'F' || buf[3] != 'F' {
+ return FourCC{}, nil, errMissingRIFFChunkHeader
+ }
+ return NewListReader(u32(buf[4:]), r)
+}
+
+// NewListReader returns a LIST chunk's list type, such as "movi" or "wavl",
+// and its chunks as a *Reader.
+func NewListReader(chunkLen uint32, chunkData io.Reader) (listType FourCC, data *Reader, err error) {
+ if chunkLen < 4 {
+ return FourCC{}, nil, errShortChunkData
+ }
+ z := &Reader{r: chunkData}
+ if _, err := io.ReadFull(chunkData, z.buf[:4]); err != nil {
+ if err == io.EOF || err == io.ErrUnexpectedEOF {
+ err = errShortChunkData
+ }
+ return FourCC{}, nil, err
+ }
+ z.totalLen = chunkLen - 4
+ return FourCC{z.buf[0], z.buf[1], z.buf[2], z.buf[3]}, z, nil
+}
+
+// Reader reads chunks from an underlying io.Reader.
+type Reader struct {
+ r io.Reader
+ err error
+
+ totalLen uint32
+ chunkLen uint32
+
+ chunkReader *chunkReader
+ buf [chunkHeaderSize]byte
+ padded bool
+}
+
+// Next returns the next chunk's ID, length and data. It returns io.EOF if there
+// are no more chunks. The io.Reader returned becomes stale after the next Next
+// call, and should no longer be used.
+//
+// It is valid to call Next even if all of the previous chunk's data has not
+// been read.
+func (z *Reader) Next() (chunkID FourCC, chunkLen uint32, chunkData io.Reader, err error) {
+ if z.err != nil {
+ return FourCC{}, 0, nil, z.err
+ }
+
+ // Drain the rest of the previous chunk.
+ if z.chunkLen != 0 {
+ want := z.chunkLen
+ var got int64
+ got, z.err = io.Copy(ioutil.Discard, z.chunkReader)
+ if z.err == nil && uint32(got) != want {
+ z.err = errShortChunkData
+ }
+ if z.err != nil {
+ return FourCC{}, 0, nil, z.err
+ }
+ }
+ z.chunkReader = nil
+ if z.padded {
+ if z.totalLen == 0 {
+ z.err = errListSubchunkTooLong
+ return FourCC{}, 0, nil, z.err
+ }
+ z.totalLen--
+ _, z.err = io.ReadFull(z.r, z.buf[:1])
+ if z.err != nil {
+ if z.err == io.EOF {
+ z.err = errMissingPaddingByte
+ }
+ return FourCC{}, 0, nil, z.err
+ }
+ }
+
+ // We are done if we have no more data.
+ if z.totalLen == 0 {
+ z.err = io.EOF
+ return FourCC{}, 0, nil, z.err
+ }
+
+ // Read the next chunk header.
+ if z.totalLen < chunkHeaderSize {
+ z.err = errShortChunkHeader
+ return FourCC{}, 0, nil, z.err
+ }
+ z.totalLen -= chunkHeaderSize
+ if _, z.err = io.ReadFull(z.r, z.buf[:chunkHeaderSize]); z.err != nil {
+ if z.err == io.EOF || z.err == io.ErrUnexpectedEOF {
+ z.err = errShortChunkHeader
+ }
+ return FourCC{}, 0, nil, z.err
+ }
+ chunkID = FourCC{z.buf[0], z.buf[1], z.buf[2], z.buf[3]}
+ z.chunkLen = u32(z.buf[4:])
+ if z.chunkLen > z.totalLen {
+ z.err = errListSubchunkTooLong
+ return FourCC{}, 0, nil, z.err
+ }
+ z.padded = z.chunkLen&1 == 1
+ z.chunkReader = &chunkReader{z}
+ return chunkID, z.chunkLen, z.chunkReader, nil
+}
+
+type chunkReader struct {
+ z *Reader
+}
+
+func (c *chunkReader) Read(p []byte) (int, error) {
+ if c != c.z.chunkReader {
+ return 0, errStaleReader
+ }
+ z := c.z
+ if z.err != nil {
+ if z.err == io.EOF {
+ return 0, errStaleReader
+ }
+ return 0, z.err
+ }
+
+ n := int(z.chunkLen)
+ if n == 0 {
+ return 0, io.EOF
+ }
+ if n < 0 {
+ // Converting uint32 to int overflowed.
+ n = math.MaxInt32
+ }
+ if n > len(p) {
+ n = len(p)
+ }
+ n, err := z.r.Read(p[:n])
+ z.totalLen -= uint32(n)
+ z.chunkLen -= uint32(n)
+ if err != io.EOF {
+ z.err = err
+ }
+ return n, err
+}
diff --git a/vendor/golang.org/x/image/tiff/buffer.go b/vendor/golang.org/x/image/tiff/buffer.go
new file mode 100644
index 0000000..d1801be
--- /dev/null
+++ b/vendor/golang.org/x/image/tiff/buffer.go
@@ -0,0 +1,69 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tiff
+
+import "io"
+
+// buffer buffers an io.Reader to satisfy io.ReaderAt.
+type buffer struct {
+ r io.Reader
+ buf []byte
+}
+
+// fill reads data from b.r until the buffer contains at least end bytes.
+func (b *buffer) fill(end int) error {
+ m := len(b.buf)
+ if end > m {
+ if end > cap(b.buf) {
+ newcap := 1024
+ for newcap < end {
+ newcap *= 2
+ }
+ newbuf := make([]byte, end, newcap)
+ copy(newbuf, b.buf)
+ b.buf = newbuf
+ } else {
+ b.buf = b.buf[:end]
+ }
+ if n, err := io.ReadFull(b.r, b.buf[m:end]); err != nil {
+ end = m + n
+ b.buf = b.buf[:end]
+ return err
+ }
+ }
+ return nil
+}
+
+func (b *buffer) ReadAt(p []byte, off int64) (int, error) {
+ o := int(off)
+ end := o + len(p)
+ if int64(end) != off+int64(len(p)) {
+ return 0, io.ErrUnexpectedEOF
+ }
+
+ err := b.fill(end)
+ return copy(p, b.buf[o:end]), err
+}
+
+// Slice returns a slice of the underlying buffer. The slice contains
+// n bytes starting at offset off.
+func (b *buffer) Slice(off, n int) ([]byte, error) {
+ end := off + n
+ if err := b.fill(end); err != nil {
+ return nil, err
+ }
+ return b.buf[off:end], nil
+}
+
+// newReaderAt converts an io.Reader into an io.ReaderAt.
+func newReaderAt(r io.Reader) io.ReaderAt {
+ if ra, ok := r.(io.ReaderAt); ok {
+ return ra
+ }
+ return &buffer{
+ r: r,
+ buf: make([]byte, 0, 1024),
+ }
+}
diff --git a/vendor/golang.org/x/image/tiff/compress.go b/vendor/golang.org/x/image/tiff/compress.go
new file mode 100644
index 0000000..3f176f0
--- /dev/null
+++ b/vendor/golang.org/x/image/tiff/compress.go
@@ -0,0 +1,58 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tiff
+
+import (
+ "bufio"
+ "io"
+)
+
+type byteReader interface {
+ io.Reader
+ io.ByteReader
+}
+
+// unpackBits decodes the PackBits-compressed data in src and returns the
+// uncompressed data.
+//
+// The PackBits compression format is described in section 9 (p. 42)
+// of the TIFF spec.
+func unpackBits(r io.Reader) ([]byte, error) {
+ buf := make([]byte, 128)
+ dst := make([]byte, 0, 1024)
+ br, ok := r.(byteReader)
+ if !ok {
+ br = bufio.NewReader(r)
+ }
+
+ for {
+ b, err := br.ReadByte()
+ if err != nil {
+ if err == io.EOF {
+ return dst, nil
+ }
+ return nil, err
+ }
+ code := int(int8(b))
+ switch {
+ case code >= 0:
+ n, err := io.ReadFull(br, buf[:code+1])
+ if err != nil {
+ return nil, err
+ }
+ dst = append(dst, buf[:n]...)
+ case code == -128:
+ // No-op.
+ default:
+ if b, err = br.ReadByte(); err != nil {
+ return nil, err
+ }
+ for j := 0; j < 1-code; j++ {
+ buf[j] = b
+ }
+ dst = append(dst, buf[:1-code]...)
+ }
+ }
+}
diff --git a/vendor/golang.org/x/image/tiff/consts.go b/vendor/golang.org/x/image/tiff/consts.go
new file mode 100644
index 0000000..3c51a70
--- /dev/null
+++ b/vendor/golang.org/x/image/tiff/consts.go
@@ -0,0 +1,133 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tiff
+
+// A tiff image file contains one or more images. The metadata
+// of each image is contained in an Image File Directory (IFD),
+// which contains entries of 12 bytes each and is described
+// on page 14-16 of the specification. An IFD entry consists of
+//
+// - a tag, which describes the signification of the entry,
+// - the data type and length of the entry,
+// - the data itself or a pointer to it if it is more than 4 bytes.
+//
+// The presence of a length means that each IFD is effectively an array.
+
+const (
+ leHeader = "II\x2A\x00" // Header for little-endian files.
+ beHeader = "MM\x00\x2A" // Header for big-endian files.
+
+ ifdLen = 12 // Length of an IFD entry in bytes.
+)
+
+// Data types (p. 14-16 of the spec).
+const (
+ dtByte = 1
+ dtASCII = 2
+ dtShort = 3
+ dtLong = 4
+ dtRational = 5
+)
+
+// The length of one instance of each data type in bytes.
+var lengths = [...]uint32{0, 1, 1, 2, 4, 8}
+
+// Tags (see p. 28-41 of the spec).
+const (
+ tImageWidth = 256
+ tImageLength = 257
+ tBitsPerSample = 258
+ tCompression = 259
+ tPhotometricInterpretation = 262
+
+ tStripOffsets = 273
+ tSamplesPerPixel = 277
+ tRowsPerStrip = 278
+ tStripByteCounts = 279
+
+ tTileWidth = 322
+ tTileLength = 323
+ tTileOffsets = 324
+ tTileByteCounts = 325
+
+ tXResolution = 282
+ tYResolution = 283
+ tResolutionUnit = 296
+
+ tPredictor = 317
+ tColorMap = 320
+ tExtraSamples = 338
+ tSampleFormat = 339
+)
+
+// Compression types (defined in various places in the spec and supplements).
+const (
+ cNone = 1
+ cCCITT = 2
+ cG3 = 3 // Group 3 Fax.
+ cG4 = 4 // Group 4 Fax.
+ cLZW = 5
+ cJPEGOld = 6 // Superseded by cJPEG.
+ cJPEG = 7
+ cDeflate = 8 // zlib compression.
+ cPackBits = 32773
+ cDeflateOld = 32946 // Superseded by cDeflate.
+)
+
+// Photometric interpretation values (see p. 37 of the spec).
+const (
+ pWhiteIsZero = 0
+ pBlackIsZero = 1
+ pRGB = 2
+ pPaletted = 3
+ pTransMask = 4 // transparency mask
+ pCMYK = 5
+ pYCbCr = 6
+ pCIELab = 8
+)
+
+// Values for the tPredictor tag (page 64-65 of the spec).
+const (
+ prNone = 1
+ prHorizontal = 2
+)
+
+// Values for the tResolutionUnit tag (page 18).
+const (
+ resNone = 1
+ resPerInch = 2 // Dots per inch.
+ resPerCM = 3 // Dots per centimeter.
+)
+
+// imageMode represents the mode of the image.
+type imageMode int
+
+const (
+ mBilevel imageMode = iota
+ mPaletted
+ mGray
+ mGrayInvert
+ mRGB
+ mRGBA
+ mNRGBA
+)
+
+// CompressionType describes the type of compression used in Options.
+type CompressionType int
+
+const (
+ Uncompressed CompressionType = iota
+ Deflate
+)
+
+// specValue returns the compression type constant from the TIFF spec that
+// is equivalent to c.
+func (c CompressionType) specValue() uint32 {
+ switch c {
+ case Deflate:
+ return cDeflate
+ }
+ return cNone
+}
diff --git a/vendor/golang.org/x/image/tiff/lzw/reader.go b/vendor/golang.org/x/image/tiff/lzw/reader.go
new file mode 100644
index 0000000..51ae39f
--- /dev/null
+++ b/vendor/golang.org/x/image/tiff/lzw/reader.go
@@ -0,0 +1,272 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package lzw implements the Lempel-Ziv-Welch compressed data format,
+// described in T. A. Welch, ``A Technique for High-Performance Data
+// Compression'', Computer, 17(6) (June 1984), pp 8-19.
+//
+// In particular, it implements LZW as used by the TIFF file format, including
+// an "off by one" algorithmic difference when compared to standard LZW.
+package lzw // import "golang.org/x/image/tiff/lzw"
+
+/*
+This file was branched from src/pkg/compress/lzw/reader.go in the
+standard library. Differences from the original are marked with "NOTE".
+
+The tif_lzw.c file in the libtiff C library has this comment:
+
+----
+The 5.0 spec describes a different algorithm than Aldus
+implements. Specifically, Aldus does code length transitions
+one code earlier than should be done (for real LZW).
+Earlier versions of this library implemented the correct
+LZW algorithm, but emitted codes in a bit order opposite
+to the TIFF spec. Thus, to maintain compatibility w/ Aldus
+we interpret MSB-LSB ordered codes to be images written w/
+old versions of this library, but otherwise adhere to the
+Aldus "off by one" algorithm.
+----
+
+The Go code doesn't read (invalid) TIFF files written by old versions of
+libtiff, but the LZW algorithm in this package still differs from the one in
+Go's standard package library to accomodate this "off by one" in valid TIFFs.
+*/
+
+import (
+ "bufio"
+ "errors"
+ "fmt"
+ "io"
+)
+
+// Order specifies the bit ordering in an LZW data stream.
+type Order int
+
+const (
+ // LSB means Least Significant Bits first, as used in the GIF file format.
+ LSB Order = iota
+ // MSB means Most Significant Bits first, as used in the TIFF and PDF
+ // file formats.
+ MSB
+)
+
+const (
+ maxWidth = 12
+ decoderInvalidCode = 0xffff
+ flushBuffer = 1 << maxWidth
+)
+
+// decoder is the state from which the readXxx method converts a byte
+// stream into a code stream.
+type decoder struct {
+ r io.ByteReader
+ bits uint32
+ nBits uint
+ width uint
+ read func(*decoder) (uint16, error) // readLSB or readMSB
+ litWidth int // width in bits of literal codes
+ err error
+
+ // The first 1<<litWidth codes are literal codes.
+ // The next two codes mean clear and EOF.
+ // Other valid codes are in the range [lo, hi] where lo := clear + 2,
+ // with the upper bound incrementing on each code seen.
+ // overflow is the code at which hi overflows the code width. NOTE: TIFF's LZW is "off by one".
+ // last is the most recently seen code, or decoderInvalidCode.
+ clear, eof, hi, overflow, last uint16
+
+ // Each code c in [lo, hi] expands to two or more bytes. For c != hi:
+ // suffix[c] is the last of these bytes.
+ // prefix[c] is the code for all but the last byte.
+ // This code can either be a literal code or another code in [lo, c).
+ // The c == hi case is a special case.
+ suffix [1 << maxWidth]uint8
+ prefix [1 << maxWidth]uint16
+
+ // output is the temporary output buffer.
+ // Literal codes are accumulated from the start of the buffer.
+ // Non-literal codes decode to a sequence of suffixes that are first
+ // written right-to-left from the end of the buffer before being copied
+ // to the start of the buffer.
+ // It is flushed when it contains >= 1<<maxWidth bytes,
+ // so that there is always room to decode an entire code.
+ output [2 * 1 << maxWidth]byte
+ o int // write index into output
+ toRead []byte // bytes to return from Read
+}
+
+// readLSB returns the next code for "Least Significant Bits first" data.
+func (d *decoder) readLSB() (uint16, error) {
+ for d.nBits < d.width {
+ x, err := d.r.ReadByte()
+ if err != nil {
+ return 0, err
+ }
+ d.bits |= uint32(x) << d.nBits
+ d.nBits += 8
+ }
+ code := uint16(d.bits & (1<<d.width - 1))
+ d.bits >>= d.width
+ d.nBits -= d.width
+ return code, nil
+}
+
+// readMSB returns the next code for "Most Significant Bits first" data.
+func (d *decoder) readMSB() (uint16, error) {
+ for d.nBits < d.width {
+ x, err := d.r.ReadByte()
+ if err != nil {
+ return 0, err
+ }
+ d.bits |= uint32(x) << (24 - d.nBits)
+ d.nBits += 8
+ }
+ code := uint16(d.bits >> (32 - d.width))
+ d.bits <<= d.width
+ d.nBits -= d.width
+ return code, nil
+}
+
+func (d *decoder) Read(b []byte) (int, error) {
+ for {
+ if len(d.toRead) > 0 {
+ n := copy(b, d.toRead)
+ d.toRead = d.toRead[n:]
+ return n, nil
+ }
+ if d.err != nil {
+ return 0, d.err
+ }
+ d.decode()
+ }
+}
+
+// decode decompresses bytes from r and leaves them in d.toRead.
+// read specifies how to decode bytes into codes.
+// litWidth is the width in bits of literal codes.
+func (d *decoder) decode() {
+ // Loop over the code stream, converting codes into decompressed bytes.
+loop:
+ for {
+ code, err := d.read(d)
+ if err != nil {
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ d.err = err
+ break
+ }
+ switch {
+ case code < d.clear:
+ // We have a literal code.
+ d.output[d.o] = uint8(code)
+ d.o++
+ if d.last != decoderInvalidCode {
+ // Save what the hi code expands to.
+ d.suffix[d.hi] = uint8(code)
+ d.prefix[d.hi] = d.last
+ }
+ case code == d.clear:
+ d.width = 1 + uint(d.litWidth)
+ d.hi = d.eof
+ d.overflow = 1 << d.width
+ d.last = decoderInvalidCode
+ continue
+ case code == d.eof:
+ d.err = io.EOF
+ break loop
+ case code <= d.hi:
+ c, i := code, len(d.output)-1
+ if code == d.hi {
+ // code == hi is a special case which expands to the last expansion
+ // followed by the head of the last expansion. To find the head, we walk
+ // the prefix chain until we find a literal code.
+ c = d.last
+ for c >= d.clear {
+ c = d.prefix[c]
+ }
+ d.output[i] = uint8(c)
+ i--
+ c = d.last
+ }
+ // Copy the suffix chain into output and then write that to w.
+ for c >= d.clear {
+ d.output[i] = d.suffix[c]
+ i--
+ c = d.prefix[c]
+ }
+ d.output[i] = uint8(c)
+ d.o += copy(d.output[d.o:], d.output[i:])
+ if d.last != decoderInvalidCode {
+ // Save what the hi code expands to.
+ d.suffix[d.hi] = uint8(c)
+ d.prefix[d.hi] = d.last
+ }
+ default:
+ d.err = errors.New("lzw: invalid code")
+ break loop
+ }
+ d.last, d.hi = code, d.hi+1
+ if d.hi+1 >= d.overflow { // NOTE: the "+1" is where TIFF's LZW differs from the standard algorithm.
+ if d.width == maxWidth {
+ d.last = decoderInvalidCode
+ } else {
+ d.width++
+ d.overflow <<= 1
+ }
+ }
+ if d.o >= flushBuffer {
+ break
+ }
+ }
+ // Flush pending output.
+ d.toRead = d.output[:d.o]
+ d.o = 0
+}
+
+var errClosed = errors.New("lzw: reader/writer is closed")
+
+func (d *decoder) Close() error {
+ d.err = errClosed // in case any Reads come along
+ return nil
+}
+
+// NewReader creates a new io.ReadCloser.
+// Reads from the returned io.ReadCloser read and decompress data from r.
+// If r does not also implement io.ByteReader,
+// the decompressor may read more data than necessary from r.
+// It is the caller's responsibility to call Close on the ReadCloser when
+// finished reading.
+// The number of bits to use for literal codes, litWidth, must be in the
+// range [2,8] and is typically 8. It must equal the litWidth
+// used during compression.
+func NewReader(r io.Reader, order Order, litWidth int) io.ReadCloser {
+ d := new(decoder)
+ switch order {
+ case LSB:
+ d.read = (*decoder).readLSB
+ case MSB:
+ d.read = (*decoder).readMSB
+ default:
+ d.err = errors.New("lzw: unknown order")
+ return d
+ }
+ if litWidth < 2 || 8 < litWidth {
+ d.err = fmt.Errorf("lzw: litWidth %d out of range", litWidth)
+ return d
+ }
+ if br, ok := r.(io.ByteReader); ok {
+ d.r = br
+ } else {
+ d.r = bufio.NewReader(r)
+ }
+ d.litWidth = litWidth
+ d.width = 1 + uint(litWidth)
+ d.clear = uint16(1) << uint(litWidth)
+ d.eof, d.hi = d.clear+1, d.clear+1
+ d.overflow = uint16(1) << d.width
+ d.last = decoderInvalidCode
+
+ return d
+}
diff --git a/vendor/golang.org/x/image/tiff/reader.go b/vendor/golang.org/x/image/tiff/reader.go
new file mode 100644
index 0000000..8a941c1
--- /dev/null
+++ b/vendor/golang.org/x/image/tiff/reader.go
@@ -0,0 +1,684 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package tiff implements a TIFF image decoder and encoder.
+//
+// The TIFF specification is at http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf
+package tiff // import "golang.org/x/image/tiff"
+
+import (
+ "compress/zlib"
+ "encoding/binary"
+ "fmt"
+ "image"
+ "image/color"
+ "io"
+ "io/ioutil"
+ "math"
+
+ "golang.org/x/image/tiff/lzw"
+)
+
+// A FormatError reports that the input is not a valid TIFF image.
+type FormatError string
+
+func (e FormatError) Error() string {
+ return "tiff: invalid format: " + string(e)
+}
+
+// An UnsupportedError reports that the input uses a valid but
+// unimplemented feature.
+type UnsupportedError string
+
+func (e UnsupportedError) Error() string {
+ return "tiff: unsupported feature: " + string(e)
+}
+
+var errNoPixels = FormatError("not enough pixel data")
+
+type decoder struct {
+ r io.ReaderAt
+ byteOrder binary.ByteOrder
+ config image.Config
+ mode imageMode
+ bpp uint
+ features map[int][]uint
+ palette []color.Color
+
+ buf []byte
+ off int // Current offset in buf.
+ v uint32 // Buffer value for reading with arbitrary bit depths.
+ nbits uint // Remaining number of bits in v.
+}
+
+// firstVal returns the first uint of the features entry with the given tag,
+// or 0 if the tag does not exist.
+func (d *decoder) firstVal(tag int) uint {
+ f := d.features[tag]
+ if len(f) == 0 {
+ return 0
+ }
+ return f[0]
+}
+
+// ifdUint decodes the IFD entry in p, which must be of the Byte, Short
+// or Long type, and returns the decoded uint values.
+func (d *decoder) ifdUint(p []byte) (u []uint, err error) {
+ var raw []byte
+ if len(p) < ifdLen {
+ return nil, FormatError("bad IFD entry")
+ }
+
+ datatype := d.byteOrder.Uint16(p[2:4])
+ if dt := int(datatype); dt <= 0 || dt >= len(lengths) {
+ return nil, UnsupportedError("IFD entry datatype")
+ }
+
+ count := d.byteOrder.Uint32(p[4:8])
+ if count > math.MaxInt32/lengths[datatype] {
+ return nil, FormatError("IFD data too large")
+ }
+ if datalen := lengths[datatype] * count; datalen > 4 {
+ // The IFD contains a pointer to the real value.
+ raw = make([]byte, datalen)
+ _, err = d.r.ReadAt(raw, int64(d.byteOrder.Uint32(p[8:12])))
+ } else {
+ raw = p[8 : 8+datalen]
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ u = make([]uint, count)
+ switch datatype {
+ case dtByte:
+ for i := uint32(0); i < count; i++ {
+ u[i] = uint(raw[i])
+ }
+ case dtShort:
+ for i := uint32(0); i < count; i++ {
+ u[i] = uint(d.byteOrder.Uint16(raw[2*i : 2*(i+1)]))
+ }
+ case dtLong:
+ for i := uint32(0); i < count; i++ {
+ u[i] = uint(d.byteOrder.Uint32(raw[4*i : 4*(i+1)]))
+ }
+ default:
+ return nil, UnsupportedError("data type")
+ }
+ return u, nil
+}
+
+// parseIFD decides whether the the IFD entry in p is "interesting" and
+// stows away the data in the decoder. It returns the tag number of the
+// entry and an error, if any.
+func (d *decoder) parseIFD(p []byte) (int, error) {
+ tag := d.byteOrder.Uint16(p[0:2])
+ switch tag {
+ case tBitsPerSample,
+ tExtraSamples,
+ tPhotometricInterpretation,
+ tCompression,
+ tPredictor,
+ tStripOffsets,
+ tStripByteCounts,
+ tRowsPerStrip,
+ tTileWidth,
+ tTileLength,
+ tTileOffsets,
+ tTileByteCounts,
+ tImageLength,
+ tImageWidth:
+ val, err := d.ifdUint(p)
+ if err != nil {
+ return 0, err
+ }
+ d.features[int(tag)] = val
+ case tColorMap:
+ val, err := d.ifdUint(p)
+ if err != nil {
+ return 0, err
+ }
+ numcolors := len(val) / 3
+ if len(val)%3 != 0 || numcolors <= 0 || numcolors > 256 {
+ return 0, FormatError("bad ColorMap length")
+ }
+ d.palette = make([]color.Color, numcolors)
+ for i := 0; i < numcolors; i++ {
+ d.palette[i] = color.RGBA64{
+ uint16(val[i]),
+ uint16(val[i+numcolors]),
+ uint16(val[i+2*numcolors]),
+ 0xffff,
+ }
+ }
+ case tSampleFormat:
+ // Page 27 of the spec: If the SampleFormat is present and
+ // the value is not 1 [= unsigned integer data], a Baseline
+ // TIFF reader that cannot handle the SampleFormat value
+ // must terminate the import process gracefully.
+ val, err := d.ifdUint(p)
+ if err != nil {
+ return 0, err
+ }
+ for _, v := range val {
+ if v != 1 {
+ return 0, UnsupportedError("sample format")
+ }
+ }
+ }
+ return int(tag), nil
+}
+
+// readBits reads n bits from the internal buffer starting at the current offset.
+func (d *decoder) readBits(n uint) (v uint32, ok bool) {
+ for d.nbits < n {
+ d.v <<= 8
+ if d.off >= len(d.buf) {
+ return 0, false
+ }
+ d.v |= uint32(d.buf[d.off])
+ d.off++
+ d.nbits += 8
+ }
+ d.nbits -= n
+ rv := d.v >> d.nbits
+ d.v &^= rv << d.nbits
+ return rv, true
+}
+
+// flushBits discards the unread bits in the buffer used by readBits.
+// It is used at the end of a line.
+func (d *decoder) flushBits() {
+ d.v = 0
+ d.nbits = 0
+}
+
+// minInt returns the smaller of x or y.
+func minInt(a, b int) int {
+ if a <= b {
+ return a
+ }
+ return b
+}
+
+// decode decodes the raw data of an image.
+// It reads from d.buf and writes the strip or tile into dst.
+func (d *decoder) decode(dst image.Image, xmin, ymin, xmax, ymax int) error {
+ d.off = 0
+
+ // Apply horizontal predictor if necessary.
+ // In this case, p contains the color difference to the preceding pixel.
+ // See page 64-65 of the spec.
+ if d.firstVal(tPredictor) == prHorizontal {
+ switch d.bpp {
+ case 16:
+ var off int
+ n := 2 * len(d.features[tBitsPerSample]) // bytes per sample times samples per pixel
+ for y := ymin; y < ymax; y++ {
+ off += n
+ for x := 0; x < (xmax-xmin-1)*n; x += 2 {
+ if off+2 > len(d.buf) {
+ return errNoPixels
+ }
+ v0 := d.byteOrder.Uint16(d.buf[off-n : off-n+2])
+ v1 := d.byteOrder.Uint16(d.buf[off : off+2])
+ d.byteOrder.PutUint16(d.buf[off:off+2], v1+v0)
+ off += 2
+ }
+ }
+ case 8:
+ var off int
+ n := 1 * len(d.features[tBitsPerSample]) // bytes per sample times samples per pixel
+ for y := ymin; y < ymax; y++ {
+ off += n
+ for x := 0; x < (xmax-xmin-1)*n; x++ {
+ if off >= len(d.buf) {
+ return errNoPixels
+ }
+ d.buf[off] += d.buf[off-n]
+ off++
+ }
+ }
+ case 1:
+ return UnsupportedError("horizontal predictor with 1 BitsPerSample")
+ }
+ }
+
+ rMaxX := minInt(xmax, dst.Bounds().Max.X)
+ rMaxY := minInt(ymax, dst.Bounds().Max.Y)
+ switch d.mode {
+ case mGray, mGrayInvert:
+ if d.bpp == 16 {
+ img := dst.(*image.Gray16)
+ for y := ymin; y < rMaxY; y++ {
+ for x := xmin; x < rMaxX; x++ {
+ if d.off+2 > len(d.buf) {
+ return errNoPixels
+ }
+ v := d.byteOrder.Uint16(d.buf[d.off : d.off+2])
+ d.off += 2
+ if d.mode == mGrayInvert {
+ v = 0xffff - v
+ }
+ img.SetGray16(x, y, color.Gray16{v})
+ }
+ if rMaxX == img.Bounds().Max.X {
+ d.off += 2 * (xmax - img.Bounds().Max.X)
+ }
+ }
+ } else {
+ img := dst.(*image.Gray)
+ max := uint32((1 << d.bpp) - 1)
+ for y := ymin; y < rMaxY; y++ {
+ for x := xmin; x < rMaxX; x++ {
+ v, ok := d.readBits(d.bpp)
+ if !ok {
+ return errNoPixels
+ }
+ v = v * 0xff / max
+ if d.mode == mGrayInvert {
+ v = 0xff - v
+ }
+ img.SetGray(x, y, color.Gray{uint8(v)})
+ }
+ d.flushBits()
+ }
+ }
+ case mPaletted:
+ img := dst.(*image.Paletted)
+ for y := ymin; y < rMaxY; y++ {
+ for x := xmin; x < rMaxX; x++ {
+ v, ok := d.readBits(d.bpp)
+ if !ok {
+ return errNoPixels
+ }
+ img.SetColorIndex(x, y, uint8(v))
+ }
+ d.flushBits()
+ }
+ case mRGB:
+ if d.bpp == 16 {
+ img := dst.(*image.RGBA64)
+ for y := ymin; y < rMaxY; y++ {
+ for x := xmin; x < rMaxX; x++ {
+ if d.off+6 > len(d.buf) {
+ return errNoPixels
+ }
+ r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2])
+ g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4])
+ b := d.byteOrder.Uint16(d.buf[d.off+4 : d.off+6])
+ d.off += 6
+ img.SetRGBA64(x, y, color.RGBA64{r, g, b, 0xffff})
+ }
+ }
+ } else {
+ img := dst.(*image.RGBA)
+ for y := ymin; y < rMaxY; y++ {
+ min := img.PixOffset(xmin, y)
+ max := img.PixOffset(rMaxX, y)
+ off := (y - ymin) * (xmax - xmin) * 3
+ for i := min; i < max; i += 4 {
+ if off+3 > len(d.buf) {
+ return errNoPixels
+ }
+ img.Pix[i+0] = d.buf[off+0]
+ img.Pix[i+1] = d.buf[off+1]
+ img.Pix[i+2] = d.buf[off+2]
+ img.Pix[i+3] = 0xff
+ off += 3
+ }
+ }
+ }
+ case mNRGBA:
+ if d.bpp == 16 {
+ img := dst.(*image.NRGBA64)
+ for y := ymin; y < rMaxY; y++ {
+ for x := xmin; x < rMaxX; x++ {
+ if d.off+8 > len(d.buf) {
+ return errNoPixels
+ }
+ r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2])
+ g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4])
+ b := d.byteOrder.Uint16(d.buf[d.off+4 : d.off+6])
+ a := d.byteOrder.Uint16(d.buf[d.off+6 : d.off+8])
+ d.off += 8
+ img.SetNRGBA64(x, y, color.NRGBA64{r, g, b, a})
+ }
+ }
+ } else {
+ img := dst.(*image.NRGBA)
+ for y := ymin; y < rMaxY; y++ {
+ min := img.PixOffset(xmin, y)
+ max := img.PixOffset(rMaxX, y)
+ i0, i1 := (y-ymin)*(xmax-xmin)*4, (y-ymin+1)*(xmax-xmin)*4
+ if i1 > len(d.buf) {
+ return errNoPixels
+ }
+ copy(img.Pix[min:max], d.buf[i0:i1])
+ }
+ }
+ case mRGBA:
+ if d.bpp == 16 {
+ img := dst.(*image.RGBA64)
+ for y := ymin; y < rMaxY; y++ {
+ for x := xmin; x < rMaxX; x++ {
+ if d.off+8 > len(d.buf) {
+ return errNoPixels
+ }
+ r := d.byteOrder.Uint16(d.buf[d.off+0 : d.off+2])
+ g := d.byteOrder.Uint16(d.buf[d.off+2 : d.off+4])
+ b := d.byteOrder.Uint16(d.buf[d.off+4 : d.off+6])
+ a := d.byteOrder.Uint16(d.buf[d.off+6 : d.off+8])
+ d.off += 8
+ img.SetRGBA64(x, y, color.RGBA64{r, g, b, a})
+ }
+ }
+ } else {
+ img := dst.(*image.RGBA)
+ for y := ymin; y < rMaxY; y++ {
+ min := img.PixOffset(xmin, y)
+ max := img.PixOffset(rMaxX, y)
+ i0, i1 := (y-ymin)*(xmax-xmin)*4, (y-ymin+1)*(xmax-xmin)*4
+ if i1 > len(d.buf) {
+ return errNoPixels
+ }
+ copy(img.Pix[min:max], d.buf[i0:i1])
+ }
+ }
+ }
+
+ return nil
+}
+
+func newDecoder(r io.Reader) (*decoder, error) {
+ d := &decoder{
+ r: newReaderAt(r),
+ features: make(map[int][]uint),
+ }
+
+ p := make([]byte, 8)
+ if _, err := d.r.ReadAt(p, 0); err != nil {
+ return nil, err
+ }
+ switch string(p[0:4]) {
+ case leHeader:
+ d.byteOrder = binary.LittleEndian
+ case beHeader:
+ d.byteOrder = binary.BigEndian
+ default:
+ return nil, FormatError("malformed header")
+ }
+
+ ifdOffset := int64(d.byteOrder.Uint32(p[4:8]))
+
+ // The first two bytes contain the number of entries (12 bytes each).
+ if _, err := d.r.ReadAt(p[0:2], ifdOffset); err != nil {
+ return nil, err
+ }
+ numItems := int(d.byteOrder.Uint16(p[0:2]))
+
+ // All IFD entries are read in one chunk.
+ p = make([]byte, ifdLen*numItems)
+ if _, err := d.r.ReadAt(p, ifdOffset+2); err != nil {
+ return nil, err
+ }
+
+ prevTag := -1
+ for i := 0; i < len(p); i += ifdLen {
+ tag, err := d.parseIFD(p[i : i+ifdLen])
+ if err != nil {
+ return nil, err
+ }
+ if tag <= prevTag {
+ return nil, FormatError("tags are not sorted in ascending order")
+ }
+ prevTag = tag
+ }
+
+ d.config.Width = int(d.firstVal(tImageWidth))
+ d.config.Height = int(d.firstVal(tImageLength))
+
+ if _, ok := d.features[tBitsPerSample]; !ok {
+ return nil, FormatError("BitsPerSample tag missing")
+ }
+ d.bpp = d.firstVal(tBitsPerSample)
+ switch d.bpp {
+ case 0:
+ return nil, FormatError("BitsPerSample must not be 0")
+ case 1, 8, 16:
+ // Nothing to do, these are accepted by this implementation.
+ default:
+ return nil, UnsupportedError(fmt.Sprintf("BitsPerSample of %v", d.bpp))
+ }
+
+ // Determine the image mode.
+ switch d.firstVal(tPhotometricInterpretation) {
+ case pRGB:
+ if d.bpp == 16 {
+ for _, b := range d.features[tBitsPerSample] {
+ if b != 16 {
+ return nil, FormatError("wrong number of samples for 16bit RGB")
+ }
+ }
+ } else {
+ for _, b := range d.features[tBitsPerSample] {
+ if b != 8 {
+ return nil, FormatError("wrong number of samples for 8bit RGB")
+ }
+ }
+ }
+ // RGB images normally have 3 samples per pixel.
+ // If there are more, ExtraSamples (p. 31-32 of the spec)
+ // gives their meaning (usually an alpha channel).
+ //
+ // This implementation does not support extra samples
+ // of an unspecified type.
+ switch len(d.features[tBitsPerSample]) {
+ case 3:
+ d.mode = mRGB
+ if d.bpp == 16 {
+ d.config.ColorModel = color.RGBA64Model
+ } else {
+ d.config.ColorModel = color.RGBAModel
+ }
+ case 4:
+ switch d.firstVal(tExtraSamples) {
+ case 1:
+ d.mode = mRGBA
+ if d.bpp == 16 {
+ d.config.ColorModel = color.RGBA64Model
+ } else {
+ d.config.ColorModel = color.RGBAModel
+ }
+ case 2:
+ d.mode = mNRGBA
+ if d.bpp == 16 {
+ d.config.ColorModel = color.NRGBA64Model
+ } else {
+ d.config.ColorModel = color.NRGBAModel
+ }
+ default:
+ return nil, FormatError("wrong number of samples for RGB")
+ }
+ default:
+ return nil, FormatError("wrong number of samples for RGB")
+ }
+ case pPaletted:
+ d.mode = mPaletted
+ d.config.ColorModel = color.Palette(d.palette)
+ case pWhiteIsZero:
+ d.mode = mGrayInvert
+ if d.bpp == 16 {
+ d.config.ColorModel = color.Gray16Model
+ } else {
+ d.config.ColorModel = color.GrayModel
+ }
+ case pBlackIsZero:
+ d.mode = mGray
+ if d.bpp == 16 {
+ d.config.ColorModel = color.Gray16Model
+ } else {
+ d.config.ColorModel = color.GrayModel
+ }
+ default:
+ return nil, UnsupportedError("color model")
+ }
+
+ return d, nil
+}
+
+// DecodeConfig returns the color model and dimensions of a TIFF image without
+// decoding the entire image.
+func DecodeConfig(r io.Reader) (image.Config, error) {
+ d, err := newDecoder(r)
+ if err != nil {
+ return image.Config{}, err
+ }
+ return d.config, nil
+}
+
+// Decode reads a TIFF image from r and returns it as an image.Image.
+// The type of Image returned depends on the contents of the TIFF.
+func Decode(r io.Reader) (img image.Image, err error) {
+ d, err := newDecoder(r)
+ if err != nil {
+ return
+ }
+
+ blockPadding := false
+ blockWidth := d.config.Width
+ blockHeight := d.config.Height
+ blocksAcross := 1
+ blocksDown := 1
+
+ if d.config.Width == 0 {
+ blocksAcross = 0
+ }
+ if d.config.Height == 0 {
+ blocksDown = 0
+ }
+
+ var blockOffsets, blockCounts []uint
+
+ if int(d.firstVal(tTileWidth)) != 0 {
+ blockPadding = true
+
+ blockWidth = int(d.firstVal(tTileWidth))
+ blockHeight = int(d.firstVal(tTileLength))
+
+ if blockWidth != 0 {
+ blocksAcross = (d.config.Width + blockWidth - 1) / blockWidth
+ }
+ if blockHeight != 0 {
+ blocksDown = (d.config.Height + blockHeight - 1) / blockHeight
+ }
+
+ blockCounts = d.features[tTileByteCounts]
+ blockOffsets = d.features[tTileOffsets]
+
+ } else {
+ if int(d.firstVal(tRowsPerStrip)) != 0 {
+ blockHeight = int(d.firstVal(tRowsPerStrip))
+ }
+
+ if blockHeight != 0 {
+ blocksDown = (d.config.Height + blockHeight - 1) / blockHeight
+ }
+
+ blockOffsets = d.features[tStripOffsets]
+ blockCounts = d.features[tStripByteCounts]
+ }
+
+ // Check if we have the right number of strips/tiles, offsets and counts.
+ if n := blocksAcross * blocksDown; len(blockOffsets) < n || len(blockCounts) < n {
+ return nil, FormatError("inconsistent header")
+ }
+
+ imgRect := image.Rect(0, 0, d.config.Width, d.config.Height)
+ switch d.mode {
+ case mGray, mGrayInvert:
+ if d.bpp == 16 {
+ img = image.NewGray16(imgRect)
+ } else {
+ img = image.NewGray(imgRect)
+ }
+ case mPaletted:
+ img = image.NewPaletted(imgRect, d.palette)
+ case mNRGBA:
+ if d.bpp == 16 {
+ img = image.NewNRGBA64(imgRect)
+ } else {
+ img = image.NewNRGBA(imgRect)
+ }
+ case mRGB, mRGBA:
+ if d.bpp == 16 {
+ img = image.NewRGBA64(imgRect)
+ } else {
+ img = image.NewRGBA(imgRect)
+ }
+ }
+
+ for i := 0; i < blocksAcross; i++ {
+ blkW := blockWidth
+ if !blockPadding && i == blocksAcross-1 && d.config.Width%blockWidth != 0 {
+ blkW = d.config.Width % blockWidth
+ }
+ for j := 0; j < blocksDown; j++ {
+ blkH := blockHeight
+ if !blockPadding && j == blocksDown-1 && d.config.Height%blockHeight != 0 {
+ blkH = d.config.Height % blockHeight
+ }
+ offset := int64(blockOffsets[j*blocksAcross+i])
+ n := int64(blockCounts[j*blocksAcross+i])
+ switch d.firstVal(tCompression) {
+
+ // According to the spec, Compression does not have a default value,
+ // but some tools interpret a missing Compression value as none so we do
+ // the same.
+ case cNone, 0:
+ if b, ok := d.r.(*buffer); ok {
+ d.buf, err = b.Slice(int(offset), int(n))
+ } else {
+ d.buf = make([]byte, n)
+ _, err = d.r.ReadAt(d.buf, offset)
+ }
+ case cLZW:
+ r := lzw.NewReader(io.NewSectionReader(d.r, offset, n), lzw.MSB, 8)
+ d.buf, err = ioutil.ReadAll(r)
+ r.Close()
+ case cDeflate, cDeflateOld:
+ var r io.ReadCloser
+ r, err = zlib.NewReader(io.NewSectionReader(d.r, offset, n))
+ if err != nil {
+ return nil, err
+ }
+ d.buf, err = ioutil.ReadAll(r)
+ r.Close()
+ case cPackBits:
+ d.buf, err = unpackBits(io.NewSectionReader(d.r, offset, n))
+ default:
+ err = UnsupportedError(fmt.Sprintf("compression value %d", d.firstVal(tCompression)))
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ xmin := i * blockWidth
+ ymin := j * blockHeight
+ xmax := xmin + blkW
+ ymax := ymin + blkH
+ err = d.decode(img, xmin, ymin, xmax, ymax)
+ if err != nil {
+ return nil, err
+ }
+ }
+ }
+ return
+}
+
+func init() {
+ image.RegisterFormat("tiff", leHeader, Decode, DecodeConfig)
+ image.RegisterFormat("tiff", beHeader, Decode, DecodeConfig)
+}
diff --git a/vendor/golang.org/x/image/tiff/writer.go b/vendor/golang.org/x/image/tiff/writer.go
new file mode 100644
index 0000000..c8a01ce
--- /dev/null
+++ b/vendor/golang.org/x/image/tiff/writer.go
@@ -0,0 +1,438 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tiff
+
+import (
+ "bytes"
+ "compress/zlib"
+ "encoding/binary"
+ "image"
+ "io"
+ "sort"
+)
+
+// The TIFF format allows to choose the order of the different elements freely.
+// The basic structure of a TIFF file written by this package is:
+//
+// 1. Header (8 bytes).
+// 2. Image data.
+// 3. Image File Directory (IFD).
+// 4. "Pointer area" for larger entries in the IFD.
+
+// We only write little-endian TIFF files.
+var enc = binary.LittleEndian
+
+// An ifdEntry is a single entry in an Image File Directory.
+// A value of type dtRational is composed of two 32-bit values,
+// thus data contains two uints (numerator and denominator) for a single number.
+type ifdEntry struct {
+ tag int
+ datatype int
+ data []uint32
+}
+
+func (e ifdEntry) putData(p []byte) {
+ for _, d := range e.data {
+ switch e.datatype {
+ case dtByte, dtASCII:
+ p[0] = byte(d)
+ p = p[1:]
+ case dtShort:
+ enc.PutUint16(p, uint16(d))
+ p = p[2:]
+ case dtLong, dtRational:
+ enc.PutUint32(p, uint32(d))
+ p = p[4:]
+ }
+ }
+}
+
+type byTag []ifdEntry
+
+func (d byTag) Len() int { return len(d) }
+func (d byTag) Less(i, j int) bool { return d[i].tag < d[j].tag }
+func (d byTag) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
+
+func encodeGray(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error {
+ if !predictor {
+ return writePix(w, pix, dy, dx, stride)
+ }
+ buf := make([]byte, dx)
+ for y := 0; y < dy; y++ {
+ min := y*stride + 0
+ max := y*stride + dx
+ off := 0
+ var v0 uint8
+ for i := min; i < max; i++ {
+ v1 := pix[i]
+ buf[off] = v1 - v0
+ v0 = v1
+ off++
+ }
+ if _, err := w.Write(buf); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func encodeGray16(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error {
+ buf := make([]byte, dx*2)
+ for y := 0; y < dy; y++ {
+ min := y*stride + 0
+ max := y*stride + dx*2
+ off := 0
+ var v0 uint16
+ for i := min; i < max; i += 2 {
+ // An image.Gray16's Pix is in big-endian order.
+ v1 := uint16(pix[i])<<8 | uint16(pix[i+1])
+ if predictor {
+ v0, v1 = v1, v1-v0
+ }
+ // We only write little-endian TIFF files.
+ buf[off+0] = byte(v1)
+ buf[off+1] = byte(v1 >> 8)
+ off += 2
+ }
+ if _, err := w.Write(buf); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func encodeRGBA(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error {
+ if !predictor {
+ return writePix(w, pix, dy, dx*4, stride)
+ }
+ buf := make([]byte, dx*4)
+ for y := 0; y < dy; y++ {
+ min := y*stride + 0
+ max := y*stride + dx*4
+ off := 0
+ var r0, g0, b0, a0 uint8
+ for i := min; i < max; i += 4 {
+ r1, g1, b1, a1 := pix[i+0], pix[i+1], pix[i+2], pix[i+3]
+ buf[off+0] = r1 - r0
+ buf[off+1] = g1 - g0
+ buf[off+2] = b1 - b0
+ buf[off+3] = a1 - a0
+ off += 4
+ r0, g0, b0, a0 = r1, g1, b1, a1
+ }
+ if _, err := w.Write(buf); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func encodeRGBA64(w io.Writer, pix []uint8, dx, dy, stride int, predictor bool) error {
+ buf := make([]byte, dx*8)
+ for y := 0; y < dy; y++ {
+ min := y*stride + 0
+ max := y*stride + dx*8
+ off := 0
+ var r0, g0, b0, a0 uint16
+ for i := min; i < max; i += 8 {
+ // An image.RGBA64's Pix is in big-endian order.
+ r1 := uint16(pix[i+0])<<8 | uint16(pix[i+1])
+ g1 := uint16(pix[i+2])<<8 | uint16(pix[i+3])
+ b1 := uint16(pix[i+4])<<8 | uint16(pix[i+5])
+ a1 := uint16(pix[i+6])<<8 | uint16(pix[i+7])
+ if predictor {
+ r0, r1 = r1, r1-r0
+ g0, g1 = g1, g1-g0
+ b0, b1 = b1, b1-b0
+ a0, a1 = a1, a1-a0
+ }
+ // We only write little-endian TIFF files.
+ buf[off+0] = byte(r1)
+ buf[off+1] = byte(r1 >> 8)
+ buf[off+2] = byte(g1)
+ buf[off+3] = byte(g1 >> 8)
+ buf[off+4] = byte(b1)
+ buf[off+5] = byte(b1 >> 8)
+ buf[off+6] = byte(a1)
+ buf[off+7] = byte(a1 >> 8)
+ off += 8
+ }
+ if _, err := w.Write(buf); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func encode(w io.Writer, m image.Image, predictor bool) error {
+ bounds := m.Bounds()
+ buf := make([]byte, 4*bounds.Dx())
+ for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
+ off := 0
+ if predictor {
+ var r0, g0, b0, a0 uint8
+ for x := bounds.Min.X; x < bounds.Max.X; x++ {
+ r, g, b, a := m.At(x, y).RGBA()
+ r1 := uint8(r >> 8)
+ g1 := uint8(g >> 8)
+ b1 := uint8(b >> 8)
+ a1 := uint8(a >> 8)
+ buf[off+0] = r1 - r0
+ buf[off+1] = g1 - g0
+ buf[off+2] = b1 - b0
+ buf[off+3] = a1 - a0
+ off += 4
+ r0, g0, b0, a0 = r1, g1, b1, a1
+ }
+ } else {
+ for x := bounds.Min.X; x < bounds.Max.X; x++ {
+ r, g, b, a := m.At(x, y).RGBA()
+ buf[off+0] = uint8(r >> 8)
+ buf[off+1] = uint8(g >> 8)
+ buf[off+2] = uint8(b >> 8)
+ buf[off+3] = uint8(a >> 8)
+ off += 4
+ }
+ }
+ if _, err := w.Write(buf); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// writePix writes the internal byte array of an image to w. It is less general
+// but much faster then encode. writePix is used when pix directly
+// corresponds to one of the TIFF image types.
+func writePix(w io.Writer, pix []byte, nrows, length, stride int) error {
+ if length == stride {
+ _, err := w.Write(pix[:nrows*length])
+ return err
+ }
+ for ; nrows > 0; nrows-- {
+ if _, err := w.Write(pix[:length]); err != nil {
+ return err
+ }
+ pix = pix[stride:]
+ }
+ return nil
+}
+
+func writeIFD(w io.Writer, ifdOffset int, d []ifdEntry) error {
+ var buf [ifdLen]byte
+ // Make space for "pointer area" containing IFD entry data
+ // longer than 4 bytes.
+ parea := make([]byte, 1024)
+ pstart := ifdOffset + ifdLen*len(d) + 6
+ var o int // Current offset in parea.
+
+ // The IFD has to be written with the tags in ascending order.
+ sort.Sort(byTag(d))
+
+ // Write the number of entries in this IFD.
+ if err := binary.Write(w, enc, uint16(len(d))); err != nil {
+ return err
+ }
+ for _, ent := range d {
+ enc.PutUint16(buf[0:2], uint16(ent.tag))
+ enc.PutUint16(buf[2:4], uint16(ent.datatype))
+ count := uint32(len(ent.data))
+ if ent.datatype == dtRational {
+ count /= 2
+ }
+ enc.PutUint32(buf[4:8], count)
+ datalen := int(count * lengths[ent.datatype])
+ if datalen <= 4 {
+ ent.putData(buf[8:12])
+ } else {
+ if (o + datalen) > len(parea) {
+ newlen := len(parea) + 1024
+ for (o + datalen) > newlen {
+ newlen += 1024
+ }
+ newarea := make([]byte, newlen)
+ copy(newarea, parea)
+ parea = newarea
+ }
+ ent.putData(parea[o : o+datalen])
+ enc.PutUint32(buf[8:12], uint32(pstart+o))
+ o += datalen
+ }
+ if _, err := w.Write(buf[:]); err != nil {
+ return err
+ }
+ }
+ // The IFD ends with the offset of the next IFD in the file,
+ // or zero if it is the last one (page 14).
+ if err := binary.Write(w, enc, uint32(0)); err != nil {
+ return err
+ }
+ _, err := w.Write(parea[:o])
+ return err
+}
+
+// Options are the encoding parameters.
+type Options struct {
+ // Compression is the type of compression used.
+ Compression CompressionType
+ // Predictor determines whether a differencing predictor is used;
+ // if true, instead of each pixel's color, the color difference to the
+ // preceding one is saved. This improves the compression for certain
+ // types of images and compressors. For example, it works well for
+ // photos with Deflate compression.
+ Predictor bool
+}
+
+// Encode writes the image m to w. opt determines the options used for
+// encoding, such as the compression type. If opt is nil, an uncompressed
+// image is written.
+func Encode(w io.Writer, m image.Image, opt *Options) error {
+ d := m.Bounds().Size()
+
+ compression := uint32(cNone)
+ predictor := false
+ if opt != nil {
+ compression = opt.Compression.specValue()
+ // The predictor field is only used with LZW. See page 64 of the spec.
+ predictor = opt.Predictor && compression == cLZW
+ }
+
+ _, err := io.WriteString(w, leHeader)
+ if err != nil {
+ return err
+ }
+
+ // Compressed data is written into a buffer first, so that we
+ // know the compressed size.
+ var buf bytes.Buffer
+ // dst holds the destination for the pixel data of the image --
+ // either w or a writer to buf.
+ var dst io.Writer
+ // imageLen is the length of the pixel data in bytes.
+ // The offset of the IFD is imageLen + 8 header bytes.
+ var imageLen int
+
+ switch compression {
+ case cNone:
+ dst = w
+ // Write IFD offset before outputting pixel data.
+ switch m.(type) {
+ case *image.Paletted:
+ imageLen = d.X * d.Y * 1
+ case *image.Gray:
+ imageLen = d.X * d.Y * 1
+ case *image.Gray16:
+ imageLen = d.X * d.Y * 2
+ case *image.RGBA64:
+ imageLen = d.X * d.Y * 8
+ case *image.NRGBA64:
+ imageLen = d.X * d.Y * 8
+ default:
+ imageLen = d.X * d.Y * 4
+ }
+ err = binary.Write(w, enc, uint32(imageLen+8))
+ if err != nil {
+ return err
+ }
+ case cDeflate:
+ dst = zlib.NewWriter(&buf)
+ }
+
+ pr := uint32(prNone)
+ photometricInterpretation := uint32(pRGB)
+ samplesPerPixel := uint32(4)
+ bitsPerSample := []uint32{8, 8, 8, 8}
+ extraSamples := uint32(0)
+ colorMap := []uint32{}
+
+ if predictor {
+ pr = prHorizontal
+ }
+ switch m := m.(type) {
+ case *image.Paletted:
+ photometricInterpretation = pPaletted
+ samplesPerPixel = 1
+ bitsPerSample = []uint32{8}
+ colorMap = make([]uint32, 256*3)
+ for i := 0; i < 256 && i < len(m.Palette); i++ {
+ r, g, b, _ := m.Palette[i].RGBA()
+ colorMap[i+0*256] = uint32(r)
+ colorMap[i+1*256] = uint32(g)
+ colorMap[i+2*256] = uint32(b)
+ }
+ err = encodeGray(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
+ case *image.Gray:
+ photometricInterpretation = pBlackIsZero
+ samplesPerPixel = 1
+ bitsPerSample = []uint32{8}
+ err = encodeGray(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
+ case *image.Gray16:
+ photometricInterpretation = pBlackIsZero
+ samplesPerPixel = 1
+ bitsPerSample = []uint32{16}
+ err = encodeGray16(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
+ case *image.NRGBA:
+ extraSamples = 2 // Unassociated alpha.
+ err = encodeRGBA(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
+ case *image.NRGBA64:
+ extraSamples = 2 // Unassociated alpha.
+ bitsPerSample = []uint32{16, 16, 16, 16}
+ err = encodeRGBA64(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
+ case *image.RGBA:
+ extraSamples = 1 // Associated alpha.
+ err = encodeRGBA(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
+ case *image.RGBA64:
+ extraSamples = 1 // Associated alpha.
+ bitsPerSample = []uint32{16, 16, 16, 16}
+ err = encodeRGBA64(dst, m.Pix, d.X, d.Y, m.Stride, predictor)
+ default:
+ extraSamples = 1 // Associated alpha.
+ err = encode(dst, m, predictor)
+ }
+ if err != nil {
+ return err
+ }
+
+ if compression != cNone {
+ if err = dst.(io.Closer).Close(); err != nil {
+ return err
+ }
+ imageLen = buf.Len()
+ if err = binary.Write(w, enc, uint32(imageLen+8)); err != nil {
+ return err
+ }
+ if _, err = buf.WriteTo(w); err != nil {
+ return err
+ }
+ }
+
+ ifd := []ifdEntry{
+ {tImageWidth, dtShort, []uint32{uint32(d.X)}},
+ {tImageLength, dtShort, []uint32{uint32(d.Y)}},
+ {tBitsPerSample, dtShort, bitsPerSample},
+ {tCompression, dtShort, []uint32{compression}},
+ {tPhotometricInterpretation, dtShort, []uint32{photometricInterpretation}},
+ {tStripOffsets, dtLong, []uint32{8}},
+ {tSamplesPerPixel, dtShort, []uint32{samplesPerPixel}},
+ {tRowsPerStrip, dtShort, []uint32{uint32(d.Y)}},
+ {tStripByteCounts, dtLong, []uint32{uint32(imageLen)}},
+ // There is currently no support for storing the image
+ // resolution, so give a bogus value of 72x72 dpi.
+ {tXResolution, dtRational, []uint32{72, 1}},
+ {tYResolution, dtRational, []uint32{72, 1}},
+ {tResolutionUnit, dtShort, []uint32{resPerInch}},
+ }
+ if pr != prNone {
+ ifd = append(ifd, ifdEntry{tPredictor, dtShort, []uint32{pr}})
+ }
+ if len(colorMap) != 0 {
+ ifd = append(ifd, ifdEntry{tColorMap, dtShort, colorMap})
+ }
+ if extraSamples > 0 {
+ ifd = append(ifd, ifdEntry{tExtraSamples, dtShort, []uint32{extraSamples}})
+ }
+
+ return writeIFD(w, imageLen+8, ifd)
+}
diff --git a/vendor/golang.org/x/image/vp8/decode.go b/vendor/golang.org/x/image/vp8/decode.go
new file mode 100644
index 0000000..1bb5028
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8/decode.go
@@ -0,0 +1,403 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package vp8 implements a decoder for the VP8 lossy image format.
+//
+// The VP8 specification is RFC 6386.
+package vp8 // import "golang.org/x/image/vp8"
+
+// This file implements the top-level decoding algorithm.
+
+import (
+ "errors"
+ "image"
+ "io"
+)
+
+// limitReader wraps an io.Reader to read at most n bytes from it.
+type limitReader struct {
+ r io.Reader
+ n int
+}
+
+// ReadFull reads exactly len(p) bytes into p.
+func (r *limitReader) ReadFull(p []byte) error {
+ if len(p) > r.n {
+ return io.ErrUnexpectedEOF
+ }
+ n, err := io.ReadFull(r.r, p)
+ r.n -= n
+ return err
+}
+
+// FrameHeader is a frame header, as specified in section 9.1.
+type FrameHeader struct {
+ KeyFrame bool
+ VersionNumber uint8
+ ShowFrame bool
+ FirstPartitionLen uint32
+ Width int
+ Height int
+ XScale uint8
+ YScale uint8
+}
+
+const (
+ nSegment = 4
+ nSegmentProb = 3
+)
+
+// segmentHeader holds segment-related header information.
+type segmentHeader struct {
+ useSegment bool
+ updateMap bool
+ relativeDelta bool
+ quantizer [nSegment]int8
+ filterStrength [nSegment]int8
+ prob [nSegmentProb]uint8
+}
+
+const (
+ nRefLFDelta = 4
+ nModeLFDelta = 4
+)
+
+// filterHeader holds filter-related header information.
+type filterHeader struct {
+ simple bool
+ level int8
+ sharpness uint8
+ useLFDelta bool
+ refLFDelta [nRefLFDelta]int8
+ modeLFDelta [nModeLFDelta]int8
+ perSegmentLevel [nSegment]int8
+}
+
+// mb is the per-macroblock decode state. A decoder maintains mbw+1 of these
+// as it is decoding macroblocks left-to-right and top-to-bottom: mbw for the
+// macroblocks in the row above, and one for the macroblock to the left.
+type mb struct {
+ // pred is the predictor mode for the 4 bottom or right 4x4 luma regions.
+ pred [4]uint8
+ // nzMask is a mask of 8 bits: 4 for the bottom or right 4x4 luma regions,
+ // and 2 + 2 for the bottom or right 4x4 chroma regions. A 1 bit indicates
+ // that that region has non-zero coefficients.
+ nzMask uint8
+ // nzY16 is a 0/1 value that is 1 if the macroblock used Y16 prediction and
+ // had non-zero coefficients.
+ nzY16 uint8
+}
+
+// Decoder decodes VP8 bitstreams into frames. Decoding one frame consists of
+// calling Init, DecodeFrameHeader and then DecodeFrame in that order.
+// A Decoder can be re-used to decode multiple frames.
+type Decoder struct {
+ // r is the input bitsream.
+ r limitReader
+ // scratch is a scratch buffer.
+ scratch [8]byte
+ // img is the YCbCr image to decode into.
+ img *image.YCbCr
+ // mbw and mbh are the number of 16x16 macroblocks wide and high the image is.
+ mbw, mbh int
+ // frameHeader is the frame header. When decoding multiple frames,
+ // frames that aren't key frames will inherit the Width, Height,
+ // XScale and YScale of the most recent key frame.
+ frameHeader FrameHeader
+ // Other headers.
+ segmentHeader segmentHeader
+ filterHeader filterHeader
+ // The image data is divided into a number of independent partitions.
+ // There is 1 "first partition" and between 1 and 8 "other partitions"
+ // for coefficient data.
+ fp partition
+ op [8]partition
+ nOP int
+ // Quantization factors.
+ quant [nSegment]quant
+ // DCT/WHT coefficient decoding probabilities.
+ tokenProb [nPlane][nBand][nContext][nProb]uint8
+ useSkipProb bool
+ skipProb uint8
+ // Loop filter parameters.
+ filterParams [nSegment][2]filterParam
+ perMBFilterParams []filterParam
+
+ // The eight fields below relate to the current macroblock being decoded.
+ //
+ // Segment-based adjustments.
+ segment int
+ // Per-macroblock state for the macroblock immediately left of and those
+ // macroblocks immediately above the current macroblock.
+ leftMB mb
+ upMB []mb
+ // Bitmasks for which 4x4 regions of coeff contain non-zero coefficients.
+ nzDCMask, nzACMask uint32
+ // Predictor modes.
+ usePredY16 bool // The libwebp C code calls this !is_i4x4_.
+ predY16 uint8
+ predC8 uint8
+ predY4 [4][4]uint8
+
+ // The two fields below form a workspace for reconstructing a macroblock.
+ // Their specific sizes are documented in reconstruct.go.
+ coeff [1*16*16 + 2*8*8 + 1*4*4]int16
+ ybr [1 + 16 + 1 + 8][32]uint8
+}
+
+// NewDecoder returns a new Decoder.
+func NewDecoder() *Decoder {
+ return &Decoder{}
+}
+
+// Init initializes the decoder to read at most n bytes from r.
+func (d *Decoder) Init(r io.Reader, n int) {
+ d.r = limitReader{r, n}
+}
+
+// DecodeFrameHeader decodes the frame header.
+func (d *Decoder) DecodeFrameHeader() (fh FrameHeader, err error) {
+ // All frame headers are at least 3 bytes long.
+ b := d.scratch[:3]
+ if err = d.r.ReadFull(b); err != nil {
+ return
+ }
+ d.frameHeader.KeyFrame = (b[0] & 1) == 0
+ d.frameHeader.VersionNumber = (b[0] >> 1) & 7
+ d.frameHeader.ShowFrame = (b[0]>>4)&1 == 1
+ d.frameHeader.FirstPartitionLen = uint32(b[0])>>5 | uint32(b[1])<<3 | uint32(b[2])<<11
+ if !d.frameHeader.KeyFrame {
+ return d.frameHeader, nil
+ }
+ // Frame headers for key frames are an additional 7 bytes long.
+ b = d.scratch[:7]
+ if err = d.r.ReadFull(b); err != nil {
+ return
+ }
+ // Check the magic sync code.
+ if b[0] != 0x9d || b[1] != 0x01 || b[2] != 0x2a {
+ err = errors.New("vp8: invalid format")
+ return
+ }
+ d.frameHeader.Width = int(b[4]&0x3f)<<8 | int(b[3])
+ d.frameHeader.Height = int(b[6]&0x3f)<<8 | int(b[5])
+ d.frameHeader.XScale = b[4] >> 6
+ d.frameHeader.YScale = b[6] >> 6
+ d.mbw = (d.frameHeader.Width + 0x0f) >> 4
+ d.mbh = (d.frameHeader.Height + 0x0f) >> 4
+ d.segmentHeader = segmentHeader{
+ prob: [3]uint8{0xff, 0xff, 0xff},
+ }
+ d.tokenProb = defaultTokenProb
+ d.segment = 0
+ return d.frameHeader, nil
+}
+
+// ensureImg ensures that d.img is large enough to hold the decoded frame.
+func (d *Decoder) ensureImg() {
+ if d.img != nil {
+ p0, p1 := d.img.Rect.Min, d.img.Rect.Max
+ if p0.X == 0 && p0.Y == 0 && p1.X >= 16*d.mbw && p1.Y >= 16*d.mbh {
+ return
+ }
+ }
+ m := image.NewYCbCr(image.Rect(0, 0, 16*d.mbw, 16*d.mbh), image.YCbCrSubsampleRatio420)
+ d.img = m.SubImage(image.Rect(0, 0, d.frameHeader.Width, d.frameHeader.Height)).(*image.YCbCr)
+ d.perMBFilterParams = make([]filterParam, d.mbw*d.mbh)
+ d.upMB = make([]mb, d.mbw)
+}
+
+// parseSegmentHeader parses the segment header, as specified in section 9.3.
+func (d *Decoder) parseSegmentHeader() {
+ d.segmentHeader.useSegment = d.fp.readBit(uniformProb)
+ if !d.segmentHeader.useSegment {
+ d.segmentHeader.updateMap = false
+ return
+ }
+ d.segmentHeader.updateMap = d.fp.readBit(uniformProb)
+ if d.fp.readBit(uniformProb) {
+ d.segmentHeader.relativeDelta = !d.fp.readBit(uniformProb)
+ for i := range d.segmentHeader.quantizer {
+ d.segmentHeader.quantizer[i] = int8(d.fp.readOptionalInt(uniformProb, 7))
+ }
+ for i := range d.segmentHeader.filterStrength {
+ d.segmentHeader.filterStrength[i] = int8(d.fp.readOptionalInt(uniformProb, 6))
+ }
+ }
+ if !d.segmentHeader.updateMap {
+ return
+ }
+ for i := range d.segmentHeader.prob {
+ if d.fp.readBit(uniformProb) {
+ d.segmentHeader.prob[i] = uint8(d.fp.readUint(uniformProb, 8))
+ } else {
+ d.segmentHeader.prob[i] = 0xff
+ }
+ }
+}
+
+// parseFilterHeader parses the filter header, as specified in section 9.4.
+func (d *Decoder) parseFilterHeader() {
+ d.filterHeader.simple = d.fp.readBit(uniformProb)
+ d.filterHeader.level = int8(d.fp.readUint(uniformProb, 6))
+ d.filterHeader.sharpness = uint8(d.fp.readUint(uniformProb, 3))
+ d.filterHeader.useLFDelta = d.fp.readBit(uniformProb)
+ if d.filterHeader.useLFDelta && d.fp.readBit(uniformProb) {
+ for i := range d.filterHeader.refLFDelta {
+ d.filterHeader.refLFDelta[i] = int8(d.fp.readOptionalInt(uniformProb, 6))
+ }
+ for i := range d.filterHeader.modeLFDelta {
+ d.filterHeader.modeLFDelta[i] = int8(d.fp.readOptionalInt(uniformProb, 6))
+ }
+ }
+ if d.filterHeader.level == 0 {
+ return
+ }
+ if d.segmentHeader.useSegment {
+ for i := range d.filterHeader.perSegmentLevel {
+ strength := d.segmentHeader.filterStrength[i]
+ if d.segmentHeader.relativeDelta {
+ strength += d.filterHeader.level
+ }
+ d.filterHeader.perSegmentLevel[i] = strength
+ }
+ } else {
+ d.filterHeader.perSegmentLevel[0] = d.filterHeader.level
+ }
+ d.computeFilterParams()
+}
+
+// parseOtherPartitions parses the other partitions, as specified in section 9.5.
+func (d *Decoder) parseOtherPartitions() error {
+ const maxNOP = 1 << 3
+ var partLens [maxNOP]int
+ d.nOP = 1 << d.fp.readUint(uniformProb, 2)
+
+ // The final partition length is implied by the the remaining chunk data
+ // (d.r.n) and the other d.nOP-1 partition lengths. Those d.nOP-1 partition
+ // lengths are stored as 24-bit uints, i.e. up to 16 MiB per partition.
+ n := 3 * (d.nOP - 1)
+ partLens[d.nOP-1] = d.r.n - n
+ if partLens[d.nOP-1] < 0 {
+ return io.ErrUnexpectedEOF
+ }
+ if n > 0 {
+ buf := make([]byte, n)
+ if err := d.r.ReadFull(buf); err != nil {
+ return err
+ }
+ for i := 0; i < d.nOP-1; i++ {
+ pl := int(buf[3*i+0]) | int(buf[3*i+1])<<8 | int(buf[3*i+2])<<16
+ if pl > partLens[d.nOP-1] {
+ return io.ErrUnexpectedEOF
+ }
+ partLens[i] = pl
+ partLens[d.nOP-1] -= pl
+ }
+ }
+
+ // We check if the final partition length can also fit into a 24-bit uint.
+ // Strictly speaking, this isn't part of the spec, but it guards against a
+ // malicious WEBP image that is too large to ReadFull the encoded DCT
+ // coefficients into memory, whether that's because the actual WEBP file is
+ // too large, or whether its RIFF metadata lists too large a chunk.
+ if 1<<24 <= partLens[d.nOP-1] {
+ return errors.New("vp8: too much data to decode")
+ }
+
+ buf := make([]byte, d.r.n)
+ if err := d.r.ReadFull(buf); err != nil {
+ return err
+ }
+ for i, pl := range partLens {
+ if i == d.nOP {
+ break
+ }
+ d.op[i].init(buf[:pl])
+ buf = buf[pl:]
+ }
+ return nil
+}
+
+// parseOtherHeaders parses header information other than the frame header.
+func (d *Decoder) parseOtherHeaders() error {
+ // Initialize and parse the first partition.
+ firstPartition := make([]byte, d.frameHeader.FirstPartitionLen)
+ if err := d.r.ReadFull(firstPartition); err != nil {
+ return err
+ }
+ d.fp.init(firstPartition)
+ if d.frameHeader.KeyFrame {
+ // Read and ignore the color space and pixel clamp values. They are
+ // specified in section 9.2, but are unimplemented.
+ d.fp.readBit(uniformProb)
+ d.fp.readBit(uniformProb)
+ }
+ d.parseSegmentHeader()
+ d.parseFilterHeader()
+ if err := d.parseOtherPartitions(); err != nil {
+ return err
+ }
+ d.parseQuant()
+ if !d.frameHeader.KeyFrame {
+ // Golden and AltRef frames are specified in section 9.7.
+ // TODO(nigeltao): implement. Note that they are only used for video, not still images.
+ return errors.New("vp8: Golden / AltRef frames are not implemented")
+ }
+ // Read and ignore the refreshLastFrameBuffer bit, specified in section 9.8.
+ // It applies only to video, and not still images.
+ d.fp.readBit(uniformProb)
+ d.parseTokenProb()
+ d.useSkipProb = d.fp.readBit(uniformProb)
+ if d.useSkipProb {
+ d.skipProb = uint8(d.fp.readUint(uniformProb, 8))
+ }
+ if d.fp.unexpectedEOF {
+ return io.ErrUnexpectedEOF
+ }
+ return nil
+}
+
+// DecodeFrame decodes the frame and returns it as an YCbCr image.
+// The image's contents are valid up until the next call to Decoder.Init.
+func (d *Decoder) DecodeFrame() (*image.YCbCr, error) {
+ d.ensureImg()
+ if err := d.parseOtherHeaders(); err != nil {
+ return nil, err
+ }
+ // Reconstruct the rows.
+ for mbx := 0; mbx < d.mbw; mbx++ {
+ d.upMB[mbx] = mb{}
+ }
+ for mby := 0; mby < d.mbh; mby++ {
+ d.leftMB = mb{}
+ for mbx := 0; mbx < d.mbw; mbx++ {
+ skip := d.reconstruct(mbx, mby)
+ fs := d.filterParams[d.segment][btou(!d.usePredY16)]
+ fs.inner = fs.inner || !skip
+ d.perMBFilterParams[d.mbw*mby+mbx] = fs
+ }
+ }
+ if d.fp.unexpectedEOF {
+ return nil, io.ErrUnexpectedEOF
+ }
+ for i := 0; i < d.nOP; i++ {
+ if d.op[i].unexpectedEOF {
+ return nil, io.ErrUnexpectedEOF
+ }
+ }
+ // Apply the loop filter.
+ //
+ // Even if we are using per-segment levels, section 15 says that "loop
+ // filtering must be skipped entirely if loop_filter_level at either the
+ // frame header level or macroblock override level is 0".
+ if d.filterHeader.level != 0 {
+ if d.filterHeader.simple {
+ d.simpleFilter()
+ } else {
+ d.normalFilter()
+ }
+ }
+ return d.img, nil
+}
diff --git a/vendor/golang.org/x/image/vp8/filter.go b/vendor/golang.org/x/image/vp8/filter.go
new file mode 100644
index 0000000..e34a811
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8/filter.go
@@ -0,0 +1,273 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vp8
+
+// filter2 modifies a 2-pixel wide or 2-pixel high band along an edge.
+func filter2(pix []byte, level, index, iStep, jStep int) {
+ for n := 16; n > 0; n, index = n-1, index+iStep {
+ p1 := int(pix[index-2*jStep])
+ p0 := int(pix[index-1*jStep])
+ q0 := int(pix[index+0*jStep])
+ q1 := int(pix[index+1*jStep])
+ if abs(p0-q0)<<1+abs(p1-q1)>>1 > level {
+ continue
+ }
+ a := 3*(q0-p0) + clamp127(p1-q1)
+ a1 := clamp15((a + 4) >> 3)
+ a2 := clamp15((a + 3) >> 3)
+ pix[index-1*jStep] = clamp255(p0 + a2)
+ pix[index+0*jStep] = clamp255(q0 - a1)
+ }
+}
+
+// filter246 modifies a 2-, 4- or 6-pixel wide or high band along an edge.
+func filter246(pix []byte, n, level, ilevel, hlevel, index, iStep, jStep int, fourNotSix bool) {
+ for ; n > 0; n, index = n-1, index+iStep {
+ p3 := int(pix[index-4*jStep])
+ p2 := int(pix[index-3*jStep])
+ p1 := int(pix[index-2*jStep])
+ p0 := int(pix[index-1*jStep])
+ q0 := int(pix[index+0*jStep])
+ q1 := int(pix[index+1*jStep])
+ q2 := int(pix[index+2*jStep])
+ q3 := int(pix[index+3*jStep])
+ if abs(p0-q0)<<1+abs(p1-q1)>>1 > level {
+ continue
+ }
+ if abs(p3-p2) > ilevel ||
+ abs(p2-p1) > ilevel ||
+ abs(p1-p0) > ilevel ||
+ abs(q1-q0) > ilevel ||
+ abs(q2-q1) > ilevel ||
+ abs(q3-q2) > ilevel {
+ continue
+ }
+ if abs(p1-p0) > hlevel || abs(q1-q0) > hlevel {
+ // Filter 2 pixels.
+ a := 3*(q0-p0) + clamp127(p1-q1)
+ a1 := clamp15((a + 4) >> 3)
+ a2 := clamp15((a + 3) >> 3)
+ pix[index-1*jStep] = clamp255(p0 + a2)
+ pix[index+0*jStep] = clamp255(q0 - a1)
+ } else if fourNotSix {
+ // Filter 4 pixels.
+ a := 3 * (q0 - p0)
+ a1 := clamp15((a + 4) >> 3)
+ a2 := clamp15((a + 3) >> 3)
+ a3 := (a1 + 1) >> 1
+ pix[index-2*jStep] = clamp255(p1 + a3)
+ pix[index-1*jStep] = clamp255(p0 + a2)
+ pix[index+0*jStep] = clamp255(q0 - a1)
+ pix[index+1*jStep] = clamp255(q1 - a3)
+ } else {
+ // Filter 6 pixels.
+ a := clamp127(3*(q0-p0) + clamp127(p1-q1))
+ a1 := (27*a + 63) >> 7
+ a2 := (18*a + 63) >> 7
+ a3 := (9*a + 63) >> 7
+ pix[index-3*jStep] = clamp255(p2 + a3)
+ pix[index-2*jStep] = clamp255(p1 + a2)
+ pix[index-1*jStep] = clamp255(p0 + a1)
+ pix[index+0*jStep] = clamp255(q0 - a1)
+ pix[index+1*jStep] = clamp255(q1 - a2)
+ pix[index+2*jStep] = clamp255(q2 - a3)
+ }
+ }
+}
+
+// simpleFilter implements the simple filter, as specified in section 15.2.
+func (d *Decoder) simpleFilter() {
+ for mby := 0; mby < d.mbh; mby++ {
+ for mbx := 0; mbx < d.mbw; mbx++ {
+ f := d.perMBFilterParams[d.mbw*mby+mbx]
+ if f.level == 0 {
+ continue
+ }
+ l := int(f.level)
+ yIndex := (mby*d.img.YStride + mbx) * 16
+ if mbx > 0 {
+ filter2(d.img.Y, l+4, yIndex, d.img.YStride, 1)
+ }
+ if f.inner {
+ filter2(d.img.Y, l, yIndex+0x4, d.img.YStride, 1)
+ filter2(d.img.Y, l, yIndex+0x8, d.img.YStride, 1)
+ filter2(d.img.Y, l, yIndex+0xc, d.img.YStride, 1)
+ }
+ if mby > 0 {
+ filter2(d.img.Y, l+4, yIndex, 1, d.img.YStride)
+ }
+ if f.inner {
+ filter2(d.img.Y, l, yIndex+d.img.YStride*0x4, 1, d.img.YStride)
+ filter2(d.img.Y, l, yIndex+d.img.YStride*0x8, 1, d.img.YStride)
+ filter2(d.img.Y, l, yIndex+d.img.YStride*0xc, 1, d.img.YStride)
+ }
+ }
+ }
+}
+
+// normalFilter implements the normal filter, as specified in section 15.3.
+func (d *Decoder) normalFilter() {
+ for mby := 0; mby < d.mbh; mby++ {
+ for mbx := 0; mbx < d.mbw; mbx++ {
+ f := d.perMBFilterParams[d.mbw*mby+mbx]
+ if f.level == 0 {
+ continue
+ }
+ l, il, hl := int(f.level), int(f.ilevel), int(f.hlevel)
+ yIndex := (mby*d.img.YStride + mbx) * 16
+ cIndex := (mby*d.img.CStride + mbx) * 8
+ if mbx > 0 {
+ filter246(d.img.Y, 16, l+4, il, hl, yIndex, d.img.YStride, 1, false)
+ filter246(d.img.Cb, 8, l+4, il, hl, cIndex, d.img.CStride, 1, false)
+ filter246(d.img.Cr, 8, l+4, il, hl, cIndex, d.img.CStride, 1, false)
+ }
+ if f.inner {
+ filter246(d.img.Y, 16, l, il, hl, yIndex+0x4, d.img.YStride, 1, true)
+ filter246(d.img.Y, 16, l, il, hl, yIndex+0x8, d.img.YStride, 1, true)
+ filter246(d.img.Y, 16, l, il, hl, yIndex+0xc, d.img.YStride, 1, true)
+ filter246(d.img.Cb, 8, l, il, hl, cIndex+0x4, d.img.CStride, 1, true)
+ filter246(d.img.Cr, 8, l, il, hl, cIndex+0x4, d.img.CStride, 1, true)
+ }
+ if mby > 0 {
+ filter246(d.img.Y, 16, l+4, il, hl, yIndex, 1, d.img.YStride, false)
+ filter246(d.img.Cb, 8, l+4, il, hl, cIndex, 1, d.img.CStride, false)
+ filter246(d.img.Cr, 8, l+4, il, hl, cIndex, 1, d.img.CStride, false)
+ }
+ if f.inner {
+ filter246(d.img.Y, 16, l, il, hl, yIndex+d.img.YStride*0x4, 1, d.img.YStride, true)
+ filter246(d.img.Y, 16, l, il, hl, yIndex+d.img.YStride*0x8, 1, d.img.YStride, true)
+ filter246(d.img.Y, 16, l, il, hl, yIndex+d.img.YStride*0xc, 1, d.img.YStride, true)
+ filter246(d.img.Cb, 8, l, il, hl, cIndex+d.img.CStride*0x4, 1, d.img.CStride, true)
+ filter246(d.img.Cr, 8, l, il, hl, cIndex+d.img.CStride*0x4, 1, d.img.CStride, true)
+ }
+ }
+ }
+}
+
+// filterParam holds the loop filter parameters for a macroblock.
+type filterParam struct {
+ // The first three fields are thresholds used by the loop filter to smooth
+ // over the edges and interior of a macroblock. level is used by both the
+ // simple and normal filters. The inner level and high edge variance level
+ // are only used by the normal filter.
+ level, ilevel, hlevel uint8
+ // inner is whether the inner loop filter cannot be optimized out as a
+ // no-op for this particular macroblock.
+ inner bool
+}
+
+// computeFilterParams computes the loop filter parameters, as specified in
+// section 15.4.
+func (d *Decoder) computeFilterParams() {
+ for i := range d.filterParams {
+ baseLevel := d.filterHeader.level
+ if d.segmentHeader.useSegment {
+ baseLevel = d.segmentHeader.filterStrength[i]
+ if d.segmentHeader.relativeDelta {
+ baseLevel += d.filterHeader.level
+ }
+ }
+
+ for j := range d.filterParams[i] {
+ p := &d.filterParams[i][j]
+ p.inner = j != 0
+ level := baseLevel
+ if d.filterHeader.useLFDelta {
+ // The libwebp C code has a "TODO: only CURRENT is handled for now."
+ level += d.filterHeader.refLFDelta[0]
+ if j != 0 {
+ level += d.filterHeader.modeLFDelta[0]
+ }
+ }
+ if level <= 0 {
+ p.level = 0
+ continue
+ }
+ if level > 63 {
+ level = 63
+ }
+ ilevel := level
+ if d.filterHeader.sharpness > 0 {
+ if d.filterHeader.sharpness > 4 {
+ ilevel >>= 2
+ } else {
+ ilevel >>= 1
+ }
+ if x := int8(9 - d.filterHeader.sharpness); ilevel > x {
+ ilevel = x
+ }
+ }
+ if ilevel < 1 {
+ ilevel = 1
+ }
+ p.ilevel = uint8(ilevel)
+ p.level = uint8(2*level + ilevel)
+ if d.frameHeader.KeyFrame {
+ if level < 15 {
+ p.hlevel = 0
+ } else if level < 40 {
+ p.hlevel = 1
+ } else {
+ p.hlevel = 2
+ }
+ } else {
+ if level < 15 {
+ p.hlevel = 0
+ } else if level < 20 {
+ p.hlevel = 1
+ } else if level < 40 {
+ p.hlevel = 2
+ } else {
+ p.hlevel = 3
+ }
+ }
+ }
+ }
+}
+
+// intSize is either 32 or 64.
+const intSize = 32 << (^uint(0) >> 63)
+
+func abs(x int) int {
+ // m := -1 if x < 0. m := 0 otherwise.
+ m := x >> (intSize - 1)
+
+ // In two's complement representation, the negative number
+ // of any number (except the smallest one) can be computed
+ // by flipping all the bits and add 1. This is faster than
+ // code with a branch.
+ // See Hacker's Delight, section 2-4.
+ return (x ^ m) - m
+}
+
+func clamp15(x int) int {
+ if x < -16 {
+ return -16
+ }
+ if x > 15 {
+ return 15
+ }
+ return x
+}
+
+func clamp127(x int) int {
+ if x < -128 {
+ return -128
+ }
+ if x > 127 {
+ return 127
+ }
+ return x
+}
+
+func clamp255(x int) uint8 {
+ if x < 0 {
+ return 0
+ }
+ if x > 255 {
+ return 255
+ }
+ return uint8(x)
+}
diff --git a/vendor/golang.org/x/image/vp8/idct.go b/vendor/golang.org/x/image/vp8/idct.go
new file mode 100644
index 0000000..929af2c
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8/idct.go
@@ -0,0 +1,98 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vp8
+
+// This file implements the inverse Discrete Cosine Transform and the inverse
+// Walsh Hadamard Transform (WHT), as specified in sections 14.3 and 14.4.
+
+func clip8(i int32) uint8 {
+ if i < 0 {
+ return 0
+ }
+ if i > 255 {
+ return 255
+ }
+ return uint8(i)
+}
+
+func (z *Decoder) inverseDCT4(y, x, coeffBase int) {
+ const (
+ c1 = 85627 // 65536 * cos(pi/8) * sqrt(2).
+ c2 = 35468 // 65536 * sin(pi/8) * sqrt(2).
+ )
+ var m [4][4]int32
+ for i := 0; i < 4; i++ {
+ a := int32(z.coeff[coeffBase+0]) + int32(z.coeff[coeffBase+8])
+ b := int32(z.coeff[coeffBase+0]) - int32(z.coeff[coeffBase+8])
+ c := (int32(z.coeff[coeffBase+4])*c2)>>16 - (int32(z.coeff[coeffBase+12])*c1)>>16
+ d := (int32(z.coeff[coeffBase+4])*c1)>>16 + (int32(z.coeff[coeffBase+12])*c2)>>16
+ m[i][0] = a + d
+ m[i][1] = b + c
+ m[i][2] = b - c
+ m[i][3] = a - d
+ coeffBase++
+ }
+ for j := 0; j < 4; j++ {
+ dc := m[0][j] + 4
+ a := dc + m[2][j]
+ b := dc - m[2][j]
+ c := (m[1][j]*c2)>>16 - (m[3][j]*c1)>>16
+ d := (m[1][j]*c1)>>16 + (m[3][j]*c2)>>16
+ z.ybr[y+j][x+0] = clip8(int32(z.ybr[y+j][x+0]) + (a+d)>>3)
+ z.ybr[y+j][x+1] = clip8(int32(z.ybr[y+j][x+1]) + (b+c)>>3)
+ z.ybr[y+j][x+2] = clip8(int32(z.ybr[y+j][x+2]) + (b-c)>>3)
+ z.ybr[y+j][x+3] = clip8(int32(z.ybr[y+j][x+3]) + (a-d)>>3)
+ }
+}
+
+func (z *Decoder) inverseDCT4DCOnly(y, x, coeffBase int) {
+ dc := (int32(z.coeff[coeffBase+0]) + 4) >> 3
+ for j := 0; j < 4; j++ {
+ for i := 0; i < 4; i++ {
+ z.ybr[y+j][x+i] = clip8(int32(z.ybr[y+j][x+i]) + dc)
+ }
+ }
+}
+
+func (z *Decoder) inverseDCT8(y, x, coeffBase int) {
+ z.inverseDCT4(y+0, x+0, coeffBase+0*16)
+ z.inverseDCT4(y+0, x+4, coeffBase+1*16)
+ z.inverseDCT4(y+4, x+0, coeffBase+2*16)
+ z.inverseDCT4(y+4, x+4, coeffBase+3*16)
+}
+
+func (z *Decoder) inverseDCT8DCOnly(y, x, coeffBase int) {
+ z.inverseDCT4DCOnly(y+0, x+0, coeffBase+0*16)
+ z.inverseDCT4DCOnly(y+0, x+4, coeffBase+1*16)
+ z.inverseDCT4DCOnly(y+4, x+0, coeffBase+2*16)
+ z.inverseDCT4DCOnly(y+4, x+4, coeffBase+3*16)
+}
+
+func (d *Decoder) inverseWHT16() {
+ var m [16]int32
+ for i := 0; i < 4; i++ {
+ a0 := int32(d.coeff[384+0+i]) + int32(d.coeff[384+12+i])
+ a1 := int32(d.coeff[384+4+i]) + int32(d.coeff[384+8+i])
+ a2 := int32(d.coeff[384+4+i]) - int32(d.coeff[384+8+i])
+ a3 := int32(d.coeff[384+0+i]) - int32(d.coeff[384+12+i])
+ m[0+i] = a0 + a1
+ m[8+i] = a0 - a1
+ m[4+i] = a3 + a2
+ m[12+i] = a3 - a2
+ }
+ out := 0
+ for i := 0; i < 4; i++ {
+ dc := m[0+i*4] + 3
+ a0 := dc + m[3+i*4]
+ a1 := m[1+i*4] + m[2+i*4]
+ a2 := m[1+i*4] - m[2+i*4]
+ a3 := dc - m[3+i*4]
+ d.coeff[out+0] = int16((a0 + a1) >> 3)
+ d.coeff[out+16] = int16((a3 + a2) >> 3)
+ d.coeff[out+32] = int16((a0 - a1) >> 3)
+ d.coeff[out+48] = int16((a3 - a2) >> 3)
+ out += 64
+ }
+}
diff --git a/vendor/golang.org/x/image/vp8/partition.go b/vendor/golang.org/x/image/vp8/partition.go
new file mode 100644
index 0000000..72288bd
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8/partition.go
@@ -0,0 +1,129 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vp8
+
+// Each VP8 frame consists of between 2 and 9 bitstream partitions.
+// Each partition is byte-aligned and is independently arithmetic-encoded.
+//
+// This file implements decoding a partition's bitstream, as specified in
+// chapter 7. The implementation follows libwebp's approach instead of the
+// specification's reference C implementation. For example, we use a look-up
+// table instead of a for loop to recalibrate the encoded range.
+
+var (
+ lutShift = [127]uint8{
+ 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }
+ lutRangeM1 = [127]uint8{
+ 127,
+ 127, 191,
+ 127, 159, 191, 223,
+ 127, 143, 159, 175, 191, 207, 223, 239,
+ 127, 135, 143, 151, 159, 167, 175, 183, 191, 199, 207, 215, 223, 231, 239, 247,
+ 127, 131, 135, 139, 143, 147, 151, 155, 159, 163, 167, 171, 175, 179, 183, 187,
+ 191, 195, 199, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251,
+ 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157,
+ 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189,
+ 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221,
+ 223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253,
+ }
+)
+
+// uniformProb represents a 50% probability that the next bit is 0.
+const uniformProb = 128
+
+// partition holds arithmetic-coded bits.
+type partition struct {
+ // buf is the input bytes.
+ buf []byte
+ // r is how many of buf's bytes have been consumed.
+ r int
+ // rangeM1 is range minus 1, where range is in the arithmetic coding sense,
+ // not the Go language sense.
+ rangeM1 uint32
+ // bits and nBits hold those bits shifted out of buf but not yet consumed.
+ bits uint32
+ nBits uint8
+ // unexpectedEOF tells whether we tried to read past buf.
+ unexpectedEOF bool
+}
+
+// init initializes the partition.
+func (p *partition) init(buf []byte) {
+ p.buf = buf
+ p.r = 0
+ p.rangeM1 = 254
+ p.bits = 0
+ p.nBits = 0
+ p.unexpectedEOF = false
+}
+
+// readBit returns the next bit.
+func (p *partition) readBit(prob uint8) bool {
+ if p.nBits < 8 {
+ if p.r >= len(p.buf) {
+ p.unexpectedEOF = true
+ return false
+ }
+ // Expression split for 386 compiler.
+ x := uint32(p.buf[p.r])
+ p.bits |= x << (8 - p.nBits)
+ p.r++
+ p.nBits += 8
+ }
+ split := (p.rangeM1*uint32(prob))>>8 + 1
+ bit := p.bits >= split<<8
+ if bit {
+ p.rangeM1 -= split
+ p.bits -= split << 8
+ } else {
+ p.rangeM1 = split - 1
+ }
+ if p.rangeM1 < 127 {
+ shift := lutShift[p.rangeM1]
+ p.rangeM1 = uint32(lutRangeM1[p.rangeM1])
+ p.bits <<= shift
+ p.nBits -= shift
+ }
+ return bit
+}
+
+// readUint returns the next n-bit unsigned integer.
+func (p *partition) readUint(prob, n uint8) uint32 {
+ var u uint32
+ for n > 0 {
+ n--
+ if p.readBit(prob) {
+ u |= 1 << n
+ }
+ }
+ return u
+}
+
+// readInt returns the next n-bit signed integer.
+func (p *partition) readInt(prob, n uint8) int32 {
+ u := p.readUint(prob, n)
+ b := p.readBit(prob)
+ if b {
+ return -int32(u)
+ }
+ return int32(u)
+}
+
+// readOptionalInt returns the next n-bit signed integer in an encoding
+// where the likely result is zero.
+func (p *partition) readOptionalInt(prob, n uint8) int32 {
+ if !p.readBit(prob) {
+ return 0
+ }
+ return p.readInt(prob, n)
+}
diff --git a/vendor/golang.org/x/image/vp8/pred.go b/vendor/golang.org/x/image/vp8/pred.go
new file mode 100644
index 0000000..58c2689
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8/pred.go
@@ -0,0 +1,201 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vp8
+
+// This file implements parsing the predictor modes, as specified in chapter
+// 11.
+
+func (d *Decoder) parsePredModeY16(mbx int) {
+ var p uint8
+ if !d.fp.readBit(156) {
+ if !d.fp.readBit(163) {
+ p = predDC
+ } else {
+ p = predVE
+ }
+ } else if !d.fp.readBit(128) {
+ p = predHE
+ } else {
+ p = predTM
+ }
+ for i := 0; i < 4; i++ {
+ d.upMB[mbx].pred[i] = p
+ d.leftMB.pred[i] = p
+ }
+ d.predY16 = p
+}
+
+func (d *Decoder) parsePredModeC8() {
+ if !d.fp.readBit(142) {
+ d.predC8 = predDC
+ } else if !d.fp.readBit(114) {
+ d.predC8 = predVE
+ } else if !d.fp.readBit(183) {
+ d.predC8 = predHE
+ } else {
+ d.predC8 = predTM
+ }
+}
+
+func (d *Decoder) parsePredModeY4(mbx int) {
+ for j := 0; j < 4; j++ {
+ p := d.leftMB.pred[j]
+ for i := 0; i < 4; i++ {
+ prob := &predProb[d.upMB[mbx].pred[i]][p]
+ if !d.fp.readBit(prob[0]) {
+ p = predDC
+ } else if !d.fp.readBit(prob[1]) {
+ p = predTM
+ } else if !d.fp.readBit(prob[2]) {
+ p = predVE
+ } else if !d.fp.readBit(prob[3]) {
+ if !d.fp.readBit(prob[4]) {
+ p = predHE
+ } else if !d.fp.readBit(prob[5]) {
+ p = predRD
+ } else {
+ p = predVR
+ }
+ } else if !d.fp.readBit(prob[6]) {
+ p = predLD
+ } else if !d.fp.readBit(prob[7]) {
+ p = predVL
+ } else if !d.fp.readBit(prob[8]) {
+ p = predHD
+ } else {
+ p = predHU
+ }
+ d.predY4[j][i] = p
+ d.upMB[mbx].pred[i] = p
+ }
+ d.leftMB.pred[j] = p
+ }
+}
+
+// predProb are the probabilities to decode a 4x4 region's predictor mode given
+// the predictor modes of the regions above and left of it.
+// These values are specified in section 11.5.
+var predProb = [nPred][nPred][9]uint8{
+ {
+ {231, 120, 48, 89, 115, 113, 120, 152, 112},
+ {152, 179, 64, 126, 170, 118, 46, 70, 95},
+ {175, 69, 143, 80, 85, 82, 72, 155, 103},
+ {56, 58, 10, 171, 218, 189, 17, 13, 152},
+ {114, 26, 17, 163, 44, 195, 21, 10, 173},
+ {121, 24, 80, 195, 26, 62, 44, 64, 85},
+ {144, 71, 10, 38, 171, 213, 144, 34, 26},
+ {170, 46, 55, 19, 136, 160, 33, 206, 71},
+ {63, 20, 8, 114, 114, 208, 12, 9, 226},
+ {81, 40, 11, 96, 182, 84, 29, 16, 36},
+ },
+ {
+ {134, 183, 89, 137, 98, 101, 106, 165, 148},
+ {72, 187, 100, 130, 157, 111, 32, 75, 80},
+ {66, 102, 167, 99, 74, 62, 40, 234, 128},
+ {41, 53, 9, 178, 241, 141, 26, 8, 107},
+ {74, 43, 26, 146, 73, 166, 49, 23, 157},
+ {65, 38, 105, 160, 51, 52, 31, 115, 128},
+ {104, 79, 12, 27, 217, 255, 87, 17, 7},
+ {87, 68, 71, 44, 114, 51, 15, 186, 23},
+ {47, 41, 14, 110, 182, 183, 21, 17, 194},
+ {66, 45, 25, 102, 197, 189, 23, 18, 22},
+ },
+ {
+ {88, 88, 147, 150, 42, 46, 45, 196, 205},
+ {43, 97, 183, 117, 85, 38, 35, 179, 61},
+ {39, 53, 200, 87, 26, 21, 43, 232, 171},
+ {56, 34, 51, 104, 114, 102, 29, 93, 77},
+ {39, 28, 85, 171, 58, 165, 90, 98, 64},
+ {34, 22, 116, 206, 23, 34, 43, 166, 73},
+ {107, 54, 32, 26, 51, 1, 81, 43, 31},
+ {68, 25, 106, 22, 64, 171, 36, 225, 114},
+ {34, 19, 21, 102, 132, 188, 16, 76, 124},
+ {62, 18, 78, 95, 85, 57, 50, 48, 51},
+ },
+ {
+ {193, 101, 35, 159, 215, 111, 89, 46, 111},
+ {60, 148, 31, 172, 219, 228, 21, 18, 111},
+ {112, 113, 77, 85, 179, 255, 38, 120, 114},
+ {40, 42, 1, 196, 245, 209, 10, 25, 109},
+ {88, 43, 29, 140, 166, 213, 37, 43, 154},
+ {61, 63, 30, 155, 67, 45, 68, 1, 209},
+ {100, 80, 8, 43, 154, 1, 51, 26, 71},
+ {142, 78, 78, 16, 255, 128, 34, 197, 171},
+ {41, 40, 5, 102, 211, 183, 4, 1, 221},
+ {51, 50, 17, 168, 209, 192, 23, 25, 82},
+ },
+ {
+ {138, 31, 36, 171, 27, 166, 38, 44, 229},
+ {67, 87, 58, 169, 82, 115, 26, 59, 179},
+ {63, 59, 90, 180, 59, 166, 93, 73, 154},
+ {40, 40, 21, 116, 143, 209, 34, 39, 175},
+ {47, 15, 16, 183, 34, 223, 49, 45, 183},
+ {46, 17, 33, 183, 6, 98, 15, 32, 183},
+ {57, 46, 22, 24, 128, 1, 54, 17, 37},
+ {65, 32, 73, 115, 28, 128, 23, 128, 205},
+ {40, 3, 9, 115, 51, 192, 18, 6, 223},
+ {87, 37, 9, 115, 59, 77, 64, 21, 47},
+ },
+ {
+ {104, 55, 44, 218, 9, 54, 53, 130, 226},
+ {64, 90, 70, 205, 40, 41, 23, 26, 57},
+ {54, 57, 112, 184, 5, 41, 38, 166, 213},
+ {30, 34, 26, 133, 152, 116, 10, 32, 134},
+ {39, 19, 53, 221, 26, 114, 32, 73, 255},
+ {31, 9, 65, 234, 2, 15, 1, 118, 73},
+ {75, 32, 12, 51, 192, 255, 160, 43, 51},
+ {88, 31, 35, 67, 102, 85, 55, 186, 85},
+ {56, 21, 23, 111, 59, 205, 45, 37, 192},
+ {55, 38, 70, 124, 73, 102, 1, 34, 98},
+ },
+ {
+ {125, 98, 42, 88, 104, 85, 117, 175, 82},
+ {95, 84, 53, 89, 128, 100, 113, 101, 45},
+ {75, 79, 123, 47, 51, 128, 81, 171, 1},
+ {57, 17, 5, 71, 102, 57, 53, 41, 49},
+ {38, 33, 13, 121, 57, 73, 26, 1, 85},
+ {41, 10, 67, 138, 77, 110, 90, 47, 114},
+ {115, 21, 2, 10, 102, 255, 166, 23, 6},
+ {101, 29, 16, 10, 85, 128, 101, 196, 26},
+ {57, 18, 10, 102, 102, 213, 34, 20, 43},
+ {117, 20, 15, 36, 163, 128, 68, 1, 26},
+ },
+ {
+ {102, 61, 71, 37, 34, 53, 31, 243, 192},
+ {69, 60, 71, 38, 73, 119, 28, 222, 37},
+ {68, 45, 128, 34, 1, 47, 11, 245, 171},
+ {62, 17, 19, 70, 146, 85, 55, 62, 70},
+ {37, 43, 37, 154, 100, 163, 85, 160, 1},
+ {63, 9, 92, 136, 28, 64, 32, 201, 85},
+ {75, 15, 9, 9, 64, 255, 184, 119, 16},
+ {86, 6, 28, 5, 64, 255, 25, 248, 1},
+ {56, 8, 17, 132, 137, 255, 55, 116, 128},
+ {58, 15, 20, 82, 135, 57, 26, 121, 40},
+ },
+ {
+ {164, 50, 31, 137, 154, 133, 25, 35, 218},
+ {51, 103, 44, 131, 131, 123, 31, 6, 158},
+ {86, 40, 64, 135, 148, 224, 45, 183, 128},
+ {22, 26, 17, 131, 240, 154, 14, 1, 209},
+ {45, 16, 21, 91, 64, 222, 7, 1, 197},
+ {56, 21, 39, 155, 60, 138, 23, 102, 213},
+ {83, 12, 13, 54, 192, 255, 68, 47, 28},
+ {85, 26, 85, 85, 128, 128, 32, 146, 171},
+ {18, 11, 7, 63, 144, 171, 4, 4, 246},
+ {35, 27, 10, 146, 174, 171, 12, 26, 128},
+ },
+ {
+ {190, 80, 35, 99, 180, 80, 126, 54, 45},
+ {85, 126, 47, 87, 176, 51, 41, 20, 32},
+ {101, 75, 128, 139, 118, 146, 116, 128, 85},
+ {56, 41, 15, 176, 236, 85, 37, 9, 62},
+ {71, 30, 17, 119, 118, 255, 17, 18, 138},
+ {101, 38, 60, 138, 55, 70, 43, 26, 142},
+ {146, 36, 19, 30, 171, 255, 97, 27, 20},
+ {138, 45, 61, 62, 219, 1, 81, 188, 64},
+ {32, 41, 20, 117, 151, 142, 20, 21, 163},
+ {112, 19, 12, 61, 195, 128, 48, 4, 24},
+ },
+}
diff --git a/vendor/golang.org/x/image/vp8/predfunc.go b/vendor/golang.org/x/image/vp8/predfunc.go
new file mode 100644
index 0000000..f899958
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8/predfunc.go
@@ -0,0 +1,553 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vp8
+
+// This file implements the predicition functions, as specified in chapter 12.
+//
+// For each macroblock (of 1x16x16 luma and 2x8x8 chroma coefficients), the
+// luma values are either predicted as one large 16x16 region or 16 separate
+// 4x4 regions. The chroma values are always predicted as one 8x8 region.
+//
+// For 4x4 regions, the target block's predicted values (Xs) are a function of
+// its previously-decoded top and left border values, as well as a number of
+// pixels from the top-right:
+//
+// a b c d e f g h
+// p X X X X
+// q X X X X
+// r X X X X
+// s X X X X
+//
+// The predictor modes are:
+// - DC: all Xs = (b + c + d + e + p + q + r + s + 4) / 8.
+// - TM: the first X = (b + p - a), the second X = (c + p - a), and so on.
+// - VE: each X = the weighted average of its column's top value and that
+// value's neighbors, i.e. averages of abc, bcd, cde or def.
+// - HE: similar to VE except rows instead of columns, and the final row is
+// an average of r, s and s.
+// - RD, VR, LD, VL, HD, HU: these diagonal modes ("Right Down", "Vertical
+// Right", etc) are more complicated and are described in section 12.3.
+// All Xs are clipped to the range [0, 255].
+//
+// For 8x8 and 16x16 regions, the target block's predicted values are a
+// function of the top and left border values without the top-right overhang,
+// i.e. without the 8x8 or 16x16 equivalent of f, g and h. Furthermore:
+// - There are no diagonal predictor modes, only DC, TM, VE and HE.
+// - The DC mode has variants for macroblocks in the top row and/or left
+// column, i.e. for macroblocks with mby == 0 || mbx == 0.
+// - The VE and HE modes take only the column top or row left values; they do
+// not smooth that top/left value with its neighbors.
+
+// nPred is the number of predictor modes, not including the Top/Left versions
+// of the DC predictor mode.
+const nPred = 10
+
+const (
+ predDC = iota
+ predTM
+ predVE
+ predHE
+ predRD
+ predVR
+ predLD
+ predVL
+ predHD
+ predHU
+ predDCTop
+ predDCLeft
+ predDCTopLeft
+)
+
+func checkTopLeftPred(mbx, mby int, p uint8) uint8 {
+ if p != predDC {
+ return p
+ }
+ if mbx == 0 {
+ if mby == 0 {
+ return predDCTopLeft
+ }
+ return predDCLeft
+ }
+ if mby == 0 {
+ return predDCTop
+ }
+ return predDC
+}
+
+var predFunc4 = [...]func(*Decoder, int, int){
+ predFunc4DC,
+ predFunc4TM,
+ predFunc4VE,
+ predFunc4HE,
+ predFunc4RD,
+ predFunc4VR,
+ predFunc4LD,
+ predFunc4VL,
+ predFunc4HD,
+ predFunc4HU,
+ nil,
+ nil,
+ nil,
+}
+
+var predFunc8 = [...]func(*Decoder, int, int){
+ predFunc8DC,
+ predFunc8TM,
+ predFunc8VE,
+ predFunc8HE,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ predFunc8DCTop,
+ predFunc8DCLeft,
+ predFunc8DCTopLeft,
+}
+
+var predFunc16 = [...]func(*Decoder, int, int){
+ predFunc16DC,
+ predFunc16TM,
+ predFunc16VE,
+ predFunc16HE,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ nil,
+ predFunc16DCTop,
+ predFunc16DCLeft,
+ predFunc16DCTopLeft,
+}
+
+func predFunc4DC(z *Decoder, y, x int) {
+ sum := uint32(4)
+ for i := 0; i < 4; i++ {
+ sum += uint32(z.ybr[y-1][x+i])
+ }
+ for j := 0; j < 4; j++ {
+ sum += uint32(z.ybr[y+j][x-1])
+ }
+ avg := uint8(sum / 8)
+ for j := 0; j < 4; j++ {
+ for i := 0; i < 4; i++ {
+ z.ybr[y+j][x+i] = avg
+ }
+ }
+}
+
+func predFunc4TM(z *Decoder, y, x int) {
+ delta0 := -int32(z.ybr[y-1][x-1])
+ for j := 0; j < 4; j++ {
+ delta1 := delta0 + int32(z.ybr[y+j][x-1])
+ for i := 0; i < 4; i++ {
+ delta2 := delta1 + int32(z.ybr[y-1][x+i])
+ z.ybr[y+j][x+i] = uint8(clip(delta2, 0, 255))
+ }
+ }
+}
+
+func predFunc4VE(z *Decoder, y, x int) {
+ a := int32(z.ybr[y-1][x-1])
+ b := int32(z.ybr[y-1][x+0])
+ c := int32(z.ybr[y-1][x+1])
+ d := int32(z.ybr[y-1][x+2])
+ e := int32(z.ybr[y-1][x+3])
+ f := int32(z.ybr[y-1][x+4])
+ abc := uint8((a + 2*b + c + 2) / 4)
+ bcd := uint8((b + 2*c + d + 2) / 4)
+ cde := uint8((c + 2*d + e + 2) / 4)
+ def := uint8((d + 2*e + f + 2) / 4)
+ for j := 0; j < 4; j++ {
+ z.ybr[y+j][x+0] = abc
+ z.ybr[y+j][x+1] = bcd
+ z.ybr[y+j][x+2] = cde
+ z.ybr[y+j][x+3] = def
+ }
+}
+
+func predFunc4HE(z *Decoder, y, x int) {
+ s := int32(z.ybr[y+3][x-1])
+ r := int32(z.ybr[y+2][x-1])
+ q := int32(z.ybr[y+1][x-1])
+ p := int32(z.ybr[y+0][x-1])
+ a := int32(z.ybr[y-1][x-1])
+ ssr := uint8((s + 2*s + r + 2) / 4)
+ srq := uint8((s + 2*r + q + 2) / 4)
+ rqp := uint8((r + 2*q + p + 2) / 4)
+ apq := uint8((a + 2*p + q + 2) / 4)
+ for i := 0; i < 4; i++ {
+ z.ybr[y+0][x+i] = apq
+ z.ybr[y+1][x+i] = rqp
+ z.ybr[y+2][x+i] = srq
+ z.ybr[y+3][x+i] = ssr
+ }
+}
+
+func predFunc4RD(z *Decoder, y, x int) {
+ s := int32(z.ybr[y+3][x-1])
+ r := int32(z.ybr[y+2][x-1])
+ q := int32(z.ybr[y+1][x-1])
+ p := int32(z.ybr[y+0][x-1])
+ a := int32(z.ybr[y-1][x-1])
+ b := int32(z.ybr[y-1][x+0])
+ c := int32(z.ybr[y-1][x+1])
+ d := int32(z.ybr[y-1][x+2])
+ e := int32(z.ybr[y-1][x+3])
+ srq := uint8((s + 2*r + q + 2) / 4)
+ rqp := uint8((r + 2*q + p + 2) / 4)
+ qpa := uint8((q + 2*p + a + 2) / 4)
+ pab := uint8((p + 2*a + b + 2) / 4)
+ abc := uint8((a + 2*b + c + 2) / 4)
+ bcd := uint8((b + 2*c + d + 2) / 4)
+ cde := uint8((c + 2*d + e + 2) / 4)
+ z.ybr[y+0][x+0] = pab
+ z.ybr[y+0][x+1] = abc
+ z.ybr[y+0][x+2] = bcd
+ z.ybr[y+0][x+3] = cde
+ z.ybr[y+1][x+0] = qpa
+ z.ybr[y+1][x+1] = pab
+ z.ybr[y+1][x+2] = abc
+ z.ybr[y+1][x+3] = bcd
+ z.ybr[y+2][x+0] = rqp
+ z.ybr[y+2][x+1] = qpa
+ z.ybr[y+2][x+2] = pab
+ z.ybr[y+2][x+3] = abc
+ z.ybr[y+3][x+0] = srq
+ z.ybr[y+3][x+1] = rqp
+ z.ybr[y+3][x+2] = qpa
+ z.ybr[y+3][x+3] = pab
+}
+
+func predFunc4VR(z *Decoder, y, x int) {
+ r := int32(z.ybr[y+2][x-1])
+ q := int32(z.ybr[y+1][x-1])
+ p := int32(z.ybr[y+0][x-1])
+ a := int32(z.ybr[y-1][x-1])
+ b := int32(z.ybr[y-1][x+0])
+ c := int32(z.ybr[y-1][x+1])
+ d := int32(z.ybr[y-1][x+2])
+ e := int32(z.ybr[y-1][x+3])
+ ab := uint8((a + b + 1) / 2)
+ bc := uint8((b + c + 1) / 2)
+ cd := uint8((c + d + 1) / 2)
+ de := uint8((d + e + 1) / 2)
+ rqp := uint8((r + 2*q + p + 2) / 4)
+ qpa := uint8((q + 2*p + a + 2) / 4)
+ pab := uint8((p + 2*a + b + 2) / 4)
+ abc := uint8((a + 2*b + c + 2) / 4)
+ bcd := uint8((b + 2*c + d + 2) / 4)
+ cde := uint8((c + 2*d + e + 2) / 4)
+ z.ybr[y+0][x+0] = ab
+ z.ybr[y+0][x+1] = bc
+ z.ybr[y+0][x+2] = cd
+ z.ybr[y+0][x+3] = de
+ z.ybr[y+1][x+0] = pab
+ z.ybr[y+1][x+1] = abc
+ z.ybr[y+1][x+2] = bcd
+ z.ybr[y+1][x+3] = cde
+ z.ybr[y+2][x+0] = qpa
+ z.ybr[y+2][x+1] = ab
+ z.ybr[y+2][x+2] = bc
+ z.ybr[y+2][x+3] = cd
+ z.ybr[y+3][x+0] = rqp
+ z.ybr[y+3][x+1] = pab
+ z.ybr[y+3][x+2] = abc
+ z.ybr[y+3][x+3] = bcd
+}
+
+func predFunc4LD(z *Decoder, y, x int) {
+ a := int32(z.ybr[y-1][x+0])
+ b := int32(z.ybr[y-1][x+1])
+ c := int32(z.ybr[y-1][x+2])
+ d := int32(z.ybr[y-1][x+3])
+ e := int32(z.ybr[y-1][x+4])
+ f := int32(z.ybr[y-1][x+5])
+ g := int32(z.ybr[y-1][x+6])
+ h := int32(z.ybr[y-1][x+7])
+ abc := uint8((a + 2*b + c + 2) / 4)
+ bcd := uint8((b + 2*c + d + 2) / 4)
+ cde := uint8((c + 2*d + e + 2) / 4)
+ def := uint8((d + 2*e + f + 2) / 4)
+ efg := uint8((e + 2*f + g + 2) / 4)
+ fgh := uint8((f + 2*g + h + 2) / 4)
+ ghh := uint8((g + 2*h + h + 2) / 4)
+ z.ybr[y+0][x+0] = abc
+ z.ybr[y+0][x+1] = bcd
+ z.ybr[y+0][x+2] = cde
+ z.ybr[y+0][x+3] = def
+ z.ybr[y+1][x+0] = bcd
+ z.ybr[y+1][x+1] = cde
+ z.ybr[y+1][x+2] = def
+ z.ybr[y+1][x+3] = efg
+ z.ybr[y+2][x+0] = cde
+ z.ybr[y+2][x+1] = def
+ z.ybr[y+2][x+2] = efg
+ z.ybr[y+2][x+3] = fgh
+ z.ybr[y+3][x+0] = def
+ z.ybr[y+3][x+1] = efg
+ z.ybr[y+3][x+2] = fgh
+ z.ybr[y+3][x+3] = ghh
+}
+
+func predFunc4VL(z *Decoder, y, x int) {
+ a := int32(z.ybr[y-1][x+0])
+ b := int32(z.ybr[y-1][x+1])
+ c := int32(z.ybr[y-1][x+2])
+ d := int32(z.ybr[y-1][x+3])
+ e := int32(z.ybr[y-1][x+4])
+ f := int32(z.ybr[y-1][x+5])
+ g := int32(z.ybr[y-1][x+6])
+ h := int32(z.ybr[y-1][x+7])
+ ab := uint8((a + b + 1) / 2)
+ bc := uint8((b + c + 1) / 2)
+ cd := uint8((c + d + 1) / 2)
+ de := uint8((d + e + 1) / 2)
+ abc := uint8((a + 2*b + c + 2) / 4)
+ bcd := uint8((b + 2*c + d + 2) / 4)
+ cde := uint8((c + 2*d + e + 2) / 4)
+ def := uint8((d + 2*e + f + 2) / 4)
+ efg := uint8((e + 2*f + g + 2) / 4)
+ fgh := uint8((f + 2*g + h + 2) / 4)
+ z.ybr[y+0][x+0] = ab
+ z.ybr[y+0][x+1] = bc
+ z.ybr[y+0][x+2] = cd
+ z.ybr[y+0][x+3] = de
+ z.ybr[y+1][x+0] = abc
+ z.ybr[y+1][x+1] = bcd
+ z.ybr[y+1][x+2] = cde
+ z.ybr[y+1][x+3] = def
+ z.ybr[y+2][x+0] = bc
+ z.ybr[y+2][x+1] = cd
+ z.ybr[y+2][x+2] = de
+ z.ybr[y+2][x+3] = efg
+ z.ybr[y+3][x+0] = bcd
+ z.ybr[y+3][x+1] = cde
+ z.ybr[y+3][x+2] = def
+ z.ybr[y+3][x+3] = fgh
+}
+
+func predFunc4HD(z *Decoder, y, x int) {
+ s := int32(z.ybr[y+3][x-1])
+ r := int32(z.ybr[y+2][x-1])
+ q := int32(z.ybr[y+1][x-1])
+ p := int32(z.ybr[y+0][x-1])
+ a := int32(z.ybr[y-1][x-1])
+ b := int32(z.ybr[y-1][x+0])
+ c := int32(z.ybr[y-1][x+1])
+ d := int32(z.ybr[y-1][x+2])
+ sr := uint8((s + r + 1) / 2)
+ rq := uint8((r + q + 1) / 2)
+ qp := uint8((q + p + 1) / 2)
+ pa := uint8((p + a + 1) / 2)
+ srq := uint8((s + 2*r + q + 2) / 4)
+ rqp := uint8((r + 2*q + p + 2) / 4)
+ qpa := uint8((q + 2*p + a + 2) / 4)
+ pab := uint8((p + 2*a + b + 2) / 4)
+ abc := uint8((a + 2*b + c + 2) / 4)
+ bcd := uint8((b + 2*c + d + 2) / 4)
+ z.ybr[y+0][x+0] = pa
+ z.ybr[y+0][x+1] = pab
+ z.ybr[y+0][x+2] = abc
+ z.ybr[y+0][x+3] = bcd
+ z.ybr[y+1][x+0] = qp
+ z.ybr[y+1][x+1] = qpa
+ z.ybr[y+1][x+2] = pa
+ z.ybr[y+1][x+3] = pab
+ z.ybr[y+2][x+0] = rq
+ z.ybr[y+2][x+1] = rqp
+ z.ybr[y+2][x+2] = qp
+ z.ybr[y+2][x+3] = qpa
+ z.ybr[y+3][x+0] = sr
+ z.ybr[y+3][x+1] = srq
+ z.ybr[y+3][x+2] = rq
+ z.ybr[y+3][x+3] = rqp
+}
+
+func predFunc4HU(z *Decoder, y, x int) {
+ s := int32(z.ybr[y+3][x-1])
+ r := int32(z.ybr[y+2][x-1])
+ q := int32(z.ybr[y+1][x-1])
+ p := int32(z.ybr[y+0][x-1])
+ pq := uint8((p + q + 1) / 2)
+ qr := uint8((q + r + 1) / 2)
+ rs := uint8((r + s + 1) / 2)
+ pqr := uint8((p + 2*q + r + 2) / 4)
+ qrs := uint8((q + 2*r + s + 2) / 4)
+ rss := uint8((r + 2*s + s + 2) / 4)
+ sss := uint8(s)
+ z.ybr[y+0][x+0] = pq
+ z.ybr[y+0][x+1] = pqr
+ z.ybr[y+0][x+2] = qr
+ z.ybr[y+0][x+3] = qrs
+ z.ybr[y+1][x+0] = qr
+ z.ybr[y+1][x+1] = qrs
+ z.ybr[y+1][x+2] = rs
+ z.ybr[y+1][x+3] = rss
+ z.ybr[y+2][x+0] = rs
+ z.ybr[y+2][x+1] = rss
+ z.ybr[y+2][x+2] = sss
+ z.ybr[y+2][x+3] = sss
+ z.ybr[y+3][x+0] = sss
+ z.ybr[y+3][x+1] = sss
+ z.ybr[y+3][x+2] = sss
+ z.ybr[y+3][x+3] = sss
+}
+
+func predFunc8DC(z *Decoder, y, x int) {
+ sum := uint32(8)
+ for i := 0; i < 8; i++ {
+ sum += uint32(z.ybr[y-1][x+i])
+ }
+ for j := 0; j < 8; j++ {
+ sum += uint32(z.ybr[y+j][x-1])
+ }
+ avg := uint8(sum / 16)
+ for j := 0; j < 8; j++ {
+ for i := 0; i < 8; i++ {
+ z.ybr[y+j][x+i] = avg
+ }
+ }
+}
+
+func predFunc8TM(z *Decoder, y, x int) {
+ delta0 := -int32(z.ybr[y-1][x-1])
+ for j := 0; j < 8; j++ {
+ delta1 := delta0 + int32(z.ybr[y+j][x-1])
+ for i := 0; i < 8; i++ {
+ delta2 := delta1 + int32(z.ybr[y-1][x+i])
+ z.ybr[y+j][x+i] = uint8(clip(delta2, 0, 255))
+ }
+ }
+}
+
+func predFunc8VE(z *Decoder, y, x int) {
+ for j := 0; j < 8; j++ {
+ for i := 0; i < 8; i++ {
+ z.ybr[y+j][x+i] = z.ybr[y-1][x+i]
+ }
+ }
+}
+
+func predFunc8HE(z *Decoder, y, x int) {
+ for j := 0; j < 8; j++ {
+ for i := 0; i < 8; i++ {
+ z.ybr[y+j][x+i] = z.ybr[y+j][x-1]
+ }
+ }
+}
+
+func predFunc8DCTop(z *Decoder, y, x int) {
+ sum := uint32(4)
+ for j := 0; j < 8; j++ {
+ sum += uint32(z.ybr[y+j][x-1])
+ }
+ avg := uint8(sum / 8)
+ for j := 0; j < 8; j++ {
+ for i := 0; i < 8; i++ {
+ z.ybr[y+j][x+i] = avg
+ }
+ }
+}
+
+func predFunc8DCLeft(z *Decoder, y, x int) {
+ sum := uint32(4)
+ for i := 0; i < 8; i++ {
+ sum += uint32(z.ybr[y-1][x+i])
+ }
+ avg := uint8(sum / 8)
+ for j := 0; j < 8; j++ {
+ for i := 0; i < 8; i++ {
+ z.ybr[y+j][x+i] = avg
+ }
+ }
+}
+
+func predFunc8DCTopLeft(z *Decoder, y, x int) {
+ for j := 0; j < 8; j++ {
+ for i := 0; i < 8; i++ {
+ z.ybr[y+j][x+i] = 0x80
+ }
+ }
+}
+
+func predFunc16DC(z *Decoder, y, x int) {
+ sum := uint32(16)
+ for i := 0; i < 16; i++ {
+ sum += uint32(z.ybr[y-1][x+i])
+ }
+ for j := 0; j < 16; j++ {
+ sum += uint32(z.ybr[y+j][x-1])
+ }
+ avg := uint8(sum / 32)
+ for j := 0; j < 16; j++ {
+ for i := 0; i < 16; i++ {
+ z.ybr[y+j][x+i] = avg
+ }
+ }
+}
+
+func predFunc16TM(z *Decoder, y, x int) {
+ delta0 := -int32(z.ybr[y-1][x-1])
+ for j := 0; j < 16; j++ {
+ delta1 := delta0 + int32(z.ybr[y+j][x-1])
+ for i := 0; i < 16; i++ {
+ delta2 := delta1 + int32(z.ybr[y-1][x+i])
+ z.ybr[y+j][x+i] = uint8(clip(delta2, 0, 255))
+ }
+ }
+}
+
+func predFunc16VE(z *Decoder, y, x int) {
+ for j := 0; j < 16; j++ {
+ for i := 0; i < 16; i++ {
+ z.ybr[y+j][x+i] = z.ybr[y-1][x+i]
+ }
+ }
+}
+
+func predFunc16HE(z *Decoder, y, x int) {
+ for j := 0; j < 16; j++ {
+ for i := 0; i < 16; i++ {
+ z.ybr[y+j][x+i] = z.ybr[y+j][x-1]
+ }
+ }
+}
+
+func predFunc16DCTop(z *Decoder, y, x int) {
+ sum := uint32(8)
+ for j := 0; j < 16; j++ {
+ sum += uint32(z.ybr[y+j][x-1])
+ }
+ avg := uint8(sum / 16)
+ for j := 0; j < 16; j++ {
+ for i := 0; i < 16; i++ {
+ z.ybr[y+j][x+i] = avg
+ }
+ }
+}
+
+func predFunc16DCLeft(z *Decoder, y, x int) {
+ sum := uint32(8)
+ for i := 0; i < 16; i++ {
+ sum += uint32(z.ybr[y-1][x+i])
+ }
+ avg := uint8(sum / 16)
+ for j := 0; j < 16; j++ {
+ for i := 0; i < 16; i++ {
+ z.ybr[y+j][x+i] = avg
+ }
+ }
+}
+
+func predFunc16DCTopLeft(z *Decoder, y, x int) {
+ for j := 0; j < 16; j++ {
+ for i := 0; i < 16; i++ {
+ z.ybr[y+j][x+i] = 0x80
+ }
+ }
+}
diff --git a/vendor/golang.org/x/image/vp8/quant.go b/vendor/golang.org/x/image/vp8/quant.go
new file mode 100644
index 0000000..da43616
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8/quant.go
@@ -0,0 +1,98 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vp8
+
+// This file implements parsing the quantization factors.
+
+// quant are DC/AC quantization factors.
+type quant struct {
+ y1 [2]uint16
+ y2 [2]uint16
+ uv [2]uint16
+}
+
+// clip clips x to the range [min, max] inclusive.
+func clip(x, min, max int32) int32 {
+ if x < min {
+ return min
+ }
+ if x > max {
+ return max
+ }
+ return x
+}
+
+// parseQuant parses the quantization factors, as specified in section 9.6.
+func (d *Decoder) parseQuant() {
+ baseQ0 := d.fp.readUint(uniformProb, 7)
+ dqy1DC := d.fp.readOptionalInt(uniformProb, 4)
+ const dqy1AC = 0
+ dqy2DC := d.fp.readOptionalInt(uniformProb, 4)
+ dqy2AC := d.fp.readOptionalInt(uniformProb, 4)
+ dquvDC := d.fp.readOptionalInt(uniformProb, 4)
+ dquvAC := d.fp.readOptionalInt(uniformProb, 4)
+ for i := 0; i < nSegment; i++ {
+ q := int32(baseQ0)
+ if d.segmentHeader.useSegment {
+ if d.segmentHeader.relativeDelta {
+ q += int32(d.segmentHeader.quantizer[i])
+ } else {
+ q = int32(d.segmentHeader.quantizer[i])
+ }
+ }
+ d.quant[i].y1[0] = dequantTableDC[clip(q+dqy1DC, 0, 127)]
+ d.quant[i].y1[1] = dequantTableAC[clip(q+dqy1AC, 0, 127)]
+ d.quant[i].y2[0] = dequantTableDC[clip(q+dqy2DC, 0, 127)] * 2
+ d.quant[i].y2[1] = dequantTableAC[clip(q+dqy2AC, 0, 127)] * 155 / 100
+ if d.quant[i].y2[1] < 8 {
+ d.quant[i].y2[1] = 8
+ }
+ // The 117 is not a typo. The dequant_init function in the spec's Reference
+ // Decoder Source Code (http://tools.ietf.org/html/rfc6386#section-9.6 Page 145)
+ // says to clamp the LHS value at 132, which is equal to dequantTableDC[117].
+ d.quant[i].uv[0] = dequantTableDC[clip(q+dquvDC, 0, 117)]
+ d.quant[i].uv[1] = dequantTableAC[clip(q+dquvAC, 0, 127)]
+ }
+}
+
+// The dequantization tables are specified in section 14.1.
+var (
+ dequantTableDC = [128]uint16{
+ 4, 5, 6, 7, 8, 9, 10, 10,
+ 11, 12, 13, 14, 15, 16, 17, 17,
+ 18, 19, 20, 20, 21, 21, 22, 22,
+ 23, 23, 24, 25, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 46, 47, 48, 49, 50,
+ 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, 61, 62, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 76, 77, 78, 79, 80, 81,
+ 82, 83, 84, 85, 86, 87, 88, 89,
+ 91, 93, 95, 96, 98, 100, 101, 102,
+ 104, 106, 108, 110, 112, 114, 116, 118,
+ 122, 124, 126, 128, 130, 132, 134, 136,
+ 138, 140, 143, 145, 148, 151, 154, 157,
+ }
+ dequantTableAC = [128]uint16{
+ 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 60,
+ 62, 64, 66, 68, 70, 72, 74, 76,
+ 78, 80, 82, 84, 86, 88, 90, 92,
+ 94, 96, 98, 100, 102, 104, 106, 108,
+ 110, 112, 114, 116, 119, 122, 125, 128,
+ 131, 134, 137, 140, 143, 146, 149, 152,
+ 155, 158, 161, 164, 167, 170, 173, 177,
+ 181, 185, 189, 193, 197, 201, 205, 209,
+ 213, 217, 221, 225, 229, 234, 239, 245,
+ 249, 254, 259, 264, 269, 274, 279, 284,
+ }
+)
diff --git a/vendor/golang.org/x/image/vp8/reconstruct.go b/vendor/golang.org/x/image/vp8/reconstruct.go
new file mode 100644
index 0000000..c1cc4b5
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8/reconstruct.go
@@ -0,0 +1,442 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vp8
+
+// This file implements decoding DCT/WHT residual coefficients and
+// reconstructing YCbCr data equal to predicted values plus residuals.
+//
+// There are 1*16*16 + 2*8*8 + 1*4*4 coefficients per macroblock:
+// - 1*16*16 luma DCT coefficients,
+// - 2*8*8 chroma DCT coefficients, and
+// - 1*4*4 luma WHT coefficients.
+// Coefficients are read in lots of 16, and the later coefficients in each lot
+// are often zero.
+//
+// The YCbCr data consists of 1*16*16 luma values and 2*8*8 chroma values,
+// plus previously decoded values along the top and left borders. The combined
+// values are laid out as a [1+16+1+8][32]uint8 so that vertically adjacent
+// samples are 32 bytes apart. In detail, the layout is:
+//
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// . . . . . . . a b b b b b b b b b b b b b b b b c c c c . . . . 0
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 1
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 2
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 3
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y c c c c . . . . 4
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 5
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 6
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 7
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y c c c c . . . . 8
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 9
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 10
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 11
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y c c c c . . . . 12
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 13
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 14
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 15
+// . . . . . . . d Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . . . . . 16
+// . . . . . . . e f f f f f f f f . . . . . . . g h h h h h h h h 17
+// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 18
+// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 19
+// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 20
+// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 21
+// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 22
+// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 23
+// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 24
+// . . . . . . . i B B B B B B B B . . . . . . . j R R R R R R R R 25
+//
+// Y, B and R are the reconstructed luma (Y) and chroma (B, R) values.
+// The Y values are predicted (either as one 16x16 region or 16 4x4 regions)
+// based on the row above's Y values (some combination of {abc} or {dYC}) and
+// the column left's Y values (either {ad} or {bY}). Similarly, B and R values
+// are predicted on the row above and column left of their respective 8x8
+// region: {efi} for B, {ghj} for R.
+//
+// For uppermost macroblocks (i.e. those with mby == 0), the {abcefgh} values
+// are initialized to 0x81. Otherwise, they are copied from the bottom row of
+// the macroblock above. The {c} values are then duplicated from row 0 to rows
+// 4, 8 and 12 of the ybr workspace.
+// Similarly, for leftmost macroblocks (i.e. those with mbx == 0), the {adeigj}
+// values are initialized to 0x7f. Otherwise, they are copied from the right
+// column of the macroblock to the left.
+// For the top-left macroblock (with mby == 0 && mbx == 0), {aeg} is 0x81.
+//
+// When moving from one macroblock to the next horizontally, the {adeigj}
+// values can simply be copied from the workspace to itself, shifted by 8 or
+// 16 columns. When moving from one macroblock to the next vertically,
+// filtering can occur and hence the row values have to be copied from the
+// post-filtered image instead of the pre-filtered workspace.
+
+const (
+ bCoeffBase = 1*16*16 + 0*8*8
+ rCoeffBase = 1*16*16 + 1*8*8
+ whtCoeffBase = 1*16*16 + 2*8*8
+)
+
+const (
+ ybrYX = 8
+ ybrYY = 1
+ ybrBX = 8
+ ybrBY = 18
+ ybrRX = 24
+ ybrRY = 18
+)
+
+// prepareYBR prepares the {abcdefghij} elements of ybr.
+func (d *Decoder) prepareYBR(mbx, mby int) {
+ if mbx == 0 {
+ for y := 0; y < 17; y++ {
+ d.ybr[y][7] = 0x81
+ }
+ for y := 17; y < 26; y++ {
+ d.ybr[y][7] = 0x81
+ d.ybr[y][23] = 0x81
+ }
+ } else {
+ for y := 0; y < 17; y++ {
+ d.ybr[y][7] = d.ybr[y][7+16]
+ }
+ for y := 17; y < 26; y++ {
+ d.ybr[y][7] = d.ybr[y][15]
+ d.ybr[y][23] = d.ybr[y][31]
+ }
+ }
+ if mby == 0 {
+ for x := 7; x < 28; x++ {
+ d.ybr[0][x] = 0x7f
+ }
+ for x := 7; x < 16; x++ {
+ d.ybr[17][x] = 0x7f
+ }
+ for x := 23; x < 32; x++ {
+ d.ybr[17][x] = 0x7f
+ }
+ } else {
+ for i := 0; i < 16; i++ {
+ d.ybr[0][8+i] = d.img.Y[(16*mby-1)*d.img.YStride+16*mbx+i]
+ }
+ for i := 0; i < 8; i++ {
+ d.ybr[17][8+i] = d.img.Cb[(8*mby-1)*d.img.CStride+8*mbx+i]
+ }
+ for i := 0; i < 8; i++ {
+ d.ybr[17][24+i] = d.img.Cr[(8*mby-1)*d.img.CStride+8*mbx+i]
+ }
+ if mbx == d.mbw-1 {
+ for i := 16; i < 20; i++ {
+ d.ybr[0][8+i] = d.img.Y[(16*mby-1)*d.img.YStride+16*mbx+15]
+ }
+ } else {
+ for i := 16; i < 20; i++ {
+ d.ybr[0][8+i] = d.img.Y[(16*mby-1)*d.img.YStride+16*mbx+i]
+ }
+ }
+ }
+ for y := 4; y < 16; y += 4 {
+ d.ybr[y][24] = d.ybr[0][24]
+ d.ybr[y][25] = d.ybr[0][25]
+ d.ybr[y][26] = d.ybr[0][26]
+ d.ybr[y][27] = d.ybr[0][27]
+ }
+}
+
+// btou converts a bool to a 0/1 value.
+func btou(b bool) uint8 {
+ if b {
+ return 1
+ }
+ return 0
+}
+
+// pack packs four 0/1 values into four bits of a uint32.
+func pack(x [4]uint8, shift int) uint32 {
+ u := uint32(x[0])<<0 | uint32(x[1])<<1 | uint32(x[2])<<2 | uint32(x[3])<<3
+ return u << uint(shift)
+}
+
+// unpack unpacks four 0/1 values from a four-bit value.
+var unpack = [16][4]uint8{
+ {0, 0, 0, 0},
+ {1, 0, 0, 0},
+ {0, 1, 0, 0},
+ {1, 1, 0, 0},
+ {0, 0, 1, 0},
+ {1, 0, 1, 0},
+ {0, 1, 1, 0},
+ {1, 1, 1, 0},
+ {0, 0, 0, 1},
+ {1, 0, 0, 1},
+ {0, 1, 0, 1},
+ {1, 1, 0, 1},
+ {0, 0, 1, 1},
+ {1, 0, 1, 1},
+ {0, 1, 1, 1},
+ {1, 1, 1, 1},
+}
+
+var (
+ // The mapping from 4x4 region position to band is specified in section 13.3.
+ bands = [17]uint8{0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 0}
+ // Category probabilties are specified in section 13.2.
+ // Decoding categories 1 and 2 are done inline.
+ cat3456 = [4][12]uint8{
+ {173, 148, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {176, 155, 140, 135, 0, 0, 0, 0, 0, 0, 0, 0},
+ {180, 157, 141, 134, 130, 0, 0, 0, 0, 0, 0, 0},
+ {254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0},
+ }
+ // The zigzag order is:
+ // 0 1 5 6
+ // 2 4 7 12
+ // 3 8 11 13
+ // 9 10 14 15
+ zigzag = [16]uint8{0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15}
+)
+
+// parseResiduals4 parses a 4x4 region of residual coefficients, as specified
+// in section 13.3, and returns a 0/1 value indicating whether there was at
+// least one non-zero coefficient.
+// r is the partition to read bits from.
+// plane and context describe which token probability table to use. context is
+// either 0, 1 or 2, and equals how many of the macroblock left and macroblock
+// above have non-zero coefficients.
+// quant are the DC/AC quantization factors.
+// skipFirstCoeff is whether the DC coefficient has already been parsed.
+// coeffBase is the base index of d.coeff to write to.
+func (d *Decoder) parseResiduals4(r *partition, plane int, context uint8, quant [2]uint16, skipFirstCoeff bool, coeffBase int) uint8 {
+ prob, n := &d.tokenProb[plane], 0
+ if skipFirstCoeff {
+ n = 1
+ }
+ p := prob[bands[n]][context]
+ if !r.readBit(p[0]) {
+ return 0
+ }
+ for n != 16 {
+ n++
+ if !r.readBit(p[1]) {
+ p = prob[bands[n]][0]
+ continue
+ }
+ var v uint32
+ if !r.readBit(p[2]) {
+ v = 1
+ p = prob[bands[n]][1]
+ } else {
+ if !r.readBit(p[3]) {
+ if !r.readBit(p[4]) {
+ v = 2
+ } else {
+ v = 3 + r.readUint(p[5], 1)
+ }
+ } else if !r.readBit(p[6]) {
+ if !r.readBit(p[7]) {
+ // Category 1.
+ v = 5 + r.readUint(159, 1)
+ } else {
+ // Category 2.
+ v = 7 + 2*r.readUint(165, 1) + r.readUint(145, 1)
+ }
+ } else {
+ // Categories 3, 4, 5 or 6.
+ b1 := r.readUint(p[8], 1)
+ b0 := r.readUint(p[9+b1], 1)
+ cat := 2*b1 + b0
+ tab := &cat3456[cat]
+ v = 0
+ for i := 0; tab[i] != 0; i++ {
+ v *= 2
+ v += r.readUint(tab[i], 1)
+ }
+ v += 3 + (8 << cat)
+ }
+ p = prob[bands[n]][2]
+ }
+ z := zigzag[n-1]
+ c := int32(v) * int32(quant[btou(z > 0)])
+ if r.readBit(uniformProb) {
+ c = -c
+ }
+ d.coeff[coeffBase+int(z)] = int16(c)
+ if n == 16 || !r.readBit(p[0]) {
+ return 1
+ }
+ }
+ return 1
+}
+
+// parseResiduals parses the residuals and returns whether inner loop filtering
+// should be skipped for this macroblock.
+func (d *Decoder) parseResiduals(mbx, mby int) (skip bool) {
+ partition := &d.op[mby&(d.nOP-1)]
+ plane := planeY1SansY2
+ quant := &d.quant[d.segment]
+
+ // Parse the DC coefficient of each 4x4 luma region.
+ if d.usePredY16 {
+ nz := d.parseResiduals4(partition, planeY2, d.leftMB.nzY16+d.upMB[mbx].nzY16, quant.y2, false, whtCoeffBase)
+ d.leftMB.nzY16 = nz
+ d.upMB[mbx].nzY16 = nz
+ d.inverseWHT16()
+ plane = planeY1WithY2
+ }
+
+ var (
+ nzDC, nzAC [4]uint8
+ nzDCMask, nzACMask uint32
+ coeffBase int
+ )
+
+ // Parse the luma coefficients.
+ lnz := unpack[d.leftMB.nzMask&0x0f]
+ unz := unpack[d.upMB[mbx].nzMask&0x0f]
+ for y := 0; y < 4; y++ {
+ nz := lnz[y]
+ for x := 0; x < 4; x++ {
+ nz = d.parseResiduals4(partition, plane, nz+unz[x], quant.y1, d.usePredY16, coeffBase)
+ unz[x] = nz
+ nzAC[x] = nz
+ nzDC[x] = btou(d.coeff[coeffBase] != 0)
+ coeffBase += 16
+ }
+ lnz[y] = nz
+ nzDCMask |= pack(nzDC, y*4)
+ nzACMask |= pack(nzAC, y*4)
+ }
+ lnzMask := pack(lnz, 0)
+ unzMask := pack(unz, 0)
+
+ // Parse the chroma coefficients.
+ lnz = unpack[d.leftMB.nzMask>>4]
+ unz = unpack[d.upMB[mbx].nzMask>>4]
+ for c := 0; c < 4; c += 2 {
+ for y := 0; y < 2; y++ {
+ nz := lnz[y+c]
+ for x := 0; x < 2; x++ {
+ nz = d.parseResiduals4(partition, planeUV, nz+unz[x+c], quant.uv, false, coeffBase)
+ unz[x+c] = nz
+ nzAC[y*2+x] = nz
+ nzDC[y*2+x] = btou(d.coeff[coeffBase] != 0)
+ coeffBase += 16
+ }
+ lnz[y+c] = nz
+ }
+ nzDCMask |= pack(nzDC, 16+c*2)
+ nzACMask |= pack(nzAC, 16+c*2)
+ }
+ lnzMask |= pack(lnz, 4)
+ unzMask |= pack(unz, 4)
+
+ // Save decoder state.
+ d.leftMB.nzMask = uint8(lnzMask)
+ d.upMB[mbx].nzMask = uint8(unzMask)
+ d.nzDCMask = nzDCMask
+ d.nzACMask = nzACMask
+
+ // Section 15.1 of the spec says that "Steps 2 and 4 [of the loop filter]
+ // are skipped... [if] there is no DCT coefficient coded for the whole
+ // macroblock."
+ return nzDCMask == 0 && nzACMask == 0
+}
+
+// reconstructMacroblock applies the predictor functions and adds the inverse-
+// DCT transformed residuals to recover the YCbCr data.
+func (d *Decoder) reconstructMacroblock(mbx, mby int) {
+ if d.usePredY16 {
+ p := checkTopLeftPred(mbx, mby, d.predY16)
+ predFunc16[p](d, 1, 8)
+ for j := 0; j < 4; j++ {
+ for i := 0; i < 4; i++ {
+ n := 4*j + i
+ y := 4*j + 1
+ x := 4*i + 8
+ mask := uint32(1) << uint(n)
+ if d.nzACMask&mask != 0 {
+ d.inverseDCT4(y, x, 16*n)
+ } else if d.nzDCMask&mask != 0 {
+ d.inverseDCT4DCOnly(y, x, 16*n)
+ }
+ }
+ }
+ } else {
+ for j := 0; j < 4; j++ {
+ for i := 0; i < 4; i++ {
+ n := 4*j + i
+ y := 4*j + 1
+ x := 4*i + 8
+ predFunc4[d.predY4[j][i]](d, y, x)
+ mask := uint32(1) << uint(n)
+ if d.nzACMask&mask != 0 {
+ d.inverseDCT4(y, x, 16*n)
+ } else if d.nzDCMask&mask != 0 {
+ d.inverseDCT4DCOnly(y, x, 16*n)
+ }
+ }
+ }
+ }
+ p := checkTopLeftPred(mbx, mby, d.predC8)
+ predFunc8[p](d, ybrBY, ybrBX)
+ if d.nzACMask&0x0f0000 != 0 {
+ d.inverseDCT8(ybrBY, ybrBX, bCoeffBase)
+ } else if d.nzDCMask&0x0f0000 != 0 {
+ d.inverseDCT8DCOnly(ybrBY, ybrBX, bCoeffBase)
+ }
+ predFunc8[p](d, ybrRY, ybrRX)
+ if d.nzACMask&0xf00000 != 0 {
+ d.inverseDCT8(ybrRY, ybrRX, rCoeffBase)
+ } else if d.nzDCMask&0xf00000 != 0 {
+ d.inverseDCT8DCOnly(ybrRY, ybrRX, rCoeffBase)
+ }
+}
+
+// reconstruct reconstructs one macroblock and returns whether inner loop
+// filtering should be skipped for it.
+func (d *Decoder) reconstruct(mbx, mby int) (skip bool) {
+ if d.segmentHeader.updateMap {
+ if !d.fp.readBit(d.segmentHeader.prob[0]) {
+ d.segment = int(d.fp.readUint(d.segmentHeader.prob[1], 1))
+ } else {
+ d.segment = int(d.fp.readUint(d.segmentHeader.prob[2], 1)) + 2
+ }
+ }
+ if d.useSkipProb {
+ skip = d.fp.readBit(d.skipProb)
+ }
+ // Prepare the workspace.
+ for i := range d.coeff {
+ d.coeff[i] = 0
+ }
+ d.prepareYBR(mbx, mby)
+ // Parse the predictor modes.
+ d.usePredY16 = d.fp.readBit(145)
+ if d.usePredY16 {
+ d.parsePredModeY16(mbx)
+ } else {
+ d.parsePredModeY4(mbx)
+ }
+ d.parsePredModeC8()
+ // Parse the residuals.
+ if !skip {
+ skip = d.parseResiduals(mbx, mby)
+ } else {
+ if d.usePredY16 {
+ d.leftMB.nzY16 = 0
+ d.upMB[mbx].nzY16 = 0
+ }
+ d.leftMB.nzMask = 0
+ d.upMB[mbx].nzMask = 0
+ d.nzDCMask = 0
+ d.nzACMask = 0
+ }
+ // Reconstruct the YCbCr data and copy it to the image.
+ d.reconstructMacroblock(mbx, mby)
+ for i, y := (mby*d.img.YStride+mbx)*16, 0; y < 16; i, y = i+d.img.YStride, y+1 {
+ copy(d.img.Y[i:i+16], d.ybr[ybrYY+y][ybrYX:ybrYX+16])
+ }
+ for i, y := (mby*d.img.CStride+mbx)*8, 0; y < 8; i, y = i+d.img.CStride, y+1 {
+ copy(d.img.Cb[i:i+8], d.ybr[ybrBY+y][ybrBX:ybrBX+8])
+ copy(d.img.Cr[i:i+8], d.ybr[ybrRY+y][ybrRX:ybrRX+8])
+ }
+ return skip
+}
diff --git a/vendor/golang.org/x/image/vp8/token.go b/vendor/golang.org/x/image/vp8/token.go
new file mode 100644
index 0000000..da99cf0
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8/token.go
@@ -0,0 +1,381 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vp8
+
+// This file contains token probabilities for decoding DCT/WHT coefficients, as
+// specified in chapter 13.
+
+func (d *Decoder) parseTokenProb() {
+ for i := range d.tokenProb {
+ for j := range d.tokenProb[i] {
+ for k := range d.tokenProb[i][j] {
+ for l := range d.tokenProb[i][j][k] {
+ if d.fp.readBit(tokenProbUpdateProb[i][j][k][l]) {
+ d.tokenProb[i][j][k][l] = uint8(d.fp.readUint(uniformProb, 8))
+ }
+ }
+ }
+ }
+ }
+}
+
+// The plane enumeration is specified in section 13.3.
+const (
+ planeY1WithY2 = iota
+ planeY2
+ planeUV
+ planeY1SansY2
+ nPlane
+)
+
+const (
+ nBand = 8
+ nContext = 3
+ nProb = 11
+)
+
+// Token probability update probabilities are specified in section 13.4.
+var tokenProbUpdateProb = [nPlane][nBand][nContext][nProb]uint8{
+ {
+ {
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255},
+ {249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255},
+ {234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255},
+ {250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255},
+ {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ },
+ {
+ {
+ {217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255},
+ {234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255},
+ },
+ {
+ {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255},
+ {250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ },
+ {
+ {
+ {186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255},
+ {234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255},
+ {251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255},
+ },
+ {
+ {255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ },
+ {
+ {
+ {248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255},
+ {248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255},
+ {246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255},
+ {252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255},
+ {248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255},
+ {253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255},
+ {252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255},
+ {250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ {
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ },
+}
+
+// Default token probabilities are specified in section 13.5.
+var defaultTokenProb = [nPlane][nBand][nContext][nProb]uint8{
+ {
+ {
+ {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
+ {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
+ {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
+ },
+ {
+ {253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128},
+ {189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128},
+ {106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128},
+ },
+ {
+ {1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128},
+ {181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128},
+ {78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128},
+ },
+ {
+ {1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128},
+ {184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128},
+ {77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128},
+ },
+ {
+ {1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128},
+ {170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128},
+ {37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128},
+ },
+ {
+ {1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128},
+ {207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128},
+ {102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128},
+ },
+ {
+ {1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128},
+ {177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128},
+ {80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128},
+ },
+ {
+ {1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
+ {246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
+ {255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
+ },
+ },
+ {
+ {
+ {198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62},
+ {131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1},
+ {68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128},
+ },
+ {
+ {1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128},
+ {184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128},
+ {81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128},
+ },
+ {
+ {1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128},
+ {99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128},
+ {23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128},
+ },
+ {
+ {1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128},
+ {109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128},
+ {44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128},
+ },
+ {
+ {1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128},
+ {94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128},
+ {22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128},
+ },
+ {
+ {1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128},
+ {124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128},
+ {35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128},
+ },
+ {
+ {1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128},
+ {121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128},
+ {45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128},
+ },
+ {
+ {1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128},
+ {203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128},
+ {137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128},
+ },
+ },
+ {
+ {
+ {253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128},
+ {175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128},
+ {73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128},
+ },
+ {
+ {1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128},
+ {239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128},
+ {155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128},
+ },
+ {
+ {1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128},
+ {201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128},
+ {69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128},
+ },
+ {
+ {1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128},
+ {223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128},
+ {141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128},
+ },
+ {
+ {1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128},
+ {190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128},
+ {149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
+ },
+ {
+ {1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128},
+ {247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128},
+ {240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128},
+ },
+ {
+ {1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128},
+ {213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128},
+ {55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128},
+ },
+ {
+ {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
+ {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
+ {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
+ },
+ },
+ {
+ {
+ {202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255},
+ {126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128},
+ {61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128},
+ },
+ {
+ {1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128},
+ {166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128},
+ {39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128},
+ },
+ {
+ {1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128},
+ {124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128},
+ {24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128},
+ },
+ {
+ {1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128},
+ {149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128},
+ {28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128},
+ },
+ {
+ {1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128},
+ {123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128},
+ {20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128},
+ },
+ {
+ {1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128},
+ {168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128},
+ {47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128},
+ },
+ {
+ {1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128},
+ {141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128},
+ {42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128},
+ },
+ {
+ {1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
+ {244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
+ {238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
+ },
+ },
+}
diff --git a/vendor/golang.org/x/image/vp8l/decode.go b/vendor/golang.org/x/image/vp8l/decode.go
new file mode 100644
index 0000000..4319487
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8l/decode.go
@@ -0,0 +1,603 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package vp8l implements a decoder for the VP8L lossless image format.
+//
+// The VP8L specification is at:
+// https://developers.google.com/speed/webp/docs/riff_container
+package vp8l // import "golang.org/x/image/vp8l"
+
+import (
+ "bufio"
+ "errors"
+ "image"
+ "image/color"
+ "io"
+)
+
+var (
+ errInvalidCodeLengths = errors.New("vp8l: invalid code lengths")
+ errInvalidHuffmanTree = errors.New("vp8l: invalid Huffman tree")
+)
+
+// colorCacheMultiplier is the multiplier used for the color cache hash
+// function, specified in section 4.2.3.
+const colorCacheMultiplier = 0x1e35a7bd
+
+// distanceMapTable is the look-up table for distanceMap.
+var distanceMapTable = [120]uint8{
+ 0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a,
+ 0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a,
+ 0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b,
+ 0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03,
+ 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c,
+ 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e,
+ 0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b,
+ 0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f,
+ 0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b,
+ 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41,
+ 0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f,
+ 0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70,
+}
+
+// distanceMap maps a LZ77 backwards reference distance to a two-dimensional
+// pixel offset, specified in section 4.2.2.
+func distanceMap(w int32, code uint32) int32 {
+ if int32(code) > int32(len(distanceMapTable)) {
+ return int32(code) - int32(len(distanceMapTable))
+ }
+ distCode := int32(distanceMapTable[code-1])
+ yOffset := distCode >> 4
+ xOffset := 8 - distCode&0xf
+ if d := yOffset*w + xOffset; d >= 1 {
+ return d
+ }
+ return 1
+}
+
+// decoder holds the bit-stream for a VP8L image.
+type decoder struct {
+ r io.ByteReader
+ bits uint32
+ nBits uint32
+}
+
+// read reads the next n bits from the decoder's bit-stream.
+func (d *decoder) read(n uint32) (uint32, error) {
+ for d.nBits < n {
+ c, err := d.r.ReadByte()
+ if err != nil {
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ return 0, err
+ }
+ d.bits |= uint32(c) << d.nBits
+ d.nBits += 8
+ }
+ u := d.bits & (1<<n - 1)
+ d.bits >>= n
+ d.nBits -= n
+ return u, nil
+}
+
+// decodeTransform decodes the next transform and the width of the image after
+// transformation (or equivalently, before inverse transformation), specified
+// in section 3.
+func (d *decoder) decodeTransform(w int32, h int32) (t transform, newWidth int32, err error) {
+ t.oldWidth = w
+ t.transformType, err = d.read(2)
+ if err != nil {
+ return transform{}, 0, err
+ }
+ switch t.transformType {
+ case transformTypePredictor, transformTypeCrossColor:
+ t.bits, err = d.read(3)
+ if err != nil {
+ return transform{}, 0, err
+ }
+ t.bits += 2
+ t.pix, err = d.decodePix(nTiles(w, t.bits), nTiles(h, t.bits), 0, false)
+ if err != nil {
+ return transform{}, 0, err
+ }
+ case transformTypeSubtractGreen:
+ // No-op.
+ case transformTypeColorIndexing:
+ nColors, err := d.read(8)
+ if err != nil {
+ return transform{}, 0, err
+ }
+ nColors++
+ t.bits = 0
+ switch {
+ case nColors <= 2:
+ t.bits = 3
+ case nColors <= 4:
+ t.bits = 2
+ case nColors <= 16:
+ t.bits = 1
+ }
+ w = nTiles(w, t.bits)
+ pix, err := d.decodePix(int32(nColors), 1, 4*256, false)
+ if err != nil {
+ return transform{}, 0, err
+ }
+ for p := 4; p < len(pix); p += 4 {
+ pix[p+0] += pix[p-4]
+ pix[p+1] += pix[p-3]
+ pix[p+2] += pix[p-2]
+ pix[p+3] += pix[p-1]
+ }
+ // The spec says that "if the index is equal or larger than color_table_size,
+ // the argb color value should be set to 0x00000000 (transparent black)."
+ // We re-slice up to 256 4-byte pixels.
+ t.pix = pix[:4*256]
+ }
+ return t, w, nil
+}
+
+// repeatsCodeLength is the minimum code length for repeated codes.
+const repeatsCodeLength = 16
+
+// These magic numbers are specified at the end of section 5.2.2.
+// The 3-length arrays apply to code lengths >= repeatsCodeLength.
+var (
+ codeLengthCodeOrder = [19]uint8{
+ 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ }
+ repeatBits = [3]uint8{2, 3, 7}
+ repeatOffsets = [3]uint8{3, 3, 11}
+)
+
+// decodeCodeLengths decodes a Huffman tree's code lengths which are themselves
+// encoded via a Huffman tree, specified in section 5.2.2.
+func (d *decoder) decodeCodeLengths(dst []uint32, codeLengthCodeLengths []uint32) error {
+ h := hTree{}
+ if err := h.build(codeLengthCodeLengths); err != nil {
+ return err
+ }
+
+ maxSymbol := len(dst)
+ useLength, err := d.read(1)
+ if err != nil {
+ return err
+ }
+ if useLength != 0 {
+ n, err := d.read(3)
+ if err != nil {
+ return err
+ }
+ n = 2 + 2*n
+ ms, err := d.read(n)
+ if err != nil {
+ return err
+ }
+ maxSymbol = int(ms) + 2
+ if maxSymbol > len(dst) {
+ return errInvalidCodeLengths
+ }
+ }
+
+ // The spec says that "if code 16 [meaning repeat] is used before
+ // a non-zero value has been emitted, a value of 8 is repeated."
+ prevCodeLength := uint32(8)
+
+ for symbol := 0; symbol < len(dst); {
+ if maxSymbol == 0 {
+ break
+ }
+ maxSymbol--
+ codeLength, err := h.next(d)
+ if err != nil {
+ return err
+ }
+ if codeLength < repeatsCodeLength {
+ dst[symbol] = codeLength
+ symbol++
+ if codeLength != 0 {
+ prevCodeLength = codeLength
+ }
+ continue
+ }
+
+ repeat, err := d.read(uint32(repeatBits[codeLength-repeatsCodeLength]))
+ if err != nil {
+ return err
+ }
+ repeat += uint32(repeatOffsets[codeLength-repeatsCodeLength])
+ if symbol+int(repeat) > len(dst) {
+ return errInvalidCodeLengths
+ }
+ // A code length of 16 repeats the previous non-zero code.
+ // A code length of 17 or 18 repeats zeroes.
+ cl := uint32(0)
+ if codeLength == 16 {
+ cl = prevCodeLength
+ }
+ for ; repeat > 0; repeat-- {
+ dst[symbol] = cl
+ symbol++
+ }
+ }
+ return nil
+}
+
+// decodeHuffmanTree decodes a Huffman tree into h.
+func (d *decoder) decodeHuffmanTree(h *hTree, alphabetSize uint32) error {
+ useSimple, err := d.read(1)
+ if err != nil {
+ return err
+ }
+ if useSimple != 0 {
+ nSymbols, err := d.read(1)
+ if err != nil {
+ return err
+ }
+ nSymbols++
+ firstSymbolLengthCode, err := d.read(1)
+ if err != nil {
+ return err
+ }
+ firstSymbolLengthCode = 7*firstSymbolLengthCode + 1
+ var symbols [2]uint32
+ symbols[0], err = d.read(firstSymbolLengthCode)
+ if err != nil {
+ return err
+ }
+ if nSymbols == 2 {
+ symbols[1], err = d.read(8)
+ if err != nil {
+ return err
+ }
+ }
+ return h.buildSimple(nSymbols, symbols, alphabetSize)
+ }
+
+ nCodes, err := d.read(4)
+ if err != nil {
+ return err
+ }
+ nCodes += 4
+ if int(nCodes) > len(codeLengthCodeOrder) {
+ return errInvalidHuffmanTree
+ }
+ codeLengthCodeLengths := [len(codeLengthCodeOrder)]uint32{}
+ for i := uint32(0); i < nCodes; i++ {
+ codeLengthCodeLengths[codeLengthCodeOrder[i]], err = d.read(3)
+ if err != nil {
+ return err
+ }
+ }
+ codeLengths := make([]uint32, alphabetSize)
+ if err = d.decodeCodeLengths(codeLengths, codeLengthCodeLengths[:]); err != nil {
+ return err
+ }
+ return h.build(codeLengths)
+}
+
+const (
+ huffGreen = 0
+ huffRed = 1
+ huffBlue = 2
+ huffAlpha = 3
+ huffDistance = 4
+ nHuff = 5
+)
+
+// hGroup is an array of 5 Huffman trees.
+type hGroup [nHuff]hTree
+
+// decodeHuffmanGroups decodes the one or more hGroups used to decode the pixel
+// data. If one hGroup is used for the entire image, then hPix and hBits will
+// be zero. If more than one hGroup is used, then hPix contains the meta-image
+// that maps tiles to hGroup index, and hBits contains the log-2 tile size.
+func (d *decoder) decodeHuffmanGroups(w int32, h int32, topLevel bool, ccBits uint32) (
+ hGroups []hGroup, hPix []byte, hBits uint32, err error) {
+
+ maxHGroupIndex := 0
+ if topLevel {
+ useMeta, err := d.read(1)
+ if err != nil {
+ return nil, nil, 0, err
+ }
+ if useMeta != 0 {
+ hBits, err = d.read(3)
+ if err != nil {
+ return nil, nil, 0, err
+ }
+ hBits += 2
+ hPix, err = d.decodePix(nTiles(w, hBits), nTiles(h, hBits), 0, false)
+ if err != nil {
+ return nil, nil, 0, err
+ }
+ for p := 0; p < len(hPix); p += 4 {
+ i := int(hPix[p])<<8 | int(hPix[p+1])
+ if maxHGroupIndex < i {
+ maxHGroupIndex = i
+ }
+ }
+ }
+ }
+ hGroups = make([]hGroup, maxHGroupIndex+1)
+ for i := range hGroups {
+ for j, alphabetSize := range alphabetSizes {
+ if j == 0 && ccBits > 0 {
+ alphabetSize += 1 << ccBits
+ }
+ if err := d.decodeHuffmanTree(&hGroups[i][j], alphabetSize); err != nil {
+ return nil, nil, 0, err
+ }
+ }
+ }
+ return hGroups, hPix, hBits, nil
+}
+
+const (
+ nLiteralCodes = 256
+ nLengthCodes = 24
+ nDistanceCodes = 40
+)
+
+var alphabetSizes = [nHuff]uint32{
+ nLiteralCodes + nLengthCodes,
+ nLiteralCodes,
+ nLiteralCodes,
+ nLiteralCodes,
+ nDistanceCodes,
+}
+
+// decodePix decodes pixel data, specified in section 5.2.2.
+func (d *decoder) decodePix(w int32, h int32, minCap int32, topLevel bool) ([]byte, error) {
+ // Decode the color cache parameters.
+ ccBits, ccShift, ccEntries := uint32(0), uint32(0), ([]uint32)(nil)
+ useColorCache, err := d.read(1)
+ if err != nil {
+ return nil, err
+ }
+ if useColorCache != 0 {
+ ccBits, err = d.read(4)
+ if err != nil {
+ return nil, err
+ }
+ if ccBits < 1 || 11 < ccBits {
+ return nil, errors.New("vp8l: invalid color cache parameters")
+ }
+ ccShift = 32 - ccBits
+ ccEntries = make([]uint32, 1<<ccBits)
+ }
+
+ // Decode the Huffman groups.
+ hGroups, hPix, hBits, err := d.decodeHuffmanGroups(w, h, topLevel, ccBits)
+ if err != nil {
+ return nil, err
+ }
+ hMask, tilesPerRow := int32(0), int32(0)
+ if hBits != 0 {
+ hMask, tilesPerRow = 1<<hBits-1, nTiles(w, hBits)
+ }
+
+ // Decode the pixels.
+ if minCap < 4*w*h {
+ minCap = 4 * w * h
+ }
+ pix := make([]byte, 4*w*h, minCap)
+ p, cachedP := 0, 0
+ x, y := int32(0), int32(0)
+ hg, lookupHG := &hGroups[0], hMask != 0
+ for p < len(pix) {
+ if lookupHG {
+ i := 4 * (tilesPerRow*(y>>hBits) + (x >> hBits))
+ hg = &hGroups[uint32(hPix[i])<<8|uint32(hPix[i+1])]
+ }
+
+ green, err := hg[huffGreen].next(d)
+ if err != nil {
+ return nil, err
+ }
+ switch {
+ case green < nLiteralCodes:
+ // We have a literal pixel.
+ red, err := hg[huffRed].next(d)
+ if err != nil {
+ return nil, err
+ }
+ blue, err := hg[huffBlue].next(d)
+ if err != nil {
+ return nil, err
+ }
+ alpha, err := hg[huffAlpha].next(d)
+ if err != nil {
+ return nil, err
+ }
+ pix[p+0] = uint8(red)
+ pix[p+1] = uint8(green)
+ pix[p+2] = uint8(blue)
+ pix[p+3] = uint8(alpha)
+ p += 4
+
+ x++
+ if x == w {
+ x, y = 0, y+1
+ }
+ lookupHG = hMask != 0 && x&hMask == 0
+
+ case green < nLiteralCodes+nLengthCodes:
+ // We have a LZ77 backwards reference.
+ length, err := d.lz77Param(green - nLiteralCodes)
+ if err != nil {
+ return nil, err
+ }
+ distSym, err := hg[huffDistance].next(d)
+ if err != nil {
+ return nil, err
+ }
+ distCode, err := d.lz77Param(distSym)
+ if err != nil {
+ return nil, err
+ }
+ dist := distanceMap(w, distCode)
+ pEnd := p + 4*int(length)
+ q := p - 4*int(dist)
+ qEnd := pEnd - 4*int(dist)
+ if p < 0 || len(pix) < pEnd || q < 0 || len(pix) < qEnd {
+ return nil, errors.New("vp8l: invalid LZ77 parameters")
+ }
+ for ; p < pEnd; p, q = p+1, q+1 {
+ pix[p] = pix[q]
+ }
+
+ x += int32(length)
+ for x >= w {
+ x, y = x-w, y+1
+ }
+ lookupHG = hMask != 0
+
+ default:
+ // We have a color cache lookup. First, insert previous pixels
+ // into the cache. Note that VP8L assumes ARGB order, but the
+ // Go image.RGBA type is in RGBA order.
+ for ; cachedP < p; cachedP += 4 {
+ argb := uint32(pix[cachedP+0])<<16 |
+ uint32(pix[cachedP+1])<<8 |
+ uint32(pix[cachedP+2])<<0 |
+ uint32(pix[cachedP+3])<<24
+ ccEntries[(argb*colorCacheMultiplier)>>ccShift] = argb
+ }
+ green -= nLiteralCodes + nLengthCodes
+ if int(green) >= len(ccEntries) {
+ return nil, errors.New("vp8l: invalid color cache index")
+ }
+ argb := ccEntries[green]
+ pix[p+0] = uint8(argb >> 16)
+ pix[p+1] = uint8(argb >> 8)
+ pix[p+2] = uint8(argb >> 0)
+ pix[p+3] = uint8(argb >> 24)
+ p += 4
+
+ x++
+ if x == w {
+ x, y = 0, y+1
+ }
+ lookupHG = hMask != 0 && x&hMask == 0
+ }
+ }
+ return pix, nil
+}
+
+// lz77Param returns the next LZ77 parameter: a length or a distance, specified
+// in section 4.2.2.
+func (d *decoder) lz77Param(symbol uint32) (uint32, error) {
+ if symbol < 4 {
+ return symbol + 1, nil
+ }
+ extraBits := (symbol - 2) >> 1
+ offset := (2 + symbol&1) << extraBits
+ n, err := d.read(extraBits)
+ if err != nil {
+ return 0, err
+ }
+ return offset + n + 1, nil
+}
+
+// decodeHeader decodes the VP8L header from r.
+func decodeHeader(r io.Reader) (d *decoder, w int32, h int32, err error) {
+ rr, ok := r.(io.ByteReader)
+ if !ok {
+ rr = bufio.NewReader(r)
+ }
+ d = &decoder{r: rr}
+ magic, err := d.read(8)
+ if err != nil {
+ return nil, 0, 0, err
+ }
+ if magic != 0x2f {
+ return nil, 0, 0, errors.New("vp8l: invalid header")
+ }
+ width, err := d.read(14)
+ if err != nil {
+ return nil, 0, 0, err
+ }
+ width++
+ height, err := d.read(14)
+ if err != nil {
+ return nil, 0, 0, err
+ }
+ height++
+ _, err = d.read(1) // Read and ignore the hasAlpha hint.
+ if err != nil {
+ return nil, 0, 0, err
+ }
+ version, err := d.read(3)
+ if err != nil {
+ return nil, 0, 0, err
+ }
+ if version != 0 {
+ return nil, 0, 0, errors.New("vp8l: invalid version")
+ }
+ return d, int32(width), int32(height), nil
+}
+
+// DecodeConfig decodes the color model and dimensions of a VP8L image from r.
+func DecodeConfig(r io.Reader) (image.Config, error) {
+ _, w, h, err := decodeHeader(r)
+ if err != nil {
+ return image.Config{}, err
+ }
+ return image.Config{
+ ColorModel: color.NRGBAModel,
+ Width: int(w),
+ Height: int(h),
+ }, nil
+}
+
+// Decode decodes a VP8L image from r.
+func Decode(r io.Reader) (image.Image, error) {
+ d, w, h, err := decodeHeader(r)
+ if err != nil {
+ return nil, err
+ }
+ // Decode the transforms.
+ var (
+ nTransforms int
+ transforms [nTransformTypes]transform
+ transformsSeen [nTransformTypes]bool
+ originalW = w
+ )
+ for {
+ more, err := d.read(1)
+ if err != nil {
+ return nil, err
+ }
+ if more == 0 {
+ break
+ }
+ var t transform
+ t, w, err = d.decodeTransform(w, h)
+ if err != nil {
+ return nil, err
+ }
+ if transformsSeen[t.transformType] {
+ return nil, errors.New("vp8l: repeated transform")
+ }
+ transformsSeen[t.transformType] = true
+ transforms[nTransforms] = t
+ nTransforms++
+ }
+ // Decode the transformed pixels.
+ pix, err := d.decodePix(w, h, 0, true)
+ if err != nil {
+ return nil, err
+ }
+ // Apply the inverse transformations.
+ for i := nTransforms - 1; i >= 0; i-- {
+ t := &transforms[i]
+ pix = inverseTransforms[t.transformType](t, pix, h)
+ }
+ return &image.NRGBA{
+ Pix: pix,
+ Stride: 4 * int(originalW),
+ Rect: image.Rect(0, 0, int(originalW), int(h)),
+ }, nil
+}
diff --git a/vendor/golang.org/x/image/vp8l/huffman.go b/vendor/golang.org/x/image/vp8l/huffman.go
new file mode 100644
index 0000000..36368a8
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8l/huffman.go
@@ -0,0 +1,245 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vp8l
+
+import (
+ "io"
+)
+
+// reverseBits reverses the bits in a byte.
+var reverseBits = [256]uint8{
+ 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+ 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+ 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+ 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+ 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+ 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+ 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+ 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+ 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+ 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+ 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+ 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+ 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+ 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+ 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+ 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
+}
+
+// hNode is a node in a Huffman tree.
+type hNode struct {
+ // symbol is the symbol held by this node.
+ symbol uint32
+ // children, if positive, is the hTree.nodes index of the first of
+ // this node's two children. Zero means an uninitialized node,
+ // and -1 means a leaf node.
+ children int32
+}
+
+const leafNode = -1
+
+// lutSize is the log-2 size of an hTree's look-up table.
+const lutSize, lutMask = 7, 1<<7 - 1
+
+// hTree is a Huffman tree.
+type hTree struct {
+ // nodes are the nodes of the Huffman tree. During construction,
+ // len(nodes) grows from 1 up to cap(nodes) by steps of two.
+ // After construction, len(nodes) == cap(nodes), and both equal
+ // 2*theNumberOfSymbols - 1.
+ nodes []hNode
+ // lut is a look-up table for walking the nodes. The x in lut[x] is
+ // the next lutSize bits in the bit-stream. The low 8 bits of lut[x]
+ // equals 1 plus the number of bits in the next code, or 0 if the
+ // next code requires more than lutSize bits. The high 24 bits are:
+ // - the symbol, if the code requires lutSize or fewer bits, or
+ // - the hTree.nodes index to start the tree traversal from, if
+ // the next code requires more than lutSize bits.
+ lut [1 << lutSize]uint32
+}
+
+// insert inserts into the hTree a symbol whose encoding is the least
+// significant codeLength bits of code.
+func (h *hTree) insert(symbol uint32, code uint32, codeLength uint32) error {
+ if symbol > 0xffff || codeLength > 0xfe {
+ return errInvalidHuffmanTree
+ }
+ baseCode := uint32(0)
+ if codeLength > lutSize {
+ baseCode = uint32(reverseBits[(code>>(codeLength-lutSize))&0xff]) >> (8 - lutSize)
+ } else {
+ baseCode = uint32(reverseBits[code&0xff]) >> (8 - codeLength)
+ for i := 0; i < 1<<(lutSize-codeLength); i++ {
+ h.lut[baseCode|uint32(i)<<codeLength] = symbol<<8 | (codeLength + 1)
+ }
+ }
+
+ n := uint32(0)
+ for jump := lutSize; codeLength > 0; {
+ codeLength--
+ if int(n) > len(h.nodes) {
+ return errInvalidHuffmanTree
+ }
+ switch h.nodes[n].children {
+ case leafNode:
+ return errInvalidHuffmanTree
+ case 0:
+ if len(h.nodes) == cap(h.nodes) {
+ return errInvalidHuffmanTree
+ }
+ // Create two empty child nodes.
+ h.nodes[n].children = int32(len(h.nodes))
+ h.nodes = h.nodes[:len(h.nodes)+2]
+ }
+ n = uint32(h.nodes[n].children) + 1&(code>>codeLength)
+ jump--
+ if jump == 0 && h.lut[baseCode] == 0 {
+ h.lut[baseCode] = n << 8
+ }
+ }
+
+ switch h.nodes[n].children {
+ case leafNode:
+ // No-op.
+ case 0:
+ // Turn the uninitialized node into a leaf.
+ h.nodes[n].children = leafNode
+ default:
+ return errInvalidHuffmanTree
+ }
+ h.nodes[n].symbol = symbol
+ return nil
+}
+
+// codeLengthsToCodes returns the canonical Huffman codes implied by the
+// sequence of code lengths.
+func codeLengthsToCodes(codeLengths []uint32) ([]uint32, error) {
+ maxCodeLength := uint32(0)
+ for _, cl := range codeLengths {
+ if maxCodeLength < cl {
+ maxCodeLength = cl
+ }
+ }
+ const maxAllowedCodeLength = 15
+ if len(codeLengths) == 0 || maxCodeLength > maxAllowedCodeLength {
+ return nil, errInvalidHuffmanTree
+ }
+ histogram := [maxAllowedCodeLength + 1]uint32{}
+ for _, cl := range codeLengths {
+ histogram[cl]++
+ }
+ currCode, nextCodes := uint32(0), [maxAllowedCodeLength + 1]uint32{}
+ for cl := 1; cl < len(nextCodes); cl++ {
+ currCode = (currCode + histogram[cl-1]) << 1
+ nextCodes[cl] = currCode
+ }
+ codes := make([]uint32, len(codeLengths))
+ for symbol, cl := range codeLengths {
+ if cl > 0 {
+ codes[symbol] = nextCodes[cl]
+ nextCodes[cl]++
+ }
+ }
+ return codes, nil
+}
+
+// build builds a canonical Huffman tree from the given code lengths.
+func (h *hTree) build(codeLengths []uint32) error {
+ // Calculate the number of symbols.
+ var nSymbols, lastSymbol uint32
+ for symbol, cl := range codeLengths {
+ if cl != 0 {
+ nSymbols++
+ lastSymbol = uint32(symbol)
+ }
+ }
+ if nSymbols == 0 {
+ return errInvalidHuffmanTree
+ }
+ h.nodes = make([]hNode, 1, 2*nSymbols-1)
+ // Handle the trivial case.
+ if nSymbols == 1 {
+ if len(codeLengths) <= int(lastSymbol) {
+ return errInvalidHuffmanTree
+ }
+ return h.insert(lastSymbol, 0, 0)
+ }
+ // Handle the non-trivial case.
+ codes, err := codeLengthsToCodes(codeLengths)
+ if err != nil {
+ return err
+ }
+ for symbol, cl := range codeLengths {
+ if cl > 0 {
+ if err := h.insert(uint32(symbol), codes[symbol], cl); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+// buildSimple builds a Huffman tree with 1 or 2 symbols.
+func (h *hTree) buildSimple(nSymbols uint32, symbols [2]uint32, alphabetSize uint32) error {
+ h.nodes = make([]hNode, 1, 2*nSymbols-1)
+ for i := uint32(0); i < nSymbols; i++ {
+ if symbols[i] >= alphabetSize {
+ return errInvalidHuffmanTree
+ }
+ if err := h.insert(symbols[i], i, nSymbols-1); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// next returns the next Huffman-encoded symbol from the bit-stream d.
+func (h *hTree) next(d *decoder) (uint32, error) {
+ var n uint32
+ // Read enough bits so that we can use the look-up table.
+ if d.nBits < lutSize {
+ c, err := d.r.ReadByte()
+ if err != nil {
+ if err == io.EOF {
+ // There are no more bytes of data, but we may still be able
+ // to read the next symbol out of the previously read bits.
+ goto slowPath
+ }
+ return 0, err
+ }
+ d.bits |= uint32(c) << d.nBits
+ d.nBits += 8
+ }
+ // Use the look-up table.
+ n = h.lut[d.bits&lutMask]
+ if b := n & 0xff; b != 0 {
+ b--
+ d.bits >>= b
+ d.nBits -= b
+ return n >> 8, nil
+ }
+ n >>= 8
+ d.bits >>= lutSize
+ d.nBits -= lutSize
+
+slowPath:
+ for h.nodes[n].children != leafNode {
+ if d.nBits == 0 {
+ c, err := d.r.ReadByte()
+ if err != nil {
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ return 0, err
+ }
+ d.bits = uint32(c)
+ d.nBits = 8
+ }
+ n = uint32(h.nodes[n].children) + 1&d.bits
+ d.bits >>= 1
+ d.nBits--
+ }
+ return h.nodes[n].symbol, nil
+}
diff --git a/vendor/golang.org/x/image/vp8l/transform.go b/vendor/golang.org/x/image/vp8l/transform.go
new file mode 100644
index 0000000..06543da
--- /dev/null
+++ b/vendor/golang.org/x/image/vp8l/transform.go
@@ -0,0 +1,299 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vp8l
+
+// This file deals with image transforms, specified in section 3.
+
+// nTiles returns the number of tiles needed to cover size pixels, where each
+// tile's side is 1<<bits pixels long.
+func nTiles(size int32, bits uint32) int32 {
+ return (size + 1<<bits - 1) >> bits
+}
+
+const (
+ transformTypePredictor = 0
+ transformTypeCrossColor = 1
+ transformTypeSubtractGreen = 2
+ transformTypeColorIndexing = 3
+ nTransformTypes = 4
+)
+
+// transform holds the parameters for an invertible transform.
+type transform struct {
+ // transformType is the type of the transform.
+ transformType uint32
+ // oldWidth is the width of the image before transformation (or
+ // equivalently, after inverse transformation). The color-indexing
+ // transform can reduce the width. For example, a 50-pixel-wide
+ // image that only needs 4 bits (half a byte) per color index can
+ // be transformed into a 25-pixel-wide image.
+ oldWidth int32
+ // bits is the log-2 size of the transform's tiles, for the predictor
+ // and cross-color transforms. 8>>bits is the number of bits per
+ // color index, for the color-index transform.
+ bits uint32
+ // pix is the tile values, for the predictor and cross-color
+ // transforms, and the color palette, for the color-index transform.
+ pix []byte
+}
+
+var inverseTransforms = [nTransformTypes]func(*transform, []byte, int32) []byte{
+ transformTypePredictor: inversePredictor,
+ transformTypeCrossColor: inverseCrossColor,
+ transformTypeSubtractGreen: inverseSubtractGreen,
+ transformTypeColorIndexing: inverseColorIndexing,
+}
+
+func inversePredictor(t *transform, pix []byte, h int32) []byte {
+ if t.oldWidth == 0 || h == 0 {
+ return pix
+ }
+ // The first pixel's predictor is mode 0 (opaque black).
+ pix[3] += 0xff
+ p, mask := int32(4), int32(1)<<t.bits-1
+ for x := int32(1); x < t.oldWidth; x++ {
+ // The rest of the first row's predictor is mode 1 (L).
+ pix[p+0] += pix[p-4]
+ pix[p+1] += pix[p-3]
+ pix[p+2] += pix[p-2]
+ pix[p+3] += pix[p-1]
+ p += 4
+ }
+ top, tilesPerRow := 0, nTiles(t.oldWidth, t.bits)
+ for y := int32(1); y < h; y++ {
+ // The first column's predictor is mode 2 (T).
+ pix[p+0] += pix[top+0]
+ pix[p+1] += pix[top+1]
+ pix[p+2] += pix[top+2]
+ pix[p+3] += pix[top+3]
+ p, top = p+4, top+4
+
+ q := 4 * (y >> t.bits) * tilesPerRow
+ predictorMode := t.pix[q+1] & 0x0f
+ q += 4
+ for x := int32(1); x < t.oldWidth; x++ {
+ if x&mask == 0 {
+ predictorMode = t.pix[q+1] & 0x0f
+ q += 4
+ }
+ switch predictorMode {
+ case 0: // Opaque black.
+ pix[p+3] += 0xff
+
+ case 1: // L.
+ pix[p+0] += pix[p-4]
+ pix[p+1] += pix[p-3]
+ pix[p+2] += pix[p-2]
+ pix[p+3] += pix[p-1]
+
+ case 2: // T.
+ pix[p+0] += pix[top+0]
+ pix[p+1] += pix[top+1]
+ pix[p+2] += pix[top+2]
+ pix[p+3] += pix[top+3]
+
+ case 3: // TR.
+ pix[p+0] += pix[top+4]
+ pix[p+1] += pix[top+5]
+ pix[p+2] += pix[top+6]
+ pix[p+3] += pix[top+7]
+
+ case 4: // TL.
+ pix[p+0] += pix[top-4]
+ pix[p+1] += pix[top-3]
+ pix[p+2] += pix[top-2]
+ pix[p+3] += pix[top-1]
+
+ case 5: // Average2(Average2(L, TR), T).
+ pix[p+0] += avg2(avg2(pix[p-4], pix[top+4]), pix[top+0])
+ pix[p+1] += avg2(avg2(pix[p-3], pix[top+5]), pix[top+1])
+ pix[p+2] += avg2(avg2(pix[p-2], pix[top+6]), pix[top+2])
+ pix[p+3] += avg2(avg2(pix[p-1], pix[top+7]), pix[top+3])
+
+ case 6: // Average2(L, TL).
+ pix[p+0] += avg2(pix[p-4], pix[top-4])
+ pix[p+1] += avg2(pix[p-3], pix[top-3])
+ pix[p+2] += avg2(pix[p-2], pix[top-2])
+ pix[p+3] += avg2(pix[p-1], pix[top-1])
+
+ case 7: // Average2(L, T).
+ pix[p+0] += avg2(pix[p-4], pix[top+0])
+ pix[p+1] += avg2(pix[p-3], pix[top+1])
+ pix[p+2] += avg2(pix[p-2], pix[top+2])
+ pix[p+3] += avg2(pix[p-1], pix[top+3])
+
+ case 8: // Average2(TL, T).
+ pix[p+0] += avg2(pix[top-4], pix[top+0])
+ pix[p+1] += avg2(pix[top-3], pix[top+1])
+ pix[p+2] += avg2(pix[top-2], pix[top+2])
+ pix[p+3] += avg2(pix[top-1], pix[top+3])
+
+ case 9: // Average2(T, TR).
+ pix[p+0] += avg2(pix[top+0], pix[top+4])
+ pix[p+1] += avg2(pix[top+1], pix[top+5])
+ pix[p+2] += avg2(pix[top+2], pix[top+6])
+ pix[p+3] += avg2(pix[top+3], pix[top+7])
+
+ case 10: // Average2(Average2(L, TL), Average2(T, TR)).
+ pix[p+0] += avg2(avg2(pix[p-4], pix[top-4]), avg2(pix[top+0], pix[top+4]))
+ pix[p+1] += avg2(avg2(pix[p-3], pix[top-3]), avg2(pix[top+1], pix[top+5]))
+ pix[p+2] += avg2(avg2(pix[p-2], pix[top-2]), avg2(pix[top+2], pix[top+6]))
+ pix[p+3] += avg2(avg2(pix[p-1], pix[top-1]), avg2(pix[top+3], pix[top+7]))
+
+ case 11: // Select(L, T, TL).
+ l0 := int32(pix[p-4])
+ l1 := int32(pix[p-3])
+ l2 := int32(pix[p-2])
+ l3 := int32(pix[p-1])
+ c0 := int32(pix[top-4])
+ c1 := int32(pix[top-3])
+ c2 := int32(pix[top-2])
+ c3 := int32(pix[top-1])
+ t0 := int32(pix[top+0])
+ t1 := int32(pix[top+1])
+ t2 := int32(pix[top+2])
+ t3 := int32(pix[top+3])
+ l := abs(c0-t0) + abs(c1-t1) + abs(c2-t2) + abs(c3-t3)
+ t := abs(c0-l0) + abs(c1-l1) + abs(c2-l2) + abs(c3-l3)
+ if l < t {
+ pix[p+0] += uint8(l0)
+ pix[p+1] += uint8(l1)
+ pix[p+2] += uint8(l2)
+ pix[p+3] += uint8(l3)
+ } else {
+ pix[p+0] += uint8(t0)
+ pix[p+1] += uint8(t1)
+ pix[p+2] += uint8(t2)
+ pix[p+3] += uint8(t3)
+ }
+
+ case 12: // ClampAddSubtractFull(L, T, TL).
+ pix[p+0] += clampAddSubtractFull(pix[p-4], pix[top+0], pix[top-4])
+ pix[p+1] += clampAddSubtractFull(pix[p-3], pix[top+1], pix[top-3])
+ pix[p+2] += clampAddSubtractFull(pix[p-2], pix[top+2], pix[top-2])
+ pix[p+3] += clampAddSubtractFull(pix[p-1], pix[top+3], pix[top-1])
+
+ case 13: // ClampAddSubtractHalf(Average2(L, T), TL).
+ pix[p+0] += clampAddSubtractHalf(avg2(pix[p-4], pix[top+0]), pix[top-4])
+ pix[p+1] += clampAddSubtractHalf(avg2(pix[p-3], pix[top+1]), pix[top-3])
+ pix[p+2] += clampAddSubtractHalf(avg2(pix[p-2], pix[top+2]), pix[top-2])
+ pix[p+3] += clampAddSubtractHalf(avg2(pix[p-1], pix[top+3]), pix[top-1])
+ }
+ p, top = p+4, top+4
+ }
+ }
+ return pix
+}
+
+func inverseCrossColor(t *transform, pix []byte, h int32) []byte {
+ var greenToRed, greenToBlue, redToBlue int32
+ p, mask, tilesPerRow := int32(0), int32(1)<<t.bits-1, nTiles(t.oldWidth, t.bits)
+ for y := int32(0); y < h; y++ {
+ q := 4 * (y >> t.bits) * tilesPerRow
+ for x := int32(0); x < t.oldWidth; x++ {
+ if x&mask == 0 {
+ redToBlue = int32(int8(t.pix[q+0]))
+ greenToBlue = int32(int8(t.pix[q+1]))
+ greenToRed = int32(int8(t.pix[q+2]))
+ q += 4
+ }
+ red := pix[p+0]
+ green := pix[p+1]
+ blue := pix[p+2]
+ red += uint8(uint32(greenToRed*int32(int8(green))) >> 5)
+ blue += uint8(uint32(greenToBlue*int32(int8(green))) >> 5)
+ blue += uint8(uint32(redToBlue*int32(int8(red))) >> 5)
+ pix[p+0] = red
+ pix[p+2] = blue
+ p += 4
+ }
+ }
+ return pix
+}
+
+func inverseSubtractGreen(t *transform, pix []byte, h int32) []byte {
+ for p := 0; p < len(pix); p += 4 {
+ green := pix[p+1]
+ pix[p+0] += green
+ pix[p+2] += green
+ }
+ return pix
+}
+
+func inverseColorIndexing(t *transform, pix []byte, h int32) []byte {
+ if t.bits == 0 {
+ for p := 0; p < len(pix); p += 4 {
+ i := 4 * uint32(pix[p+1])
+ pix[p+0] = t.pix[i+0]
+ pix[p+1] = t.pix[i+1]
+ pix[p+2] = t.pix[i+2]
+ pix[p+3] = t.pix[i+3]
+ }
+ return pix
+ }
+
+ vMask, xMask, bitsPerPixel := uint32(0), int32(0), uint32(8>>t.bits)
+ switch t.bits {
+ case 1:
+ vMask, xMask = 0x0f, 0x01
+ case 2:
+ vMask, xMask = 0x03, 0x03
+ case 3:
+ vMask, xMask = 0x01, 0x07
+ }
+
+ d, p, v, dst := 0, 0, uint32(0), make([]byte, 4*t.oldWidth*h)
+ for y := int32(0); y < h; y++ {
+ for x := int32(0); x < t.oldWidth; x++ {
+ if x&xMask == 0 {
+ v = uint32(pix[p+1])
+ p += 4
+ }
+
+ i := 4 * (v & vMask)
+ dst[d+0] = t.pix[i+0]
+ dst[d+1] = t.pix[i+1]
+ dst[d+2] = t.pix[i+2]
+ dst[d+3] = t.pix[i+3]
+ d += 4
+
+ v >>= bitsPerPixel
+ }
+ }
+ return dst
+}
+
+func abs(x int32) int32 {
+ if x < 0 {
+ return -x
+ }
+ return x
+}
+
+func avg2(a, b uint8) uint8 {
+ return uint8((int32(a) + int32(b)) / 2)
+}
+
+func clampAddSubtractFull(a, b, c uint8) uint8 {
+ x := int32(a) + int32(b) - int32(c)
+ if x < 0 {
+ return 0
+ }
+ if x > 255 {
+ return 255
+ }
+ return uint8(x)
+}
+
+func clampAddSubtractHalf(a, b uint8) uint8 {
+ x := int32(a) + (int32(a)-int32(b))/2
+ if x < 0 {
+ return 0
+ }
+ if x > 255 {
+ return 255
+ }
+ return uint8(x)
+}
diff --git a/vendor/golang.org/x/image/webp/decode.go b/vendor/golang.org/x/image/webp/decode.go
new file mode 100644
index 0000000..111f358
--- /dev/null
+++ b/vendor/golang.org/x/image/webp/decode.go
@@ -0,0 +1,272 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.6
+
+package webp
+
+import (
+ "bytes"
+ "errors"
+ "image"
+ "image/color"
+ "io"
+
+ "golang.org/x/image/riff"
+ "golang.org/x/image/vp8"
+ "golang.org/x/image/vp8l"
+)
+
+var errInvalidFormat = errors.New("webp: invalid format")
+
+var (
+ fccALPH = riff.FourCC{'A', 'L', 'P', 'H'}
+ fccVP8 = riff.FourCC{'V', 'P', '8', ' '}
+ fccVP8L = riff.FourCC{'V', 'P', '8', 'L'}
+ fccVP8X = riff.FourCC{'V', 'P', '8', 'X'}
+ fccWEBP = riff.FourCC{'W', 'E', 'B', 'P'}
+)
+
+func decode(r io.Reader, configOnly bool) (image.Image, image.Config, error) {
+ formType, riffReader, err := riff.NewReader(r)
+ if err != nil {
+ return nil, image.Config{}, err
+ }
+ if formType != fccWEBP {
+ return nil, image.Config{}, errInvalidFormat
+ }
+
+ var (
+ alpha []byte
+ alphaStride int
+ wantAlpha bool
+ widthMinusOne uint32
+ heightMinusOne uint32
+ buf [10]byte
+ )
+ for {
+ chunkID, chunkLen, chunkData, err := riffReader.Next()
+ if err == io.EOF {
+ err = errInvalidFormat
+ }
+ if err != nil {
+ return nil, image.Config{}, err
+ }
+
+ switch chunkID {
+ case fccALPH:
+ if !wantAlpha {
+ return nil, image.Config{}, errInvalidFormat
+ }
+ wantAlpha = false
+ // Read the Pre-processing | Filter | Compression byte.
+ if _, err := io.ReadFull(chunkData, buf[:1]); err != nil {
+ if err == io.EOF {
+ err = errInvalidFormat
+ }
+ return nil, image.Config{}, err
+ }
+ alpha, alphaStride, err = readAlpha(chunkData, widthMinusOne, heightMinusOne, buf[0]&0x03)
+ if err != nil {
+ return nil, image.Config{}, err
+ }
+ unfilterAlpha(alpha, alphaStride, (buf[0]>>2)&0x03)
+
+ case fccVP8:
+ if wantAlpha || int32(chunkLen) < 0 {
+ return nil, image.Config{}, errInvalidFormat
+ }
+ d := vp8.NewDecoder()
+ d.Init(chunkData, int(chunkLen))
+ fh, err := d.DecodeFrameHeader()
+ if err != nil {
+ return nil, image.Config{}, err
+ }
+ if configOnly {
+ return nil, image.Config{
+ ColorModel: color.YCbCrModel,
+ Width: fh.Width,
+ Height: fh.Height,
+ }, nil
+ }
+ m, err := d.DecodeFrame()
+ if err != nil {
+ return nil, image.Config{}, err
+ }
+ if alpha != nil {
+ return &image.NYCbCrA{
+ YCbCr: *m,
+ A: alpha,
+ AStride: alphaStride,
+ }, image.Config{}, nil
+ }
+ return m, image.Config{}, nil
+
+ case fccVP8L:
+ if wantAlpha || alpha != nil {
+ return nil, image.Config{}, errInvalidFormat
+ }
+ if configOnly {
+ c, err := vp8l.DecodeConfig(chunkData)
+ return nil, c, err
+ }
+ m, err := vp8l.Decode(chunkData)
+ return m, image.Config{}, err
+
+ case fccVP8X:
+ if chunkLen != 10 {
+ return nil, image.Config{}, errInvalidFormat
+ }
+ if _, err := io.ReadFull(chunkData, buf[:10]); err != nil {
+ return nil, image.Config{}, err
+ }
+ const (
+ animationBit = 1 << 1
+ xmpMetadataBit = 1 << 2
+ exifMetadataBit = 1 << 3
+ alphaBit = 1 << 4
+ iccProfileBit = 1 << 5
+ )
+ if buf[0] != alphaBit {
+ return nil, image.Config{}, errors.New("webp: non-Alpha VP8X is not implemented")
+ }
+ widthMinusOne = uint32(buf[4]) | uint32(buf[5])<<8 | uint32(buf[6])<<16
+ heightMinusOne = uint32(buf[7]) | uint32(buf[8])<<8 | uint32(buf[9])<<16
+ if configOnly {
+ return nil, image.Config{
+ ColorModel: color.NYCbCrAModel,
+ Width: int(widthMinusOne) + 1,
+ Height: int(heightMinusOne) + 1,
+ }, nil
+ }
+ wantAlpha = true
+
+ default:
+ return nil, image.Config{}, errInvalidFormat
+ }
+ }
+}
+
+func readAlpha(chunkData io.Reader, widthMinusOne, heightMinusOne uint32, compression byte) (
+ alpha []byte, alphaStride int, err error) {
+
+ switch compression {
+ case 0:
+ w := int(widthMinusOne) + 1
+ h := int(heightMinusOne) + 1
+ alpha = make([]byte, w*h)
+ if _, err := io.ReadFull(chunkData, alpha); err != nil {
+ return nil, 0, err
+ }
+ return alpha, w, nil
+
+ case 1:
+ // Read the VP8L-compressed alpha values. First, synthesize a 5-byte VP8L header:
+ // a 1-byte magic number, a 14-bit widthMinusOne, a 14-bit heightMinusOne,
+ // a 1-bit (ignored, zero) alphaIsUsed and a 3-bit (zero) version.
+ // TODO(nigeltao): be more efficient than decoding an *image.NRGBA just to
+ // extract the green values to a separately allocated []byte. Fixing this
+ // will require changes to the vp8l package's API.
+ if widthMinusOne > 0x3fff || heightMinusOne > 0x3fff {
+ return nil, 0, errors.New("webp: invalid format")
+ }
+ alphaImage, err := vp8l.Decode(io.MultiReader(
+ bytes.NewReader([]byte{
+ 0x2f, // VP8L magic number.
+ uint8(widthMinusOne),
+ uint8(widthMinusOne>>8) | uint8(heightMinusOne<<6),
+ uint8(heightMinusOne >> 2),
+ uint8(heightMinusOne >> 10),
+ }),
+ chunkData,
+ ))
+ if err != nil {
+ return nil, 0, err
+ }
+ // The green values of the inner NRGBA image are the alpha values of the
+ // outer NYCbCrA image.
+ pix := alphaImage.(*image.NRGBA).Pix
+ alpha = make([]byte, len(pix)/4)
+ for i := range alpha {
+ alpha[i] = pix[4*i+1]
+ }
+ return alpha, int(widthMinusOne) + 1, nil
+ }
+ return nil, 0, errInvalidFormat
+}
+
+func unfilterAlpha(alpha []byte, alphaStride int, filter byte) {
+ if len(alpha) == 0 || alphaStride == 0 {
+ return
+ }
+ switch filter {
+ case 1: // Horizontal filter.
+ for i := 1; i < alphaStride; i++ {
+ alpha[i] += alpha[i-1]
+ }
+ for i := alphaStride; i < len(alpha); i += alphaStride {
+ // The first column is equivalent to the vertical filter.
+ alpha[i] += alpha[i-alphaStride]
+
+ for j := 1; j < alphaStride; j++ {
+ alpha[i+j] += alpha[i+j-1]
+ }
+ }
+
+ case 2: // Vertical filter.
+ // The first row is equivalent to the horizontal filter.
+ for i := 1; i < alphaStride; i++ {
+ alpha[i] += alpha[i-1]
+ }
+
+ for i := alphaStride; i < len(alpha); i++ {
+ alpha[i] += alpha[i-alphaStride]
+ }
+
+ case 3: // Gradient filter.
+ // The first row is equivalent to the horizontal filter.
+ for i := 1; i < alphaStride; i++ {
+ alpha[i] += alpha[i-1]
+ }
+
+ for i := alphaStride; i < len(alpha); i += alphaStride {
+ // The first column is equivalent to the vertical filter.
+ alpha[i] += alpha[i-alphaStride]
+
+ // The interior is predicted on the three top/left pixels.
+ for j := 1; j < alphaStride; j++ {
+ c := int(alpha[i+j-alphaStride-1])
+ b := int(alpha[i+j-alphaStride])
+ a := int(alpha[i+j-1])
+ x := a + b - c
+ if x < 0 {
+ x = 0
+ } else if x > 255 {
+ x = 255
+ }
+ alpha[i+j] += uint8(x)
+ }
+ }
+ }
+}
+
+// Decode reads a WEBP image from r and returns it as an image.Image.
+func Decode(r io.Reader) (image.Image, error) {
+ m, _, err := decode(r, false)
+ if err != nil {
+ return nil, err
+ }
+ return m, err
+}
+
+// DecodeConfig returns the color model and dimensions of a WEBP image without
+// decoding the entire image.
+func DecodeConfig(r io.Reader) (image.Config, error) {
+ _, c, err := decode(r, true)
+ return c, err
+}
+
+func init() {
+ image.RegisterFormat("webp", "RIFF????WEBPVP8", Decode, DecodeConfig)
+}
diff --git a/vendor/golang.org/x/image/webp/webp.go b/vendor/golang.org/x/image/webp/webp.go
new file mode 100644
index 0000000..850cdc8
--- /dev/null
+++ b/vendor/golang.org/x/image/webp/webp.go
@@ -0,0 +1,30 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package webp implements a decoder for WEBP images.
+//
+// WEBP is defined at:
+// https://developers.google.com/speed/webp/docs/riff_container
+//
+// It requires Go 1.6 or later.
+package webp // import "golang.org/x/image/webp"
+
+// This blank Go file, other than the package clause, exists so that this
+// package can be built for Go 1.5 and earlier. (The other files in this
+// package are all marked "+build go1.6" for the NYCbCrA types introduced in Go
+// 1.6). There is no functionality in a blank package, but some image
+// manipulation programs might still underscore import this package for the
+// side effect of registering the WEBP format with the standard library's
+// image.RegisterFormat and image.Decode functions. For example, that program
+// might contain:
+//
+// // Underscore imports to register some formats for image.Decode.
+// import _ "image/gif"
+// import _ "image/jpeg"
+// import _ "image/png"
+// import _ "golang.org/x/image/webp"
+//
+// Such a program will still compile for Go 1.5 (due to this placeholder Go
+// file). It will simply not be able to recognize and decode WEBP (but still
+// handle GIF, JPEG and PNG).
diff --git a/vendor/golang.org/x/net/AUTHORS b/vendor/golang.org/x/net/AUTHORS
new file mode 100644
index 0000000..15167cd
--- /dev/null
+++ b/vendor/golang.org/x/net/AUTHORS
@@ -0,0 +1,3 @@
+# This source code refers to The Go Authors for copyright purposes.
+# The master list of authors is in the main Go distribution,
+# visible at http://tip.golang.org/AUTHORS.
diff --git a/vendor/golang.org/x/net/CONTRIBUTORS b/vendor/golang.org/x/net/CONTRIBUTORS
new file mode 100644
index 0000000..1c4577e
--- /dev/null
+++ b/vendor/golang.org/x/net/CONTRIBUTORS
@@ -0,0 +1,3 @@
+# This source code was written by the Go contributors.
+# The master list of contributors is in the main Go distribution,
+# visible at http://tip.golang.org/CONTRIBUTORS.
diff --git a/vendor/golang.org/x/net/LICENSE b/vendor/golang.org/x/net/LICENSE
new file mode 100644
index 0000000..6a66aea
--- /dev/null
+++ b/vendor/golang.org/x/net/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/golang.org/x/net/PATENTS b/vendor/golang.org/x/net/PATENTS
new file mode 100644
index 0000000..7330990
--- /dev/null
+++ b/vendor/golang.org/x/net/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go. This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation. If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
diff --git a/vendor/golang.org/x/net/html/atom/atom.go b/vendor/golang.org/x/net/html/atom/atom.go
new file mode 100644
index 0000000..cd0a8ac
--- /dev/null
+++ b/vendor/golang.org/x/net/html/atom/atom.go
@@ -0,0 +1,78 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package atom provides integer codes (also known as atoms) for a fixed set of
+// frequently occurring HTML strings: tag names and attribute keys such as "p"
+// and "id".
+//
+// Sharing an atom's name between all elements with the same tag can result in
+// fewer string allocations when tokenizing and parsing HTML. Integer
+// comparisons are also generally faster than string comparisons.
+//
+// The value of an atom's particular code is not guaranteed to stay the same
+// between versions of this package. Neither is any ordering guaranteed:
+// whether atom.H1 < atom.H2 may also change. The codes are not guaranteed to
+// be dense. The only guarantees are that e.g. looking up "div" will yield
+// atom.Div, calling atom.Div.String will return "div", and atom.Div != 0.
+package atom // import "golang.org/x/net/html/atom"
+
+// Atom is an integer code for a string. The zero value maps to "".
+type Atom uint32
+
+// String returns the atom's name.
+func (a Atom) String() string {
+ start := uint32(a >> 8)
+ n := uint32(a & 0xff)
+ if start+n > uint32(len(atomText)) {
+ return ""
+ }
+ return atomText[start : start+n]
+}
+
+func (a Atom) string() string {
+ return atomText[a>>8 : a>>8+a&0xff]
+}
+
+// fnv computes the FNV hash with an arbitrary starting value h.
+func fnv(h uint32, s []byte) uint32 {
+ for i := range s {
+ h ^= uint32(s[i])
+ h *= 16777619
+ }
+ return h
+}
+
+func match(s string, t []byte) bool {
+ for i, c := range t {
+ if s[i] != c {
+ return false
+ }
+ }
+ return true
+}
+
+// Lookup returns the atom whose name is s. It returns zero if there is no
+// such atom. The lookup is case sensitive.
+func Lookup(s []byte) Atom {
+ if len(s) == 0 || len(s) > maxAtomLen {
+ return 0
+ }
+ h := fnv(hash0, s)
+ if a := table[h&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) {
+ return a
+ }
+ if a := table[(h>>16)&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) {
+ return a
+ }
+ return 0
+}
+
+// String returns a string whose contents are equal to s. In that sense, it is
+// equivalent to string(s) but may be more efficient.
+func String(s []byte) string {
+ if a := Lookup(s); a != 0 {
+ return a.String()
+ }
+ return string(s)
+}
diff --git a/vendor/golang.org/x/net/html/atom/gen.go b/vendor/golang.org/x/net/html/atom/gen.go
new file mode 100644
index 0000000..5d05278
--- /dev/null
+++ b/vendor/golang.org/x/net/html/atom/gen.go
@@ -0,0 +1,712 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+//go:generate go run gen.go
+//go:generate go run gen.go -test
+
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "go/format"
+ "io/ioutil"
+ "math/rand"
+ "os"
+ "sort"
+ "strings"
+)
+
+// identifier converts s to a Go exported identifier.
+// It converts "div" to "Div" and "accept-charset" to "AcceptCharset".
+func identifier(s string) string {
+ b := make([]byte, 0, len(s))
+ cap := true
+ for _, c := range s {
+ if c == '-' {
+ cap = true
+ continue
+ }
+ if cap && 'a' <= c && c <= 'z' {
+ c -= 'a' - 'A'
+ }
+ cap = false
+ b = append(b, byte(c))
+ }
+ return string(b)
+}
+
+var test = flag.Bool("test", false, "generate table_test.go")
+
+func genFile(name string, buf *bytes.Buffer) {
+ b, err := format.Source(buf.Bytes())
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ if err := ioutil.WriteFile(name, b, 0644); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}
+
+func main() {
+ flag.Parse()
+
+ var all []string
+ all = append(all, elements...)
+ all = append(all, attributes...)
+ all = append(all, eventHandlers...)
+ all = append(all, extra...)
+ sort.Strings(all)
+
+ // uniq - lists have dups
+ w := 0
+ for _, s := range all {
+ if w == 0 || all[w-1] != s {
+ all[w] = s
+ w++
+ }
+ }
+ all = all[:w]
+
+ if *test {
+ var buf bytes.Buffer
+ fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n")
+ fmt.Fprintln(&buf, "//go:generate go run gen.go -test\n")
+ fmt.Fprintln(&buf, "package atom\n")
+ fmt.Fprintln(&buf, "var testAtomList = []string{")
+ for _, s := range all {
+ fmt.Fprintf(&buf, "\t%q,\n", s)
+ }
+ fmt.Fprintln(&buf, "}")
+
+ genFile("table_test.go", &buf)
+ return
+ }
+
+ // Find hash that minimizes table size.
+ var best *table
+ for i := 0; i < 1000000; i++ {
+ if best != nil && 1<<(best.k-1) < len(all) {
+ break
+ }
+ h := rand.Uint32()
+ for k := uint(0); k <= 16; k++ {
+ if best != nil && k >= best.k {
+ break
+ }
+ var t table
+ if t.init(h, k, all) {
+ best = &t
+ break
+ }
+ }
+ }
+ if best == nil {
+ fmt.Fprintf(os.Stderr, "failed to construct string table\n")
+ os.Exit(1)
+ }
+
+ // Lay out strings, using overlaps when possible.
+ layout := append([]string{}, all...)
+
+ // Remove strings that are substrings of other strings
+ for changed := true; changed; {
+ changed = false
+ for i, s := range layout {
+ if s == "" {
+ continue
+ }
+ for j, t := range layout {
+ if i != j && t != "" && strings.Contains(s, t) {
+ changed = true
+ layout[j] = ""
+ }
+ }
+ }
+ }
+
+ // Join strings where one suffix matches another prefix.
+ for {
+ // Find best i, j, k such that layout[i][len-k:] == layout[j][:k],
+ // maximizing overlap length k.
+ besti := -1
+ bestj := -1
+ bestk := 0
+ for i, s := range layout {
+ if s == "" {
+ continue
+ }
+ for j, t := range layout {
+ if i == j {
+ continue
+ }
+ for k := bestk + 1; k <= len(s) && k <= len(t); k++ {
+ if s[len(s)-k:] == t[:k] {
+ besti = i
+ bestj = j
+ bestk = k
+ }
+ }
+ }
+ }
+ if bestk > 0 {
+ layout[besti] += layout[bestj][bestk:]
+ layout[bestj] = ""
+ continue
+ }
+ break
+ }
+
+ text := strings.Join(layout, "")
+
+ atom := map[string]uint32{}
+ for _, s := range all {
+ off := strings.Index(text, s)
+ if off < 0 {
+ panic("lost string " + s)
+ }
+ atom[s] = uint32(off<<8 | len(s))
+ }
+
+ var buf bytes.Buffer
+ // Generate the Go code.
+ fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n")
+ fmt.Fprintln(&buf, "//go:generate go run gen.go\n")
+ fmt.Fprintln(&buf, "package atom\n\nconst (")
+
+ // compute max len
+ maxLen := 0
+ for _, s := range all {
+ if maxLen < len(s) {
+ maxLen = len(s)
+ }
+ fmt.Fprintf(&buf, "\t%s Atom = %#x\n", identifier(s), atom[s])
+ }
+ fmt.Fprintln(&buf, ")\n")
+
+ fmt.Fprintf(&buf, "const hash0 = %#x\n\n", best.h0)
+ fmt.Fprintf(&buf, "const maxAtomLen = %d\n\n", maxLen)
+
+ fmt.Fprintf(&buf, "var table = [1<<%d]Atom{\n", best.k)
+ for i, s := range best.tab {
+ if s == "" {
+ continue
+ }
+ fmt.Fprintf(&buf, "\t%#x: %#x, // %s\n", i, atom[s], s)
+ }
+ fmt.Fprintf(&buf, "}\n")
+ datasize := (1 << best.k) * 4
+
+ fmt.Fprintln(&buf, "const atomText =")
+ textsize := len(text)
+ for len(text) > 60 {
+ fmt.Fprintf(&buf, "\t%q +\n", text[:60])
+ text = text[60:]
+ }
+ fmt.Fprintf(&buf, "\t%q\n\n", text)
+
+ genFile("table.go", &buf)
+
+ fmt.Fprintf(os.Stdout, "%d atoms; %d string bytes + %d tables = %d total data\n", len(all), textsize, datasize, textsize+datasize)
+}
+
+type byLen []string
+
+func (x byLen) Less(i, j int) bool { return len(x[i]) > len(x[j]) }
+func (x byLen) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+func (x byLen) Len() int { return len(x) }
+
+// fnv computes the FNV hash with an arbitrary starting value h.
+func fnv(h uint32, s string) uint32 {
+ for i := 0; i < len(s); i++ {
+ h ^= uint32(s[i])
+ h *= 16777619
+ }
+ return h
+}
+
+// A table represents an attempt at constructing the lookup table.
+// The lookup table uses cuckoo hashing, meaning that each string
+// can be found in one of two positions.
+type table struct {
+ h0 uint32
+ k uint
+ mask uint32
+ tab []string
+}
+
+// hash returns the two hashes for s.
+func (t *table) hash(s string) (h1, h2 uint32) {
+ h := fnv(t.h0, s)
+ h1 = h & t.mask
+ h2 = (h >> 16) & t.mask
+ return
+}
+
+// init initializes the table with the given parameters.
+// h0 is the initial hash value,
+// k is the number of bits of hash value to use, and
+// x is the list of strings to store in the table.
+// init returns false if the table cannot be constructed.
+func (t *table) init(h0 uint32, k uint, x []string) bool {
+ t.h0 = h0
+ t.k = k
+ t.tab = make([]string, 1<<k)
+ t.mask = 1<<k - 1
+ for _, s := range x {
+ if !t.insert(s) {
+ return false
+ }
+ }
+ return true
+}
+
+// insert inserts s in the table.
+func (t *table) insert(s string) bool {
+ h1, h2 := t.hash(s)
+ if t.tab[h1] == "" {
+ t.tab[h1] = s
+ return true
+ }
+ if t.tab[h2] == "" {
+ t.tab[h2] = s
+ return true
+ }
+ if t.push(h1, 0) {
+ t.tab[h1] = s
+ return true
+ }
+ if t.push(h2, 0) {
+ t.tab[h2] = s
+ return true
+ }
+ return false
+}
+
+// push attempts to push aside the entry in slot i.
+func (t *table) push(i uint32, depth int) bool {
+ if depth > len(t.tab) {
+ return false
+ }
+ s := t.tab[i]
+ h1, h2 := t.hash(s)
+ j := h1 + h2 - i
+ if t.tab[j] != "" && !t.push(j, depth+1) {
+ return false
+ }
+ t.tab[j] = s
+ return true
+}
+
+// The lists of element names and attribute keys were taken from
+// https://html.spec.whatwg.org/multipage/indices.html#index
+// as of the "HTML Living Standard - Last Updated 16 April 2018" version.
+
+// "command", "keygen" and "menuitem" have been removed from the spec,
+// but are kept here for backwards compatibility.
+var elements = []string{
+ "a",
+ "abbr",
+ "address",
+ "area",
+ "article",
+ "aside",
+ "audio",
+ "b",
+ "base",
+ "bdi",
+ "bdo",
+ "blockquote",
+ "body",
+ "br",
+ "button",
+ "canvas",
+ "caption",
+ "cite",
+ "code",
+ "col",
+ "colgroup",
+ "command",
+ "data",
+ "datalist",
+ "dd",
+ "del",
+ "details",
+ "dfn",
+ "dialog",
+ "div",
+ "dl",
+ "dt",
+ "em",
+ "embed",
+ "fieldset",
+ "figcaption",
+ "figure",
+ "footer",
+ "form",
+ "h1",
+ "h2",
+ "h3",
+ "h4",
+ "h5",
+ "h6",
+ "head",
+ "header",
+ "hgroup",
+ "hr",
+ "html",
+ "i",
+ "iframe",
+ "img",
+ "input",
+ "ins",
+ "kbd",
+ "keygen",
+ "label",
+ "legend",
+ "li",
+ "link",
+ "main",
+ "map",
+ "mark",
+ "menu",
+ "menuitem",
+ "meta",
+ "meter",
+ "nav",
+ "noscript",
+ "object",
+ "ol",
+ "optgroup",
+ "option",
+ "output",
+ "p",
+ "param",
+ "picture",
+ "pre",
+ "progress",
+ "q",
+ "rp",
+ "rt",
+ "ruby",
+ "s",
+ "samp",
+ "script",
+ "section",
+ "select",
+ "slot",
+ "small",
+ "source",
+ "span",
+ "strong",
+ "style",
+ "sub",
+ "summary",
+ "sup",
+ "table",
+ "tbody",
+ "td",
+ "template",
+ "textarea",
+ "tfoot",
+ "th",
+ "thead",
+ "time",
+ "title",
+ "tr",
+ "track",
+ "u",
+ "ul",
+ "var",
+ "video",
+ "wbr",
+}
+
+// https://html.spec.whatwg.org/multipage/indices.html#attributes-3
+//
+// "challenge", "command", "contextmenu", "dropzone", "icon", "keytype", "mediagroup",
+// "radiogroup", "spellcheck", "scoped", "seamless", "sortable" and "sorted" have been removed from the spec,
+// but are kept here for backwards compatibility.
+var attributes = []string{
+ "abbr",
+ "accept",
+ "accept-charset",
+ "accesskey",
+ "action",
+ "allowfullscreen",
+ "allowpaymentrequest",
+ "allowusermedia",
+ "alt",
+ "as",
+ "async",
+ "autocomplete",
+ "autofocus",
+ "autoplay",
+ "challenge",
+ "charset",
+ "checked",
+ "cite",
+ "class",
+ "color",
+ "cols",
+ "colspan",
+ "command",
+ "content",
+ "contenteditable",
+ "contextmenu",
+ "controls",
+ "coords",
+ "crossorigin",
+ "data",
+ "datetime",
+ "default",
+ "defer",
+ "dir",
+ "dirname",
+ "disabled",
+ "download",
+ "draggable",
+ "dropzone",
+ "enctype",
+ "for",
+ "form",
+ "formaction",
+ "formenctype",
+ "formmethod",
+ "formnovalidate",
+ "formtarget",
+ "headers",
+ "height",
+ "hidden",
+ "high",
+ "href",
+ "hreflang",
+ "http-equiv",
+ "icon",
+ "id",
+ "inputmode",
+ "integrity",
+ "is",
+ "ismap",
+ "itemid",
+ "itemprop",
+ "itemref",
+ "itemscope",
+ "itemtype",
+ "keytype",
+ "kind",
+ "label",
+ "lang",
+ "list",
+ "loop",
+ "low",
+ "manifest",
+ "max",
+ "maxlength",
+ "media",
+ "mediagroup",
+ "method",
+ "min",
+ "minlength",
+ "multiple",
+ "muted",
+ "name",
+ "nomodule",
+ "nonce",
+ "novalidate",
+ "open",
+ "optimum",
+ "pattern",
+ "ping",
+ "placeholder",
+ "playsinline",
+ "poster",
+ "preload",
+ "radiogroup",
+ "readonly",
+ "referrerpolicy",
+ "rel",
+ "required",
+ "reversed",
+ "rows",
+ "rowspan",
+ "sandbox",
+ "spellcheck",
+ "scope",
+ "scoped",
+ "seamless",
+ "selected",
+ "shape",
+ "size",
+ "sizes",
+ "sortable",
+ "sorted",
+ "slot",
+ "span",
+ "spellcheck",
+ "src",
+ "srcdoc",
+ "srclang",
+ "srcset",
+ "start",
+ "step",
+ "style",
+ "tabindex",
+ "target",
+ "title",
+ "translate",
+ "type",
+ "typemustmatch",
+ "updateviacache",
+ "usemap",
+ "value",
+ "width",
+ "workertype",
+ "wrap",
+}
+
+// "onautocomplete", "onautocompleteerror", "onmousewheel",
+// "onshow" and "onsort" have been removed from the spec,
+// but are kept here for backwards compatibility.
+var eventHandlers = []string{
+ "onabort",
+ "onautocomplete",
+ "onautocompleteerror",
+ "onauxclick",
+ "onafterprint",
+ "onbeforeprint",
+ "onbeforeunload",
+ "onblur",
+ "oncancel",
+ "oncanplay",
+ "oncanplaythrough",
+ "onchange",
+ "onclick",
+ "onclose",
+ "oncontextmenu",
+ "oncopy",
+ "oncuechange",
+ "oncut",
+ "ondblclick",
+ "ondrag",
+ "ondragend",
+ "ondragenter",
+ "ondragexit",
+ "ondragleave",
+ "ondragover",
+ "ondragstart",
+ "ondrop",
+ "ondurationchange",
+ "onemptied",
+ "onended",
+ "onerror",
+ "onfocus",
+ "onhashchange",
+ "oninput",
+ "oninvalid",
+ "onkeydown",
+ "onkeypress",
+ "onkeyup",
+ "onlanguagechange",
+ "onload",
+ "onloadeddata",
+ "onloadedmetadata",
+ "onloadend",
+ "onloadstart",
+ "onmessage",
+ "onmessageerror",
+ "onmousedown",
+ "onmouseenter",
+ "onmouseleave",
+ "onmousemove",
+ "onmouseout",
+ "onmouseover",
+ "onmouseup",
+ "onmousewheel",
+ "onwheel",
+ "onoffline",
+ "ononline",
+ "onpagehide",
+ "onpageshow",
+ "onpaste",
+ "onpause",
+ "onplay",
+ "onplaying",
+ "onpopstate",
+ "onprogress",
+ "onratechange",
+ "onreset",
+ "onresize",
+ "onrejectionhandled",
+ "onscroll",
+ "onsecuritypolicyviolation",
+ "onseeked",
+ "onseeking",
+ "onselect",
+ "onshow",
+ "onsort",
+ "onstalled",
+ "onstorage",
+ "onsubmit",
+ "onsuspend",
+ "ontimeupdate",
+ "ontoggle",
+ "onunhandledrejection",
+ "onunload",
+ "onvolumechange",
+ "onwaiting",
+}
+
+// extra are ad-hoc values not covered by any of the lists above.
+var extra = []string{
+ "acronym",
+ "align",
+ "annotation",
+ "annotation-xml",
+ "applet",
+ "basefont",
+ "bgsound",
+ "big",
+ "blink",
+ "center",
+ "color",
+ "desc",
+ "face",
+ "font",
+ "foreignObject", // HTML is case-insensitive, but SVG-embedded-in-HTML is case-sensitive.
+ "foreignobject",
+ "frame",
+ "frameset",
+ "image",
+ "isindex",
+ "listing",
+ "malignmark",
+ "marquee",
+ "math",
+ "mglyph",
+ "mi",
+ "mn",
+ "mo",
+ "ms",
+ "mtext",
+ "nobr",
+ "noembed",
+ "noframes",
+ "plaintext",
+ "prompt",
+ "public",
+ "rb",
+ "rtc",
+ "spacer",
+ "strike",
+ "svg",
+ "system",
+ "tt",
+ "xmp",
+}
diff --git a/vendor/golang.org/x/net/html/atom/table.go b/vendor/golang.org/x/net/html/atom/table.go
new file mode 100644
index 0000000..2a93886
--- /dev/null
+++ b/vendor/golang.org/x/net/html/atom/table.go
@@ -0,0 +1,783 @@
+// Code generated by go generate gen.go; DO NOT EDIT.
+
+//go:generate go run gen.go
+
+package atom
+
+const (
+ A Atom = 0x1
+ Abbr Atom = 0x4
+ Accept Atom = 0x1a06
+ AcceptCharset Atom = 0x1a0e
+ Accesskey Atom = 0x2c09
+ Acronym Atom = 0xaa07
+ Action Atom = 0x27206
+ Address Atom = 0x6f307
+ Align Atom = 0xb105
+ Allowfullscreen Atom = 0x2080f
+ Allowpaymentrequest Atom = 0xc113
+ Allowusermedia Atom = 0xdd0e
+ Alt Atom = 0xf303
+ Annotation Atom = 0x1c90a
+ AnnotationXml Atom = 0x1c90e
+ Applet Atom = 0x31906
+ Area Atom = 0x35604
+ Article Atom = 0x3fc07
+ As Atom = 0x3c02
+ Aside Atom = 0x10705
+ Async Atom = 0xff05
+ Audio Atom = 0x11505
+ Autocomplete Atom = 0x2780c
+ Autofocus Atom = 0x12109
+ Autoplay Atom = 0x13c08
+ B Atom = 0x101
+ Base Atom = 0x3b04
+ Basefont Atom = 0x3b08
+ Bdi Atom = 0xba03
+ Bdo Atom = 0x14b03
+ Bgsound Atom = 0x15e07
+ Big Atom = 0x17003
+ Blink Atom = 0x17305
+ Blockquote Atom = 0x1870a
+ Body Atom = 0x2804
+ Br Atom = 0x202
+ Button Atom = 0x19106
+ Canvas Atom = 0x10306
+ Caption Atom = 0x23107
+ Center Atom = 0x22006
+ Challenge Atom = 0x29b09
+ Charset Atom = 0x2107
+ Checked Atom = 0x47907
+ Cite Atom = 0x19c04
+ Class Atom = 0x56405
+ Code Atom = 0x5c504
+ Col Atom = 0x1ab03
+ Colgroup Atom = 0x1ab08
+ Color Atom = 0x1bf05
+ Cols Atom = 0x1c404
+ Colspan Atom = 0x1c407
+ Command Atom = 0x1d707
+ Content Atom = 0x58b07
+ Contenteditable Atom = 0x58b0f
+ Contextmenu Atom = 0x3800b
+ Controls Atom = 0x1de08
+ Coords Atom = 0x1ea06
+ Crossorigin Atom = 0x1fb0b
+ Data Atom = 0x4a504
+ Datalist Atom = 0x4a508
+ Datetime Atom = 0x2b808
+ Dd Atom = 0x2d702
+ Default Atom = 0x10a07
+ Defer Atom = 0x5c705
+ Del Atom = 0x45203
+ Desc Atom = 0x56104
+ Details Atom = 0x7207
+ Dfn Atom = 0x8703
+ Dialog Atom = 0xbb06
+ Dir Atom = 0x9303
+ Dirname Atom = 0x9307
+ Disabled Atom = 0x16408
+ Div Atom = 0x16b03
+ Dl Atom = 0x5e602
+ Download Atom = 0x46308
+ Draggable Atom = 0x17a09
+ Dropzone Atom = 0x40508
+ Dt Atom = 0x64b02
+ Em Atom = 0x6e02
+ Embed Atom = 0x6e05
+ Enctype Atom = 0x28d07
+ Face Atom = 0x21e04
+ Fieldset Atom = 0x22608
+ Figcaption Atom = 0x22e0a
+ Figure Atom = 0x24806
+ Font Atom = 0x3f04
+ Footer Atom = 0xf606
+ For Atom = 0x25403
+ ForeignObject Atom = 0x2540d
+ Foreignobject Atom = 0x2610d
+ Form Atom = 0x26e04
+ Formaction Atom = 0x26e0a
+ Formenctype Atom = 0x2890b
+ Formmethod Atom = 0x2a40a
+ Formnovalidate Atom = 0x2ae0e
+ Formtarget Atom = 0x2c00a
+ Frame Atom = 0x8b05
+ Frameset Atom = 0x8b08
+ H1 Atom = 0x15c02
+ H2 Atom = 0x2de02
+ H3 Atom = 0x30d02
+ H4 Atom = 0x34502
+ H5 Atom = 0x34f02
+ H6 Atom = 0x64d02
+ Head Atom = 0x33104
+ Header Atom = 0x33106
+ Headers Atom = 0x33107
+ Height Atom = 0x5206
+ Hgroup Atom = 0x2ca06
+ Hidden Atom = 0x2d506
+ High Atom = 0x2db04
+ Hr Atom = 0x15702
+ Href Atom = 0x2e004
+ Hreflang Atom = 0x2e008
+ Html Atom = 0x5604
+ HttpEquiv Atom = 0x2e80a
+ I Atom = 0x601
+ Icon Atom = 0x58a04
+ Id Atom = 0x10902
+ Iframe Atom = 0x2fc06
+ Image Atom = 0x30205
+ Img Atom = 0x30703
+ Input Atom = 0x44b05
+ Inputmode Atom = 0x44b09
+ Ins Atom = 0x20403
+ Integrity Atom = 0x23f09
+ Is Atom = 0x16502
+ Isindex Atom = 0x30f07
+ Ismap Atom = 0x31605
+ Itemid Atom = 0x38b06
+ Itemprop Atom = 0x19d08
+ Itemref Atom = 0x3cd07
+ Itemscope Atom = 0x67109
+ Itemtype Atom = 0x31f08
+ Kbd Atom = 0xb903
+ Keygen Atom = 0x3206
+ Keytype Atom = 0xd607
+ Kind Atom = 0x17704
+ Label Atom = 0x5905
+ Lang Atom = 0x2e404
+ Legend Atom = 0x18106
+ Li Atom = 0xb202
+ Link Atom = 0x17404
+ List Atom = 0x4a904
+ Listing Atom = 0x4a907
+ Loop Atom = 0x5d04
+ Low Atom = 0xc303
+ Main Atom = 0x1004
+ Malignmark Atom = 0xb00a
+ Manifest Atom = 0x6d708
+ Map Atom = 0x31803
+ Mark Atom = 0xb604
+ Marquee Atom = 0x32707
+ Math Atom = 0x32e04
+ Max Atom = 0x33d03
+ Maxlength Atom = 0x33d09
+ Media Atom = 0xe605
+ Mediagroup Atom = 0xe60a
+ Menu Atom = 0x38704
+ Menuitem Atom = 0x38708
+ Meta Atom = 0x4b804
+ Meter Atom = 0x9805
+ Method Atom = 0x2a806
+ Mglyph Atom = 0x30806
+ Mi Atom = 0x34702
+ Min Atom = 0x34703
+ Minlength Atom = 0x34709
+ Mn Atom = 0x2b102
+ Mo Atom = 0xa402
+ Ms Atom = 0x67402
+ Mtext Atom = 0x35105
+ Multiple Atom = 0x35f08
+ Muted Atom = 0x36705
+ Name Atom = 0x9604
+ Nav Atom = 0x1303
+ Nobr Atom = 0x3704
+ Noembed Atom = 0x6c07
+ Noframes Atom = 0x8908
+ Nomodule Atom = 0xa208
+ Nonce Atom = 0x1a605
+ Noscript Atom = 0x21608
+ Novalidate Atom = 0x2b20a
+ Object Atom = 0x26806
+ Ol Atom = 0x13702
+ Onabort Atom = 0x19507
+ Onafterprint Atom = 0x2360c
+ Onautocomplete Atom = 0x2760e
+ Onautocompleteerror Atom = 0x27613
+ Onauxclick Atom = 0x61f0a
+ Onbeforeprint Atom = 0x69e0d
+ Onbeforeunload Atom = 0x6e70e
+ Onblur Atom = 0x56d06
+ Oncancel Atom = 0x11908
+ Oncanplay Atom = 0x14d09
+ Oncanplaythrough Atom = 0x14d10
+ Onchange Atom = 0x41b08
+ Onclick Atom = 0x2f507
+ Onclose Atom = 0x36c07
+ Oncontextmenu Atom = 0x37e0d
+ Oncopy Atom = 0x39106
+ Oncuechange Atom = 0x3970b
+ Oncut Atom = 0x3a205
+ Ondblclick Atom = 0x3a70a
+ Ondrag Atom = 0x3b106
+ Ondragend Atom = 0x3b109
+ Ondragenter Atom = 0x3ba0b
+ Ondragexit Atom = 0x3c50a
+ Ondragleave Atom = 0x3df0b
+ Ondragover Atom = 0x3ea0a
+ Ondragstart Atom = 0x3f40b
+ Ondrop Atom = 0x40306
+ Ondurationchange Atom = 0x41310
+ Onemptied Atom = 0x40a09
+ Onended Atom = 0x42307
+ Onerror Atom = 0x42a07
+ Onfocus Atom = 0x43107
+ Onhashchange Atom = 0x43d0c
+ Oninput Atom = 0x44907
+ Oninvalid Atom = 0x45509
+ Onkeydown Atom = 0x45e09
+ Onkeypress Atom = 0x46b0a
+ Onkeyup Atom = 0x48007
+ Onlanguagechange Atom = 0x48d10
+ Onload Atom = 0x49d06
+ Onloadeddata Atom = 0x49d0c
+ Onloadedmetadata Atom = 0x4b010
+ Onloadend Atom = 0x4c609
+ Onloadstart Atom = 0x4cf0b
+ Onmessage Atom = 0x4da09
+ Onmessageerror Atom = 0x4da0e
+ Onmousedown Atom = 0x4e80b
+ Onmouseenter Atom = 0x4f30c
+ Onmouseleave Atom = 0x4ff0c
+ Onmousemove Atom = 0x50b0b
+ Onmouseout Atom = 0x5160a
+ Onmouseover Atom = 0x5230b
+ Onmouseup Atom = 0x52e09
+ Onmousewheel Atom = 0x53c0c
+ Onoffline Atom = 0x54809
+ Ononline Atom = 0x55108
+ Onpagehide Atom = 0x5590a
+ Onpageshow Atom = 0x5730a
+ Onpaste Atom = 0x57f07
+ Onpause Atom = 0x59a07
+ Onplay Atom = 0x5a406
+ Onplaying Atom = 0x5a409
+ Onpopstate Atom = 0x5ad0a
+ Onprogress Atom = 0x5b70a
+ Onratechange Atom = 0x5cc0c
+ Onrejectionhandled Atom = 0x5d812
+ Onreset Atom = 0x5ea07
+ Onresize Atom = 0x5f108
+ Onscroll Atom = 0x60008
+ Onsecuritypolicyviolation Atom = 0x60819
+ Onseeked Atom = 0x62908
+ Onseeking Atom = 0x63109
+ Onselect Atom = 0x63a08
+ Onshow Atom = 0x64406
+ Onsort Atom = 0x64f06
+ Onstalled Atom = 0x65909
+ Onstorage Atom = 0x66209
+ Onsubmit Atom = 0x66b08
+ Onsuspend Atom = 0x67b09
+ Ontimeupdate Atom = 0x400c
+ Ontoggle Atom = 0x68408
+ Onunhandledrejection Atom = 0x68c14
+ Onunload Atom = 0x6ab08
+ Onvolumechange Atom = 0x6b30e
+ Onwaiting Atom = 0x6c109
+ Onwheel Atom = 0x6ca07
+ Open Atom = 0x1a304
+ Optgroup Atom = 0x5f08
+ Optimum Atom = 0x6d107
+ Option Atom = 0x6e306
+ Output Atom = 0x51d06
+ P Atom = 0xc01
+ Param Atom = 0xc05
+ Pattern Atom = 0x6607
+ Picture Atom = 0x7b07
+ Ping Atom = 0xef04
+ Placeholder Atom = 0x1310b
+ Plaintext Atom = 0x1b209
+ Playsinline Atom = 0x1400b
+ Poster Atom = 0x2cf06
+ Pre Atom = 0x47003
+ Preload Atom = 0x48607
+ Progress Atom = 0x5b908
+ Prompt Atom = 0x53606
+ Public Atom = 0x58606
+ Q Atom = 0xcf01
+ Radiogroup Atom = 0x30a
+ Rb Atom = 0x3a02
+ Readonly Atom = 0x35708
+ Referrerpolicy Atom = 0x3d10e
+ Rel Atom = 0x48703
+ Required Atom = 0x24c08
+ Reversed Atom = 0x8008
+ Rows Atom = 0x9c04
+ Rowspan Atom = 0x9c07
+ Rp Atom = 0x23c02
+ Rt Atom = 0x19a02
+ Rtc Atom = 0x19a03
+ Ruby Atom = 0xfb04
+ S Atom = 0x2501
+ Samp Atom = 0x7804
+ Sandbox Atom = 0x12907
+ Scope Atom = 0x67505
+ Scoped Atom = 0x67506
+ Script Atom = 0x21806
+ Seamless Atom = 0x37108
+ Section Atom = 0x56807
+ Select Atom = 0x63c06
+ Selected Atom = 0x63c08
+ Shape Atom = 0x1e505
+ Size Atom = 0x5f504
+ Sizes Atom = 0x5f505
+ Slot Atom = 0x1ef04
+ Small Atom = 0x20605
+ Sortable Atom = 0x65108
+ Sorted Atom = 0x33706
+ Source Atom = 0x37806
+ Spacer Atom = 0x43706
+ Span Atom = 0x9f04
+ Spellcheck Atom = 0x4740a
+ Src Atom = 0x5c003
+ Srcdoc Atom = 0x5c006
+ Srclang Atom = 0x5f907
+ Srcset Atom = 0x6f906
+ Start Atom = 0x3fa05
+ Step Atom = 0x58304
+ Strike Atom = 0xd206
+ Strong Atom = 0x6dd06
+ Style Atom = 0x6ff05
+ Sub Atom = 0x66d03
+ Summary Atom = 0x70407
+ Sup Atom = 0x70b03
+ Svg Atom = 0x70e03
+ System Atom = 0x71106
+ Tabindex Atom = 0x4be08
+ Table Atom = 0x59505
+ Target Atom = 0x2c406
+ Tbody Atom = 0x2705
+ Td Atom = 0x9202
+ Template Atom = 0x71408
+ Textarea Atom = 0x35208
+ Tfoot Atom = 0xf505
+ Th Atom = 0x15602
+ Thead Atom = 0x33005
+ Time Atom = 0x4204
+ Title Atom = 0x11005
+ Tr Atom = 0xcc02
+ Track Atom = 0x1ba05
+ Translate Atom = 0x1f209
+ Tt Atom = 0x6802
+ Type Atom = 0xd904
+ Typemustmatch Atom = 0x2900d
+ U Atom = 0xb01
+ Ul Atom = 0xa702
+ Updateviacache Atom = 0x460e
+ Usemap Atom = 0x59e06
+ Value Atom = 0x1505
+ Var Atom = 0x16d03
+ Video Atom = 0x2f105
+ Wbr Atom = 0x57c03
+ Width Atom = 0x64905
+ Workertype Atom = 0x71c0a
+ Wrap Atom = 0x72604
+ Xmp Atom = 0x12f03
+)
+
+const hash0 = 0x81cdf10e
+
+const maxAtomLen = 25
+
+var table = [1 << 9]Atom{
+ 0x1: 0xe60a, // mediagroup
+ 0x2: 0x2e404, // lang
+ 0x4: 0x2c09, // accesskey
+ 0x5: 0x8b08, // frameset
+ 0x7: 0x63a08, // onselect
+ 0x8: 0x71106, // system
+ 0xa: 0x64905, // width
+ 0xc: 0x2890b, // formenctype
+ 0xd: 0x13702, // ol
+ 0xe: 0x3970b, // oncuechange
+ 0x10: 0x14b03, // bdo
+ 0x11: 0x11505, // audio
+ 0x12: 0x17a09, // draggable
+ 0x14: 0x2f105, // video
+ 0x15: 0x2b102, // mn
+ 0x16: 0x38704, // menu
+ 0x17: 0x2cf06, // poster
+ 0x19: 0xf606, // footer
+ 0x1a: 0x2a806, // method
+ 0x1b: 0x2b808, // datetime
+ 0x1c: 0x19507, // onabort
+ 0x1d: 0x460e, // updateviacache
+ 0x1e: 0xff05, // async
+ 0x1f: 0x49d06, // onload
+ 0x21: 0x11908, // oncancel
+ 0x22: 0x62908, // onseeked
+ 0x23: 0x30205, // image
+ 0x24: 0x5d812, // onrejectionhandled
+ 0x26: 0x17404, // link
+ 0x27: 0x51d06, // output
+ 0x28: 0x33104, // head
+ 0x29: 0x4ff0c, // onmouseleave
+ 0x2a: 0x57f07, // onpaste
+ 0x2b: 0x5a409, // onplaying
+ 0x2c: 0x1c407, // colspan
+ 0x2f: 0x1bf05, // color
+ 0x30: 0x5f504, // size
+ 0x31: 0x2e80a, // http-equiv
+ 0x33: 0x601, // i
+ 0x34: 0x5590a, // onpagehide
+ 0x35: 0x68c14, // onunhandledrejection
+ 0x37: 0x42a07, // onerror
+ 0x3a: 0x3b08, // basefont
+ 0x3f: 0x1303, // nav
+ 0x40: 0x17704, // kind
+ 0x41: 0x35708, // readonly
+ 0x42: 0x30806, // mglyph
+ 0x44: 0xb202, // li
+ 0x46: 0x2d506, // hidden
+ 0x47: 0x70e03, // svg
+ 0x48: 0x58304, // step
+ 0x49: 0x23f09, // integrity
+ 0x4a: 0x58606, // public
+ 0x4c: 0x1ab03, // col
+ 0x4d: 0x1870a, // blockquote
+ 0x4e: 0x34f02, // h5
+ 0x50: 0x5b908, // progress
+ 0x51: 0x5f505, // sizes
+ 0x52: 0x34502, // h4
+ 0x56: 0x33005, // thead
+ 0x57: 0xd607, // keytype
+ 0x58: 0x5b70a, // onprogress
+ 0x59: 0x44b09, // inputmode
+ 0x5a: 0x3b109, // ondragend
+ 0x5d: 0x3a205, // oncut
+ 0x5e: 0x43706, // spacer
+ 0x5f: 0x1ab08, // colgroup
+ 0x62: 0x16502, // is
+ 0x65: 0x3c02, // as
+ 0x66: 0x54809, // onoffline
+ 0x67: 0x33706, // sorted
+ 0x69: 0x48d10, // onlanguagechange
+ 0x6c: 0x43d0c, // onhashchange
+ 0x6d: 0x9604, // name
+ 0x6e: 0xf505, // tfoot
+ 0x6f: 0x56104, // desc
+ 0x70: 0x33d03, // max
+ 0x72: 0x1ea06, // coords
+ 0x73: 0x30d02, // h3
+ 0x74: 0x6e70e, // onbeforeunload
+ 0x75: 0x9c04, // rows
+ 0x76: 0x63c06, // select
+ 0x77: 0x9805, // meter
+ 0x78: 0x38b06, // itemid
+ 0x79: 0x53c0c, // onmousewheel
+ 0x7a: 0x5c006, // srcdoc
+ 0x7d: 0x1ba05, // track
+ 0x7f: 0x31f08, // itemtype
+ 0x82: 0xa402, // mo
+ 0x83: 0x41b08, // onchange
+ 0x84: 0x33107, // headers
+ 0x85: 0x5cc0c, // onratechange
+ 0x86: 0x60819, // onsecuritypolicyviolation
+ 0x88: 0x4a508, // datalist
+ 0x89: 0x4e80b, // onmousedown
+ 0x8a: 0x1ef04, // slot
+ 0x8b: 0x4b010, // onloadedmetadata
+ 0x8c: 0x1a06, // accept
+ 0x8d: 0x26806, // object
+ 0x91: 0x6b30e, // onvolumechange
+ 0x92: 0x2107, // charset
+ 0x93: 0x27613, // onautocompleteerror
+ 0x94: 0xc113, // allowpaymentrequest
+ 0x95: 0x2804, // body
+ 0x96: 0x10a07, // default
+ 0x97: 0x63c08, // selected
+ 0x98: 0x21e04, // face
+ 0x99: 0x1e505, // shape
+ 0x9b: 0x68408, // ontoggle
+ 0x9e: 0x64b02, // dt
+ 0x9f: 0xb604, // mark
+ 0xa1: 0xb01, // u
+ 0xa4: 0x6ab08, // onunload
+ 0xa5: 0x5d04, // loop
+ 0xa6: 0x16408, // disabled
+ 0xaa: 0x42307, // onended
+ 0xab: 0xb00a, // malignmark
+ 0xad: 0x67b09, // onsuspend
+ 0xae: 0x35105, // mtext
+ 0xaf: 0x64f06, // onsort
+ 0xb0: 0x19d08, // itemprop
+ 0xb3: 0x67109, // itemscope
+ 0xb4: 0x17305, // blink
+ 0xb6: 0x3b106, // ondrag
+ 0xb7: 0xa702, // ul
+ 0xb8: 0x26e04, // form
+ 0xb9: 0x12907, // sandbox
+ 0xba: 0x8b05, // frame
+ 0xbb: 0x1505, // value
+ 0xbc: 0x66209, // onstorage
+ 0xbf: 0xaa07, // acronym
+ 0xc0: 0x19a02, // rt
+ 0xc2: 0x202, // br
+ 0xc3: 0x22608, // fieldset
+ 0xc4: 0x2900d, // typemustmatch
+ 0xc5: 0xa208, // nomodule
+ 0xc6: 0x6c07, // noembed
+ 0xc7: 0x69e0d, // onbeforeprint
+ 0xc8: 0x19106, // button
+ 0xc9: 0x2f507, // onclick
+ 0xca: 0x70407, // summary
+ 0xcd: 0xfb04, // ruby
+ 0xce: 0x56405, // class
+ 0xcf: 0x3f40b, // ondragstart
+ 0xd0: 0x23107, // caption
+ 0xd4: 0xdd0e, // allowusermedia
+ 0xd5: 0x4cf0b, // onloadstart
+ 0xd9: 0x16b03, // div
+ 0xda: 0x4a904, // list
+ 0xdb: 0x32e04, // math
+ 0xdc: 0x44b05, // input
+ 0xdf: 0x3ea0a, // ondragover
+ 0xe0: 0x2de02, // h2
+ 0xe2: 0x1b209, // plaintext
+ 0xe4: 0x4f30c, // onmouseenter
+ 0xe7: 0x47907, // checked
+ 0xe8: 0x47003, // pre
+ 0xea: 0x35f08, // multiple
+ 0xeb: 0xba03, // bdi
+ 0xec: 0x33d09, // maxlength
+ 0xed: 0xcf01, // q
+ 0xee: 0x61f0a, // onauxclick
+ 0xf0: 0x57c03, // wbr
+ 0xf2: 0x3b04, // base
+ 0xf3: 0x6e306, // option
+ 0xf5: 0x41310, // ondurationchange
+ 0xf7: 0x8908, // noframes
+ 0xf9: 0x40508, // dropzone
+ 0xfb: 0x67505, // scope
+ 0xfc: 0x8008, // reversed
+ 0xfd: 0x3ba0b, // ondragenter
+ 0xfe: 0x3fa05, // start
+ 0xff: 0x12f03, // xmp
+ 0x100: 0x5f907, // srclang
+ 0x101: 0x30703, // img
+ 0x104: 0x101, // b
+ 0x105: 0x25403, // for
+ 0x106: 0x10705, // aside
+ 0x107: 0x44907, // oninput
+ 0x108: 0x35604, // area
+ 0x109: 0x2a40a, // formmethod
+ 0x10a: 0x72604, // wrap
+ 0x10c: 0x23c02, // rp
+ 0x10d: 0x46b0a, // onkeypress
+ 0x10e: 0x6802, // tt
+ 0x110: 0x34702, // mi
+ 0x111: 0x36705, // muted
+ 0x112: 0xf303, // alt
+ 0x113: 0x5c504, // code
+ 0x114: 0x6e02, // em
+ 0x115: 0x3c50a, // ondragexit
+ 0x117: 0x9f04, // span
+ 0x119: 0x6d708, // manifest
+ 0x11a: 0x38708, // menuitem
+ 0x11b: 0x58b07, // content
+ 0x11d: 0x6c109, // onwaiting
+ 0x11f: 0x4c609, // onloadend
+ 0x121: 0x37e0d, // oncontextmenu
+ 0x123: 0x56d06, // onblur
+ 0x124: 0x3fc07, // article
+ 0x125: 0x9303, // dir
+ 0x126: 0xef04, // ping
+ 0x127: 0x24c08, // required
+ 0x128: 0x45509, // oninvalid
+ 0x129: 0xb105, // align
+ 0x12b: 0x58a04, // icon
+ 0x12c: 0x64d02, // h6
+ 0x12d: 0x1c404, // cols
+ 0x12e: 0x22e0a, // figcaption
+ 0x12f: 0x45e09, // onkeydown
+ 0x130: 0x66b08, // onsubmit
+ 0x131: 0x14d09, // oncanplay
+ 0x132: 0x70b03, // sup
+ 0x133: 0xc01, // p
+ 0x135: 0x40a09, // onemptied
+ 0x136: 0x39106, // oncopy
+ 0x137: 0x19c04, // cite
+ 0x138: 0x3a70a, // ondblclick
+ 0x13a: 0x50b0b, // onmousemove
+ 0x13c: 0x66d03, // sub
+ 0x13d: 0x48703, // rel
+ 0x13e: 0x5f08, // optgroup
+ 0x142: 0x9c07, // rowspan
+ 0x143: 0x37806, // source
+ 0x144: 0x21608, // noscript
+ 0x145: 0x1a304, // open
+ 0x146: 0x20403, // ins
+ 0x147: 0x2540d, // foreignObject
+ 0x148: 0x5ad0a, // onpopstate
+ 0x14a: 0x28d07, // enctype
+ 0x14b: 0x2760e, // onautocomplete
+ 0x14c: 0x35208, // textarea
+ 0x14e: 0x2780c, // autocomplete
+ 0x14f: 0x15702, // hr
+ 0x150: 0x1de08, // controls
+ 0x151: 0x10902, // id
+ 0x153: 0x2360c, // onafterprint
+ 0x155: 0x2610d, // foreignobject
+ 0x156: 0x32707, // marquee
+ 0x157: 0x59a07, // onpause
+ 0x158: 0x5e602, // dl
+ 0x159: 0x5206, // height
+ 0x15a: 0x34703, // min
+ 0x15b: 0x9307, // dirname
+ 0x15c: 0x1f209, // translate
+ 0x15d: 0x5604, // html
+ 0x15e: 0x34709, // minlength
+ 0x15f: 0x48607, // preload
+ 0x160: 0x71408, // template
+ 0x161: 0x3df0b, // ondragleave
+ 0x162: 0x3a02, // rb
+ 0x164: 0x5c003, // src
+ 0x165: 0x6dd06, // strong
+ 0x167: 0x7804, // samp
+ 0x168: 0x6f307, // address
+ 0x169: 0x55108, // ononline
+ 0x16b: 0x1310b, // placeholder
+ 0x16c: 0x2c406, // target
+ 0x16d: 0x20605, // small
+ 0x16e: 0x6ca07, // onwheel
+ 0x16f: 0x1c90a, // annotation
+ 0x170: 0x4740a, // spellcheck
+ 0x171: 0x7207, // details
+ 0x172: 0x10306, // canvas
+ 0x173: 0x12109, // autofocus
+ 0x174: 0xc05, // param
+ 0x176: 0x46308, // download
+ 0x177: 0x45203, // del
+ 0x178: 0x36c07, // onclose
+ 0x179: 0xb903, // kbd
+ 0x17a: 0x31906, // applet
+ 0x17b: 0x2e004, // href
+ 0x17c: 0x5f108, // onresize
+ 0x17e: 0x49d0c, // onloadeddata
+ 0x180: 0xcc02, // tr
+ 0x181: 0x2c00a, // formtarget
+ 0x182: 0x11005, // title
+ 0x183: 0x6ff05, // style
+ 0x184: 0xd206, // strike
+ 0x185: 0x59e06, // usemap
+ 0x186: 0x2fc06, // iframe
+ 0x187: 0x1004, // main
+ 0x189: 0x7b07, // picture
+ 0x18c: 0x31605, // ismap
+ 0x18e: 0x4a504, // data
+ 0x18f: 0x5905, // label
+ 0x191: 0x3d10e, // referrerpolicy
+ 0x192: 0x15602, // th
+ 0x194: 0x53606, // prompt
+ 0x195: 0x56807, // section
+ 0x197: 0x6d107, // optimum
+ 0x198: 0x2db04, // high
+ 0x199: 0x15c02, // h1
+ 0x19a: 0x65909, // onstalled
+ 0x19b: 0x16d03, // var
+ 0x19c: 0x4204, // time
+ 0x19e: 0x67402, // ms
+ 0x19f: 0x33106, // header
+ 0x1a0: 0x4da09, // onmessage
+ 0x1a1: 0x1a605, // nonce
+ 0x1a2: 0x26e0a, // formaction
+ 0x1a3: 0x22006, // center
+ 0x1a4: 0x3704, // nobr
+ 0x1a5: 0x59505, // table
+ 0x1a6: 0x4a907, // listing
+ 0x1a7: 0x18106, // legend
+ 0x1a9: 0x29b09, // challenge
+ 0x1aa: 0x24806, // figure
+ 0x1ab: 0xe605, // media
+ 0x1ae: 0xd904, // type
+ 0x1af: 0x3f04, // font
+ 0x1b0: 0x4da0e, // onmessageerror
+ 0x1b1: 0x37108, // seamless
+ 0x1b2: 0x8703, // dfn
+ 0x1b3: 0x5c705, // defer
+ 0x1b4: 0xc303, // low
+ 0x1b5: 0x19a03, // rtc
+ 0x1b6: 0x5230b, // onmouseover
+ 0x1b7: 0x2b20a, // novalidate
+ 0x1b8: 0x71c0a, // workertype
+ 0x1ba: 0x3cd07, // itemref
+ 0x1bd: 0x1, // a
+ 0x1be: 0x31803, // map
+ 0x1bf: 0x400c, // ontimeupdate
+ 0x1c0: 0x15e07, // bgsound
+ 0x1c1: 0x3206, // keygen
+ 0x1c2: 0x2705, // tbody
+ 0x1c5: 0x64406, // onshow
+ 0x1c7: 0x2501, // s
+ 0x1c8: 0x6607, // pattern
+ 0x1cc: 0x14d10, // oncanplaythrough
+ 0x1ce: 0x2d702, // dd
+ 0x1cf: 0x6f906, // srcset
+ 0x1d0: 0x17003, // big
+ 0x1d2: 0x65108, // sortable
+ 0x1d3: 0x48007, // onkeyup
+ 0x1d5: 0x5a406, // onplay
+ 0x1d7: 0x4b804, // meta
+ 0x1d8: 0x40306, // ondrop
+ 0x1da: 0x60008, // onscroll
+ 0x1db: 0x1fb0b, // crossorigin
+ 0x1dc: 0x5730a, // onpageshow
+ 0x1dd: 0x4, // abbr
+ 0x1de: 0x9202, // td
+ 0x1df: 0x58b0f, // contenteditable
+ 0x1e0: 0x27206, // action
+ 0x1e1: 0x1400b, // playsinline
+ 0x1e2: 0x43107, // onfocus
+ 0x1e3: 0x2e008, // hreflang
+ 0x1e5: 0x5160a, // onmouseout
+ 0x1e6: 0x5ea07, // onreset
+ 0x1e7: 0x13c08, // autoplay
+ 0x1e8: 0x63109, // onseeking
+ 0x1ea: 0x67506, // scoped
+ 0x1ec: 0x30a, // radiogroup
+ 0x1ee: 0x3800b, // contextmenu
+ 0x1ef: 0x52e09, // onmouseup
+ 0x1f1: 0x2ca06, // hgroup
+ 0x1f2: 0x2080f, // allowfullscreen
+ 0x1f3: 0x4be08, // tabindex
+ 0x1f6: 0x30f07, // isindex
+ 0x1f7: 0x1a0e, // accept-charset
+ 0x1f8: 0x2ae0e, // formnovalidate
+ 0x1fb: 0x1c90e, // annotation-xml
+ 0x1fc: 0x6e05, // embed
+ 0x1fd: 0x21806, // script
+ 0x1fe: 0xbb06, // dialog
+ 0x1ff: 0x1d707, // command
+}
+
+const atomText = "abbradiogrouparamainavalueaccept-charsetbodyaccesskeygenobrb" +
+ "asefontimeupdateviacacheightmlabelooptgroupatternoembedetail" +
+ "sampictureversedfnoframesetdirnameterowspanomoduleacronymali" +
+ "gnmarkbdialogallowpaymentrequestrikeytypeallowusermediagroup" +
+ "ingaltfooterubyasyncanvasidefaultitleaudioncancelautofocusan" +
+ "dboxmplaceholderautoplaysinlinebdoncanplaythrough1bgsoundisa" +
+ "bledivarbigblinkindraggablegendblockquotebuttonabortcitempro" +
+ "penoncecolgrouplaintextrackcolorcolspannotation-xmlcommandco" +
+ "ntrolshapecoordslotranslatecrossoriginsmallowfullscreenoscri" +
+ "ptfacenterfieldsetfigcaptionafterprintegrityfigurequiredfore" +
+ "ignObjectforeignobjectformactionautocompleteerrorformenctype" +
+ "mustmatchallengeformmethodformnovalidatetimeformtargethgroup" +
+ "osterhiddenhigh2hreflanghttp-equivideonclickiframeimageimgly" +
+ "ph3isindexismappletitemtypemarqueematheadersortedmaxlength4m" +
+ "inlength5mtextareadonlymultiplemutedoncloseamlessourceoncont" +
+ "extmenuitemidoncopyoncuechangeoncutondblclickondragendondrag" +
+ "enterondragexitemreferrerpolicyondragleaveondragoverondragst" +
+ "articleondropzonemptiedondurationchangeonendedonerroronfocus" +
+ "paceronhashchangeoninputmodeloninvalidonkeydownloadonkeypres" +
+ "spellcheckedonkeyupreloadonlanguagechangeonloadeddatalisting" +
+ "onloadedmetadatabindexonloadendonloadstartonmessageerroronmo" +
+ "usedownonmouseenteronmouseleaveonmousemoveonmouseoutputonmou" +
+ "seoveronmouseupromptonmousewheelonofflineononlineonpagehides" +
+ "classectionbluronpageshowbronpastepublicontenteditableonpaus" +
+ "emaponplayingonpopstateonprogressrcdocodeferonratechangeonre" +
+ "jectionhandledonresetonresizesrclangonscrollonsecuritypolicy" +
+ "violationauxclickonseekedonseekingonselectedonshowidth6onsor" +
+ "tableonstalledonstorageonsubmitemscopedonsuspendontoggleonun" +
+ "handledrejectionbeforeprintonunloadonvolumechangeonwaitingon" +
+ "wheeloptimumanifestrongoptionbeforeunloaddressrcsetstylesumm" +
+ "arysupsvgsystemplateworkertypewrap"
diff --git a/vendor/golang.org/x/net/html/const.go b/vendor/golang.org/x/net/html/const.go
new file mode 100644
index 0000000..5eb7c5a
--- /dev/null
+++ b/vendor/golang.org/x/net/html/const.go
@@ -0,0 +1,104 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+// Section 12.2.4.2 of the HTML5 specification says "The following elements
+// have varying levels of special parsing rules".
+// https://html.spec.whatwg.org/multipage/syntax.html#the-stack-of-open-elements
+var isSpecialElementMap = map[string]bool{
+ "address": true,
+ "applet": true,
+ "area": true,
+ "article": true,
+ "aside": true,
+ "base": true,
+ "basefont": true,
+ "bgsound": true,
+ "blockquote": true,
+ "body": true,
+ "br": true,
+ "button": true,
+ "caption": true,
+ "center": true,
+ "col": true,
+ "colgroup": true,
+ "dd": true,
+ "details": true,
+ "dir": true,
+ "div": true,
+ "dl": true,
+ "dt": true,
+ "embed": true,
+ "fieldset": true,
+ "figcaption": true,
+ "figure": true,
+ "footer": true,
+ "form": true,
+ "frame": true,
+ "frameset": true,
+ "h1": true,
+ "h2": true,
+ "h3": true,
+ "h4": true,
+ "h5": true,
+ "h6": true,
+ "head": true,
+ "header": true,
+ "hgroup": true,
+ "hr": true,
+ "html": true,
+ "iframe": true,
+ "img": true,
+ "input": true,
+ "isindex": true, // The 'isindex' element has been removed, but keep it for backwards compatibility.
+ "keygen": true,
+ "li": true,
+ "link": true,
+ "listing": true,
+ "main": true,
+ "marquee": true,
+ "menu": true,
+ "meta": true,
+ "nav": true,
+ "noembed": true,
+ "noframes": true,
+ "noscript": true,
+ "object": true,
+ "ol": true,
+ "p": true,
+ "param": true,
+ "plaintext": true,
+ "pre": true,
+ "script": true,
+ "section": true,
+ "select": true,
+ "source": true,
+ "style": true,
+ "summary": true,
+ "table": true,
+ "tbody": true,
+ "td": true,
+ "template": true,
+ "textarea": true,
+ "tfoot": true,
+ "th": true,
+ "thead": true,
+ "title": true,
+ "tr": true,
+ "track": true,
+ "ul": true,
+ "wbr": true,
+ "xmp": true,
+}
+
+func isSpecialElement(element *Node) bool {
+ switch element.Namespace {
+ case "", "html":
+ return isSpecialElementMap[element.Data]
+ case "svg":
+ return element.Data == "foreignObject"
+ }
+ return false
+}
diff --git a/vendor/golang.org/x/net/html/doc.go b/vendor/golang.org/x/net/html/doc.go
new file mode 100644
index 0000000..822ed42
--- /dev/null
+++ b/vendor/golang.org/x/net/html/doc.go
@@ -0,0 +1,106 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package html implements an HTML5-compliant tokenizer and parser.
+
+Tokenization is done by creating a Tokenizer for an io.Reader r. It is the
+caller's responsibility to ensure that r provides UTF-8 encoded HTML.
+
+ z := html.NewTokenizer(r)
+
+Given a Tokenizer z, the HTML is tokenized by repeatedly calling z.Next(),
+which parses the next token and returns its type, or an error:
+
+ for {
+ tt := z.Next()
+ if tt == html.ErrorToken {
+ // ...
+ return ...
+ }
+ // Process the current token.
+ }
+
+There are two APIs for retrieving the current token. The high-level API is to
+call Token; the low-level API is to call Text or TagName / TagAttr. Both APIs
+allow optionally calling Raw after Next but before Token, Text, TagName, or
+TagAttr. In EBNF notation, the valid call sequence per token is:
+
+ Next {Raw} [ Token | Text | TagName {TagAttr} ]
+
+Token returns an independent data structure that completely describes a token.
+Entities (such as "&lt;") are unescaped, tag names and attribute keys are
+lower-cased, and attributes are collected into a []Attribute. For example:
+
+ for {
+ if z.Next() == html.ErrorToken {
+ // Returning io.EOF indicates success.
+ return z.Err()
+ }
+ emitToken(z.Token())
+ }
+
+The low-level API performs fewer allocations and copies, but the contents of
+the []byte values returned by Text, TagName and TagAttr may change on the next
+call to Next. For example, to extract an HTML page's anchor text:
+
+ depth := 0
+ for {
+ tt := z.Next()
+ switch tt {
+ case html.ErrorToken:
+ return z.Err()
+ case html.TextToken:
+ if depth > 0 {
+ // emitBytes should copy the []byte it receives,
+ // if it doesn't process it immediately.
+ emitBytes(z.Text())
+ }
+ case html.StartTagToken, html.EndTagToken:
+ tn, _ := z.TagName()
+ if len(tn) == 1 && tn[0] == 'a' {
+ if tt == html.StartTagToken {
+ depth++
+ } else {
+ depth--
+ }
+ }
+ }
+ }
+
+Parsing is done by calling Parse with an io.Reader, which returns the root of
+the parse tree (the document element) as a *Node. It is the caller's
+responsibility to ensure that the Reader provides UTF-8 encoded HTML. For
+example, to process each anchor node in depth-first order:
+
+ doc, err := html.Parse(r)
+ if err != nil {
+ // ...
+ }
+ var f func(*html.Node)
+ f = func(n *html.Node) {
+ if n.Type == html.ElementNode && n.Data == "a" {
+ // Do something with n...
+ }
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
+ f(c)
+ }
+ }
+ f(doc)
+
+The relevant specifications include:
+https://html.spec.whatwg.org/multipage/syntax.html and
+https://html.spec.whatwg.org/multipage/syntax.html#tokenization
+*/
+package html // import "golang.org/x/net/html"
+
+// The tokenization algorithm implemented by this package is not a line-by-line
+// transliteration of the relatively verbose state-machine in the WHATWG
+// specification. A more direct approach is used instead, where the program
+// counter implies the state, such as whether it is tokenizing a tag or a text
+// node. Specification compliance is verified by checking expected and actual
+// outputs over a test suite rather than aiming for algorithmic fidelity.
+
+// TODO(nigeltao): Does a DOM API belong in this package or a separate one?
+// TODO(nigeltao): How does parsing interact with a JavaScript engine?
diff --git a/vendor/golang.org/x/net/html/doctype.go b/vendor/golang.org/x/net/html/doctype.go
new file mode 100644
index 0000000..c484e5a
--- /dev/null
+++ b/vendor/golang.org/x/net/html/doctype.go
@@ -0,0 +1,156 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "strings"
+)
+
+// parseDoctype parses the data from a DoctypeToken into a name,
+// public identifier, and system identifier. It returns a Node whose Type
+// is DoctypeNode, whose Data is the name, and which has attributes
+// named "system" and "public" for the two identifiers if they were present.
+// quirks is whether the document should be parsed in "quirks mode".
+func parseDoctype(s string) (n *Node, quirks bool) {
+ n = &Node{Type: DoctypeNode}
+
+ // Find the name.
+ space := strings.IndexAny(s, whitespace)
+ if space == -1 {
+ space = len(s)
+ }
+ n.Data = s[:space]
+ // The comparison to "html" is case-sensitive.
+ if n.Data != "html" {
+ quirks = true
+ }
+ n.Data = strings.ToLower(n.Data)
+ s = strings.TrimLeft(s[space:], whitespace)
+
+ if len(s) < 6 {
+ // It can't start with "PUBLIC" or "SYSTEM".
+ // Ignore the rest of the string.
+ return n, quirks || s != ""
+ }
+
+ key := strings.ToLower(s[:6])
+ s = s[6:]
+ for key == "public" || key == "system" {
+ s = strings.TrimLeft(s, whitespace)
+ if s == "" {
+ break
+ }
+ quote := s[0]
+ if quote != '"' && quote != '\'' {
+ break
+ }
+ s = s[1:]
+ q := strings.IndexRune(s, rune(quote))
+ var id string
+ if q == -1 {
+ id = s
+ s = ""
+ } else {
+ id = s[:q]
+ s = s[q+1:]
+ }
+ n.Attr = append(n.Attr, Attribute{Key: key, Val: id})
+ if key == "public" {
+ key = "system"
+ } else {
+ key = ""
+ }
+ }
+
+ if key != "" || s != "" {
+ quirks = true
+ } else if len(n.Attr) > 0 {
+ if n.Attr[0].Key == "public" {
+ public := strings.ToLower(n.Attr[0].Val)
+ switch public {
+ case "-//w3o//dtd w3 html strict 3.0//en//", "-/w3d/dtd html 4.0 transitional/en", "html":
+ quirks = true
+ default:
+ for _, q := range quirkyIDs {
+ if strings.HasPrefix(public, q) {
+ quirks = true
+ break
+ }
+ }
+ }
+ // The following two public IDs only cause quirks mode if there is no system ID.
+ if len(n.Attr) == 1 && (strings.HasPrefix(public, "-//w3c//dtd html 4.01 frameset//") ||
+ strings.HasPrefix(public, "-//w3c//dtd html 4.01 transitional//")) {
+ quirks = true
+ }
+ }
+ if lastAttr := n.Attr[len(n.Attr)-1]; lastAttr.Key == "system" &&
+ strings.ToLower(lastAttr.Val) == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd" {
+ quirks = true
+ }
+ }
+
+ return n, quirks
+}
+
+// quirkyIDs is a list of public doctype identifiers that cause a document
+// to be interpreted in quirks mode. The identifiers should be in lower case.
+var quirkyIDs = []string{
+ "+//silmaril//dtd html pro v0r11 19970101//",
+ "-//advasoft ltd//dtd html 3.0 aswedit + extensions//",
+ "-//as//dtd html 3.0 aswedit + extensions//",
+ "-//ietf//dtd html 2.0 level 1//",
+ "-//ietf//dtd html 2.0 level 2//",
+ "-//ietf//dtd html 2.0 strict level 1//",
+ "-//ietf//dtd html 2.0 strict level 2//",
+ "-//ietf//dtd html 2.0 strict//",
+ "-//ietf//dtd html 2.0//",
+ "-//ietf//dtd html 2.1e//",
+ "-//ietf//dtd html 3.0//",
+ "-//ietf//dtd html 3.2 final//",
+ "-//ietf//dtd html 3.2//",
+ "-//ietf//dtd html 3//",
+ "-//ietf//dtd html level 0//",
+ "-//ietf//dtd html level 1//",
+ "-//ietf//dtd html level 2//",
+ "-//ietf//dtd html level 3//",
+ "-//ietf//dtd html strict level 0//",
+ "-//ietf//dtd html strict level 1//",
+ "-//ietf//dtd html strict level 2//",
+ "-//ietf//dtd html strict level 3//",
+ "-//ietf//dtd html strict//",
+ "-//ietf//dtd html//",
+ "-//metrius//dtd metrius presentational//",
+ "-//microsoft//dtd internet explorer 2.0 html strict//",
+ "-//microsoft//dtd internet explorer 2.0 html//",
+ "-//microsoft//dtd internet explorer 2.0 tables//",
+ "-//microsoft//dtd internet explorer 3.0 html strict//",
+ "-//microsoft//dtd internet explorer 3.0 html//",
+ "-//microsoft//dtd internet explorer 3.0 tables//",
+ "-//netscape comm. corp.//dtd html//",
+ "-//netscape comm. corp.//dtd strict html//",
+ "-//o'reilly and associates//dtd html 2.0//",
+ "-//o'reilly and associates//dtd html extended 1.0//",
+ "-//o'reilly and associates//dtd html extended relaxed 1.0//",
+ "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//",
+ "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//",
+ "-//spyglass//dtd html 2.0 extended//",
+ "-//sq//dtd html 2.0 hotmetal + extensions//",
+ "-//sun microsystems corp.//dtd hotjava html//",
+ "-//sun microsystems corp.//dtd hotjava strict html//",
+ "-//w3c//dtd html 3 1995-03-24//",
+ "-//w3c//dtd html 3.2 draft//",
+ "-//w3c//dtd html 3.2 final//",
+ "-//w3c//dtd html 3.2//",
+ "-//w3c//dtd html 3.2s draft//",
+ "-//w3c//dtd html 4.0 frameset//",
+ "-//w3c//dtd html 4.0 transitional//",
+ "-//w3c//dtd html experimental 19960712//",
+ "-//w3c//dtd html experimental 970421//",
+ "-//w3c//dtd w3 html//",
+ "-//w3o//dtd w3 html 3.0//",
+ "-//webtechs//dtd mozilla html 2.0//",
+ "-//webtechs//dtd mozilla html//",
+}
diff --git a/vendor/golang.org/x/net/html/entity.go b/vendor/golang.org/x/net/html/entity.go
new file mode 100644
index 0000000..a50c04c
--- /dev/null
+++ b/vendor/golang.org/x/net/html/entity.go
@@ -0,0 +1,2253 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+// All entities that do not end with ';' are 6 or fewer bytes long.
+const longestEntityWithoutSemicolon = 6
+
+// entity is a map from HTML entity names to their values. The semicolon matters:
+// https://html.spec.whatwg.org/multipage/syntax.html#named-character-references
+// lists both "amp" and "amp;" as two separate entries.
+//
+// Note that the HTML5 list is larger than the HTML4 list at
+// http://www.w3.org/TR/html4/sgml/entities.html
+var entity = map[string]rune{
+ "AElig;": '\U000000C6',
+ "AMP;": '\U00000026',
+ "Aacute;": '\U000000C1',
+ "Abreve;": '\U00000102',
+ "Acirc;": '\U000000C2',
+ "Acy;": '\U00000410',
+ "Afr;": '\U0001D504',
+ "Agrave;": '\U000000C0',
+ "Alpha;": '\U00000391',
+ "Amacr;": '\U00000100',
+ "And;": '\U00002A53',
+ "Aogon;": '\U00000104',
+ "Aopf;": '\U0001D538',
+ "ApplyFunction;": '\U00002061',
+ "Aring;": '\U000000C5',
+ "Ascr;": '\U0001D49C',
+ "Assign;": '\U00002254',
+ "Atilde;": '\U000000C3',
+ "Auml;": '\U000000C4',
+ "Backslash;": '\U00002216',
+ "Barv;": '\U00002AE7',
+ "Barwed;": '\U00002306',
+ "Bcy;": '\U00000411',
+ "Because;": '\U00002235',
+ "Bernoullis;": '\U0000212C',
+ "Beta;": '\U00000392',
+ "Bfr;": '\U0001D505',
+ "Bopf;": '\U0001D539',
+ "Breve;": '\U000002D8',
+ "Bscr;": '\U0000212C',
+ "Bumpeq;": '\U0000224E',
+ "CHcy;": '\U00000427',
+ "COPY;": '\U000000A9',
+ "Cacute;": '\U00000106',
+ "Cap;": '\U000022D2',
+ "CapitalDifferentialD;": '\U00002145',
+ "Cayleys;": '\U0000212D',
+ "Ccaron;": '\U0000010C',
+ "Ccedil;": '\U000000C7',
+ "Ccirc;": '\U00000108',
+ "Cconint;": '\U00002230',
+ "Cdot;": '\U0000010A',
+ "Cedilla;": '\U000000B8',
+ "CenterDot;": '\U000000B7',
+ "Cfr;": '\U0000212D',
+ "Chi;": '\U000003A7',
+ "CircleDot;": '\U00002299',
+ "CircleMinus;": '\U00002296',
+ "CirclePlus;": '\U00002295',
+ "CircleTimes;": '\U00002297',
+ "ClockwiseContourIntegral;": '\U00002232',
+ "CloseCurlyDoubleQuote;": '\U0000201D',
+ "CloseCurlyQuote;": '\U00002019',
+ "Colon;": '\U00002237',
+ "Colone;": '\U00002A74',
+ "Congruent;": '\U00002261',
+ "Conint;": '\U0000222F',
+ "ContourIntegral;": '\U0000222E',
+ "Copf;": '\U00002102',
+ "Coproduct;": '\U00002210',
+ "CounterClockwiseContourIntegral;": '\U00002233',
+ "Cross;": '\U00002A2F',
+ "Cscr;": '\U0001D49E',
+ "Cup;": '\U000022D3',
+ "CupCap;": '\U0000224D',
+ "DD;": '\U00002145',
+ "DDotrahd;": '\U00002911',
+ "DJcy;": '\U00000402',
+ "DScy;": '\U00000405',
+ "DZcy;": '\U0000040F',
+ "Dagger;": '\U00002021',
+ "Darr;": '\U000021A1',
+ "Dashv;": '\U00002AE4',
+ "Dcaron;": '\U0000010E',
+ "Dcy;": '\U00000414',
+ "Del;": '\U00002207',
+ "Delta;": '\U00000394',
+ "Dfr;": '\U0001D507',
+ "DiacriticalAcute;": '\U000000B4',
+ "DiacriticalDot;": '\U000002D9',
+ "DiacriticalDoubleAcute;": '\U000002DD',
+ "DiacriticalGrave;": '\U00000060',
+ "DiacriticalTilde;": '\U000002DC',
+ "Diamond;": '\U000022C4',
+ "DifferentialD;": '\U00002146',
+ "Dopf;": '\U0001D53B',
+ "Dot;": '\U000000A8',
+ "DotDot;": '\U000020DC',
+ "DotEqual;": '\U00002250',
+ "DoubleContourIntegral;": '\U0000222F',
+ "DoubleDot;": '\U000000A8',
+ "DoubleDownArrow;": '\U000021D3',
+ "DoubleLeftArrow;": '\U000021D0',
+ "DoubleLeftRightArrow;": '\U000021D4',
+ "DoubleLeftTee;": '\U00002AE4',
+ "DoubleLongLeftArrow;": '\U000027F8',
+ "DoubleLongLeftRightArrow;": '\U000027FA',
+ "DoubleLongRightArrow;": '\U000027F9',
+ "DoubleRightArrow;": '\U000021D2',
+ "DoubleRightTee;": '\U000022A8',
+ "DoubleUpArrow;": '\U000021D1',
+ "DoubleUpDownArrow;": '\U000021D5',
+ "DoubleVerticalBar;": '\U00002225',
+ "DownArrow;": '\U00002193',
+ "DownArrowBar;": '\U00002913',
+ "DownArrowUpArrow;": '\U000021F5',
+ "DownBreve;": '\U00000311',
+ "DownLeftRightVector;": '\U00002950',
+ "DownLeftTeeVector;": '\U0000295E',
+ "DownLeftVector;": '\U000021BD',
+ "DownLeftVectorBar;": '\U00002956',
+ "DownRightTeeVector;": '\U0000295F',
+ "DownRightVector;": '\U000021C1',
+ "DownRightVectorBar;": '\U00002957',
+ "DownTee;": '\U000022A4',
+ "DownTeeArrow;": '\U000021A7',
+ "Downarrow;": '\U000021D3',
+ "Dscr;": '\U0001D49F',
+ "Dstrok;": '\U00000110',
+ "ENG;": '\U0000014A',
+ "ETH;": '\U000000D0',
+ "Eacute;": '\U000000C9',
+ "Ecaron;": '\U0000011A',
+ "Ecirc;": '\U000000CA',
+ "Ecy;": '\U0000042D',
+ "Edot;": '\U00000116',
+ "Efr;": '\U0001D508',
+ "Egrave;": '\U000000C8',
+ "Element;": '\U00002208',
+ "Emacr;": '\U00000112',
+ "EmptySmallSquare;": '\U000025FB',
+ "EmptyVerySmallSquare;": '\U000025AB',
+ "Eogon;": '\U00000118',
+ "Eopf;": '\U0001D53C',
+ "Epsilon;": '\U00000395',
+ "Equal;": '\U00002A75',
+ "EqualTilde;": '\U00002242',
+ "Equilibrium;": '\U000021CC',
+ "Escr;": '\U00002130',
+ "Esim;": '\U00002A73',
+ "Eta;": '\U00000397',
+ "Euml;": '\U000000CB',
+ "Exists;": '\U00002203',
+ "ExponentialE;": '\U00002147',
+ "Fcy;": '\U00000424',
+ "Ffr;": '\U0001D509',
+ "FilledSmallSquare;": '\U000025FC',
+ "FilledVerySmallSquare;": '\U000025AA',
+ "Fopf;": '\U0001D53D',
+ "ForAll;": '\U00002200',
+ "Fouriertrf;": '\U00002131',
+ "Fscr;": '\U00002131',
+ "GJcy;": '\U00000403',
+ "GT;": '\U0000003E',
+ "Gamma;": '\U00000393',
+ "Gammad;": '\U000003DC',
+ "Gbreve;": '\U0000011E',
+ "Gcedil;": '\U00000122',
+ "Gcirc;": '\U0000011C',
+ "Gcy;": '\U00000413',
+ "Gdot;": '\U00000120',
+ "Gfr;": '\U0001D50A',
+ "Gg;": '\U000022D9',
+ "Gopf;": '\U0001D53E',
+ "GreaterEqual;": '\U00002265',
+ "GreaterEqualLess;": '\U000022DB',
+ "GreaterFullEqual;": '\U00002267',
+ "GreaterGreater;": '\U00002AA2',
+ "GreaterLess;": '\U00002277',
+ "GreaterSlantEqual;": '\U00002A7E',
+ "GreaterTilde;": '\U00002273',
+ "Gscr;": '\U0001D4A2',
+ "Gt;": '\U0000226B',
+ "HARDcy;": '\U0000042A',
+ "Hacek;": '\U000002C7',
+ "Hat;": '\U0000005E',
+ "Hcirc;": '\U00000124',
+ "Hfr;": '\U0000210C',
+ "HilbertSpace;": '\U0000210B',
+ "Hopf;": '\U0000210D',
+ "HorizontalLine;": '\U00002500',
+ "Hscr;": '\U0000210B',
+ "Hstrok;": '\U00000126',
+ "HumpDownHump;": '\U0000224E',
+ "HumpEqual;": '\U0000224F',
+ "IEcy;": '\U00000415',
+ "IJlig;": '\U00000132',
+ "IOcy;": '\U00000401',
+ "Iacute;": '\U000000CD',
+ "Icirc;": '\U000000CE',
+ "Icy;": '\U00000418',
+ "Idot;": '\U00000130',
+ "Ifr;": '\U00002111',
+ "Igrave;": '\U000000CC',
+ "Im;": '\U00002111',
+ "Imacr;": '\U0000012A',
+ "ImaginaryI;": '\U00002148',
+ "Implies;": '\U000021D2',
+ "Int;": '\U0000222C',
+ "Integral;": '\U0000222B',
+ "Intersection;": '\U000022C2',
+ "InvisibleComma;": '\U00002063',
+ "InvisibleTimes;": '\U00002062',
+ "Iogon;": '\U0000012E',
+ "Iopf;": '\U0001D540',
+ "Iota;": '\U00000399',
+ "Iscr;": '\U00002110',
+ "Itilde;": '\U00000128',
+ "Iukcy;": '\U00000406',
+ "Iuml;": '\U000000CF',
+ "Jcirc;": '\U00000134',
+ "Jcy;": '\U00000419',
+ "Jfr;": '\U0001D50D',
+ "Jopf;": '\U0001D541',
+ "Jscr;": '\U0001D4A5',
+ "Jsercy;": '\U00000408',
+ "Jukcy;": '\U00000404',
+ "KHcy;": '\U00000425',
+ "KJcy;": '\U0000040C',
+ "Kappa;": '\U0000039A',
+ "Kcedil;": '\U00000136',
+ "Kcy;": '\U0000041A',
+ "Kfr;": '\U0001D50E',
+ "Kopf;": '\U0001D542',
+ "Kscr;": '\U0001D4A6',
+ "LJcy;": '\U00000409',
+ "LT;": '\U0000003C',
+ "Lacute;": '\U00000139',
+ "Lambda;": '\U0000039B',
+ "Lang;": '\U000027EA',
+ "Laplacetrf;": '\U00002112',
+ "Larr;": '\U0000219E',
+ "Lcaron;": '\U0000013D',
+ "Lcedil;": '\U0000013B',
+ "Lcy;": '\U0000041B',
+ "LeftAngleBracket;": '\U000027E8',
+ "LeftArrow;": '\U00002190',
+ "LeftArrowBar;": '\U000021E4',
+ "LeftArrowRightArrow;": '\U000021C6',
+ "LeftCeiling;": '\U00002308',
+ "LeftDoubleBracket;": '\U000027E6',
+ "LeftDownTeeVector;": '\U00002961',
+ "LeftDownVector;": '\U000021C3',
+ "LeftDownVectorBar;": '\U00002959',
+ "LeftFloor;": '\U0000230A',
+ "LeftRightArrow;": '\U00002194',
+ "LeftRightVector;": '\U0000294E',
+ "LeftTee;": '\U000022A3',
+ "LeftTeeArrow;": '\U000021A4',
+ "LeftTeeVector;": '\U0000295A',
+ "LeftTriangle;": '\U000022B2',
+ "LeftTriangleBar;": '\U000029CF',
+ "LeftTriangleEqual;": '\U000022B4',
+ "LeftUpDownVector;": '\U00002951',
+ "LeftUpTeeVector;": '\U00002960',
+ "LeftUpVector;": '\U000021BF',
+ "LeftUpVectorBar;": '\U00002958',
+ "LeftVector;": '\U000021BC',
+ "LeftVectorBar;": '\U00002952',
+ "Leftarrow;": '\U000021D0',
+ "Leftrightarrow;": '\U000021D4',
+ "LessEqualGreater;": '\U000022DA',
+ "LessFullEqual;": '\U00002266',
+ "LessGreater;": '\U00002276',
+ "LessLess;": '\U00002AA1',
+ "LessSlantEqual;": '\U00002A7D',
+ "LessTilde;": '\U00002272',
+ "Lfr;": '\U0001D50F',
+ "Ll;": '\U000022D8',
+ "Lleftarrow;": '\U000021DA',
+ "Lmidot;": '\U0000013F',
+ "LongLeftArrow;": '\U000027F5',
+ "LongLeftRightArrow;": '\U000027F7',
+ "LongRightArrow;": '\U000027F6',
+ "Longleftarrow;": '\U000027F8',
+ "Longleftrightarrow;": '\U000027FA',
+ "Longrightarrow;": '\U000027F9',
+ "Lopf;": '\U0001D543',
+ "LowerLeftArrow;": '\U00002199',
+ "LowerRightArrow;": '\U00002198',
+ "Lscr;": '\U00002112',
+ "Lsh;": '\U000021B0',
+ "Lstrok;": '\U00000141',
+ "Lt;": '\U0000226A',
+ "Map;": '\U00002905',
+ "Mcy;": '\U0000041C',
+ "MediumSpace;": '\U0000205F',
+ "Mellintrf;": '\U00002133',
+ "Mfr;": '\U0001D510',
+ "MinusPlus;": '\U00002213',
+ "Mopf;": '\U0001D544',
+ "Mscr;": '\U00002133',
+ "Mu;": '\U0000039C',
+ "NJcy;": '\U0000040A',
+ "Nacute;": '\U00000143',
+ "Ncaron;": '\U00000147',
+ "Ncedil;": '\U00000145',
+ "Ncy;": '\U0000041D',
+ "NegativeMediumSpace;": '\U0000200B',
+ "NegativeThickSpace;": '\U0000200B',
+ "NegativeThinSpace;": '\U0000200B',
+ "NegativeVeryThinSpace;": '\U0000200B',
+ "NestedGreaterGreater;": '\U0000226B',
+ "NestedLessLess;": '\U0000226A',
+ "NewLine;": '\U0000000A',
+ "Nfr;": '\U0001D511',
+ "NoBreak;": '\U00002060',
+ "NonBreakingSpace;": '\U000000A0',
+ "Nopf;": '\U00002115',
+ "Not;": '\U00002AEC',
+ "NotCongruent;": '\U00002262',
+ "NotCupCap;": '\U0000226D',
+ "NotDoubleVerticalBar;": '\U00002226',
+ "NotElement;": '\U00002209',
+ "NotEqual;": '\U00002260',
+ "NotExists;": '\U00002204',
+ "NotGreater;": '\U0000226F',
+ "NotGreaterEqual;": '\U00002271',
+ "NotGreaterLess;": '\U00002279',
+ "NotGreaterTilde;": '\U00002275',
+ "NotLeftTriangle;": '\U000022EA',
+ "NotLeftTriangleEqual;": '\U000022EC',
+ "NotLess;": '\U0000226E',
+ "NotLessEqual;": '\U00002270',
+ "NotLessGreater;": '\U00002278',
+ "NotLessTilde;": '\U00002274',
+ "NotPrecedes;": '\U00002280',
+ "NotPrecedesSlantEqual;": '\U000022E0',
+ "NotReverseElement;": '\U0000220C',
+ "NotRightTriangle;": '\U000022EB',
+ "NotRightTriangleEqual;": '\U000022ED',
+ "NotSquareSubsetEqual;": '\U000022E2',
+ "NotSquareSupersetEqual;": '\U000022E3',
+ "NotSubsetEqual;": '\U00002288',
+ "NotSucceeds;": '\U00002281',
+ "NotSucceedsSlantEqual;": '\U000022E1',
+ "NotSupersetEqual;": '\U00002289',
+ "NotTilde;": '\U00002241',
+ "NotTildeEqual;": '\U00002244',
+ "NotTildeFullEqual;": '\U00002247',
+ "NotTildeTilde;": '\U00002249',
+ "NotVerticalBar;": '\U00002224',
+ "Nscr;": '\U0001D4A9',
+ "Ntilde;": '\U000000D1',
+ "Nu;": '\U0000039D',
+ "OElig;": '\U00000152',
+ "Oacute;": '\U000000D3',
+ "Ocirc;": '\U000000D4',
+ "Ocy;": '\U0000041E',
+ "Odblac;": '\U00000150',
+ "Ofr;": '\U0001D512',
+ "Ograve;": '\U000000D2',
+ "Omacr;": '\U0000014C',
+ "Omega;": '\U000003A9',
+ "Omicron;": '\U0000039F',
+ "Oopf;": '\U0001D546',
+ "OpenCurlyDoubleQuote;": '\U0000201C',
+ "OpenCurlyQuote;": '\U00002018',
+ "Or;": '\U00002A54',
+ "Oscr;": '\U0001D4AA',
+ "Oslash;": '\U000000D8',
+ "Otilde;": '\U000000D5',
+ "Otimes;": '\U00002A37',
+ "Ouml;": '\U000000D6',
+ "OverBar;": '\U0000203E',
+ "OverBrace;": '\U000023DE',
+ "OverBracket;": '\U000023B4',
+ "OverParenthesis;": '\U000023DC',
+ "PartialD;": '\U00002202',
+ "Pcy;": '\U0000041F',
+ "Pfr;": '\U0001D513',
+ "Phi;": '\U000003A6',
+ "Pi;": '\U000003A0',
+ "PlusMinus;": '\U000000B1',
+ "Poincareplane;": '\U0000210C',
+ "Popf;": '\U00002119',
+ "Pr;": '\U00002ABB',
+ "Precedes;": '\U0000227A',
+ "PrecedesEqual;": '\U00002AAF',
+ "PrecedesSlantEqual;": '\U0000227C',
+ "PrecedesTilde;": '\U0000227E',
+ "Prime;": '\U00002033',
+ "Product;": '\U0000220F',
+ "Proportion;": '\U00002237',
+ "Proportional;": '\U0000221D',
+ "Pscr;": '\U0001D4AB',
+ "Psi;": '\U000003A8',
+ "QUOT;": '\U00000022',
+ "Qfr;": '\U0001D514',
+ "Qopf;": '\U0000211A',
+ "Qscr;": '\U0001D4AC',
+ "RBarr;": '\U00002910',
+ "REG;": '\U000000AE',
+ "Racute;": '\U00000154',
+ "Rang;": '\U000027EB',
+ "Rarr;": '\U000021A0',
+ "Rarrtl;": '\U00002916',
+ "Rcaron;": '\U00000158',
+ "Rcedil;": '\U00000156',
+ "Rcy;": '\U00000420',
+ "Re;": '\U0000211C',
+ "ReverseElement;": '\U0000220B',
+ "ReverseEquilibrium;": '\U000021CB',
+ "ReverseUpEquilibrium;": '\U0000296F',
+ "Rfr;": '\U0000211C',
+ "Rho;": '\U000003A1',
+ "RightAngleBracket;": '\U000027E9',
+ "RightArrow;": '\U00002192',
+ "RightArrowBar;": '\U000021E5',
+ "RightArrowLeftArrow;": '\U000021C4',
+ "RightCeiling;": '\U00002309',
+ "RightDoubleBracket;": '\U000027E7',
+ "RightDownTeeVector;": '\U0000295D',
+ "RightDownVector;": '\U000021C2',
+ "RightDownVectorBar;": '\U00002955',
+ "RightFloor;": '\U0000230B',
+ "RightTee;": '\U000022A2',
+ "RightTeeArrow;": '\U000021A6',
+ "RightTeeVector;": '\U0000295B',
+ "RightTriangle;": '\U000022B3',
+ "RightTriangleBar;": '\U000029D0',
+ "RightTriangleEqual;": '\U000022B5',
+ "RightUpDownVector;": '\U0000294F',
+ "RightUpTeeVector;": '\U0000295C',
+ "RightUpVector;": '\U000021BE',
+ "RightUpVectorBar;": '\U00002954',
+ "RightVector;": '\U000021C0',
+ "RightVectorBar;": '\U00002953',
+ "Rightarrow;": '\U000021D2',
+ "Ropf;": '\U0000211D',
+ "RoundImplies;": '\U00002970',
+ "Rrightarrow;": '\U000021DB',
+ "Rscr;": '\U0000211B',
+ "Rsh;": '\U000021B1',
+ "RuleDelayed;": '\U000029F4',
+ "SHCHcy;": '\U00000429',
+ "SHcy;": '\U00000428',
+ "SOFTcy;": '\U0000042C',
+ "Sacute;": '\U0000015A',
+ "Sc;": '\U00002ABC',
+ "Scaron;": '\U00000160',
+ "Scedil;": '\U0000015E',
+ "Scirc;": '\U0000015C',
+ "Scy;": '\U00000421',
+ "Sfr;": '\U0001D516',
+ "ShortDownArrow;": '\U00002193',
+ "ShortLeftArrow;": '\U00002190',
+ "ShortRightArrow;": '\U00002192',
+ "ShortUpArrow;": '\U00002191',
+ "Sigma;": '\U000003A3',
+ "SmallCircle;": '\U00002218',
+ "Sopf;": '\U0001D54A',
+ "Sqrt;": '\U0000221A',
+ "Square;": '\U000025A1',
+ "SquareIntersection;": '\U00002293',
+ "SquareSubset;": '\U0000228F',
+ "SquareSubsetEqual;": '\U00002291',
+ "SquareSuperset;": '\U00002290',
+ "SquareSupersetEqual;": '\U00002292',
+ "SquareUnion;": '\U00002294',
+ "Sscr;": '\U0001D4AE',
+ "Star;": '\U000022C6',
+ "Sub;": '\U000022D0',
+ "Subset;": '\U000022D0',
+ "SubsetEqual;": '\U00002286',
+ "Succeeds;": '\U0000227B',
+ "SucceedsEqual;": '\U00002AB0',
+ "SucceedsSlantEqual;": '\U0000227D',
+ "SucceedsTilde;": '\U0000227F',
+ "SuchThat;": '\U0000220B',
+ "Sum;": '\U00002211',
+ "Sup;": '\U000022D1',
+ "Superset;": '\U00002283',
+ "SupersetEqual;": '\U00002287',
+ "Supset;": '\U000022D1',
+ "THORN;": '\U000000DE',
+ "TRADE;": '\U00002122',
+ "TSHcy;": '\U0000040B',
+ "TScy;": '\U00000426',
+ "Tab;": '\U00000009',
+ "Tau;": '\U000003A4',
+ "Tcaron;": '\U00000164',
+ "Tcedil;": '\U00000162',
+ "Tcy;": '\U00000422',
+ "Tfr;": '\U0001D517',
+ "Therefore;": '\U00002234',
+ "Theta;": '\U00000398',
+ "ThinSpace;": '\U00002009',
+ "Tilde;": '\U0000223C',
+ "TildeEqual;": '\U00002243',
+ "TildeFullEqual;": '\U00002245',
+ "TildeTilde;": '\U00002248',
+ "Topf;": '\U0001D54B',
+ "TripleDot;": '\U000020DB',
+ "Tscr;": '\U0001D4AF',
+ "Tstrok;": '\U00000166',
+ "Uacute;": '\U000000DA',
+ "Uarr;": '\U0000219F',
+ "Uarrocir;": '\U00002949',
+ "Ubrcy;": '\U0000040E',
+ "Ubreve;": '\U0000016C',
+ "Ucirc;": '\U000000DB',
+ "Ucy;": '\U00000423',
+ "Udblac;": '\U00000170',
+ "Ufr;": '\U0001D518',
+ "Ugrave;": '\U000000D9',
+ "Umacr;": '\U0000016A',
+ "UnderBar;": '\U0000005F',
+ "UnderBrace;": '\U000023DF',
+ "UnderBracket;": '\U000023B5',
+ "UnderParenthesis;": '\U000023DD',
+ "Union;": '\U000022C3',
+ "UnionPlus;": '\U0000228E',
+ "Uogon;": '\U00000172',
+ "Uopf;": '\U0001D54C',
+ "UpArrow;": '\U00002191',
+ "UpArrowBar;": '\U00002912',
+ "UpArrowDownArrow;": '\U000021C5',
+ "UpDownArrow;": '\U00002195',
+ "UpEquilibrium;": '\U0000296E',
+ "UpTee;": '\U000022A5',
+ "UpTeeArrow;": '\U000021A5',
+ "Uparrow;": '\U000021D1',
+ "Updownarrow;": '\U000021D5',
+ "UpperLeftArrow;": '\U00002196',
+ "UpperRightArrow;": '\U00002197',
+ "Upsi;": '\U000003D2',
+ "Upsilon;": '\U000003A5',
+ "Uring;": '\U0000016E',
+ "Uscr;": '\U0001D4B0',
+ "Utilde;": '\U00000168',
+ "Uuml;": '\U000000DC',
+ "VDash;": '\U000022AB',
+ "Vbar;": '\U00002AEB',
+ "Vcy;": '\U00000412',
+ "Vdash;": '\U000022A9',
+ "Vdashl;": '\U00002AE6',
+ "Vee;": '\U000022C1',
+ "Verbar;": '\U00002016',
+ "Vert;": '\U00002016',
+ "VerticalBar;": '\U00002223',
+ "VerticalLine;": '\U0000007C',
+ "VerticalSeparator;": '\U00002758',
+ "VerticalTilde;": '\U00002240',
+ "VeryThinSpace;": '\U0000200A',
+ "Vfr;": '\U0001D519',
+ "Vopf;": '\U0001D54D',
+ "Vscr;": '\U0001D4B1',
+ "Vvdash;": '\U000022AA',
+ "Wcirc;": '\U00000174',
+ "Wedge;": '\U000022C0',
+ "Wfr;": '\U0001D51A',
+ "Wopf;": '\U0001D54E',
+ "Wscr;": '\U0001D4B2',
+ "Xfr;": '\U0001D51B',
+ "Xi;": '\U0000039E',
+ "Xopf;": '\U0001D54F',
+ "Xscr;": '\U0001D4B3',
+ "YAcy;": '\U0000042F',
+ "YIcy;": '\U00000407',
+ "YUcy;": '\U0000042E',
+ "Yacute;": '\U000000DD',
+ "Ycirc;": '\U00000176',
+ "Ycy;": '\U0000042B',
+ "Yfr;": '\U0001D51C',
+ "Yopf;": '\U0001D550',
+ "Yscr;": '\U0001D4B4',
+ "Yuml;": '\U00000178',
+ "ZHcy;": '\U00000416',
+ "Zacute;": '\U00000179',
+ "Zcaron;": '\U0000017D',
+ "Zcy;": '\U00000417',
+ "Zdot;": '\U0000017B',
+ "ZeroWidthSpace;": '\U0000200B',
+ "Zeta;": '\U00000396',
+ "Zfr;": '\U00002128',
+ "Zopf;": '\U00002124',
+ "Zscr;": '\U0001D4B5',
+ "aacute;": '\U000000E1',
+ "abreve;": '\U00000103',
+ "ac;": '\U0000223E',
+ "acd;": '\U0000223F',
+ "acirc;": '\U000000E2',
+ "acute;": '\U000000B4',
+ "acy;": '\U00000430',
+ "aelig;": '\U000000E6',
+ "af;": '\U00002061',
+ "afr;": '\U0001D51E',
+ "agrave;": '\U000000E0',
+ "alefsym;": '\U00002135',
+ "aleph;": '\U00002135',
+ "alpha;": '\U000003B1',
+ "amacr;": '\U00000101',
+ "amalg;": '\U00002A3F',
+ "amp;": '\U00000026',
+ "and;": '\U00002227',
+ "andand;": '\U00002A55',
+ "andd;": '\U00002A5C',
+ "andslope;": '\U00002A58',
+ "andv;": '\U00002A5A',
+ "ang;": '\U00002220',
+ "ange;": '\U000029A4',
+ "angle;": '\U00002220',
+ "angmsd;": '\U00002221',
+ "angmsdaa;": '\U000029A8',
+ "angmsdab;": '\U000029A9',
+ "angmsdac;": '\U000029AA',
+ "angmsdad;": '\U000029AB',
+ "angmsdae;": '\U000029AC',
+ "angmsdaf;": '\U000029AD',
+ "angmsdag;": '\U000029AE',
+ "angmsdah;": '\U000029AF',
+ "angrt;": '\U0000221F',
+ "angrtvb;": '\U000022BE',
+ "angrtvbd;": '\U0000299D',
+ "angsph;": '\U00002222',
+ "angst;": '\U000000C5',
+ "angzarr;": '\U0000237C',
+ "aogon;": '\U00000105',
+ "aopf;": '\U0001D552',
+ "ap;": '\U00002248',
+ "apE;": '\U00002A70',
+ "apacir;": '\U00002A6F',
+ "ape;": '\U0000224A',
+ "apid;": '\U0000224B',
+ "apos;": '\U00000027',
+ "approx;": '\U00002248',
+ "approxeq;": '\U0000224A',
+ "aring;": '\U000000E5',
+ "ascr;": '\U0001D4B6',
+ "ast;": '\U0000002A',
+ "asymp;": '\U00002248',
+ "asympeq;": '\U0000224D',
+ "atilde;": '\U000000E3',
+ "auml;": '\U000000E4',
+ "awconint;": '\U00002233',
+ "awint;": '\U00002A11',
+ "bNot;": '\U00002AED',
+ "backcong;": '\U0000224C',
+ "backepsilon;": '\U000003F6',
+ "backprime;": '\U00002035',
+ "backsim;": '\U0000223D',
+ "backsimeq;": '\U000022CD',
+ "barvee;": '\U000022BD',
+ "barwed;": '\U00002305',
+ "barwedge;": '\U00002305',
+ "bbrk;": '\U000023B5',
+ "bbrktbrk;": '\U000023B6',
+ "bcong;": '\U0000224C',
+ "bcy;": '\U00000431',
+ "bdquo;": '\U0000201E',
+ "becaus;": '\U00002235',
+ "because;": '\U00002235',
+ "bemptyv;": '\U000029B0',
+ "bepsi;": '\U000003F6',
+ "bernou;": '\U0000212C',
+ "beta;": '\U000003B2',
+ "beth;": '\U00002136',
+ "between;": '\U0000226C',
+ "bfr;": '\U0001D51F',
+ "bigcap;": '\U000022C2',
+ "bigcirc;": '\U000025EF',
+ "bigcup;": '\U000022C3',
+ "bigodot;": '\U00002A00',
+ "bigoplus;": '\U00002A01',
+ "bigotimes;": '\U00002A02',
+ "bigsqcup;": '\U00002A06',
+ "bigstar;": '\U00002605',
+ "bigtriangledown;": '\U000025BD',
+ "bigtriangleup;": '\U000025B3',
+ "biguplus;": '\U00002A04',
+ "bigvee;": '\U000022C1',
+ "bigwedge;": '\U000022C0',
+ "bkarow;": '\U0000290D',
+ "blacklozenge;": '\U000029EB',
+ "blacksquare;": '\U000025AA',
+ "blacktriangle;": '\U000025B4',
+ "blacktriangledown;": '\U000025BE',
+ "blacktriangleleft;": '\U000025C2',
+ "blacktriangleright;": '\U000025B8',
+ "blank;": '\U00002423',
+ "blk12;": '\U00002592',
+ "blk14;": '\U00002591',
+ "blk34;": '\U00002593',
+ "block;": '\U00002588',
+ "bnot;": '\U00002310',
+ "bopf;": '\U0001D553',
+ "bot;": '\U000022A5',
+ "bottom;": '\U000022A5',
+ "bowtie;": '\U000022C8',
+ "boxDL;": '\U00002557',
+ "boxDR;": '\U00002554',
+ "boxDl;": '\U00002556',
+ "boxDr;": '\U00002553',
+ "boxH;": '\U00002550',
+ "boxHD;": '\U00002566',
+ "boxHU;": '\U00002569',
+ "boxHd;": '\U00002564',
+ "boxHu;": '\U00002567',
+ "boxUL;": '\U0000255D',
+ "boxUR;": '\U0000255A',
+ "boxUl;": '\U0000255C',
+ "boxUr;": '\U00002559',
+ "boxV;": '\U00002551',
+ "boxVH;": '\U0000256C',
+ "boxVL;": '\U00002563',
+ "boxVR;": '\U00002560',
+ "boxVh;": '\U0000256B',
+ "boxVl;": '\U00002562',
+ "boxVr;": '\U0000255F',
+ "boxbox;": '\U000029C9',
+ "boxdL;": '\U00002555',
+ "boxdR;": '\U00002552',
+ "boxdl;": '\U00002510',
+ "boxdr;": '\U0000250C',
+ "boxh;": '\U00002500',
+ "boxhD;": '\U00002565',
+ "boxhU;": '\U00002568',
+ "boxhd;": '\U0000252C',
+ "boxhu;": '\U00002534',
+ "boxminus;": '\U0000229F',
+ "boxplus;": '\U0000229E',
+ "boxtimes;": '\U000022A0',
+ "boxuL;": '\U0000255B',
+ "boxuR;": '\U00002558',
+ "boxul;": '\U00002518',
+ "boxur;": '\U00002514',
+ "boxv;": '\U00002502',
+ "boxvH;": '\U0000256A',
+ "boxvL;": '\U00002561',
+ "boxvR;": '\U0000255E',
+ "boxvh;": '\U0000253C',
+ "boxvl;": '\U00002524',
+ "boxvr;": '\U0000251C',
+ "bprime;": '\U00002035',
+ "breve;": '\U000002D8',
+ "brvbar;": '\U000000A6',
+ "bscr;": '\U0001D4B7',
+ "bsemi;": '\U0000204F',
+ "bsim;": '\U0000223D',
+ "bsime;": '\U000022CD',
+ "bsol;": '\U0000005C',
+ "bsolb;": '\U000029C5',
+ "bsolhsub;": '\U000027C8',
+ "bull;": '\U00002022',
+ "bullet;": '\U00002022',
+ "bump;": '\U0000224E',
+ "bumpE;": '\U00002AAE',
+ "bumpe;": '\U0000224F',
+ "bumpeq;": '\U0000224F',
+ "cacute;": '\U00000107',
+ "cap;": '\U00002229',
+ "capand;": '\U00002A44',
+ "capbrcup;": '\U00002A49',
+ "capcap;": '\U00002A4B',
+ "capcup;": '\U00002A47',
+ "capdot;": '\U00002A40',
+ "caret;": '\U00002041',
+ "caron;": '\U000002C7',
+ "ccaps;": '\U00002A4D',
+ "ccaron;": '\U0000010D',
+ "ccedil;": '\U000000E7',
+ "ccirc;": '\U00000109',
+ "ccups;": '\U00002A4C',
+ "ccupssm;": '\U00002A50',
+ "cdot;": '\U0000010B',
+ "cedil;": '\U000000B8',
+ "cemptyv;": '\U000029B2',
+ "cent;": '\U000000A2',
+ "centerdot;": '\U000000B7',
+ "cfr;": '\U0001D520',
+ "chcy;": '\U00000447',
+ "check;": '\U00002713',
+ "checkmark;": '\U00002713',
+ "chi;": '\U000003C7',
+ "cir;": '\U000025CB',
+ "cirE;": '\U000029C3',
+ "circ;": '\U000002C6',
+ "circeq;": '\U00002257',
+ "circlearrowleft;": '\U000021BA',
+ "circlearrowright;": '\U000021BB',
+ "circledR;": '\U000000AE',
+ "circledS;": '\U000024C8',
+ "circledast;": '\U0000229B',
+ "circledcirc;": '\U0000229A',
+ "circleddash;": '\U0000229D',
+ "cire;": '\U00002257',
+ "cirfnint;": '\U00002A10',
+ "cirmid;": '\U00002AEF',
+ "cirscir;": '\U000029C2',
+ "clubs;": '\U00002663',
+ "clubsuit;": '\U00002663',
+ "colon;": '\U0000003A',
+ "colone;": '\U00002254',
+ "coloneq;": '\U00002254',
+ "comma;": '\U0000002C',
+ "commat;": '\U00000040',
+ "comp;": '\U00002201',
+ "compfn;": '\U00002218',
+ "complement;": '\U00002201',
+ "complexes;": '\U00002102',
+ "cong;": '\U00002245',
+ "congdot;": '\U00002A6D',
+ "conint;": '\U0000222E',
+ "copf;": '\U0001D554',
+ "coprod;": '\U00002210',
+ "copy;": '\U000000A9',
+ "copysr;": '\U00002117',
+ "crarr;": '\U000021B5',
+ "cross;": '\U00002717',
+ "cscr;": '\U0001D4B8',
+ "csub;": '\U00002ACF',
+ "csube;": '\U00002AD1',
+ "csup;": '\U00002AD0',
+ "csupe;": '\U00002AD2',
+ "ctdot;": '\U000022EF',
+ "cudarrl;": '\U00002938',
+ "cudarrr;": '\U00002935',
+ "cuepr;": '\U000022DE',
+ "cuesc;": '\U000022DF',
+ "cularr;": '\U000021B6',
+ "cularrp;": '\U0000293D',
+ "cup;": '\U0000222A',
+ "cupbrcap;": '\U00002A48',
+ "cupcap;": '\U00002A46',
+ "cupcup;": '\U00002A4A',
+ "cupdot;": '\U0000228D',
+ "cupor;": '\U00002A45',
+ "curarr;": '\U000021B7',
+ "curarrm;": '\U0000293C',
+ "curlyeqprec;": '\U000022DE',
+ "curlyeqsucc;": '\U000022DF',
+ "curlyvee;": '\U000022CE',
+ "curlywedge;": '\U000022CF',
+ "curren;": '\U000000A4',
+ "curvearrowleft;": '\U000021B6',
+ "curvearrowright;": '\U000021B7',
+ "cuvee;": '\U000022CE',
+ "cuwed;": '\U000022CF',
+ "cwconint;": '\U00002232',
+ "cwint;": '\U00002231',
+ "cylcty;": '\U0000232D',
+ "dArr;": '\U000021D3',
+ "dHar;": '\U00002965',
+ "dagger;": '\U00002020',
+ "daleth;": '\U00002138',
+ "darr;": '\U00002193',
+ "dash;": '\U00002010',
+ "dashv;": '\U000022A3',
+ "dbkarow;": '\U0000290F',
+ "dblac;": '\U000002DD',
+ "dcaron;": '\U0000010F',
+ "dcy;": '\U00000434',
+ "dd;": '\U00002146',
+ "ddagger;": '\U00002021',
+ "ddarr;": '\U000021CA',
+ "ddotseq;": '\U00002A77',
+ "deg;": '\U000000B0',
+ "delta;": '\U000003B4',
+ "demptyv;": '\U000029B1',
+ "dfisht;": '\U0000297F',
+ "dfr;": '\U0001D521',
+ "dharl;": '\U000021C3',
+ "dharr;": '\U000021C2',
+ "diam;": '\U000022C4',
+ "diamond;": '\U000022C4',
+ "diamondsuit;": '\U00002666',
+ "diams;": '\U00002666',
+ "die;": '\U000000A8',
+ "digamma;": '\U000003DD',
+ "disin;": '\U000022F2',
+ "div;": '\U000000F7',
+ "divide;": '\U000000F7',
+ "divideontimes;": '\U000022C7',
+ "divonx;": '\U000022C7',
+ "djcy;": '\U00000452',
+ "dlcorn;": '\U0000231E',
+ "dlcrop;": '\U0000230D',
+ "dollar;": '\U00000024',
+ "dopf;": '\U0001D555',
+ "dot;": '\U000002D9',
+ "doteq;": '\U00002250',
+ "doteqdot;": '\U00002251',
+ "dotminus;": '\U00002238',
+ "dotplus;": '\U00002214',
+ "dotsquare;": '\U000022A1',
+ "doublebarwedge;": '\U00002306',
+ "downarrow;": '\U00002193',
+ "downdownarrows;": '\U000021CA',
+ "downharpoonleft;": '\U000021C3',
+ "downharpoonright;": '\U000021C2',
+ "drbkarow;": '\U00002910',
+ "drcorn;": '\U0000231F',
+ "drcrop;": '\U0000230C',
+ "dscr;": '\U0001D4B9',
+ "dscy;": '\U00000455',
+ "dsol;": '\U000029F6',
+ "dstrok;": '\U00000111',
+ "dtdot;": '\U000022F1',
+ "dtri;": '\U000025BF',
+ "dtrif;": '\U000025BE',
+ "duarr;": '\U000021F5',
+ "duhar;": '\U0000296F',
+ "dwangle;": '\U000029A6',
+ "dzcy;": '\U0000045F',
+ "dzigrarr;": '\U000027FF',
+ "eDDot;": '\U00002A77',
+ "eDot;": '\U00002251',
+ "eacute;": '\U000000E9',
+ "easter;": '\U00002A6E',
+ "ecaron;": '\U0000011B',
+ "ecir;": '\U00002256',
+ "ecirc;": '\U000000EA',
+ "ecolon;": '\U00002255',
+ "ecy;": '\U0000044D',
+ "edot;": '\U00000117',
+ "ee;": '\U00002147',
+ "efDot;": '\U00002252',
+ "efr;": '\U0001D522',
+ "eg;": '\U00002A9A',
+ "egrave;": '\U000000E8',
+ "egs;": '\U00002A96',
+ "egsdot;": '\U00002A98',
+ "el;": '\U00002A99',
+ "elinters;": '\U000023E7',
+ "ell;": '\U00002113',
+ "els;": '\U00002A95',
+ "elsdot;": '\U00002A97',
+ "emacr;": '\U00000113',
+ "empty;": '\U00002205',
+ "emptyset;": '\U00002205',
+ "emptyv;": '\U00002205',
+ "emsp;": '\U00002003',
+ "emsp13;": '\U00002004',
+ "emsp14;": '\U00002005',
+ "eng;": '\U0000014B',
+ "ensp;": '\U00002002',
+ "eogon;": '\U00000119',
+ "eopf;": '\U0001D556',
+ "epar;": '\U000022D5',
+ "eparsl;": '\U000029E3',
+ "eplus;": '\U00002A71',
+ "epsi;": '\U000003B5',
+ "epsilon;": '\U000003B5',
+ "epsiv;": '\U000003F5',
+ "eqcirc;": '\U00002256',
+ "eqcolon;": '\U00002255',
+ "eqsim;": '\U00002242',
+ "eqslantgtr;": '\U00002A96',
+ "eqslantless;": '\U00002A95',
+ "equals;": '\U0000003D',
+ "equest;": '\U0000225F',
+ "equiv;": '\U00002261',
+ "equivDD;": '\U00002A78',
+ "eqvparsl;": '\U000029E5',
+ "erDot;": '\U00002253',
+ "erarr;": '\U00002971',
+ "escr;": '\U0000212F',
+ "esdot;": '\U00002250',
+ "esim;": '\U00002242',
+ "eta;": '\U000003B7',
+ "eth;": '\U000000F0',
+ "euml;": '\U000000EB',
+ "euro;": '\U000020AC',
+ "excl;": '\U00000021',
+ "exist;": '\U00002203',
+ "expectation;": '\U00002130',
+ "exponentiale;": '\U00002147',
+ "fallingdotseq;": '\U00002252',
+ "fcy;": '\U00000444',
+ "female;": '\U00002640',
+ "ffilig;": '\U0000FB03',
+ "fflig;": '\U0000FB00',
+ "ffllig;": '\U0000FB04',
+ "ffr;": '\U0001D523',
+ "filig;": '\U0000FB01',
+ "flat;": '\U0000266D',
+ "fllig;": '\U0000FB02',
+ "fltns;": '\U000025B1',
+ "fnof;": '\U00000192',
+ "fopf;": '\U0001D557',
+ "forall;": '\U00002200',
+ "fork;": '\U000022D4',
+ "forkv;": '\U00002AD9',
+ "fpartint;": '\U00002A0D',
+ "frac12;": '\U000000BD',
+ "frac13;": '\U00002153',
+ "frac14;": '\U000000BC',
+ "frac15;": '\U00002155',
+ "frac16;": '\U00002159',
+ "frac18;": '\U0000215B',
+ "frac23;": '\U00002154',
+ "frac25;": '\U00002156',
+ "frac34;": '\U000000BE',
+ "frac35;": '\U00002157',
+ "frac38;": '\U0000215C',
+ "frac45;": '\U00002158',
+ "frac56;": '\U0000215A',
+ "frac58;": '\U0000215D',
+ "frac78;": '\U0000215E',
+ "frasl;": '\U00002044',
+ "frown;": '\U00002322',
+ "fscr;": '\U0001D4BB',
+ "gE;": '\U00002267',
+ "gEl;": '\U00002A8C',
+ "gacute;": '\U000001F5',
+ "gamma;": '\U000003B3',
+ "gammad;": '\U000003DD',
+ "gap;": '\U00002A86',
+ "gbreve;": '\U0000011F',
+ "gcirc;": '\U0000011D',
+ "gcy;": '\U00000433',
+ "gdot;": '\U00000121',
+ "ge;": '\U00002265',
+ "gel;": '\U000022DB',
+ "geq;": '\U00002265',
+ "geqq;": '\U00002267',
+ "geqslant;": '\U00002A7E',
+ "ges;": '\U00002A7E',
+ "gescc;": '\U00002AA9',
+ "gesdot;": '\U00002A80',
+ "gesdoto;": '\U00002A82',
+ "gesdotol;": '\U00002A84',
+ "gesles;": '\U00002A94',
+ "gfr;": '\U0001D524',
+ "gg;": '\U0000226B',
+ "ggg;": '\U000022D9',
+ "gimel;": '\U00002137',
+ "gjcy;": '\U00000453',
+ "gl;": '\U00002277',
+ "glE;": '\U00002A92',
+ "gla;": '\U00002AA5',
+ "glj;": '\U00002AA4',
+ "gnE;": '\U00002269',
+ "gnap;": '\U00002A8A',
+ "gnapprox;": '\U00002A8A',
+ "gne;": '\U00002A88',
+ "gneq;": '\U00002A88',
+ "gneqq;": '\U00002269',
+ "gnsim;": '\U000022E7',
+ "gopf;": '\U0001D558',
+ "grave;": '\U00000060',
+ "gscr;": '\U0000210A',
+ "gsim;": '\U00002273',
+ "gsime;": '\U00002A8E',
+ "gsiml;": '\U00002A90',
+ "gt;": '\U0000003E',
+ "gtcc;": '\U00002AA7',
+ "gtcir;": '\U00002A7A',
+ "gtdot;": '\U000022D7',
+ "gtlPar;": '\U00002995',
+ "gtquest;": '\U00002A7C',
+ "gtrapprox;": '\U00002A86',
+ "gtrarr;": '\U00002978',
+ "gtrdot;": '\U000022D7',
+ "gtreqless;": '\U000022DB',
+ "gtreqqless;": '\U00002A8C',
+ "gtrless;": '\U00002277',
+ "gtrsim;": '\U00002273',
+ "hArr;": '\U000021D4',
+ "hairsp;": '\U0000200A',
+ "half;": '\U000000BD',
+ "hamilt;": '\U0000210B',
+ "hardcy;": '\U0000044A',
+ "harr;": '\U00002194',
+ "harrcir;": '\U00002948',
+ "harrw;": '\U000021AD',
+ "hbar;": '\U0000210F',
+ "hcirc;": '\U00000125',
+ "hearts;": '\U00002665',
+ "heartsuit;": '\U00002665',
+ "hellip;": '\U00002026',
+ "hercon;": '\U000022B9',
+ "hfr;": '\U0001D525',
+ "hksearow;": '\U00002925',
+ "hkswarow;": '\U00002926',
+ "hoarr;": '\U000021FF',
+ "homtht;": '\U0000223B',
+ "hookleftarrow;": '\U000021A9',
+ "hookrightarrow;": '\U000021AA',
+ "hopf;": '\U0001D559',
+ "horbar;": '\U00002015',
+ "hscr;": '\U0001D4BD',
+ "hslash;": '\U0000210F',
+ "hstrok;": '\U00000127',
+ "hybull;": '\U00002043',
+ "hyphen;": '\U00002010',
+ "iacute;": '\U000000ED',
+ "ic;": '\U00002063',
+ "icirc;": '\U000000EE',
+ "icy;": '\U00000438',
+ "iecy;": '\U00000435',
+ "iexcl;": '\U000000A1',
+ "iff;": '\U000021D4',
+ "ifr;": '\U0001D526',
+ "igrave;": '\U000000EC',
+ "ii;": '\U00002148',
+ "iiiint;": '\U00002A0C',
+ "iiint;": '\U0000222D',
+ "iinfin;": '\U000029DC',
+ "iiota;": '\U00002129',
+ "ijlig;": '\U00000133',
+ "imacr;": '\U0000012B',
+ "image;": '\U00002111',
+ "imagline;": '\U00002110',
+ "imagpart;": '\U00002111',
+ "imath;": '\U00000131',
+ "imof;": '\U000022B7',
+ "imped;": '\U000001B5',
+ "in;": '\U00002208',
+ "incare;": '\U00002105',
+ "infin;": '\U0000221E',
+ "infintie;": '\U000029DD',
+ "inodot;": '\U00000131',
+ "int;": '\U0000222B',
+ "intcal;": '\U000022BA',
+ "integers;": '\U00002124',
+ "intercal;": '\U000022BA',
+ "intlarhk;": '\U00002A17',
+ "intprod;": '\U00002A3C',
+ "iocy;": '\U00000451',
+ "iogon;": '\U0000012F',
+ "iopf;": '\U0001D55A',
+ "iota;": '\U000003B9',
+ "iprod;": '\U00002A3C',
+ "iquest;": '\U000000BF',
+ "iscr;": '\U0001D4BE',
+ "isin;": '\U00002208',
+ "isinE;": '\U000022F9',
+ "isindot;": '\U000022F5',
+ "isins;": '\U000022F4',
+ "isinsv;": '\U000022F3',
+ "isinv;": '\U00002208',
+ "it;": '\U00002062',
+ "itilde;": '\U00000129',
+ "iukcy;": '\U00000456',
+ "iuml;": '\U000000EF',
+ "jcirc;": '\U00000135',
+ "jcy;": '\U00000439',
+ "jfr;": '\U0001D527',
+ "jmath;": '\U00000237',
+ "jopf;": '\U0001D55B',
+ "jscr;": '\U0001D4BF',
+ "jsercy;": '\U00000458',
+ "jukcy;": '\U00000454',
+ "kappa;": '\U000003BA',
+ "kappav;": '\U000003F0',
+ "kcedil;": '\U00000137',
+ "kcy;": '\U0000043A',
+ "kfr;": '\U0001D528',
+ "kgreen;": '\U00000138',
+ "khcy;": '\U00000445',
+ "kjcy;": '\U0000045C',
+ "kopf;": '\U0001D55C',
+ "kscr;": '\U0001D4C0',
+ "lAarr;": '\U000021DA',
+ "lArr;": '\U000021D0',
+ "lAtail;": '\U0000291B',
+ "lBarr;": '\U0000290E',
+ "lE;": '\U00002266',
+ "lEg;": '\U00002A8B',
+ "lHar;": '\U00002962',
+ "lacute;": '\U0000013A',
+ "laemptyv;": '\U000029B4',
+ "lagran;": '\U00002112',
+ "lambda;": '\U000003BB',
+ "lang;": '\U000027E8',
+ "langd;": '\U00002991',
+ "langle;": '\U000027E8',
+ "lap;": '\U00002A85',
+ "laquo;": '\U000000AB',
+ "larr;": '\U00002190',
+ "larrb;": '\U000021E4',
+ "larrbfs;": '\U0000291F',
+ "larrfs;": '\U0000291D',
+ "larrhk;": '\U000021A9',
+ "larrlp;": '\U000021AB',
+ "larrpl;": '\U00002939',
+ "larrsim;": '\U00002973',
+ "larrtl;": '\U000021A2',
+ "lat;": '\U00002AAB',
+ "latail;": '\U00002919',
+ "late;": '\U00002AAD',
+ "lbarr;": '\U0000290C',
+ "lbbrk;": '\U00002772',
+ "lbrace;": '\U0000007B',
+ "lbrack;": '\U0000005B',
+ "lbrke;": '\U0000298B',
+ "lbrksld;": '\U0000298F',
+ "lbrkslu;": '\U0000298D',
+ "lcaron;": '\U0000013E',
+ "lcedil;": '\U0000013C',
+ "lceil;": '\U00002308',
+ "lcub;": '\U0000007B',
+ "lcy;": '\U0000043B',
+ "ldca;": '\U00002936',
+ "ldquo;": '\U0000201C',
+ "ldquor;": '\U0000201E',
+ "ldrdhar;": '\U00002967',
+ "ldrushar;": '\U0000294B',
+ "ldsh;": '\U000021B2',
+ "le;": '\U00002264',
+ "leftarrow;": '\U00002190',
+ "leftarrowtail;": '\U000021A2',
+ "leftharpoondown;": '\U000021BD',
+ "leftharpoonup;": '\U000021BC',
+ "leftleftarrows;": '\U000021C7',
+ "leftrightarrow;": '\U00002194',
+ "leftrightarrows;": '\U000021C6',
+ "leftrightharpoons;": '\U000021CB',
+ "leftrightsquigarrow;": '\U000021AD',
+ "leftthreetimes;": '\U000022CB',
+ "leg;": '\U000022DA',
+ "leq;": '\U00002264',
+ "leqq;": '\U00002266',
+ "leqslant;": '\U00002A7D',
+ "les;": '\U00002A7D',
+ "lescc;": '\U00002AA8',
+ "lesdot;": '\U00002A7F',
+ "lesdoto;": '\U00002A81',
+ "lesdotor;": '\U00002A83',
+ "lesges;": '\U00002A93',
+ "lessapprox;": '\U00002A85',
+ "lessdot;": '\U000022D6',
+ "lesseqgtr;": '\U000022DA',
+ "lesseqqgtr;": '\U00002A8B',
+ "lessgtr;": '\U00002276',
+ "lesssim;": '\U00002272',
+ "lfisht;": '\U0000297C',
+ "lfloor;": '\U0000230A',
+ "lfr;": '\U0001D529',
+ "lg;": '\U00002276',
+ "lgE;": '\U00002A91',
+ "lhard;": '\U000021BD',
+ "lharu;": '\U000021BC',
+ "lharul;": '\U0000296A',
+ "lhblk;": '\U00002584',
+ "ljcy;": '\U00000459',
+ "ll;": '\U0000226A',
+ "llarr;": '\U000021C7',
+ "llcorner;": '\U0000231E',
+ "llhard;": '\U0000296B',
+ "lltri;": '\U000025FA',
+ "lmidot;": '\U00000140',
+ "lmoust;": '\U000023B0',
+ "lmoustache;": '\U000023B0',
+ "lnE;": '\U00002268',
+ "lnap;": '\U00002A89',
+ "lnapprox;": '\U00002A89',
+ "lne;": '\U00002A87',
+ "lneq;": '\U00002A87',
+ "lneqq;": '\U00002268',
+ "lnsim;": '\U000022E6',
+ "loang;": '\U000027EC',
+ "loarr;": '\U000021FD',
+ "lobrk;": '\U000027E6',
+ "longleftarrow;": '\U000027F5',
+ "longleftrightarrow;": '\U000027F7',
+ "longmapsto;": '\U000027FC',
+ "longrightarrow;": '\U000027F6',
+ "looparrowleft;": '\U000021AB',
+ "looparrowright;": '\U000021AC',
+ "lopar;": '\U00002985',
+ "lopf;": '\U0001D55D',
+ "loplus;": '\U00002A2D',
+ "lotimes;": '\U00002A34',
+ "lowast;": '\U00002217',
+ "lowbar;": '\U0000005F',
+ "loz;": '\U000025CA',
+ "lozenge;": '\U000025CA',
+ "lozf;": '\U000029EB',
+ "lpar;": '\U00000028',
+ "lparlt;": '\U00002993',
+ "lrarr;": '\U000021C6',
+ "lrcorner;": '\U0000231F',
+ "lrhar;": '\U000021CB',
+ "lrhard;": '\U0000296D',
+ "lrm;": '\U0000200E',
+ "lrtri;": '\U000022BF',
+ "lsaquo;": '\U00002039',
+ "lscr;": '\U0001D4C1',
+ "lsh;": '\U000021B0',
+ "lsim;": '\U00002272',
+ "lsime;": '\U00002A8D',
+ "lsimg;": '\U00002A8F',
+ "lsqb;": '\U0000005B',
+ "lsquo;": '\U00002018',
+ "lsquor;": '\U0000201A',
+ "lstrok;": '\U00000142',
+ "lt;": '\U0000003C',
+ "ltcc;": '\U00002AA6',
+ "ltcir;": '\U00002A79',
+ "ltdot;": '\U000022D6',
+ "lthree;": '\U000022CB',
+ "ltimes;": '\U000022C9',
+ "ltlarr;": '\U00002976',
+ "ltquest;": '\U00002A7B',
+ "ltrPar;": '\U00002996',
+ "ltri;": '\U000025C3',
+ "ltrie;": '\U000022B4',
+ "ltrif;": '\U000025C2',
+ "lurdshar;": '\U0000294A',
+ "luruhar;": '\U00002966',
+ "mDDot;": '\U0000223A',
+ "macr;": '\U000000AF',
+ "male;": '\U00002642',
+ "malt;": '\U00002720',
+ "maltese;": '\U00002720',
+ "map;": '\U000021A6',
+ "mapsto;": '\U000021A6',
+ "mapstodown;": '\U000021A7',
+ "mapstoleft;": '\U000021A4',
+ "mapstoup;": '\U000021A5',
+ "marker;": '\U000025AE',
+ "mcomma;": '\U00002A29',
+ "mcy;": '\U0000043C',
+ "mdash;": '\U00002014',
+ "measuredangle;": '\U00002221',
+ "mfr;": '\U0001D52A',
+ "mho;": '\U00002127',
+ "micro;": '\U000000B5',
+ "mid;": '\U00002223',
+ "midast;": '\U0000002A',
+ "midcir;": '\U00002AF0',
+ "middot;": '\U000000B7',
+ "minus;": '\U00002212',
+ "minusb;": '\U0000229F',
+ "minusd;": '\U00002238',
+ "minusdu;": '\U00002A2A',
+ "mlcp;": '\U00002ADB',
+ "mldr;": '\U00002026',
+ "mnplus;": '\U00002213',
+ "models;": '\U000022A7',
+ "mopf;": '\U0001D55E',
+ "mp;": '\U00002213',
+ "mscr;": '\U0001D4C2',
+ "mstpos;": '\U0000223E',
+ "mu;": '\U000003BC',
+ "multimap;": '\U000022B8',
+ "mumap;": '\U000022B8',
+ "nLeftarrow;": '\U000021CD',
+ "nLeftrightarrow;": '\U000021CE',
+ "nRightarrow;": '\U000021CF',
+ "nVDash;": '\U000022AF',
+ "nVdash;": '\U000022AE',
+ "nabla;": '\U00002207',
+ "nacute;": '\U00000144',
+ "nap;": '\U00002249',
+ "napos;": '\U00000149',
+ "napprox;": '\U00002249',
+ "natur;": '\U0000266E',
+ "natural;": '\U0000266E',
+ "naturals;": '\U00002115',
+ "nbsp;": '\U000000A0',
+ "ncap;": '\U00002A43',
+ "ncaron;": '\U00000148',
+ "ncedil;": '\U00000146',
+ "ncong;": '\U00002247',
+ "ncup;": '\U00002A42',
+ "ncy;": '\U0000043D',
+ "ndash;": '\U00002013',
+ "ne;": '\U00002260',
+ "neArr;": '\U000021D7',
+ "nearhk;": '\U00002924',
+ "nearr;": '\U00002197',
+ "nearrow;": '\U00002197',
+ "nequiv;": '\U00002262',
+ "nesear;": '\U00002928',
+ "nexist;": '\U00002204',
+ "nexists;": '\U00002204',
+ "nfr;": '\U0001D52B',
+ "nge;": '\U00002271',
+ "ngeq;": '\U00002271',
+ "ngsim;": '\U00002275',
+ "ngt;": '\U0000226F',
+ "ngtr;": '\U0000226F',
+ "nhArr;": '\U000021CE',
+ "nharr;": '\U000021AE',
+ "nhpar;": '\U00002AF2',
+ "ni;": '\U0000220B',
+ "nis;": '\U000022FC',
+ "nisd;": '\U000022FA',
+ "niv;": '\U0000220B',
+ "njcy;": '\U0000045A',
+ "nlArr;": '\U000021CD',
+ "nlarr;": '\U0000219A',
+ "nldr;": '\U00002025',
+ "nle;": '\U00002270',
+ "nleftarrow;": '\U0000219A',
+ "nleftrightarrow;": '\U000021AE',
+ "nleq;": '\U00002270',
+ "nless;": '\U0000226E',
+ "nlsim;": '\U00002274',
+ "nlt;": '\U0000226E',
+ "nltri;": '\U000022EA',
+ "nltrie;": '\U000022EC',
+ "nmid;": '\U00002224',
+ "nopf;": '\U0001D55F',
+ "not;": '\U000000AC',
+ "notin;": '\U00002209',
+ "notinva;": '\U00002209',
+ "notinvb;": '\U000022F7',
+ "notinvc;": '\U000022F6',
+ "notni;": '\U0000220C',
+ "notniva;": '\U0000220C',
+ "notnivb;": '\U000022FE',
+ "notnivc;": '\U000022FD',
+ "npar;": '\U00002226',
+ "nparallel;": '\U00002226',
+ "npolint;": '\U00002A14',
+ "npr;": '\U00002280',
+ "nprcue;": '\U000022E0',
+ "nprec;": '\U00002280',
+ "nrArr;": '\U000021CF',
+ "nrarr;": '\U0000219B',
+ "nrightarrow;": '\U0000219B',
+ "nrtri;": '\U000022EB',
+ "nrtrie;": '\U000022ED',
+ "nsc;": '\U00002281',
+ "nsccue;": '\U000022E1',
+ "nscr;": '\U0001D4C3',
+ "nshortmid;": '\U00002224',
+ "nshortparallel;": '\U00002226',
+ "nsim;": '\U00002241',
+ "nsime;": '\U00002244',
+ "nsimeq;": '\U00002244',
+ "nsmid;": '\U00002224',
+ "nspar;": '\U00002226',
+ "nsqsube;": '\U000022E2',
+ "nsqsupe;": '\U000022E3',
+ "nsub;": '\U00002284',
+ "nsube;": '\U00002288',
+ "nsubseteq;": '\U00002288',
+ "nsucc;": '\U00002281',
+ "nsup;": '\U00002285',
+ "nsupe;": '\U00002289',
+ "nsupseteq;": '\U00002289',
+ "ntgl;": '\U00002279',
+ "ntilde;": '\U000000F1',
+ "ntlg;": '\U00002278',
+ "ntriangleleft;": '\U000022EA',
+ "ntrianglelefteq;": '\U000022EC',
+ "ntriangleright;": '\U000022EB',
+ "ntrianglerighteq;": '\U000022ED',
+ "nu;": '\U000003BD',
+ "num;": '\U00000023',
+ "numero;": '\U00002116',
+ "numsp;": '\U00002007',
+ "nvDash;": '\U000022AD',
+ "nvHarr;": '\U00002904',
+ "nvdash;": '\U000022AC',
+ "nvinfin;": '\U000029DE',
+ "nvlArr;": '\U00002902',
+ "nvrArr;": '\U00002903',
+ "nwArr;": '\U000021D6',
+ "nwarhk;": '\U00002923',
+ "nwarr;": '\U00002196',
+ "nwarrow;": '\U00002196',
+ "nwnear;": '\U00002927',
+ "oS;": '\U000024C8',
+ "oacute;": '\U000000F3',
+ "oast;": '\U0000229B',
+ "ocir;": '\U0000229A',
+ "ocirc;": '\U000000F4',
+ "ocy;": '\U0000043E',
+ "odash;": '\U0000229D',
+ "odblac;": '\U00000151',
+ "odiv;": '\U00002A38',
+ "odot;": '\U00002299',
+ "odsold;": '\U000029BC',
+ "oelig;": '\U00000153',
+ "ofcir;": '\U000029BF',
+ "ofr;": '\U0001D52C',
+ "ogon;": '\U000002DB',
+ "ograve;": '\U000000F2',
+ "ogt;": '\U000029C1',
+ "ohbar;": '\U000029B5',
+ "ohm;": '\U000003A9',
+ "oint;": '\U0000222E',
+ "olarr;": '\U000021BA',
+ "olcir;": '\U000029BE',
+ "olcross;": '\U000029BB',
+ "oline;": '\U0000203E',
+ "olt;": '\U000029C0',
+ "omacr;": '\U0000014D',
+ "omega;": '\U000003C9',
+ "omicron;": '\U000003BF',
+ "omid;": '\U000029B6',
+ "ominus;": '\U00002296',
+ "oopf;": '\U0001D560',
+ "opar;": '\U000029B7',
+ "operp;": '\U000029B9',
+ "oplus;": '\U00002295',
+ "or;": '\U00002228',
+ "orarr;": '\U000021BB',
+ "ord;": '\U00002A5D',
+ "order;": '\U00002134',
+ "orderof;": '\U00002134',
+ "ordf;": '\U000000AA',
+ "ordm;": '\U000000BA',
+ "origof;": '\U000022B6',
+ "oror;": '\U00002A56',
+ "orslope;": '\U00002A57',
+ "orv;": '\U00002A5B',
+ "oscr;": '\U00002134',
+ "oslash;": '\U000000F8',
+ "osol;": '\U00002298',
+ "otilde;": '\U000000F5',
+ "otimes;": '\U00002297',
+ "otimesas;": '\U00002A36',
+ "ouml;": '\U000000F6',
+ "ovbar;": '\U0000233D',
+ "par;": '\U00002225',
+ "para;": '\U000000B6',
+ "parallel;": '\U00002225',
+ "parsim;": '\U00002AF3',
+ "parsl;": '\U00002AFD',
+ "part;": '\U00002202',
+ "pcy;": '\U0000043F',
+ "percnt;": '\U00000025',
+ "period;": '\U0000002E',
+ "permil;": '\U00002030',
+ "perp;": '\U000022A5',
+ "pertenk;": '\U00002031',
+ "pfr;": '\U0001D52D',
+ "phi;": '\U000003C6',
+ "phiv;": '\U000003D5',
+ "phmmat;": '\U00002133',
+ "phone;": '\U0000260E',
+ "pi;": '\U000003C0',
+ "pitchfork;": '\U000022D4',
+ "piv;": '\U000003D6',
+ "planck;": '\U0000210F',
+ "planckh;": '\U0000210E',
+ "plankv;": '\U0000210F',
+ "plus;": '\U0000002B',
+ "plusacir;": '\U00002A23',
+ "plusb;": '\U0000229E',
+ "pluscir;": '\U00002A22',
+ "plusdo;": '\U00002214',
+ "plusdu;": '\U00002A25',
+ "pluse;": '\U00002A72',
+ "plusmn;": '\U000000B1',
+ "plussim;": '\U00002A26',
+ "plustwo;": '\U00002A27',
+ "pm;": '\U000000B1',
+ "pointint;": '\U00002A15',
+ "popf;": '\U0001D561',
+ "pound;": '\U000000A3',
+ "pr;": '\U0000227A',
+ "prE;": '\U00002AB3',
+ "prap;": '\U00002AB7',
+ "prcue;": '\U0000227C',
+ "pre;": '\U00002AAF',
+ "prec;": '\U0000227A',
+ "precapprox;": '\U00002AB7',
+ "preccurlyeq;": '\U0000227C',
+ "preceq;": '\U00002AAF',
+ "precnapprox;": '\U00002AB9',
+ "precneqq;": '\U00002AB5',
+ "precnsim;": '\U000022E8',
+ "precsim;": '\U0000227E',
+ "prime;": '\U00002032',
+ "primes;": '\U00002119',
+ "prnE;": '\U00002AB5',
+ "prnap;": '\U00002AB9',
+ "prnsim;": '\U000022E8',
+ "prod;": '\U0000220F',
+ "profalar;": '\U0000232E',
+ "profline;": '\U00002312',
+ "profsurf;": '\U00002313',
+ "prop;": '\U0000221D',
+ "propto;": '\U0000221D',
+ "prsim;": '\U0000227E',
+ "prurel;": '\U000022B0',
+ "pscr;": '\U0001D4C5',
+ "psi;": '\U000003C8',
+ "puncsp;": '\U00002008',
+ "qfr;": '\U0001D52E',
+ "qint;": '\U00002A0C',
+ "qopf;": '\U0001D562',
+ "qprime;": '\U00002057',
+ "qscr;": '\U0001D4C6',
+ "quaternions;": '\U0000210D',
+ "quatint;": '\U00002A16',
+ "quest;": '\U0000003F',
+ "questeq;": '\U0000225F',
+ "quot;": '\U00000022',
+ "rAarr;": '\U000021DB',
+ "rArr;": '\U000021D2',
+ "rAtail;": '\U0000291C',
+ "rBarr;": '\U0000290F',
+ "rHar;": '\U00002964',
+ "racute;": '\U00000155',
+ "radic;": '\U0000221A',
+ "raemptyv;": '\U000029B3',
+ "rang;": '\U000027E9',
+ "rangd;": '\U00002992',
+ "range;": '\U000029A5',
+ "rangle;": '\U000027E9',
+ "raquo;": '\U000000BB',
+ "rarr;": '\U00002192',
+ "rarrap;": '\U00002975',
+ "rarrb;": '\U000021E5',
+ "rarrbfs;": '\U00002920',
+ "rarrc;": '\U00002933',
+ "rarrfs;": '\U0000291E',
+ "rarrhk;": '\U000021AA',
+ "rarrlp;": '\U000021AC',
+ "rarrpl;": '\U00002945',
+ "rarrsim;": '\U00002974',
+ "rarrtl;": '\U000021A3',
+ "rarrw;": '\U0000219D',
+ "ratail;": '\U0000291A',
+ "ratio;": '\U00002236',
+ "rationals;": '\U0000211A',
+ "rbarr;": '\U0000290D',
+ "rbbrk;": '\U00002773',
+ "rbrace;": '\U0000007D',
+ "rbrack;": '\U0000005D',
+ "rbrke;": '\U0000298C',
+ "rbrksld;": '\U0000298E',
+ "rbrkslu;": '\U00002990',
+ "rcaron;": '\U00000159',
+ "rcedil;": '\U00000157',
+ "rceil;": '\U00002309',
+ "rcub;": '\U0000007D',
+ "rcy;": '\U00000440',
+ "rdca;": '\U00002937',
+ "rdldhar;": '\U00002969',
+ "rdquo;": '\U0000201D',
+ "rdquor;": '\U0000201D',
+ "rdsh;": '\U000021B3',
+ "real;": '\U0000211C',
+ "realine;": '\U0000211B',
+ "realpart;": '\U0000211C',
+ "reals;": '\U0000211D',
+ "rect;": '\U000025AD',
+ "reg;": '\U000000AE',
+ "rfisht;": '\U0000297D',
+ "rfloor;": '\U0000230B',
+ "rfr;": '\U0001D52F',
+ "rhard;": '\U000021C1',
+ "rharu;": '\U000021C0',
+ "rharul;": '\U0000296C',
+ "rho;": '\U000003C1',
+ "rhov;": '\U000003F1',
+ "rightarrow;": '\U00002192',
+ "rightarrowtail;": '\U000021A3',
+ "rightharpoondown;": '\U000021C1',
+ "rightharpoonup;": '\U000021C0',
+ "rightleftarrows;": '\U000021C4',
+ "rightleftharpoons;": '\U000021CC',
+ "rightrightarrows;": '\U000021C9',
+ "rightsquigarrow;": '\U0000219D',
+ "rightthreetimes;": '\U000022CC',
+ "ring;": '\U000002DA',
+ "risingdotseq;": '\U00002253',
+ "rlarr;": '\U000021C4',
+ "rlhar;": '\U000021CC',
+ "rlm;": '\U0000200F',
+ "rmoust;": '\U000023B1',
+ "rmoustache;": '\U000023B1',
+ "rnmid;": '\U00002AEE',
+ "roang;": '\U000027ED',
+ "roarr;": '\U000021FE',
+ "robrk;": '\U000027E7',
+ "ropar;": '\U00002986',
+ "ropf;": '\U0001D563',
+ "roplus;": '\U00002A2E',
+ "rotimes;": '\U00002A35',
+ "rpar;": '\U00000029',
+ "rpargt;": '\U00002994',
+ "rppolint;": '\U00002A12',
+ "rrarr;": '\U000021C9',
+ "rsaquo;": '\U0000203A',
+ "rscr;": '\U0001D4C7',
+ "rsh;": '\U000021B1',
+ "rsqb;": '\U0000005D',
+ "rsquo;": '\U00002019',
+ "rsquor;": '\U00002019',
+ "rthree;": '\U000022CC',
+ "rtimes;": '\U000022CA',
+ "rtri;": '\U000025B9',
+ "rtrie;": '\U000022B5',
+ "rtrif;": '\U000025B8',
+ "rtriltri;": '\U000029CE',
+ "ruluhar;": '\U00002968',
+ "rx;": '\U0000211E',
+ "sacute;": '\U0000015B',
+ "sbquo;": '\U0000201A',
+ "sc;": '\U0000227B',
+ "scE;": '\U00002AB4',
+ "scap;": '\U00002AB8',
+ "scaron;": '\U00000161',
+ "sccue;": '\U0000227D',
+ "sce;": '\U00002AB0',
+ "scedil;": '\U0000015F',
+ "scirc;": '\U0000015D',
+ "scnE;": '\U00002AB6',
+ "scnap;": '\U00002ABA',
+ "scnsim;": '\U000022E9',
+ "scpolint;": '\U00002A13',
+ "scsim;": '\U0000227F',
+ "scy;": '\U00000441',
+ "sdot;": '\U000022C5',
+ "sdotb;": '\U000022A1',
+ "sdote;": '\U00002A66',
+ "seArr;": '\U000021D8',
+ "searhk;": '\U00002925',
+ "searr;": '\U00002198',
+ "searrow;": '\U00002198',
+ "sect;": '\U000000A7',
+ "semi;": '\U0000003B',
+ "seswar;": '\U00002929',
+ "setminus;": '\U00002216',
+ "setmn;": '\U00002216',
+ "sext;": '\U00002736',
+ "sfr;": '\U0001D530',
+ "sfrown;": '\U00002322',
+ "sharp;": '\U0000266F',
+ "shchcy;": '\U00000449',
+ "shcy;": '\U00000448',
+ "shortmid;": '\U00002223',
+ "shortparallel;": '\U00002225',
+ "shy;": '\U000000AD',
+ "sigma;": '\U000003C3',
+ "sigmaf;": '\U000003C2',
+ "sigmav;": '\U000003C2',
+ "sim;": '\U0000223C',
+ "simdot;": '\U00002A6A',
+ "sime;": '\U00002243',
+ "simeq;": '\U00002243',
+ "simg;": '\U00002A9E',
+ "simgE;": '\U00002AA0',
+ "siml;": '\U00002A9D',
+ "simlE;": '\U00002A9F',
+ "simne;": '\U00002246',
+ "simplus;": '\U00002A24',
+ "simrarr;": '\U00002972',
+ "slarr;": '\U00002190',
+ "smallsetminus;": '\U00002216',
+ "smashp;": '\U00002A33',
+ "smeparsl;": '\U000029E4',
+ "smid;": '\U00002223',
+ "smile;": '\U00002323',
+ "smt;": '\U00002AAA',
+ "smte;": '\U00002AAC',
+ "softcy;": '\U0000044C',
+ "sol;": '\U0000002F',
+ "solb;": '\U000029C4',
+ "solbar;": '\U0000233F',
+ "sopf;": '\U0001D564',
+ "spades;": '\U00002660',
+ "spadesuit;": '\U00002660',
+ "spar;": '\U00002225',
+ "sqcap;": '\U00002293',
+ "sqcup;": '\U00002294',
+ "sqsub;": '\U0000228F',
+ "sqsube;": '\U00002291',
+ "sqsubset;": '\U0000228F',
+ "sqsubseteq;": '\U00002291',
+ "sqsup;": '\U00002290',
+ "sqsupe;": '\U00002292',
+ "sqsupset;": '\U00002290',
+ "sqsupseteq;": '\U00002292',
+ "squ;": '\U000025A1',
+ "square;": '\U000025A1',
+ "squarf;": '\U000025AA',
+ "squf;": '\U000025AA',
+ "srarr;": '\U00002192',
+ "sscr;": '\U0001D4C8',
+ "ssetmn;": '\U00002216',
+ "ssmile;": '\U00002323',
+ "sstarf;": '\U000022C6',
+ "star;": '\U00002606',
+ "starf;": '\U00002605',
+ "straightepsilon;": '\U000003F5',
+ "straightphi;": '\U000003D5',
+ "strns;": '\U000000AF',
+ "sub;": '\U00002282',
+ "subE;": '\U00002AC5',
+ "subdot;": '\U00002ABD',
+ "sube;": '\U00002286',
+ "subedot;": '\U00002AC3',
+ "submult;": '\U00002AC1',
+ "subnE;": '\U00002ACB',
+ "subne;": '\U0000228A',
+ "subplus;": '\U00002ABF',
+ "subrarr;": '\U00002979',
+ "subset;": '\U00002282',
+ "subseteq;": '\U00002286',
+ "subseteqq;": '\U00002AC5',
+ "subsetneq;": '\U0000228A',
+ "subsetneqq;": '\U00002ACB',
+ "subsim;": '\U00002AC7',
+ "subsub;": '\U00002AD5',
+ "subsup;": '\U00002AD3',
+ "succ;": '\U0000227B',
+ "succapprox;": '\U00002AB8',
+ "succcurlyeq;": '\U0000227D',
+ "succeq;": '\U00002AB0',
+ "succnapprox;": '\U00002ABA',
+ "succneqq;": '\U00002AB6',
+ "succnsim;": '\U000022E9',
+ "succsim;": '\U0000227F',
+ "sum;": '\U00002211',
+ "sung;": '\U0000266A',
+ "sup;": '\U00002283',
+ "sup1;": '\U000000B9',
+ "sup2;": '\U000000B2',
+ "sup3;": '\U000000B3',
+ "supE;": '\U00002AC6',
+ "supdot;": '\U00002ABE',
+ "supdsub;": '\U00002AD8',
+ "supe;": '\U00002287',
+ "supedot;": '\U00002AC4',
+ "suphsol;": '\U000027C9',
+ "suphsub;": '\U00002AD7',
+ "suplarr;": '\U0000297B',
+ "supmult;": '\U00002AC2',
+ "supnE;": '\U00002ACC',
+ "supne;": '\U0000228B',
+ "supplus;": '\U00002AC0',
+ "supset;": '\U00002283',
+ "supseteq;": '\U00002287',
+ "supseteqq;": '\U00002AC6',
+ "supsetneq;": '\U0000228B',
+ "supsetneqq;": '\U00002ACC',
+ "supsim;": '\U00002AC8',
+ "supsub;": '\U00002AD4',
+ "supsup;": '\U00002AD6',
+ "swArr;": '\U000021D9',
+ "swarhk;": '\U00002926',
+ "swarr;": '\U00002199',
+ "swarrow;": '\U00002199',
+ "swnwar;": '\U0000292A',
+ "szlig;": '\U000000DF',
+ "target;": '\U00002316',
+ "tau;": '\U000003C4',
+ "tbrk;": '\U000023B4',
+ "tcaron;": '\U00000165',
+ "tcedil;": '\U00000163',
+ "tcy;": '\U00000442',
+ "tdot;": '\U000020DB',
+ "telrec;": '\U00002315',
+ "tfr;": '\U0001D531',
+ "there4;": '\U00002234',
+ "therefore;": '\U00002234',
+ "theta;": '\U000003B8',
+ "thetasym;": '\U000003D1',
+ "thetav;": '\U000003D1',
+ "thickapprox;": '\U00002248',
+ "thicksim;": '\U0000223C',
+ "thinsp;": '\U00002009',
+ "thkap;": '\U00002248',
+ "thksim;": '\U0000223C',
+ "thorn;": '\U000000FE',
+ "tilde;": '\U000002DC',
+ "times;": '\U000000D7',
+ "timesb;": '\U000022A0',
+ "timesbar;": '\U00002A31',
+ "timesd;": '\U00002A30',
+ "tint;": '\U0000222D',
+ "toea;": '\U00002928',
+ "top;": '\U000022A4',
+ "topbot;": '\U00002336',
+ "topcir;": '\U00002AF1',
+ "topf;": '\U0001D565',
+ "topfork;": '\U00002ADA',
+ "tosa;": '\U00002929',
+ "tprime;": '\U00002034',
+ "trade;": '\U00002122',
+ "triangle;": '\U000025B5',
+ "triangledown;": '\U000025BF',
+ "triangleleft;": '\U000025C3',
+ "trianglelefteq;": '\U000022B4',
+ "triangleq;": '\U0000225C',
+ "triangleright;": '\U000025B9',
+ "trianglerighteq;": '\U000022B5',
+ "tridot;": '\U000025EC',
+ "trie;": '\U0000225C',
+ "triminus;": '\U00002A3A',
+ "triplus;": '\U00002A39',
+ "trisb;": '\U000029CD',
+ "tritime;": '\U00002A3B',
+ "trpezium;": '\U000023E2',
+ "tscr;": '\U0001D4C9',
+ "tscy;": '\U00000446',
+ "tshcy;": '\U0000045B',
+ "tstrok;": '\U00000167',
+ "twixt;": '\U0000226C',
+ "twoheadleftarrow;": '\U0000219E',
+ "twoheadrightarrow;": '\U000021A0',
+ "uArr;": '\U000021D1',
+ "uHar;": '\U00002963',
+ "uacute;": '\U000000FA',
+ "uarr;": '\U00002191',
+ "ubrcy;": '\U0000045E',
+ "ubreve;": '\U0000016D',
+ "ucirc;": '\U000000FB',
+ "ucy;": '\U00000443',
+ "udarr;": '\U000021C5',
+ "udblac;": '\U00000171',
+ "udhar;": '\U0000296E',
+ "ufisht;": '\U0000297E',
+ "ufr;": '\U0001D532',
+ "ugrave;": '\U000000F9',
+ "uharl;": '\U000021BF',
+ "uharr;": '\U000021BE',
+ "uhblk;": '\U00002580',
+ "ulcorn;": '\U0000231C',
+ "ulcorner;": '\U0000231C',
+ "ulcrop;": '\U0000230F',
+ "ultri;": '\U000025F8',
+ "umacr;": '\U0000016B',
+ "uml;": '\U000000A8',
+ "uogon;": '\U00000173',
+ "uopf;": '\U0001D566',
+ "uparrow;": '\U00002191',
+ "updownarrow;": '\U00002195',
+ "upharpoonleft;": '\U000021BF',
+ "upharpoonright;": '\U000021BE',
+ "uplus;": '\U0000228E',
+ "upsi;": '\U000003C5',
+ "upsih;": '\U000003D2',
+ "upsilon;": '\U000003C5',
+ "upuparrows;": '\U000021C8',
+ "urcorn;": '\U0000231D',
+ "urcorner;": '\U0000231D',
+ "urcrop;": '\U0000230E',
+ "uring;": '\U0000016F',
+ "urtri;": '\U000025F9',
+ "uscr;": '\U0001D4CA',
+ "utdot;": '\U000022F0',
+ "utilde;": '\U00000169',
+ "utri;": '\U000025B5',
+ "utrif;": '\U000025B4',
+ "uuarr;": '\U000021C8',
+ "uuml;": '\U000000FC',
+ "uwangle;": '\U000029A7',
+ "vArr;": '\U000021D5',
+ "vBar;": '\U00002AE8',
+ "vBarv;": '\U00002AE9',
+ "vDash;": '\U000022A8',
+ "vangrt;": '\U0000299C',
+ "varepsilon;": '\U000003F5',
+ "varkappa;": '\U000003F0',
+ "varnothing;": '\U00002205',
+ "varphi;": '\U000003D5',
+ "varpi;": '\U000003D6',
+ "varpropto;": '\U0000221D',
+ "varr;": '\U00002195',
+ "varrho;": '\U000003F1',
+ "varsigma;": '\U000003C2',
+ "vartheta;": '\U000003D1',
+ "vartriangleleft;": '\U000022B2',
+ "vartriangleright;": '\U000022B3',
+ "vcy;": '\U00000432',
+ "vdash;": '\U000022A2',
+ "vee;": '\U00002228',
+ "veebar;": '\U000022BB',
+ "veeeq;": '\U0000225A',
+ "vellip;": '\U000022EE',
+ "verbar;": '\U0000007C',
+ "vert;": '\U0000007C',
+ "vfr;": '\U0001D533',
+ "vltri;": '\U000022B2',
+ "vopf;": '\U0001D567',
+ "vprop;": '\U0000221D',
+ "vrtri;": '\U000022B3',
+ "vscr;": '\U0001D4CB',
+ "vzigzag;": '\U0000299A',
+ "wcirc;": '\U00000175',
+ "wedbar;": '\U00002A5F',
+ "wedge;": '\U00002227',
+ "wedgeq;": '\U00002259',
+ "weierp;": '\U00002118',
+ "wfr;": '\U0001D534',
+ "wopf;": '\U0001D568',
+ "wp;": '\U00002118',
+ "wr;": '\U00002240',
+ "wreath;": '\U00002240',
+ "wscr;": '\U0001D4CC',
+ "xcap;": '\U000022C2',
+ "xcirc;": '\U000025EF',
+ "xcup;": '\U000022C3',
+ "xdtri;": '\U000025BD',
+ "xfr;": '\U0001D535',
+ "xhArr;": '\U000027FA',
+ "xharr;": '\U000027F7',
+ "xi;": '\U000003BE',
+ "xlArr;": '\U000027F8',
+ "xlarr;": '\U000027F5',
+ "xmap;": '\U000027FC',
+ "xnis;": '\U000022FB',
+ "xodot;": '\U00002A00',
+ "xopf;": '\U0001D569',
+ "xoplus;": '\U00002A01',
+ "xotime;": '\U00002A02',
+ "xrArr;": '\U000027F9',
+ "xrarr;": '\U000027F6',
+ "xscr;": '\U0001D4CD',
+ "xsqcup;": '\U00002A06',
+ "xuplus;": '\U00002A04',
+ "xutri;": '\U000025B3',
+ "xvee;": '\U000022C1',
+ "xwedge;": '\U000022C0',
+ "yacute;": '\U000000FD',
+ "yacy;": '\U0000044F',
+ "ycirc;": '\U00000177',
+ "ycy;": '\U0000044B',
+ "yen;": '\U000000A5',
+ "yfr;": '\U0001D536',
+ "yicy;": '\U00000457',
+ "yopf;": '\U0001D56A',
+ "yscr;": '\U0001D4CE',
+ "yucy;": '\U0000044E',
+ "yuml;": '\U000000FF',
+ "zacute;": '\U0000017A',
+ "zcaron;": '\U0000017E',
+ "zcy;": '\U00000437',
+ "zdot;": '\U0000017C',
+ "zeetrf;": '\U00002128',
+ "zeta;": '\U000003B6',
+ "zfr;": '\U0001D537',
+ "zhcy;": '\U00000436',
+ "zigrarr;": '\U000021DD',
+ "zopf;": '\U0001D56B',
+ "zscr;": '\U0001D4CF',
+ "zwj;": '\U0000200D',
+ "zwnj;": '\U0000200C',
+ "AElig": '\U000000C6',
+ "AMP": '\U00000026',
+ "Aacute": '\U000000C1',
+ "Acirc": '\U000000C2',
+ "Agrave": '\U000000C0',
+ "Aring": '\U000000C5',
+ "Atilde": '\U000000C3',
+ "Auml": '\U000000C4',
+ "COPY": '\U000000A9',
+ "Ccedil": '\U000000C7',
+ "ETH": '\U000000D0',
+ "Eacute": '\U000000C9',
+ "Ecirc": '\U000000CA',
+ "Egrave": '\U000000C8',
+ "Euml": '\U000000CB',
+ "GT": '\U0000003E',
+ "Iacute": '\U000000CD',
+ "Icirc": '\U000000CE',
+ "Igrave": '\U000000CC',
+ "Iuml": '\U000000CF',
+ "LT": '\U0000003C',
+ "Ntilde": '\U000000D1',
+ "Oacute": '\U000000D3',
+ "Ocirc": '\U000000D4',
+ "Ograve": '\U000000D2',
+ "Oslash": '\U000000D8',
+ "Otilde": '\U000000D5',
+ "Ouml": '\U000000D6',
+ "QUOT": '\U00000022',
+ "REG": '\U000000AE',
+ "THORN": '\U000000DE',
+ "Uacute": '\U000000DA',
+ "Ucirc": '\U000000DB',
+ "Ugrave": '\U000000D9',
+ "Uuml": '\U000000DC',
+ "Yacute": '\U000000DD',
+ "aacute": '\U000000E1',
+ "acirc": '\U000000E2',
+ "acute": '\U000000B4',
+ "aelig": '\U000000E6',
+ "agrave": '\U000000E0',
+ "amp": '\U00000026',
+ "aring": '\U000000E5',
+ "atilde": '\U000000E3',
+ "auml": '\U000000E4',
+ "brvbar": '\U000000A6',
+ "ccedil": '\U000000E7',
+ "cedil": '\U000000B8',
+ "cent": '\U000000A2',
+ "copy": '\U000000A9',
+ "curren": '\U000000A4',
+ "deg": '\U000000B0',
+ "divide": '\U000000F7',
+ "eacute": '\U000000E9',
+ "ecirc": '\U000000EA',
+ "egrave": '\U000000E8',
+ "eth": '\U000000F0',
+ "euml": '\U000000EB',
+ "frac12": '\U000000BD',
+ "frac14": '\U000000BC',
+ "frac34": '\U000000BE',
+ "gt": '\U0000003E',
+ "iacute": '\U000000ED',
+ "icirc": '\U000000EE',
+ "iexcl": '\U000000A1',
+ "igrave": '\U000000EC',
+ "iquest": '\U000000BF',
+ "iuml": '\U000000EF',
+ "laquo": '\U000000AB',
+ "lt": '\U0000003C',
+ "macr": '\U000000AF',
+ "micro": '\U000000B5',
+ "middot": '\U000000B7',
+ "nbsp": '\U000000A0',
+ "not": '\U000000AC',
+ "ntilde": '\U000000F1',
+ "oacute": '\U000000F3',
+ "ocirc": '\U000000F4',
+ "ograve": '\U000000F2',
+ "ordf": '\U000000AA',
+ "ordm": '\U000000BA',
+ "oslash": '\U000000F8',
+ "otilde": '\U000000F5',
+ "ouml": '\U000000F6',
+ "para": '\U000000B6',
+ "plusmn": '\U000000B1',
+ "pound": '\U000000A3',
+ "quot": '\U00000022',
+ "raquo": '\U000000BB',
+ "reg": '\U000000AE',
+ "sect": '\U000000A7',
+ "shy": '\U000000AD',
+ "sup1": '\U000000B9',
+ "sup2": '\U000000B2',
+ "sup3": '\U000000B3',
+ "szlig": '\U000000DF',
+ "thorn": '\U000000FE',
+ "times": '\U000000D7',
+ "uacute": '\U000000FA',
+ "ucirc": '\U000000FB',
+ "ugrave": '\U000000F9',
+ "uml": '\U000000A8',
+ "uuml": '\U000000FC',
+ "yacute": '\U000000FD',
+ "yen": '\U000000A5',
+ "yuml": '\U000000FF',
+}
+
+// HTML entities that are two unicode codepoints.
+var entity2 = map[string][2]rune{
+ // TODO(nigeltao): Handle replacements that are wider than their names.
+ // "nLt;": {'\u226A', '\u20D2'},
+ // "nGt;": {'\u226B', '\u20D2'},
+ "NotEqualTilde;": {'\u2242', '\u0338'},
+ "NotGreaterFullEqual;": {'\u2267', '\u0338'},
+ "NotGreaterGreater;": {'\u226B', '\u0338'},
+ "NotGreaterSlantEqual;": {'\u2A7E', '\u0338'},
+ "NotHumpDownHump;": {'\u224E', '\u0338'},
+ "NotHumpEqual;": {'\u224F', '\u0338'},
+ "NotLeftTriangleBar;": {'\u29CF', '\u0338'},
+ "NotLessLess;": {'\u226A', '\u0338'},
+ "NotLessSlantEqual;": {'\u2A7D', '\u0338'},
+ "NotNestedGreaterGreater;": {'\u2AA2', '\u0338'},
+ "NotNestedLessLess;": {'\u2AA1', '\u0338'},
+ "NotPrecedesEqual;": {'\u2AAF', '\u0338'},
+ "NotRightTriangleBar;": {'\u29D0', '\u0338'},
+ "NotSquareSubset;": {'\u228F', '\u0338'},
+ "NotSquareSuperset;": {'\u2290', '\u0338'},
+ "NotSubset;": {'\u2282', '\u20D2'},
+ "NotSucceedsEqual;": {'\u2AB0', '\u0338'},
+ "NotSucceedsTilde;": {'\u227F', '\u0338'},
+ "NotSuperset;": {'\u2283', '\u20D2'},
+ "ThickSpace;": {'\u205F', '\u200A'},
+ "acE;": {'\u223E', '\u0333'},
+ "bne;": {'\u003D', '\u20E5'},
+ "bnequiv;": {'\u2261', '\u20E5'},
+ "caps;": {'\u2229', '\uFE00'},
+ "cups;": {'\u222A', '\uFE00'},
+ "fjlig;": {'\u0066', '\u006A'},
+ "gesl;": {'\u22DB', '\uFE00'},
+ "gvertneqq;": {'\u2269', '\uFE00'},
+ "gvnE;": {'\u2269', '\uFE00'},
+ "lates;": {'\u2AAD', '\uFE00'},
+ "lesg;": {'\u22DA', '\uFE00'},
+ "lvertneqq;": {'\u2268', '\uFE00'},
+ "lvnE;": {'\u2268', '\uFE00'},
+ "nGg;": {'\u22D9', '\u0338'},
+ "nGtv;": {'\u226B', '\u0338'},
+ "nLl;": {'\u22D8', '\u0338'},
+ "nLtv;": {'\u226A', '\u0338'},
+ "nang;": {'\u2220', '\u20D2'},
+ "napE;": {'\u2A70', '\u0338'},
+ "napid;": {'\u224B', '\u0338'},
+ "nbump;": {'\u224E', '\u0338'},
+ "nbumpe;": {'\u224F', '\u0338'},
+ "ncongdot;": {'\u2A6D', '\u0338'},
+ "nedot;": {'\u2250', '\u0338'},
+ "nesim;": {'\u2242', '\u0338'},
+ "ngE;": {'\u2267', '\u0338'},
+ "ngeqq;": {'\u2267', '\u0338'},
+ "ngeqslant;": {'\u2A7E', '\u0338'},
+ "nges;": {'\u2A7E', '\u0338'},
+ "nlE;": {'\u2266', '\u0338'},
+ "nleqq;": {'\u2266', '\u0338'},
+ "nleqslant;": {'\u2A7D', '\u0338'},
+ "nles;": {'\u2A7D', '\u0338'},
+ "notinE;": {'\u22F9', '\u0338'},
+ "notindot;": {'\u22F5', '\u0338'},
+ "nparsl;": {'\u2AFD', '\u20E5'},
+ "npart;": {'\u2202', '\u0338'},
+ "npre;": {'\u2AAF', '\u0338'},
+ "npreceq;": {'\u2AAF', '\u0338'},
+ "nrarrc;": {'\u2933', '\u0338'},
+ "nrarrw;": {'\u219D', '\u0338'},
+ "nsce;": {'\u2AB0', '\u0338'},
+ "nsubE;": {'\u2AC5', '\u0338'},
+ "nsubset;": {'\u2282', '\u20D2'},
+ "nsubseteqq;": {'\u2AC5', '\u0338'},
+ "nsucceq;": {'\u2AB0', '\u0338'},
+ "nsupE;": {'\u2AC6', '\u0338'},
+ "nsupset;": {'\u2283', '\u20D2'},
+ "nsupseteqq;": {'\u2AC6', '\u0338'},
+ "nvap;": {'\u224D', '\u20D2'},
+ "nvge;": {'\u2265', '\u20D2'},
+ "nvgt;": {'\u003E', '\u20D2'},
+ "nvle;": {'\u2264', '\u20D2'},
+ "nvlt;": {'\u003C', '\u20D2'},
+ "nvltrie;": {'\u22B4', '\u20D2'},
+ "nvrtrie;": {'\u22B5', '\u20D2'},
+ "nvsim;": {'\u223C', '\u20D2'},
+ "race;": {'\u223D', '\u0331'},
+ "smtes;": {'\u2AAC', '\uFE00'},
+ "sqcaps;": {'\u2293', '\uFE00'},
+ "sqcups;": {'\u2294', '\uFE00'},
+ "varsubsetneq;": {'\u228A', '\uFE00'},
+ "varsubsetneqq;": {'\u2ACB', '\uFE00'},
+ "varsupsetneq;": {'\u228B', '\uFE00'},
+ "varsupsetneqq;": {'\u2ACC', '\uFE00'},
+ "vnsub;": {'\u2282', '\u20D2'},
+ "vnsup;": {'\u2283', '\u20D2'},
+ "vsubnE;": {'\u2ACB', '\uFE00'},
+ "vsubne;": {'\u228A', '\uFE00'},
+ "vsupnE;": {'\u2ACC', '\uFE00'},
+ "vsupne;": {'\u228B', '\uFE00'},
+}
diff --git a/vendor/golang.org/x/net/html/escape.go b/vendor/golang.org/x/net/html/escape.go
new file mode 100644
index 0000000..d856139
--- /dev/null
+++ b/vendor/golang.org/x/net/html/escape.go
@@ -0,0 +1,258 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "bytes"
+ "strings"
+ "unicode/utf8"
+)
+
+// These replacements permit compatibility with old numeric entities that
+// assumed Windows-1252 encoding.
+// https://html.spec.whatwg.org/multipage/syntax.html#consume-a-character-reference
+var replacementTable = [...]rune{
+ '\u20AC', // First entry is what 0x80 should be replaced with.
+ '\u0081',
+ '\u201A',
+ '\u0192',
+ '\u201E',
+ '\u2026',
+ '\u2020',
+ '\u2021',
+ '\u02C6',
+ '\u2030',
+ '\u0160',
+ '\u2039',
+ '\u0152',
+ '\u008D',
+ '\u017D',
+ '\u008F',
+ '\u0090',
+ '\u2018',
+ '\u2019',
+ '\u201C',
+ '\u201D',
+ '\u2022',
+ '\u2013',
+ '\u2014',
+ '\u02DC',
+ '\u2122',
+ '\u0161',
+ '\u203A',
+ '\u0153',
+ '\u009D',
+ '\u017E',
+ '\u0178', // Last entry is 0x9F.
+ // 0x00->'\uFFFD' is handled programmatically.
+ // 0x0D->'\u000D' is a no-op.
+}
+
+// unescapeEntity reads an entity like "&lt;" from b[src:] and writes the
+// corresponding "<" to b[dst:], returning the incremented dst and src cursors.
+// Precondition: b[src] == '&' && dst <= src.
+// attribute should be true if parsing an attribute value.
+func unescapeEntity(b []byte, dst, src int, attribute bool) (dst1, src1 int) {
+ // https://html.spec.whatwg.org/multipage/syntax.html#consume-a-character-reference
+
+ // i starts at 1 because we already know that s[0] == '&'.
+ i, s := 1, b[src:]
+
+ if len(s) <= 1 {
+ b[dst] = b[src]
+ return dst + 1, src + 1
+ }
+
+ if s[i] == '#' {
+ if len(s) <= 3 { // We need to have at least "&#.".
+ b[dst] = b[src]
+ return dst + 1, src + 1
+ }
+ i++
+ c := s[i]
+ hex := false
+ if c == 'x' || c == 'X' {
+ hex = true
+ i++
+ }
+
+ x := '\x00'
+ for i < len(s) {
+ c = s[i]
+ i++
+ if hex {
+ if '0' <= c && c <= '9' {
+ x = 16*x + rune(c) - '0'
+ continue
+ } else if 'a' <= c && c <= 'f' {
+ x = 16*x + rune(c) - 'a' + 10
+ continue
+ } else if 'A' <= c && c <= 'F' {
+ x = 16*x + rune(c) - 'A' + 10
+ continue
+ }
+ } else if '0' <= c && c <= '9' {
+ x = 10*x + rune(c) - '0'
+ continue
+ }
+ if c != ';' {
+ i--
+ }
+ break
+ }
+
+ if i <= 3 { // No characters matched.
+ b[dst] = b[src]
+ return dst + 1, src + 1
+ }
+
+ if 0x80 <= x && x <= 0x9F {
+ // Replace characters from Windows-1252 with UTF-8 equivalents.
+ x = replacementTable[x-0x80]
+ } else if x == 0 || (0xD800 <= x && x <= 0xDFFF) || x > 0x10FFFF {
+ // Replace invalid characters with the replacement character.
+ x = '\uFFFD'
+ }
+
+ return dst + utf8.EncodeRune(b[dst:], x), src + i
+ }
+
+ // Consume the maximum number of characters possible, with the
+ // consumed characters matching one of the named references.
+
+ for i < len(s) {
+ c := s[i]
+ i++
+ // Lower-cased characters are more common in entities, so we check for them first.
+ if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' {
+ continue
+ }
+ if c != ';' {
+ i--
+ }
+ break
+ }
+
+ entityName := string(s[1:i])
+ if entityName == "" {
+ // No-op.
+ } else if attribute && entityName[len(entityName)-1] != ';' && len(s) > i && s[i] == '=' {
+ // No-op.
+ } else if x := entity[entityName]; x != 0 {
+ return dst + utf8.EncodeRune(b[dst:], x), src + i
+ } else if x := entity2[entityName]; x[0] != 0 {
+ dst1 := dst + utf8.EncodeRune(b[dst:], x[0])
+ return dst1 + utf8.EncodeRune(b[dst1:], x[1]), src + i
+ } else if !attribute {
+ maxLen := len(entityName) - 1
+ if maxLen > longestEntityWithoutSemicolon {
+ maxLen = longestEntityWithoutSemicolon
+ }
+ for j := maxLen; j > 1; j-- {
+ if x := entity[entityName[:j]]; x != 0 {
+ return dst + utf8.EncodeRune(b[dst:], x), src + j + 1
+ }
+ }
+ }
+
+ dst1, src1 = dst+i, src+i
+ copy(b[dst:dst1], b[src:src1])
+ return dst1, src1
+}
+
+// unescape unescapes b's entities in-place, so that "a&lt;b" becomes "a<b".
+// attribute should be true if parsing an attribute value.
+func unescape(b []byte, attribute bool) []byte {
+ for i, c := range b {
+ if c == '&' {
+ dst, src := unescapeEntity(b, i, i, attribute)
+ for src < len(b) {
+ c := b[src]
+ if c == '&' {
+ dst, src = unescapeEntity(b, dst, src, attribute)
+ } else {
+ b[dst] = c
+ dst, src = dst+1, src+1
+ }
+ }
+ return b[0:dst]
+ }
+ }
+ return b
+}
+
+// lower lower-cases the A-Z bytes in b in-place, so that "aBc" becomes "abc".
+func lower(b []byte) []byte {
+ for i, c := range b {
+ if 'A' <= c && c <= 'Z' {
+ b[i] = c + 'a' - 'A'
+ }
+ }
+ return b
+}
+
+const escapedChars = "&'<>\"\r"
+
+func escape(w writer, s string) error {
+ i := strings.IndexAny(s, escapedChars)
+ for i != -1 {
+ if _, err := w.WriteString(s[:i]); err != nil {
+ return err
+ }
+ var esc string
+ switch s[i] {
+ case '&':
+ esc = "&amp;"
+ case '\'':
+ // "&#39;" is shorter than "&apos;" and apos was not in HTML until HTML5.
+ esc = "&#39;"
+ case '<':
+ esc = "&lt;"
+ case '>':
+ esc = "&gt;"
+ case '"':
+ // "&#34;" is shorter than "&quot;".
+ esc = "&#34;"
+ case '\r':
+ esc = "&#13;"
+ default:
+ panic("unrecognized escape character")
+ }
+ s = s[i+1:]
+ if _, err := w.WriteString(esc); err != nil {
+ return err
+ }
+ i = strings.IndexAny(s, escapedChars)
+ }
+ _, err := w.WriteString(s)
+ return err
+}
+
+// EscapeString escapes special characters like "<" to become "&lt;". It
+// escapes only five such characters: <, >, &, ' and ".
+// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
+// always true.
+func EscapeString(s string) string {
+ if strings.IndexAny(s, escapedChars) == -1 {
+ return s
+ }
+ var buf bytes.Buffer
+ escape(&buf, s)
+ return buf.String()
+}
+
+// UnescapeString unescapes entities like "&lt;" to become "<". It unescapes a
+// larger range of entities than EscapeString escapes. For example, "&aacute;"
+// unescapes to "á", as does "&#225;" and "&xE1;".
+// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
+// always true.
+func UnescapeString(s string) string {
+ for _, c := range s {
+ if c == '&' {
+ return string(unescape([]byte(s), false))
+ }
+ }
+ return s
+}
diff --git a/vendor/golang.org/x/net/html/foreign.go b/vendor/golang.org/x/net/html/foreign.go
new file mode 100644
index 0000000..01477a9
--- /dev/null
+++ b/vendor/golang.org/x/net/html/foreign.go
@@ -0,0 +1,226 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "strings"
+)
+
+func adjustAttributeNames(aa []Attribute, nameMap map[string]string) {
+ for i := range aa {
+ if newName, ok := nameMap[aa[i].Key]; ok {
+ aa[i].Key = newName
+ }
+ }
+}
+
+func adjustForeignAttributes(aa []Attribute) {
+ for i, a := range aa {
+ if a.Key == "" || a.Key[0] != 'x' {
+ continue
+ }
+ switch a.Key {
+ case "xlink:actuate", "xlink:arcrole", "xlink:href", "xlink:role", "xlink:show",
+ "xlink:title", "xlink:type", "xml:base", "xml:lang", "xml:space", "xmlns:xlink":
+ j := strings.Index(a.Key, ":")
+ aa[i].Namespace = a.Key[:j]
+ aa[i].Key = a.Key[j+1:]
+ }
+ }
+}
+
+func htmlIntegrationPoint(n *Node) bool {
+ if n.Type != ElementNode {
+ return false
+ }
+ switch n.Namespace {
+ case "math":
+ if n.Data == "annotation-xml" {
+ for _, a := range n.Attr {
+ if a.Key == "encoding" {
+ val := strings.ToLower(a.Val)
+ if val == "text/html" || val == "application/xhtml+xml" {
+ return true
+ }
+ }
+ }
+ }
+ case "svg":
+ switch n.Data {
+ case "desc", "foreignObject", "title":
+ return true
+ }
+ }
+ return false
+}
+
+func mathMLTextIntegrationPoint(n *Node) bool {
+ if n.Namespace != "math" {
+ return false
+ }
+ switch n.Data {
+ case "mi", "mo", "mn", "ms", "mtext":
+ return true
+ }
+ return false
+}
+
+// Section 12.2.6.5.
+var breakout = map[string]bool{
+ "b": true,
+ "big": true,
+ "blockquote": true,
+ "body": true,
+ "br": true,
+ "center": true,
+ "code": true,
+ "dd": true,
+ "div": true,
+ "dl": true,
+ "dt": true,
+ "em": true,
+ "embed": true,
+ "h1": true,
+ "h2": true,
+ "h3": true,
+ "h4": true,
+ "h5": true,
+ "h6": true,
+ "head": true,
+ "hr": true,
+ "i": true,
+ "img": true,
+ "li": true,
+ "listing": true,
+ "menu": true,
+ "meta": true,
+ "nobr": true,
+ "ol": true,
+ "p": true,
+ "pre": true,
+ "ruby": true,
+ "s": true,
+ "small": true,
+ "span": true,
+ "strong": true,
+ "strike": true,
+ "sub": true,
+ "sup": true,
+ "table": true,
+ "tt": true,
+ "u": true,
+ "ul": true,
+ "var": true,
+}
+
+// Section 12.2.6.5.
+var svgTagNameAdjustments = map[string]string{
+ "altglyph": "altGlyph",
+ "altglyphdef": "altGlyphDef",
+ "altglyphitem": "altGlyphItem",
+ "animatecolor": "animateColor",
+ "animatemotion": "animateMotion",
+ "animatetransform": "animateTransform",
+ "clippath": "clipPath",
+ "feblend": "feBlend",
+ "fecolormatrix": "feColorMatrix",
+ "fecomponenttransfer": "feComponentTransfer",
+ "fecomposite": "feComposite",
+ "feconvolvematrix": "feConvolveMatrix",
+ "fediffuselighting": "feDiffuseLighting",
+ "fedisplacementmap": "feDisplacementMap",
+ "fedistantlight": "feDistantLight",
+ "feflood": "feFlood",
+ "fefunca": "feFuncA",
+ "fefuncb": "feFuncB",
+ "fefuncg": "feFuncG",
+ "fefuncr": "feFuncR",
+ "fegaussianblur": "feGaussianBlur",
+ "feimage": "feImage",
+ "femerge": "feMerge",
+ "femergenode": "feMergeNode",
+ "femorphology": "feMorphology",
+ "feoffset": "feOffset",
+ "fepointlight": "fePointLight",
+ "fespecularlighting": "feSpecularLighting",
+ "fespotlight": "feSpotLight",
+ "fetile": "feTile",
+ "feturbulence": "feTurbulence",
+ "foreignobject": "foreignObject",
+ "glyphref": "glyphRef",
+ "lineargradient": "linearGradient",
+ "radialgradient": "radialGradient",
+ "textpath": "textPath",
+}
+
+// Section 12.2.6.1
+var mathMLAttributeAdjustments = map[string]string{
+ "definitionurl": "definitionURL",
+}
+
+var svgAttributeAdjustments = map[string]string{
+ "attributename": "attributeName",
+ "attributetype": "attributeType",
+ "basefrequency": "baseFrequency",
+ "baseprofile": "baseProfile",
+ "calcmode": "calcMode",
+ "clippathunits": "clipPathUnits",
+ "contentscripttype": "contentScriptType",
+ "contentstyletype": "contentStyleType",
+ "diffuseconstant": "diffuseConstant",
+ "edgemode": "edgeMode",
+ "externalresourcesrequired": "externalResourcesRequired",
+ "filterres": "filterRes",
+ "filterunits": "filterUnits",
+ "glyphref": "glyphRef",
+ "gradienttransform": "gradientTransform",
+ "gradientunits": "gradientUnits",
+ "kernelmatrix": "kernelMatrix",
+ "kernelunitlength": "kernelUnitLength",
+ "keypoints": "keyPoints",
+ "keysplines": "keySplines",
+ "keytimes": "keyTimes",
+ "lengthadjust": "lengthAdjust",
+ "limitingconeangle": "limitingConeAngle",
+ "markerheight": "markerHeight",
+ "markerunits": "markerUnits",
+ "markerwidth": "markerWidth",
+ "maskcontentunits": "maskContentUnits",
+ "maskunits": "maskUnits",
+ "numoctaves": "numOctaves",
+ "pathlength": "pathLength",
+ "patterncontentunits": "patternContentUnits",
+ "patterntransform": "patternTransform",
+ "patternunits": "patternUnits",
+ "pointsatx": "pointsAtX",
+ "pointsaty": "pointsAtY",
+ "pointsatz": "pointsAtZ",
+ "preservealpha": "preserveAlpha",
+ "preserveaspectratio": "preserveAspectRatio",
+ "primitiveunits": "primitiveUnits",
+ "refx": "refX",
+ "refy": "refY",
+ "repeatcount": "repeatCount",
+ "repeatdur": "repeatDur",
+ "requiredextensions": "requiredExtensions",
+ "requiredfeatures": "requiredFeatures",
+ "specularconstant": "specularConstant",
+ "specularexponent": "specularExponent",
+ "spreadmethod": "spreadMethod",
+ "startoffset": "startOffset",
+ "stddeviation": "stdDeviation",
+ "stitchtiles": "stitchTiles",
+ "surfacescale": "surfaceScale",
+ "systemlanguage": "systemLanguage",
+ "tablevalues": "tableValues",
+ "targetx": "targetX",
+ "targety": "targetY",
+ "textlength": "textLength",
+ "viewbox": "viewBox",
+ "viewtarget": "viewTarget",
+ "xchannelselector": "xChannelSelector",
+ "ychannelselector": "yChannelSelector",
+ "zoomandpan": "zoomAndPan",
+}
diff --git a/vendor/golang.org/x/net/html/node.go b/vendor/golang.org/x/net/html/node.go
new file mode 100644
index 0000000..2c1cade
--- /dev/null
+++ b/vendor/golang.org/x/net/html/node.go
@@ -0,0 +1,220 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "golang.org/x/net/html/atom"
+)
+
+// A NodeType is the type of a Node.
+type NodeType uint32
+
+const (
+ ErrorNode NodeType = iota
+ TextNode
+ DocumentNode
+ ElementNode
+ CommentNode
+ DoctypeNode
+ scopeMarkerNode
+)
+
+// Section 12.2.4.3 says "The markers are inserted when entering applet,
+// object, marquee, template, td, th, and caption elements, and are used
+// to prevent formatting from "leaking" into applet, object, marquee,
+// template, td, th, and caption elements".
+var scopeMarker = Node{Type: scopeMarkerNode}
+
+// A Node consists of a NodeType and some Data (tag name for element nodes,
+// content for text) and are part of a tree of Nodes. Element nodes may also
+// have a Namespace and contain a slice of Attributes. Data is unescaped, so
+// that it looks like "a<b" rather than "a&lt;b". For element nodes, DataAtom
+// is the atom for Data, or zero if Data is not a known tag name.
+//
+// An empty Namespace implies a "http://www.w3.org/1999/xhtml" namespace.
+// Similarly, "math" is short for "http://www.w3.org/1998/Math/MathML", and
+// "svg" is short for "http://www.w3.org/2000/svg".
+type Node struct {
+ Parent, FirstChild, LastChild, PrevSibling, NextSibling *Node
+
+ Type NodeType
+ DataAtom atom.Atom
+ Data string
+ Namespace string
+ Attr []Attribute
+}
+
+// InsertBefore inserts newChild as a child of n, immediately before oldChild
+// in the sequence of n's children. oldChild may be nil, in which case newChild
+// is appended to the end of n's children.
+//
+// It will panic if newChild already has a parent or siblings.
+func (n *Node) InsertBefore(newChild, oldChild *Node) {
+ if newChild.Parent != nil || newChild.PrevSibling != nil || newChild.NextSibling != nil {
+ panic("html: InsertBefore called for an attached child Node")
+ }
+ var prev, next *Node
+ if oldChild != nil {
+ prev, next = oldChild.PrevSibling, oldChild
+ } else {
+ prev = n.LastChild
+ }
+ if prev != nil {
+ prev.NextSibling = newChild
+ } else {
+ n.FirstChild = newChild
+ }
+ if next != nil {
+ next.PrevSibling = newChild
+ } else {
+ n.LastChild = newChild
+ }
+ newChild.Parent = n
+ newChild.PrevSibling = prev
+ newChild.NextSibling = next
+}
+
+// AppendChild adds a node c as a child of n.
+//
+// It will panic if c already has a parent or siblings.
+func (n *Node) AppendChild(c *Node) {
+ if c.Parent != nil || c.PrevSibling != nil || c.NextSibling != nil {
+ panic("html: AppendChild called for an attached child Node")
+ }
+ last := n.LastChild
+ if last != nil {
+ last.NextSibling = c
+ } else {
+ n.FirstChild = c
+ }
+ n.LastChild = c
+ c.Parent = n
+ c.PrevSibling = last
+}
+
+// RemoveChild removes a node c that is a child of n. Afterwards, c will have
+// no parent and no siblings.
+//
+// It will panic if c's parent is not n.
+func (n *Node) RemoveChild(c *Node) {
+ if c.Parent != n {
+ panic("html: RemoveChild called for a non-child Node")
+ }
+ if n.FirstChild == c {
+ n.FirstChild = c.NextSibling
+ }
+ if c.NextSibling != nil {
+ c.NextSibling.PrevSibling = c.PrevSibling
+ }
+ if n.LastChild == c {
+ n.LastChild = c.PrevSibling
+ }
+ if c.PrevSibling != nil {
+ c.PrevSibling.NextSibling = c.NextSibling
+ }
+ c.Parent = nil
+ c.PrevSibling = nil
+ c.NextSibling = nil
+}
+
+// reparentChildren reparents all of src's child nodes to dst.
+func reparentChildren(dst, src *Node) {
+ for {
+ child := src.FirstChild
+ if child == nil {
+ break
+ }
+ src.RemoveChild(child)
+ dst.AppendChild(child)
+ }
+}
+
+// clone returns a new node with the same type, data and attributes.
+// The clone has no parent, no siblings and no children.
+func (n *Node) clone() *Node {
+ m := &Node{
+ Type: n.Type,
+ DataAtom: n.DataAtom,
+ Data: n.Data,
+ Attr: make([]Attribute, len(n.Attr)),
+ }
+ copy(m.Attr, n.Attr)
+ return m
+}
+
+// nodeStack is a stack of nodes.
+type nodeStack []*Node
+
+// pop pops the stack. It will panic if s is empty.
+func (s *nodeStack) pop() *Node {
+ i := len(*s)
+ n := (*s)[i-1]
+ *s = (*s)[:i-1]
+ return n
+}
+
+// top returns the most recently pushed node, or nil if s is empty.
+func (s *nodeStack) top() *Node {
+ if i := len(*s); i > 0 {
+ return (*s)[i-1]
+ }
+ return nil
+}
+
+// index returns the index of the top-most occurrence of n in the stack, or -1
+// if n is not present.
+func (s *nodeStack) index(n *Node) int {
+ for i := len(*s) - 1; i >= 0; i-- {
+ if (*s)[i] == n {
+ return i
+ }
+ }
+ return -1
+}
+
+// contains returns whether a is within s.
+func (s *nodeStack) contains(a atom.Atom) bool {
+ for _, n := range *s {
+ if n.DataAtom == a {
+ return true
+ }
+ }
+ return false
+}
+
+// insert inserts a node at the given index.
+func (s *nodeStack) insert(i int, n *Node) {
+ (*s) = append(*s, nil)
+ copy((*s)[i+1:], (*s)[i:])
+ (*s)[i] = n
+}
+
+// remove removes a node from the stack. It is a no-op if n is not present.
+func (s *nodeStack) remove(n *Node) {
+ i := s.index(n)
+ if i == -1 {
+ return
+ }
+ copy((*s)[i:], (*s)[i+1:])
+ j := len(*s) - 1
+ (*s)[j] = nil
+ *s = (*s)[:j]
+}
+
+type insertionModeStack []insertionMode
+
+func (s *insertionModeStack) pop() (im insertionMode) {
+ i := len(*s)
+ im = (*s)[i-1]
+ *s = (*s)[:i-1]
+ return im
+}
+
+func (s *insertionModeStack) top() insertionMode {
+ if i := len(*s); i > 0 {
+ return (*s)[i-1]
+ }
+ return nil
+}
diff --git a/vendor/golang.org/x/net/html/parse.go b/vendor/golang.org/x/net/html/parse.go
new file mode 100644
index 0000000..d23e05e
--- /dev/null
+++ b/vendor/golang.org/x/net/html/parse.go
@@ -0,0 +1,2305 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "strings"
+
+ a "golang.org/x/net/html/atom"
+)
+
+// A parser implements the HTML5 parsing algorithm:
+// https://html.spec.whatwg.org/multipage/syntax.html#tree-construction
+type parser struct {
+ // tokenizer provides the tokens for the parser.
+ tokenizer *Tokenizer
+ // tok is the most recently read token.
+ tok Token
+ // Self-closing tags like <hr/> are treated as start tags, except that
+ // hasSelfClosingToken is set while they are being processed.
+ hasSelfClosingToken bool
+ // doc is the document root element.
+ doc *Node
+ // The stack of open elements (section 12.2.4.2) and active formatting
+ // elements (section 12.2.4.3).
+ oe, afe nodeStack
+ // Element pointers (section 12.2.4.4).
+ head, form *Node
+ // Other parsing state flags (section 12.2.4.5).
+ scripting, framesetOK bool
+ // The stack of template insertion modes
+ templateStack insertionModeStack
+ // im is the current insertion mode.
+ im insertionMode
+ // originalIM is the insertion mode to go back to after completing a text
+ // or inTableText insertion mode.
+ originalIM insertionMode
+ // fosterParenting is whether new elements should be inserted according to
+ // the foster parenting rules (section 12.2.6.1).
+ fosterParenting bool
+ // quirks is whether the parser is operating in "quirks mode."
+ quirks bool
+ // fragment is whether the parser is parsing an HTML fragment.
+ fragment bool
+ // context is the context element when parsing an HTML fragment
+ // (section 12.4).
+ context *Node
+}
+
+func (p *parser) top() *Node {
+ if n := p.oe.top(); n != nil {
+ return n
+ }
+ return p.doc
+}
+
+// Stop tags for use in popUntil. These come from section 12.2.4.2.
+var (
+ defaultScopeStopTags = map[string][]a.Atom{
+ "": {a.Applet, a.Caption, a.Html, a.Table, a.Td, a.Th, a.Marquee, a.Object, a.Template},
+ "math": {a.AnnotationXml, a.Mi, a.Mn, a.Mo, a.Ms, a.Mtext},
+ "svg": {a.Desc, a.ForeignObject, a.Title},
+ }
+)
+
+type scope int
+
+const (
+ defaultScope scope = iota
+ listItemScope
+ buttonScope
+ tableScope
+ tableRowScope
+ tableBodyScope
+ selectScope
+)
+
+// popUntil pops the stack of open elements at the highest element whose tag
+// is in matchTags, provided there is no higher element in the scope's stop
+// tags (as defined in section 12.2.4.2). It returns whether or not there was
+// such an element. If there was not, popUntil leaves the stack unchanged.
+//
+// For example, the set of stop tags for table scope is: "html", "table". If
+// the stack was:
+// ["html", "body", "font", "table", "b", "i", "u"]
+// then popUntil(tableScope, "font") would return false, but
+// popUntil(tableScope, "i") would return true and the stack would become:
+// ["html", "body", "font", "table", "b"]
+//
+// If an element's tag is in both the stop tags and matchTags, then the stack
+// will be popped and the function returns true (provided, of course, there was
+// no higher element in the stack that was also in the stop tags). For example,
+// popUntil(tableScope, "table") returns true and leaves:
+// ["html", "body", "font"]
+func (p *parser) popUntil(s scope, matchTags ...a.Atom) bool {
+ if i := p.indexOfElementInScope(s, matchTags...); i != -1 {
+ p.oe = p.oe[:i]
+ return true
+ }
+ return false
+}
+
+// indexOfElementInScope returns the index in p.oe of the highest element whose
+// tag is in matchTags that is in scope. If no matching element is in scope, it
+// returns -1.
+func (p *parser) indexOfElementInScope(s scope, matchTags ...a.Atom) int {
+ for i := len(p.oe) - 1; i >= 0; i-- {
+ tagAtom := p.oe[i].DataAtom
+ if p.oe[i].Namespace == "" {
+ for _, t := range matchTags {
+ if t == tagAtom {
+ return i
+ }
+ }
+ switch s {
+ case defaultScope:
+ // No-op.
+ case listItemScope:
+ if tagAtom == a.Ol || tagAtom == a.Ul {
+ return -1
+ }
+ case buttonScope:
+ if tagAtom == a.Button {
+ return -1
+ }
+ case tableScope:
+ if tagAtom == a.Html || tagAtom == a.Table || tagAtom == a.Template {
+ return -1
+ }
+ case selectScope:
+ if tagAtom != a.Optgroup && tagAtom != a.Option {
+ return -1
+ }
+ default:
+ panic("unreachable")
+ }
+ }
+ switch s {
+ case defaultScope, listItemScope, buttonScope:
+ for _, t := range defaultScopeStopTags[p.oe[i].Namespace] {
+ if t == tagAtom {
+ return -1
+ }
+ }
+ }
+ }
+ return -1
+}
+
+// elementInScope is like popUntil, except that it doesn't modify the stack of
+// open elements.
+func (p *parser) elementInScope(s scope, matchTags ...a.Atom) bool {
+ return p.indexOfElementInScope(s, matchTags...) != -1
+}
+
+// clearStackToContext pops elements off the stack of open elements until a
+// scope-defined element is found.
+func (p *parser) clearStackToContext(s scope) {
+ for i := len(p.oe) - 1; i >= 0; i-- {
+ tagAtom := p.oe[i].DataAtom
+ switch s {
+ case tableScope:
+ if tagAtom == a.Html || tagAtom == a.Table || tagAtom == a.Template {
+ p.oe = p.oe[:i+1]
+ return
+ }
+ case tableRowScope:
+ if tagAtom == a.Html || tagAtom == a.Tr || tagAtom == a.Template {
+ p.oe = p.oe[:i+1]
+ return
+ }
+ case tableBodyScope:
+ if tagAtom == a.Html || tagAtom == a.Tbody || tagAtom == a.Tfoot || tagAtom == a.Thead || tagAtom == a.Template {
+ p.oe = p.oe[:i+1]
+ return
+ }
+ default:
+ panic("unreachable")
+ }
+ }
+}
+
+// generateImpliedEndTags pops nodes off the stack of open elements as long as
+// the top node has a tag name of dd, dt, li, optgroup, option, p, rb, rp, rt or rtc.
+// If exceptions are specified, nodes with that name will not be popped off.
+func (p *parser) generateImpliedEndTags(exceptions ...string) {
+ var i int
+loop:
+ for i = len(p.oe) - 1; i >= 0; i-- {
+ n := p.oe[i]
+ if n.Type == ElementNode {
+ switch n.DataAtom {
+ case a.Dd, a.Dt, a.Li, a.Optgroup, a.Option, a.P, a.Rb, a.Rp, a.Rt, a.Rtc:
+ for _, except := range exceptions {
+ if n.Data == except {
+ break loop
+ }
+ }
+ continue
+ }
+ }
+ break
+ }
+
+ p.oe = p.oe[:i+1]
+}
+
+// generateAllImpliedEndTags pops nodes off the stack of open elements as long as
+// the top node has a tag name of caption, colgroup, dd, div, dt, li, optgroup, option, p, rb,
+// rp, rt, rtc, span, tbody, td, tfoot, th, thead or tr.
+func (p *parser) generateAllImpliedEndTags() {
+ var i int
+ for i = len(p.oe) - 1; i >= 0; i-- {
+ n := p.oe[i]
+ if n.Type == ElementNode {
+ switch n.DataAtom {
+ // TODO: remove this divergence from the HTML5 spec
+ case a.Caption, a.Colgroup, a.Dd, a.Div, a.Dt, a.Li, a.Optgroup, a.Option, a.P, a.Rb,
+ a.Rp, a.Rt, a.Rtc, a.Span, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
+ continue
+ }
+ }
+ break
+ }
+
+ p.oe = p.oe[:i+1]
+}
+
+// addChild adds a child node n to the top element, and pushes n onto the stack
+// of open elements if it is an element node.
+func (p *parser) addChild(n *Node) {
+ if p.shouldFosterParent() {
+ p.fosterParent(n)
+ } else {
+ p.top().AppendChild(n)
+ }
+
+ if n.Type == ElementNode {
+ p.oe = append(p.oe, n)
+ }
+}
+
+// shouldFosterParent returns whether the next node to be added should be
+// foster parented.
+func (p *parser) shouldFosterParent() bool {
+ if p.fosterParenting {
+ switch p.top().DataAtom {
+ case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
+ return true
+ }
+ }
+ return false
+}
+
+// fosterParent adds a child node according to the foster parenting rules.
+// Section 12.2.6.1, "foster parenting".
+func (p *parser) fosterParent(n *Node) {
+ var table, parent, prev, template *Node
+ var i int
+ for i = len(p.oe) - 1; i >= 0; i-- {
+ if p.oe[i].DataAtom == a.Table {
+ table = p.oe[i]
+ break
+ }
+ }
+
+ var j int
+ for j = len(p.oe) - 1; j >= 0; j-- {
+ if p.oe[j].DataAtom == a.Template {
+ template = p.oe[j]
+ break
+ }
+ }
+
+ if template != nil && (table == nil || j < i) {
+ template.AppendChild(n)
+ return
+ }
+
+ if table == nil {
+ // The foster parent is the html element.
+ parent = p.oe[0]
+ } else {
+ parent = table.Parent
+ }
+ if parent == nil {
+ parent = p.oe[i-1]
+ }
+
+ if table != nil {
+ prev = table.PrevSibling
+ } else {
+ prev = parent.LastChild
+ }
+ if prev != nil && prev.Type == TextNode && n.Type == TextNode {
+ prev.Data += n.Data
+ return
+ }
+
+ parent.InsertBefore(n, table)
+}
+
+// addText adds text to the preceding node if it is a text node, or else it
+// calls addChild with a new text node.
+func (p *parser) addText(text string) {
+ if text == "" {
+ return
+ }
+
+ if p.shouldFosterParent() {
+ p.fosterParent(&Node{
+ Type: TextNode,
+ Data: text,
+ })
+ return
+ }
+
+ t := p.top()
+ if n := t.LastChild; n != nil && n.Type == TextNode {
+ n.Data += text
+ return
+ }
+ p.addChild(&Node{
+ Type: TextNode,
+ Data: text,
+ })
+}
+
+// addElement adds a child element based on the current token.
+func (p *parser) addElement() {
+ p.addChild(&Node{
+ Type: ElementNode,
+ DataAtom: p.tok.DataAtom,
+ Data: p.tok.Data,
+ Attr: p.tok.Attr,
+ })
+}
+
+// Section 12.2.4.3.
+func (p *parser) addFormattingElement() {
+ tagAtom, attr := p.tok.DataAtom, p.tok.Attr
+ p.addElement()
+
+ // Implement the Noah's Ark clause, but with three per family instead of two.
+ identicalElements := 0
+findIdenticalElements:
+ for i := len(p.afe) - 1; i >= 0; i-- {
+ n := p.afe[i]
+ if n.Type == scopeMarkerNode {
+ break
+ }
+ if n.Type != ElementNode {
+ continue
+ }
+ if n.Namespace != "" {
+ continue
+ }
+ if n.DataAtom != tagAtom {
+ continue
+ }
+ if len(n.Attr) != len(attr) {
+ continue
+ }
+ compareAttributes:
+ for _, t0 := range n.Attr {
+ for _, t1 := range attr {
+ if t0.Key == t1.Key && t0.Namespace == t1.Namespace && t0.Val == t1.Val {
+ // Found a match for this attribute, continue with the next attribute.
+ continue compareAttributes
+ }
+ }
+ // If we get here, there is no attribute that matches a.
+ // Therefore the element is not identical to the new one.
+ continue findIdenticalElements
+ }
+
+ identicalElements++
+ if identicalElements >= 3 {
+ p.afe.remove(n)
+ }
+ }
+
+ p.afe = append(p.afe, p.top())
+}
+
+// Section 12.2.4.3.
+func (p *parser) clearActiveFormattingElements() {
+ for {
+ n := p.afe.pop()
+ if len(p.afe) == 0 || n.Type == scopeMarkerNode {
+ return
+ }
+ }
+}
+
+// Section 12.2.4.3.
+func (p *parser) reconstructActiveFormattingElements() {
+ n := p.afe.top()
+ if n == nil {
+ return
+ }
+ if n.Type == scopeMarkerNode || p.oe.index(n) != -1 {
+ return
+ }
+ i := len(p.afe) - 1
+ for n.Type != scopeMarkerNode && p.oe.index(n) == -1 {
+ if i == 0 {
+ i = -1
+ break
+ }
+ i--
+ n = p.afe[i]
+ }
+ for {
+ i++
+ clone := p.afe[i].clone()
+ p.addChild(clone)
+ p.afe[i] = clone
+ if i == len(p.afe)-1 {
+ break
+ }
+ }
+}
+
+// Section 12.2.5.
+func (p *parser) acknowledgeSelfClosingTag() {
+ p.hasSelfClosingToken = false
+}
+
+// An insertion mode (section 12.2.4.1) is the state transition function from
+// a particular state in the HTML5 parser's state machine. It updates the
+// parser's fields depending on parser.tok (where ErrorToken means EOF).
+// It returns whether the token was consumed.
+type insertionMode func(*parser) bool
+
+// setOriginalIM sets the insertion mode to return to after completing a text or
+// inTableText insertion mode.
+// Section 12.2.4.1, "using the rules for".
+func (p *parser) setOriginalIM() {
+ if p.originalIM != nil {
+ panic("html: bad parser state: originalIM was set twice")
+ }
+ p.originalIM = p.im
+}
+
+// Section 12.2.4.1, "reset the insertion mode".
+func (p *parser) resetInsertionMode() {
+ for i := len(p.oe) - 1; i >= 0; i-- {
+ n := p.oe[i]
+ last := i == 0
+ if last && p.context != nil {
+ n = p.context
+ }
+
+ switch n.DataAtom {
+ case a.Select:
+ if !last {
+ for ancestor, first := n, p.oe[0]; ancestor != first; {
+ if ancestor == first {
+ break
+ }
+ ancestor = p.oe[p.oe.index(ancestor)-1]
+ switch ancestor.DataAtom {
+ case a.Template:
+ p.im = inSelectIM
+ return
+ case a.Table:
+ p.im = inSelectInTableIM
+ return
+ }
+ }
+ }
+ p.im = inSelectIM
+ case a.Td, a.Th:
+ // TODO: remove this divergence from the HTML5 spec.
+ //
+ // See https://bugs.chromium.org/p/chromium/issues/detail?id=829668
+ p.im = inCellIM
+ case a.Tr:
+ p.im = inRowIM
+ case a.Tbody, a.Thead, a.Tfoot:
+ p.im = inTableBodyIM
+ case a.Caption:
+ p.im = inCaptionIM
+ case a.Colgroup:
+ p.im = inColumnGroupIM
+ case a.Table:
+ p.im = inTableIM
+ case a.Template:
+ p.im = p.templateStack.top()
+ case a.Head:
+ // TODO: remove this divergence from the HTML5 spec.
+ //
+ // See https://bugs.chromium.org/p/chromium/issues/detail?id=829668
+ p.im = inHeadIM
+ case a.Body:
+ p.im = inBodyIM
+ case a.Frameset:
+ p.im = inFramesetIM
+ case a.Html:
+ if p.head == nil {
+ p.im = beforeHeadIM
+ } else {
+ p.im = afterHeadIM
+ }
+ default:
+ if last {
+ p.im = inBodyIM
+ return
+ }
+ continue
+ }
+ return
+ }
+}
+
+const whitespace = " \t\r\n\f"
+
+// Section 12.2.6.4.1.
+func initialIM(p *parser) bool {
+ switch p.tok.Type {
+ case TextToken:
+ p.tok.Data = strings.TrimLeft(p.tok.Data, whitespace)
+ if len(p.tok.Data) == 0 {
+ // It was all whitespace, so ignore it.
+ return true
+ }
+ case CommentToken:
+ p.doc.AppendChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ return true
+ case DoctypeToken:
+ n, quirks := parseDoctype(p.tok.Data)
+ p.doc.AppendChild(n)
+ p.quirks = quirks
+ p.im = beforeHTMLIM
+ return true
+ }
+ p.quirks = true
+ p.im = beforeHTMLIM
+ return false
+}
+
+// Section 12.2.6.4.2.
+func beforeHTMLIM(p *parser) bool {
+ switch p.tok.Type {
+ case DoctypeToken:
+ // Ignore the token.
+ return true
+ case TextToken:
+ p.tok.Data = strings.TrimLeft(p.tok.Data, whitespace)
+ if len(p.tok.Data) == 0 {
+ // It was all whitespace, so ignore it.
+ return true
+ }
+ case StartTagToken:
+ if p.tok.DataAtom == a.Html {
+ p.addElement()
+ p.im = beforeHeadIM
+ return true
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Head, a.Body, a.Html, a.Br:
+ p.parseImpliedToken(StartTagToken, a.Html, a.Html.String())
+ return false
+ default:
+ // Ignore the token.
+ return true
+ }
+ case CommentToken:
+ p.doc.AppendChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ return true
+ }
+ p.parseImpliedToken(StartTagToken, a.Html, a.Html.String())
+ return false
+}
+
+// Section 12.2.6.4.3.
+func beforeHeadIM(p *parser) bool {
+ switch p.tok.Type {
+ case TextToken:
+ p.tok.Data = strings.TrimLeft(p.tok.Data, whitespace)
+ if len(p.tok.Data) == 0 {
+ // It was all whitespace, so ignore it.
+ return true
+ }
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Head:
+ p.addElement()
+ p.head = p.top()
+ p.im = inHeadIM
+ return true
+ case a.Html:
+ return inBodyIM(p)
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Head, a.Body, a.Html, a.Br:
+ p.parseImpliedToken(StartTagToken, a.Head, a.Head.String())
+ return false
+ default:
+ // Ignore the token.
+ return true
+ }
+ case CommentToken:
+ p.addChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ return true
+ case DoctypeToken:
+ // Ignore the token.
+ return true
+ }
+
+ p.parseImpliedToken(StartTagToken, a.Head, a.Head.String())
+ return false
+}
+
+// Section 12.2.6.4.4.
+func inHeadIM(p *parser) bool {
+ switch p.tok.Type {
+ case TextToken:
+ s := strings.TrimLeft(p.tok.Data, whitespace)
+ if len(s) < len(p.tok.Data) {
+ // Add the initial whitespace to the current node.
+ p.addText(p.tok.Data[:len(p.tok.Data)-len(s)])
+ if s == "" {
+ return true
+ }
+ p.tok.Data = s
+ }
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Html:
+ return inBodyIM(p)
+ case a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta:
+ p.addElement()
+ p.oe.pop()
+ p.acknowledgeSelfClosingTag()
+ return true
+ case a.Script, a.Title, a.Noscript, a.Noframes, a.Style:
+ p.addElement()
+ p.setOriginalIM()
+ p.im = textIM
+ return true
+ case a.Head:
+ // Ignore the token.
+ return true
+ case a.Template:
+ p.addElement()
+ p.afe = append(p.afe, &scopeMarker)
+ p.framesetOK = false
+ p.im = inTemplateIM
+ p.templateStack = append(p.templateStack, inTemplateIM)
+ return true
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Head:
+ p.oe.pop()
+ p.im = afterHeadIM
+ return true
+ case a.Body, a.Html, a.Br:
+ p.parseImpliedToken(EndTagToken, a.Head, a.Head.String())
+ return false
+ case a.Template:
+ if !p.oe.contains(a.Template) {
+ return true
+ }
+ p.generateAllImpliedEndTags()
+ if n := p.oe.top(); n.DataAtom != a.Template {
+ return true
+ }
+ p.popUntil(defaultScope, a.Template)
+ p.clearActiveFormattingElements()
+ p.templateStack.pop()
+ p.resetInsertionMode()
+ return true
+ default:
+ // Ignore the token.
+ return true
+ }
+ case CommentToken:
+ p.addChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ return true
+ case DoctypeToken:
+ // Ignore the token.
+ return true
+ }
+
+ p.parseImpliedToken(EndTagToken, a.Head, a.Head.String())
+ return false
+}
+
+// Section 12.2.6.4.6.
+func afterHeadIM(p *parser) bool {
+ switch p.tok.Type {
+ case TextToken:
+ s := strings.TrimLeft(p.tok.Data, whitespace)
+ if len(s) < len(p.tok.Data) {
+ // Add the initial whitespace to the current node.
+ p.addText(p.tok.Data[:len(p.tok.Data)-len(s)])
+ if s == "" {
+ return true
+ }
+ p.tok.Data = s
+ }
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Html:
+ return inBodyIM(p)
+ case a.Body:
+ p.addElement()
+ p.framesetOK = false
+ p.im = inBodyIM
+ return true
+ case a.Frameset:
+ p.addElement()
+ p.im = inFramesetIM
+ return true
+ case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title:
+ p.oe = append(p.oe, p.head)
+ defer p.oe.remove(p.head)
+ return inHeadIM(p)
+ case a.Head:
+ // Ignore the token.
+ return true
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Body, a.Html, a.Br:
+ // Drop down to creating an implied <body> tag.
+ case a.Template:
+ return inHeadIM(p)
+ default:
+ // Ignore the token.
+ return true
+ }
+ case CommentToken:
+ p.addChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ return true
+ case DoctypeToken:
+ // Ignore the token.
+ return true
+ }
+
+ p.parseImpliedToken(StartTagToken, a.Body, a.Body.String())
+ p.framesetOK = true
+ return false
+}
+
+// copyAttributes copies attributes of src not found on dst to dst.
+func copyAttributes(dst *Node, src Token) {
+ if len(src.Attr) == 0 {
+ return
+ }
+ attr := map[string]string{}
+ for _, t := range dst.Attr {
+ attr[t.Key] = t.Val
+ }
+ for _, t := range src.Attr {
+ if _, ok := attr[t.Key]; !ok {
+ dst.Attr = append(dst.Attr, t)
+ attr[t.Key] = t.Val
+ }
+ }
+}
+
+// Section 12.2.6.4.7.
+func inBodyIM(p *parser) bool {
+ switch p.tok.Type {
+ case TextToken:
+ d := p.tok.Data
+ switch n := p.oe.top(); n.DataAtom {
+ case a.Pre, a.Listing:
+ if n.FirstChild == nil {
+ // Ignore a newline at the start of a <pre> block.
+ if d != "" && d[0] == '\r' {
+ d = d[1:]
+ }
+ if d != "" && d[0] == '\n' {
+ d = d[1:]
+ }
+ }
+ }
+ d = strings.Replace(d, "\x00", "", -1)
+ if d == "" {
+ return true
+ }
+ p.reconstructActiveFormattingElements()
+ p.addText(d)
+ if p.framesetOK && strings.TrimLeft(d, whitespace) != "" {
+ // There were non-whitespace characters inserted.
+ p.framesetOK = false
+ }
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Html:
+ if p.oe.contains(a.Template) {
+ return true
+ }
+ copyAttributes(p.oe[0], p.tok)
+ case a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title:
+ return inHeadIM(p)
+ case a.Body:
+ if p.oe.contains(a.Template) {
+ return true
+ }
+ if len(p.oe) >= 2 {
+ body := p.oe[1]
+ if body.Type == ElementNode && body.DataAtom == a.Body {
+ p.framesetOK = false
+ copyAttributes(body, p.tok)
+ }
+ }
+ case a.Frameset:
+ if !p.framesetOK || len(p.oe) < 2 || p.oe[1].DataAtom != a.Body {
+ // Ignore the token.
+ return true
+ }
+ body := p.oe[1]
+ if body.Parent != nil {
+ body.Parent.RemoveChild(body)
+ }
+ p.oe = p.oe[:1]
+ p.addElement()
+ p.im = inFramesetIM
+ return true
+ case a.Address, a.Article, a.Aside, a.Blockquote, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Menu, a.Nav, a.Ol, a.P, a.Section, a.Summary, a.Ul:
+ p.popUntil(buttonScope, a.P)
+ p.addElement()
+ case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
+ p.popUntil(buttonScope, a.P)
+ switch n := p.top(); n.DataAtom {
+ case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
+ p.oe.pop()
+ }
+ p.addElement()
+ case a.Pre, a.Listing:
+ p.popUntil(buttonScope, a.P)
+ p.addElement()
+ // The newline, if any, will be dealt with by the TextToken case.
+ p.framesetOK = false
+ case a.Form:
+ if p.oe.contains(a.Template) || p.form == nil {
+ p.popUntil(buttonScope, a.P)
+ p.addElement()
+ p.form = p.top()
+ }
+ case a.Li:
+ p.framesetOK = false
+ for i := len(p.oe) - 1; i >= 0; i-- {
+ node := p.oe[i]
+ switch node.DataAtom {
+ case a.Li:
+ p.oe = p.oe[:i]
+ case a.Address, a.Div, a.P:
+ continue
+ default:
+ if !isSpecialElement(node) {
+ continue
+ }
+ }
+ break
+ }
+ p.popUntil(buttonScope, a.P)
+ p.addElement()
+ case a.Dd, a.Dt:
+ p.framesetOK = false
+ for i := len(p.oe) - 1; i >= 0; i-- {
+ node := p.oe[i]
+ switch node.DataAtom {
+ case a.Dd, a.Dt:
+ p.oe = p.oe[:i]
+ case a.Address, a.Div, a.P:
+ continue
+ default:
+ if !isSpecialElement(node) {
+ continue
+ }
+ }
+ break
+ }
+ p.popUntil(buttonScope, a.P)
+ p.addElement()
+ case a.Plaintext:
+ p.popUntil(buttonScope, a.P)
+ p.addElement()
+ case a.Button:
+ p.popUntil(defaultScope, a.Button)
+ p.reconstructActiveFormattingElements()
+ p.addElement()
+ p.framesetOK = false
+ case a.A:
+ for i := len(p.afe) - 1; i >= 0 && p.afe[i].Type != scopeMarkerNode; i-- {
+ if n := p.afe[i]; n.Type == ElementNode && n.DataAtom == a.A {
+ p.inBodyEndTagFormatting(a.A)
+ p.oe.remove(n)
+ p.afe.remove(n)
+ break
+ }
+ }
+ p.reconstructActiveFormattingElements()
+ p.addFormattingElement()
+ case a.B, a.Big, a.Code, a.Em, a.Font, a.I, a.S, a.Small, a.Strike, a.Strong, a.Tt, a.U:
+ p.reconstructActiveFormattingElements()
+ p.addFormattingElement()
+ case a.Nobr:
+ p.reconstructActiveFormattingElements()
+ if p.elementInScope(defaultScope, a.Nobr) {
+ p.inBodyEndTagFormatting(a.Nobr)
+ p.reconstructActiveFormattingElements()
+ }
+ p.addFormattingElement()
+ case a.Applet, a.Marquee, a.Object:
+ p.reconstructActiveFormattingElements()
+ p.addElement()
+ p.afe = append(p.afe, &scopeMarker)
+ p.framesetOK = false
+ case a.Table:
+ if !p.quirks {
+ p.popUntil(buttonScope, a.P)
+ }
+ p.addElement()
+ p.framesetOK = false
+ p.im = inTableIM
+ return true
+ case a.Area, a.Br, a.Embed, a.Img, a.Input, a.Keygen, a.Wbr:
+ p.reconstructActiveFormattingElements()
+ p.addElement()
+ p.oe.pop()
+ p.acknowledgeSelfClosingTag()
+ if p.tok.DataAtom == a.Input {
+ for _, t := range p.tok.Attr {
+ if t.Key == "type" {
+ if strings.ToLower(t.Val) == "hidden" {
+ // Skip setting framesetOK = false
+ return true
+ }
+ }
+ }
+ }
+ p.framesetOK = false
+ case a.Param, a.Source, a.Track:
+ p.addElement()
+ p.oe.pop()
+ p.acknowledgeSelfClosingTag()
+ case a.Hr:
+ p.popUntil(buttonScope, a.P)
+ p.addElement()
+ p.oe.pop()
+ p.acknowledgeSelfClosingTag()
+ p.framesetOK = false
+ case a.Image:
+ p.tok.DataAtom = a.Img
+ p.tok.Data = a.Img.String()
+ return false
+ case a.Isindex:
+ if p.form != nil {
+ // Ignore the token.
+ return true
+ }
+ action := ""
+ prompt := "This is a searchable index. Enter search keywords: "
+ attr := []Attribute{{Key: "name", Val: "isindex"}}
+ for _, t := range p.tok.Attr {
+ switch t.Key {
+ case "action":
+ action = t.Val
+ case "name":
+ // Ignore the attribute.
+ case "prompt":
+ prompt = t.Val
+ default:
+ attr = append(attr, t)
+ }
+ }
+ p.acknowledgeSelfClosingTag()
+ p.popUntil(buttonScope, a.P)
+ p.parseImpliedToken(StartTagToken, a.Form, a.Form.String())
+ if action != "" {
+ p.form.Attr = []Attribute{{Key: "action", Val: action}}
+ }
+ p.parseImpliedToken(StartTagToken, a.Hr, a.Hr.String())
+ p.parseImpliedToken(StartTagToken, a.Label, a.Label.String())
+ p.addText(prompt)
+ p.addChild(&Node{
+ Type: ElementNode,
+ DataAtom: a.Input,
+ Data: a.Input.String(),
+ Attr: attr,
+ })
+ p.oe.pop()
+ p.parseImpliedToken(EndTagToken, a.Label, a.Label.String())
+ p.parseImpliedToken(StartTagToken, a.Hr, a.Hr.String())
+ p.parseImpliedToken(EndTagToken, a.Form, a.Form.String())
+ case a.Textarea:
+ p.addElement()
+ p.setOriginalIM()
+ p.framesetOK = false
+ p.im = textIM
+ case a.Xmp:
+ p.popUntil(buttonScope, a.P)
+ p.reconstructActiveFormattingElements()
+ p.framesetOK = false
+ p.addElement()
+ p.setOriginalIM()
+ p.im = textIM
+ case a.Iframe:
+ p.framesetOK = false
+ p.addElement()
+ p.setOriginalIM()
+ p.im = textIM
+ case a.Noembed, a.Noscript:
+ p.addElement()
+ p.setOriginalIM()
+ p.im = textIM
+ case a.Select:
+ p.reconstructActiveFormattingElements()
+ p.addElement()
+ p.framesetOK = false
+ p.im = inSelectIM
+ return true
+ case a.Optgroup, a.Option:
+ if p.top().DataAtom == a.Option {
+ p.oe.pop()
+ }
+ p.reconstructActiveFormattingElements()
+ p.addElement()
+ case a.Rb, a.Rtc:
+ if p.elementInScope(defaultScope, a.Ruby) {
+ p.generateImpliedEndTags()
+ }
+ p.addElement()
+ case a.Rp, a.Rt:
+ if p.elementInScope(defaultScope, a.Ruby) {
+ p.generateImpliedEndTags("rtc")
+ }
+ p.addElement()
+ case a.Math, a.Svg:
+ p.reconstructActiveFormattingElements()
+ if p.tok.DataAtom == a.Math {
+ adjustAttributeNames(p.tok.Attr, mathMLAttributeAdjustments)
+ } else {
+ adjustAttributeNames(p.tok.Attr, svgAttributeAdjustments)
+ }
+ adjustForeignAttributes(p.tok.Attr)
+ p.addElement()
+ p.top().Namespace = p.tok.Data
+ if p.hasSelfClosingToken {
+ p.oe.pop()
+ p.acknowledgeSelfClosingTag()
+ }
+ return true
+ case a.Frame:
+ // TODO: remove this divergence from the HTML5 spec.
+ if p.oe.contains(a.Template) {
+ p.addElement()
+ return true
+ }
+ case a.Caption, a.Col, a.Colgroup, a.Head, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
+ // Ignore the token.
+ default:
+ p.reconstructActiveFormattingElements()
+ p.addElement()
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Body:
+ if p.elementInScope(defaultScope, a.Body) {
+ p.im = afterBodyIM
+ }
+ case a.Html:
+ if p.elementInScope(defaultScope, a.Body) {
+ p.parseImpliedToken(EndTagToken, a.Body, a.Body.String())
+ return false
+ }
+ return true
+ case a.Address, a.Article, a.Aside, a.Blockquote, a.Button, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Listing, a.Menu, a.Nav, a.Ol, a.Pre, a.Section, a.Summary, a.Ul:
+ p.popUntil(defaultScope, p.tok.DataAtom)
+ case a.Form:
+ if p.oe.contains(a.Template) {
+ if !p.oe.contains(a.Form) {
+ // Ignore the token.
+ return true
+ }
+ p.generateImpliedEndTags()
+ if p.tok.DataAtom == a.Form {
+ // Ignore the token.
+ return true
+ }
+ p.popUntil(defaultScope, a.Form)
+ } else {
+ node := p.form
+ p.form = nil
+ i := p.indexOfElementInScope(defaultScope, a.Form)
+ if node == nil || i == -1 || p.oe[i] != node {
+ // Ignore the token.
+ return true
+ }
+ p.generateImpliedEndTags()
+ p.oe.remove(node)
+ }
+ case a.P:
+ if !p.elementInScope(buttonScope, a.P) {
+ p.parseImpliedToken(StartTagToken, a.P, a.P.String())
+ }
+ p.popUntil(buttonScope, a.P)
+ case a.Li:
+ p.popUntil(listItemScope, a.Li)
+ case a.Dd, a.Dt:
+ p.popUntil(defaultScope, p.tok.DataAtom)
+ case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
+ p.popUntil(defaultScope, a.H1, a.H2, a.H3, a.H4, a.H5, a.H6)
+ case a.A, a.B, a.Big, a.Code, a.Em, a.Font, a.I, a.Nobr, a.S, a.Small, a.Strike, a.Strong, a.Tt, a.U:
+ p.inBodyEndTagFormatting(p.tok.DataAtom)
+ case a.Applet, a.Marquee, a.Object:
+ if p.popUntil(defaultScope, p.tok.DataAtom) {
+ p.clearActiveFormattingElements()
+ }
+ case a.Br:
+ p.tok.Type = StartTagToken
+ return false
+ case a.Template:
+ return inHeadIM(p)
+ default:
+ p.inBodyEndTagOther(p.tok.DataAtom)
+ }
+ case CommentToken:
+ p.addChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ case ErrorToken:
+ // TODO: remove this divergence from the HTML5 spec.
+ if len(p.templateStack) > 0 {
+ p.im = inTemplateIM
+ return false
+ } else {
+ for _, e := range p.oe {
+ switch e.DataAtom {
+ case a.Dd, a.Dt, a.Li, a.Optgroup, a.Option, a.P, a.Rb, a.Rp, a.Rt, a.Rtc, a.Tbody, a.Td, a.Tfoot, a.Th,
+ a.Thead, a.Tr, a.Body, a.Html:
+ default:
+ return true
+ }
+ }
+ }
+ }
+
+ return true
+}
+
+func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) {
+ // This is the "adoption agency" algorithm, described at
+ // https://html.spec.whatwg.org/multipage/syntax.html#adoptionAgency
+
+ // TODO: this is a fairly literal line-by-line translation of that algorithm.
+ // Once the code successfully parses the comprehensive test suite, we should
+ // refactor this code to be more idiomatic.
+
+ // Steps 1-4. The outer loop.
+ for i := 0; i < 8; i++ {
+ // Step 5. Find the formatting element.
+ var formattingElement *Node
+ for j := len(p.afe) - 1; j >= 0; j-- {
+ if p.afe[j].Type == scopeMarkerNode {
+ break
+ }
+ if p.afe[j].DataAtom == tagAtom {
+ formattingElement = p.afe[j]
+ break
+ }
+ }
+ if formattingElement == nil {
+ p.inBodyEndTagOther(tagAtom)
+ return
+ }
+ feIndex := p.oe.index(formattingElement)
+ if feIndex == -1 {
+ p.afe.remove(formattingElement)
+ return
+ }
+ if !p.elementInScope(defaultScope, tagAtom) {
+ // Ignore the tag.
+ return
+ }
+
+ // Steps 9-10. Find the furthest block.
+ var furthestBlock *Node
+ for _, e := range p.oe[feIndex:] {
+ if isSpecialElement(e) {
+ furthestBlock = e
+ break
+ }
+ }
+ if furthestBlock == nil {
+ e := p.oe.pop()
+ for e != formattingElement {
+ e = p.oe.pop()
+ }
+ p.afe.remove(e)
+ return
+ }
+
+ // Steps 11-12. Find the common ancestor and bookmark node.
+ commonAncestor := p.oe[feIndex-1]
+ bookmark := p.afe.index(formattingElement)
+
+ // Step 13. The inner loop. Find the lastNode to reparent.
+ lastNode := furthestBlock
+ node := furthestBlock
+ x := p.oe.index(node)
+ // Steps 13.1-13.2
+ for j := 0; j < 3; j++ {
+ // Step 13.3.
+ x--
+ node = p.oe[x]
+ // Step 13.4 - 13.5.
+ if p.afe.index(node) == -1 {
+ p.oe.remove(node)
+ continue
+ }
+ // Step 13.6.
+ if node == formattingElement {
+ break
+ }
+ // Step 13.7.
+ clone := node.clone()
+ p.afe[p.afe.index(node)] = clone
+ p.oe[p.oe.index(node)] = clone
+ node = clone
+ // Step 13.8.
+ if lastNode == furthestBlock {
+ bookmark = p.afe.index(node) + 1
+ }
+ // Step 13.9.
+ if lastNode.Parent != nil {
+ lastNode.Parent.RemoveChild(lastNode)
+ }
+ node.AppendChild(lastNode)
+ // Step 13.10.
+ lastNode = node
+ }
+
+ // Step 14. Reparent lastNode to the common ancestor,
+ // or for misnested table nodes, to the foster parent.
+ if lastNode.Parent != nil {
+ lastNode.Parent.RemoveChild(lastNode)
+ }
+ switch commonAncestor.DataAtom {
+ case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
+ p.fosterParent(lastNode)
+ case a.Template:
+ // TODO: remove namespace checking
+ if commonAncestor.Namespace == "html" {
+ commonAncestor = commonAncestor.LastChild
+ }
+ fallthrough
+ default:
+ commonAncestor.AppendChild(lastNode)
+ }
+
+ // Steps 15-17. Reparent nodes from the furthest block's children
+ // to a clone of the formatting element.
+ clone := formattingElement.clone()
+ reparentChildren(clone, furthestBlock)
+ furthestBlock.AppendChild(clone)
+
+ // Step 18. Fix up the list of active formatting elements.
+ if oldLoc := p.afe.index(formattingElement); oldLoc != -1 && oldLoc < bookmark {
+ // Move the bookmark with the rest of the list.
+ bookmark--
+ }
+ p.afe.remove(formattingElement)
+ p.afe.insert(bookmark, clone)
+
+ // Step 19. Fix up the stack of open elements.
+ p.oe.remove(formattingElement)
+ p.oe.insert(p.oe.index(furthestBlock)+1, clone)
+ }
+}
+
+// inBodyEndTagOther performs the "any other end tag" algorithm for inBodyIM.
+// "Any other end tag" handling from 12.2.6.5 The rules for parsing tokens in foreign content
+// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inforeign
+func (p *parser) inBodyEndTagOther(tagAtom a.Atom) {
+ for i := len(p.oe) - 1; i >= 0; i-- {
+ if p.oe[i].DataAtom == tagAtom {
+ p.oe = p.oe[:i]
+ break
+ }
+ if isSpecialElement(p.oe[i]) {
+ break
+ }
+ }
+}
+
+// Section 12.2.6.4.8.
+func textIM(p *parser) bool {
+ switch p.tok.Type {
+ case ErrorToken:
+ p.oe.pop()
+ case TextToken:
+ d := p.tok.Data
+ if n := p.oe.top(); n.DataAtom == a.Textarea && n.FirstChild == nil {
+ // Ignore a newline at the start of a <textarea> block.
+ if d != "" && d[0] == '\r' {
+ d = d[1:]
+ }
+ if d != "" && d[0] == '\n' {
+ d = d[1:]
+ }
+ }
+ if d == "" {
+ return true
+ }
+ p.addText(d)
+ return true
+ case EndTagToken:
+ p.oe.pop()
+ }
+ p.im = p.originalIM
+ p.originalIM = nil
+ return p.tok.Type == EndTagToken
+}
+
+// Section 12.2.6.4.9.
+func inTableIM(p *parser) bool {
+ switch p.tok.Type {
+ case ErrorToken:
+ // Stop parsing.
+ return true
+ case TextToken:
+ p.tok.Data = strings.Replace(p.tok.Data, "\x00", "", -1)
+ switch p.oe.top().DataAtom {
+ case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
+ if strings.Trim(p.tok.Data, whitespace) == "" {
+ p.addText(p.tok.Data)
+ return true
+ }
+ }
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Caption:
+ p.clearStackToContext(tableScope)
+ p.afe = append(p.afe, &scopeMarker)
+ p.addElement()
+ p.im = inCaptionIM
+ return true
+ case a.Colgroup:
+ p.clearStackToContext(tableScope)
+ p.addElement()
+ p.im = inColumnGroupIM
+ return true
+ case a.Col:
+ p.parseImpliedToken(StartTagToken, a.Colgroup, a.Colgroup.String())
+ return false
+ case a.Tbody, a.Tfoot, a.Thead:
+ p.clearStackToContext(tableScope)
+ p.addElement()
+ p.im = inTableBodyIM
+ return true
+ case a.Td, a.Th, a.Tr:
+ p.parseImpliedToken(StartTagToken, a.Tbody, a.Tbody.String())
+ return false
+ case a.Table:
+ if p.popUntil(tableScope, a.Table) {
+ p.resetInsertionMode()
+ return false
+ }
+ // Ignore the token.
+ return true
+ case a.Style, a.Script, a.Template:
+ return inHeadIM(p)
+ case a.Input:
+ for _, t := range p.tok.Attr {
+ if t.Key == "type" && strings.ToLower(t.Val) == "hidden" {
+ p.addElement()
+ p.oe.pop()
+ return true
+ }
+ }
+ // Otherwise drop down to the default action.
+ case a.Form:
+ if p.oe.contains(a.Template) || p.form != nil {
+ // Ignore the token.
+ return true
+ }
+ p.addElement()
+ p.form = p.oe.pop()
+ case a.Select:
+ p.reconstructActiveFormattingElements()
+ switch p.top().DataAtom {
+ case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
+ p.fosterParenting = true
+ }
+ p.addElement()
+ p.fosterParenting = false
+ p.framesetOK = false
+ p.im = inSelectInTableIM
+ return true
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Table:
+ if p.popUntil(tableScope, a.Table) {
+ p.resetInsertionMode()
+ return true
+ }
+ // Ignore the token.
+ return true
+ case a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
+ // Ignore the token.
+ return true
+ case a.Template:
+ return inHeadIM(p)
+ }
+ case CommentToken:
+ p.addChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ return true
+ case DoctypeToken:
+ // Ignore the token.
+ return true
+ }
+
+ p.fosterParenting = true
+ defer func() { p.fosterParenting = false }()
+
+ return inBodyIM(p)
+}
+
+// Section 12.2.6.4.11.
+func inCaptionIM(p *parser) bool {
+ switch p.tok.Type {
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Td, a.Tfoot, a.Thead, a.Tr:
+ if p.popUntil(tableScope, a.Caption) {
+ p.clearActiveFormattingElements()
+ p.im = inTableIM
+ return false
+ } else {
+ // Ignore the token.
+ return true
+ }
+ case a.Select:
+ p.reconstructActiveFormattingElements()
+ p.addElement()
+ p.framesetOK = false
+ p.im = inSelectInTableIM
+ return true
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Caption:
+ if p.popUntil(tableScope, a.Caption) {
+ p.clearActiveFormattingElements()
+ p.im = inTableIM
+ }
+ return true
+ case a.Table:
+ if p.popUntil(tableScope, a.Caption) {
+ p.clearActiveFormattingElements()
+ p.im = inTableIM
+ return false
+ } else {
+ // Ignore the token.
+ return true
+ }
+ case a.Body, a.Col, a.Colgroup, a.Html, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
+ // Ignore the token.
+ return true
+ }
+ }
+ return inBodyIM(p)
+}
+
+// Section 12.2.6.4.12.
+func inColumnGroupIM(p *parser) bool {
+ switch p.tok.Type {
+ case TextToken:
+ s := strings.TrimLeft(p.tok.Data, whitespace)
+ if len(s) < len(p.tok.Data) {
+ // Add the initial whitespace to the current node.
+ p.addText(p.tok.Data[:len(p.tok.Data)-len(s)])
+ if s == "" {
+ return true
+ }
+ p.tok.Data = s
+ }
+ case CommentToken:
+ p.addChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ return true
+ case DoctypeToken:
+ // Ignore the token.
+ return true
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Html:
+ return inBodyIM(p)
+ case a.Col:
+ p.addElement()
+ p.oe.pop()
+ p.acknowledgeSelfClosingTag()
+ return true
+ case a.Template:
+ return inHeadIM(p)
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Colgroup:
+ if p.oe.top().DataAtom == a.Colgroup {
+ p.oe.pop()
+ p.im = inTableIM
+ }
+ return true
+ case a.Col:
+ // Ignore the token.
+ return true
+ case a.Template:
+ return inHeadIM(p)
+ }
+ }
+ if p.oe.top().DataAtom != a.Colgroup {
+ return true
+ }
+ p.oe.pop()
+ p.im = inTableIM
+ return false
+}
+
+// Section 12.2.6.4.13.
+func inTableBodyIM(p *parser) bool {
+ switch p.tok.Type {
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Tr:
+ p.clearStackToContext(tableBodyScope)
+ p.addElement()
+ p.im = inRowIM
+ return true
+ case a.Td, a.Th:
+ p.parseImpliedToken(StartTagToken, a.Tr, a.Tr.String())
+ return false
+ case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Tfoot, a.Thead:
+ if p.popUntil(tableScope, a.Tbody, a.Thead, a.Tfoot) {
+ p.im = inTableIM
+ return false
+ }
+ // Ignore the token.
+ return true
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Tbody, a.Tfoot, a.Thead:
+ if p.elementInScope(tableScope, p.tok.DataAtom) {
+ p.clearStackToContext(tableBodyScope)
+ p.oe.pop()
+ p.im = inTableIM
+ }
+ return true
+ case a.Table:
+ if p.popUntil(tableScope, a.Tbody, a.Thead, a.Tfoot) {
+ p.im = inTableIM
+ return false
+ }
+ // Ignore the token.
+ return true
+ case a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Td, a.Th, a.Tr:
+ // Ignore the token.
+ return true
+ }
+ case CommentToken:
+ p.addChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ return true
+ }
+
+ return inTableIM(p)
+}
+
+// Section 12.2.6.4.14.
+func inRowIM(p *parser) bool {
+ switch p.tok.Type {
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Td, a.Th:
+ p.clearStackToContext(tableRowScope)
+ p.addElement()
+ p.afe = append(p.afe, &scopeMarker)
+ p.im = inCellIM
+ return true
+ case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Tfoot, a.Thead, a.Tr:
+ if p.popUntil(tableScope, a.Tr) {
+ p.im = inTableBodyIM
+ return false
+ }
+ // Ignore the token.
+ return true
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Tr:
+ if p.popUntil(tableScope, a.Tr) {
+ p.im = inTableBodyIM
+ return true
+ }
+ // Ignore the token.
+ return true
+ case a.Table:
+ if p.popUntil(tableScope, a.Tr) {
+ p.im = inTableBodyIM
+ return false
+ }
+ // Ignore the token.
+ return true
+ case a.Tbody, a.Tfoot, a.Thead:
+ if p.elementInScope(tableScope, p.tok.DataAtom) {
+ p.parseImpliedToken(EndTagToken, a.Tr, a.Tr.String())
+ return false
+ }
+ // Ignore the token.
+ return true
+ case a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Td, a.Th:
+ // Ignore the token.
+ return true
+ }
+ }
+
+ return inTableIM(p)
+}
+
+// Section 12.2.6.4.15.
+func inCellIM(p *parser) bool {
+ switch p.tok.Type {
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
+ if p.popUntil(tableScope, a.Td, a.Th) {
+ // Close the cell and reprocess.
+ p.clearActiveFormattingElements()
+ p.im = inRowIM
+ return false
+ }
+ // Ignore the token.
+ return true
+ case a.Select:
+ p.reconstructActiveFormattingElements()
+ p.addElement()
+ p.framesetOK = false
+ p.im = inSelectInTableIM
+ return true
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Td, a.Th:
+ if !p.popUntil(tableScope, p.tok.DataAtom) {
+ // Ignore the token.
+ return true
+ }
+ p.clearActiveFormattingElements()
+ p.im = inRowIM
+ return true
+ case a.Body, a.Caption, a.Col, a.Colgroup, a.Html:
+ // Ignore the token.
+ return true
+ case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
+ if !p.elementInScope(tableScope, p.tok.DataAtom) {
+ // Ignore the token.
+ return true
+ }
+ // Close the cell and reprocess.
+ p.popUntil(tableScope, a.Td, a.Th)
+ p.clearActiveFormattingElements()
+ p.im = inRowIM
+ return false
+ }
+ }
+ return inBodyIM(p)
+}
+
+// Section 12.2.6.4.16.
+func inSelectIM(p *parser) bool {
+ switch p.tok.Type {
+ case ErrorToken:
+ // Stop parsing.
+ return true
+ case TextToken:
+ p.addText(strings.Replace(p.tok.Data, "\x00", "", -1))
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Html:
+ return inBodyIM(p)
+ case a.Option:
+ if p.top().DataAtom == a.Option {
+ p.oe.pop()
+ }
+ p.addElement()
+ case a.Optgroup:
+ if p.top().DataAtom == a.Option {
+ p.oe.pop()
+ }
+ if p.top().DataAtom == a.Optgroup {
+ p.oe.pop()
+ }
+ p.addElement()
+ case a.Select:
+ p.tok.Type = EndTagToken
+ return false
+ case a.Input, a.Keygen, a.Textarea:
+ if p.elementInScope(selectScope, a.Select) {
+ p.parseImpliedToken(EndTagToken, a.Select, a.Select.String())
+ return false
+ }
+ // In order to properly ignore <textarea>, we need to change the tokenizer mode.
+ p.tokenizer.NextIsNotRawText()
+ // Ignore the token.
+ return true
+ case a.Script, a.Template:
+ return inHeadIM(p)
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Option:
+ if p.top().DataAtom == a.Option {
+ p.oe.pop()
+ }
+ case a.Optgroup:
+ i := len(p.oe) - 1
+ if p.oe[i].DataAtom == a.Option {
+ i--
+ }
+ if p.oe[i].DataAtom == a.Optgroup {
+ p.oe = p.oe[:i]
+ }
+ case a.Select:
+ if p.popUntil(selectScope, a.Select) {
+ p.resetInsertionMode()
+ }
+ case a.Template:
+ return inHeadIM(p)
+ }
+ case CommentToken:
+ p.addChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ case DoctypeToken:
+ // Ignore the token.
+ return true
+ }
+
+ return true
+}
+
+// Section 12.2.6.4.17.
+func inSelectInTableIM(p *parser) bool {
+ switch p.tok.Type {
+ case StartTagToken, EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Caption, a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr, a.Td, a.Th:
+ if p.tok.Type == StartTagToken || p.elementInScope(tableScope, p.tok.DataAtom) {
+ p.parseImpliedToken(EndTagToken, a.Select, a.Select.String())
+ return false
+ } else {
+ // Ignore the token.
+ return true
+ }
+ }
+ }
+ return inSelectIM(p)
+}
+
+// Section 12.2.6.4.18.
+func inTemplateIM(p *parser) bool {
+ switch p.tok.Type {
+ case TextToken, CommentToken, DoctypeToken:
+ return inBodyIM(p)
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title:
+ return inHeadIM(p)
+ case a.Caption, a.Colgroup, a.Tbody, a.Tfoot, a.Thead:
+ p.templateStack.pop()
+ p.templateStack = append(p.templateStack, inTableIM)
+ p.im = inTableIM
+ return false
+ case a.Col:
+ p.templateStack.pop()
+ p.templateStack = append(p.templateStack, inColumnGroupIM)
+ p.im = inColumnGroupIM
+ return false
+ case a.Tr:
+ p.templateStack.pop()
+ p.templateStack = append(p.templateStack, inTableBodyIM)
+ p.im = inTableBodyIM
+ return false
+ case a.Td, a.Th:
+ p.templateStack.pop()
+ p.templateStack = append(p.templateStack, inRowIM)
+ p.im = inRowIM
+ return false
+ default:
+ p.templateStack.pop()
+ p.templateStack = append(p.templateStack, inBodyIM)
+ p.im = inBodyIM
+ return false
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Template:
+ return inHeadIM(p)
+ default:
+ // Ignore the token.
+ return true
+ }
+ }
+ if !p.oe.contains(a.Template) {
+ // Ignore the token.
+ return true
+ }
+ p.popUntil(defaultScope, a.Template)
+ p.clearActiveFormattingElements()
+ p.templateStack.pop()
+ p.resetInsertionMode()
+ return false
+}
+
+// Section 12.2.6.4.19.
+func afterBodyIM(p *parser) bool {
+ switch p.tok.Type {
+ case ErrorToken:
+ // Stop parsing.
+ return true
+ case TextToken:
+ s := strings.TrimLeft(p.tok.Data, whitespace)
+ if len(s) == 0 {
+ // It was all whitespace.
+ return inBodyIM(p)
+ }
+ case StartTagToken:
+ if p.tok.DataAtom == a.Html {
+ return inBodyIM(p)
+ }
+ case EndTagToken:
+ if p.tok.DataAtom == a.Html {
+ if !p.fragment {
+ p.im = afterAfterBodyIM
+ }
+ return true
+ }
+ case CommentToken:
+ // The comment is attached to the <html> element.
+ if len(p.oe) < 1 || p.oe[0].DataAtom != a.Html {
+ panic("html: bad parser state: <html> element not found, in the after-body insertion mode")
+ }
+ p.oe[0].AppendChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ return true
+ }
+ p.im = inBodyIM
+ return false
+}
+
+// Section 12.2.6.4.20.
+func inFramesetIM(p *parser) bool {
+ switch p.tok.Type {
+ case CommentToken:
+ p.addChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ case TextToken:
+ // Ignore all text but whitespace.
+ s := strings.Map(func(c rune) rune {
+ switch c {
+ case ' ', '\t', '\n', '\f', '\r':
+ return c
+ }
+ return -1
+ }, p.tok.Data)
+ if s != "" {
+ p.addText(s)
+ }
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Html:
+ return inBodyIM(p)
+ case a.Frameset:
+ p.addElement()
+ case a.Frame:
+ p.addElement()
+ p.oe.pop()
+ p.acknowledgeSelfClosingTag()
+ case a.Noframes:
+ return inHeadIM(p)
+ case a.Template:
+ // TODO: remove this divergence from the HTML5 spec.
+ //
+ // See https://bugs.chromium.org/p/chromium/issues/detail?id=829668
+ return inTemplateIM(p)
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Frameset:
+ if p.oe.top().DataAtom != a.Html {
+ p.oe.pop()
+ if p.oe.top().DataAtom != a.Frameset {
+ p.im = afterFramesetIM
+ return true
+ }
+ }
+ }
+ default:
+ // Ignore the token.
+ }
+ return true
+}
+
+// Section 12.2.6.4.21.
+func afterFramesetIM(p *parser) bool {
+ switch p.tok.Type {
+ case CommentToken:
+ p.addChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ case TextToken:
+ // Ignore all text but whitespace.
+ s := strings.Map(func(c rune) rune {
+ switch c {
+ case ' ', '\t', '\n', '\f', '\r':
+ return c
+ }
+ return -1
+ }, p.tok.Data)
+ if s != "" {
+ p.addText(s)
+ }
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Html:
+ return inBodyIM(p)
+ case a.Noframes:
+ return inHeadIM(p)
+ }
+ case EndTagToken:
+ switch p.tok.DataAtom {
+ case a.Html:
+ p.im = afterAfterFramesetIM
+ return true
+ }
+ default:
+ // Ignore the token.
+ }
+ return true
+}
+
+// Section 12.2.6.4.22.
+func afterAfterBodyIM(p *parser) bool {
+ switch p.tok.Type {
+ case ErrorToken:
+ // Stop parsing.
+ return true
+ case TextToken:
+ s := strings.TrimLeft(p.tok.Data, whitespace)
+ if len(s) == 0 {
+ // It was all whitespace.
+ return inBodyIM(p)
+ }
+ case StartTagToken:
+ if p.tok.DataAtom == a.Html {
+ return inBodyIM(p)
+ }
+ case CommentToken:
+ p.doc.AppendChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ return true
+ case DoctypeToken:
+ return inBodyIM(p)
+ }
+ p.im = inBodyIM
+ return false
+}
+
+// Section 12.2.6.4.23.
+func afterAfterFramesetIM(p *parser) bool {
+ switch p.tok.Type {
+ case CommentToken:
+ p.doc.AppendChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ case TextToken:
+ // Ignore all text but whitespace.
+ s := strings.Map(func(c rune) rune {
+ switch c {
+ case ' ', '\t', '\n', '\f', '\r':
+ return c
+ }
+ return -1
+ }, p.tok.Data)
+ if s != "" {
+ p.tok.Data = s
+ return inBodyIM(p)
+ }
+ case StartTagToken:
+ switch p.tok.DataAtom {
+ case a.Html:
+ return inBodyIM(p)
+ case a.Noframes:
+ return inHeadIM(p)
+ }
+ case DoctypeToken:
+ return inBodyIM(p)
+ default:
+ // Ignore the token.
+ }
+ return true
+}
+
+const whitespaceOrNUL = whitespace + "\x00"
+
+// Section 12.2.6.5
+func parseForeignContent(p *parser) bool {
+ switch p.tok.Type {
+ case TextToken:
+ if p.framesetOK {
+ p.framesetOK = strings.TrimLeft(p.tok.Data, whitespaceOrNUL) == ""
+ }
+ p.tok.Data = strings.Replace(p.tok.Data, "\x00", "\ufffd", -1)
+ p.addText(p.tok.Data)
+ case CommentToken:
+ p.addChild(&Node{
+ Type: CommentNode,
+ Data: p.tok.Data,
+ })
+ case StartTagToken:
+ b := breakout[p.tok.Data]
+ if p.tok.DataAtom == a.Font {
+ loop:
+ for _, attr := range p.tok.Attr {
+ switch attr.Key {
+ case "color", "face", "size":
+ b = true
+ break loop
+ }
+ }
+ }
+ if b {
+ for i := len(p.oe) - 1; i >= 0; i-- {
+ n := p.oe[i]
+ if n.Namespace == "" || htmlIntegrationPoint(n) || mathMLTextIntegrationPoint(n) {
+ p.oe = p.oe[:i+1]
+ break
+ }
+ }
+ return false
+ }
+ switch p.top().Namespace {
+ case "math":
+ adjustAttributeNames(p.tok.Attr, mathMLAttributeAdjustments)
+ case "svg":
+ // Adjust SVG tag names. The tokenizer lower-cases tag names, but
+ // SVG wants e.g. "foreignObject" with a capital second "O".
+ if x := svgTagNameAdjustments[p.tok.Data]; x != "" {
+ p.tok.DataAtom = a.Lookup([]byte(x))
+ p.tok.Data = x
+ }
+ adjustAttributeNames(p.tok.Attr, svgAttributeAdjustments)
+ default:
+ panic("html: bad parser state: unexpected namespace")
+ }
+ adjustForeignAttributes(p.tok.Attr)
+ namespace := p.top().Namespace
+ p.addElement()
+ p.top().Namespace = namespace
+ if namespace != "" {
+ // Don't let the tokenizer go into raw text mode in foreign content
+ // (e.g. in an SVG <title> tag).
+ p.tokenizer.NextIsNotRawText()
+ }
+ if p.hasSelfClosingToken {
+ p.oe.pop()
+ p.acknowledgeSelfClosingTag()
+ }
+ case EndTagToken:
+ for i := len(p.oe) - 1; i >= 0; i-- {
+ if p.oe[i].Namespace == "" {
+ return p.im(p)
+ }
+ if strings.EqualFold(p.oe[i].Data, p.tok.Data) {
+ p.oe = p.oe[:i]
+ break
+ }
+ }
+ return true
+ default:
+ // Ignore the token.
+ }
+ return true
+}
+
+// Section 12.2.6.
+func (p *parser) inForeignContent() bool {
+ if len(p.oe) == 0 {
+ return false
+ }
+ n := p.oe[len(p.oe)-1]
+ if n.Namespace == "" {
+ return false
+ }
+ if mathMLTextIntegrationPoint(n) {
+ if p.tok.Type == StartTagToken && p.tok.DataAtom != a.Mglyph && p.tok.DataAtom != a.Malignmark {
+ return false
+ }
+ if p.tok.Type == TextToken {
+ return false
+ }
+ }
+ if n.Namespace == "math" && n.DataAtom == a.AnnotationXml && p.tok.Type == StartTagToken && p.tok.DataAtom == a.Svg {
+ return false
+ }
+ if htmlIntegrationPoint(n) && (p.tok.Type == StartTagToken || p.tok.Type == TextToken) {
+ return false
+ }
+ if p.tok.Type == ErrorToken {
+ return false
+ }
+ return true
+}
+
+// parseImpliedToken parses a token as though it had appeared in the parser's
+// input.
+func (p *parser) parseImpliedToken(t TokenType, dataAtom a.Atom, data string) {
+ realToken, selfClosing := p.tok, p.hasSelfClosingToken
+ p.tok = Token{
+ Type: t,
+ DataAtom: dataAtom,
+ Data: data,
+ }
+ p.hasSelfClosingToken = false
+ p.parseCurrentToken()
+ p.tok, p.hasSelfClosingToken = realToken, selfClosing
+}
+
+// parseCurrentToken runs the current token through the parsing routines
+// until it is consumed.
+func (p *parser) parseCurrentToken() {
+ if p.tok.Type == SelfClosingTagToken {
+ p.hasSelfClosingToken = true
+ p.tok.Type = StartTagToken
+ }
+
+ consumed := false
+ for !consumed {
+ if p.inForeignContent() {
+ consumed = parseForeignContent(p)
+ } else {
+ consumed = p.im(p)
+ }
+ }
+
+ if p.hasSelfClosingToken {
+ // This is a parse error, but ignore it.
+ p.hasSelfClosingToken = false
+ }
+}
+
+func (p *parser) parse() error {
+ // Iterate until EOF. Any other error will cause an early return.
+ var err error
+ for err != io.EOF {
+ // CDATA sections are allowed only in foreign content.
+ n := p.oe.top()
+ p.tokenizer.AllowCDATA(n != nil && n.Namespace != "")
+ // Read and parse the next token.
+ p.tokenizer.Next()
+ p.tok = p.tokenizer.Token()
+ if p.tok.Type == ErrorToken {
+ err = p.tokenizer.Err()
+ if err != nil && err != io.EOF {
+ return err
+ }
+ }
+ p.parseCurrentToken()
+ }
+ return nil
+}
+
+// Parse returns the parse tree for the HTML from the given Reader.
+// The input is assumed to be UTF-8 encoded.
+func Parse(r io.Reader) (*Node, error) {
+ p := &parser{
+ tokenizer: NewTokenizer(r),
+ doc: &Node{
+ Type: DocumentNode,
+ },
+ scripting: true,
+ framesetOK: true,
+ im: initialIM,
+ }
+ err := p.parse()
+ if err != nil {
+ return nil, err
+ }
+ return p.doc, nil
+}
+
+// ParseFragment parses a fragment of HTML and returns the nodes that were
+// found. If the fragment is the InnerHTML for an existing element, pass that
+// element in context.
+func ParseFragment(r io.Reader, context *Node) ([]*Node, error) {
+ contextTag := ""
+ if context != nil {
+ if context.Type != ElementNode {
+ return nil, errors.New("html: ParseFragment of non-element Node")
+ }
+ // The next check isn't just context.DataAtom.String() == context.Data because
+ // it is valid to pass an element whose tag isn't a known atom. For example,
+ // DataAtom == 0 and Data = "tagfromthefuture" is perfectly consistent.
+ if context.DataAtom != a.Lookup([]byte(context.Data)) {
+ return nil, fmt.Errorf("html: inconsistent Node: DataAtom=%q, Data=%q", context.DataAtom, context.Data)
+ }
+ contextTag = context.DataAtom.String()
+ }
+ p := &parser{
+ tokenizer: NewTokenizerFragment(r, contextTag),
+ doc: &Node{
+ Type: DocumentNode,
+ },
+ scripting: true,
+ fragment: true,
+ context: context,
+ }
+
+ root := &Node{
+ Type: ElementNode,
+ DataAtom: a.Html,
+ Data: a.Html.String(),
+ }
+ p.doc.AppendChild(root)
+ p.oe = nodeStack{root}
+ if context != nil && context.DataAtom == a.Template {
+ p.templateStack = append(p.templateStack, inTemplateIM)
+ }
+ p.resetInsertionMode()
+
+ for n := context; n != nil; n = n.Parent {
+ if n.Type == ElementNode && n.DataAtom == a.Form {
+ p.form = n
+ break
+ }
+ }
+
+ err := p.parse()
+ if err != nil {
+ return nil, err
+ }
+
+ parent := p.doc
+ if context != nil {
+ parent = root
+ }
+
+ var result []*Node
+ for c := parent.FirstChild; c != nil; {
+ next := c.NextSibling
+ parent.RemoveChild(c)
+ result = append(result, c)
+ c = next
+ }
+ return result, nil
+}
diff --git a/vendor/golang.org/x/net/html/render.go b/vendor/golang.org/x/net/html/render.go
new file mode 100644
index 0000000..d34564f
--- /dev/null
+++ b/vendor/golang.org/x/net/html/render.go
@@ -0,0 +1,271 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "bufio"
+ "errors"
+ "fmt"
+ "io"
+ "strings"
+)
+
+type writer interface {
+ io.Writer
+ io.ByteWriter
+ WriteString(string) (int, error)
+}
+
+// Render renders the parse tree n to the given writer.
+//
+// Rendering is done on a 'best effort' basis: calling Parse on the output of
+// Render will always result in something similar to the original tree, but it
+// is not necessarily an exact clone unless the original tree was 'well-formed'.
+// 'Well-formed' is not easily specified; the HTML5 specification is
+// complicated.
+//
+// Calling Parse on arbitrary input typically results in a 'well-formed' parse
+// tree. However, it is possible for Parse to yield a 'badly-formed' parse tree.
+// For example, in a 'well-formed' parse tree, no <a> element is a child of
+// another <a> element: parsing "<a><a>" results in two sibling elements.
+// Similarly, in a 'well-formed' parse tree, no <a> element is a child of a
+// <table> element: parsing "<p><table><a>" results in a <p> with two sibling
+// children; the <a> is reparented to the <table>'s parent. However, calling
+// Parse on "<a><table><a>" does not return an error, but the result has an <a>
+// element with an <a> child, and is therefore not 'well-formed'.
+//
+// Programmatically constructed trees are typically also 'well-formed', but it
+// is possible to construct a tree that looks innocuous but, when rendered and
+// re-parsed, results in a different tree. A simple example is that a solitary
+// text node would become a tree containing <html>, <head> and <body> elements.
+// Another example is that the programmatic equivalent of "a<head>b</head>c"
+// becomes "<html><head><head/><body>abc</body></html>".
+func Render(w io.Writer, n *Node) error {
+ if x, ok := w.(writer); ok {
+ return render(x, n)
+ }
+ buf := bufio.NewWriter(w)
+ if err := render(buf, n); err != nil {
+ return err
+ }
+ return buf.Flush()
+}
+
+// plaintextAbort is returned from render1 when a <plaintext> element
+// has been rendered. No more end tags should be rendered after that.
+var plaintextAbort = errors.New("html: internal error (plaintext abort)")
+
+func render(w writer, n *Node) error {
+ err := render1(w, n)
+ if err == plaintextAbort {
+ err = nil
+ }
+ return err
+}
+
+func render1(w writer, n *Node) error {
+ // Render non-element nodes; these are the easy cases.
+ switch n.Type {
+ case ErrorNode:
+ return errors.New("html: cannot render an ErrorNode node")
+ case TextNode:
+ return escape(w, n.Data)
+ case DocumentNode:
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
+ if err := render1(w, c); err != nil {
+ return err
+ }
+ }
+ return nil
+ case ElementNode:
+ // No-op.
+ case CommentNode:
+ if _, err := w.WriteString("<!--"); err != nil {
+ return err
+ }
+ if _, err := w.WriteString(n.Data); err != nil {
+ return err
+ }
+ if _, err := w.WriteString("-->"); err != nil {
+ return err
+ }
+ return nil
+ case DoctypeNode:
+ if _, err := w.WriteString("<!DOCTYPE "); err != nil {
+ return err
+ }
+ if _, err := w.WriteString(n.Data); err != nil {
+ return err
+ }
+ if n.Attr != nil {
+ var p, s string
+ for _, a := range n.Attr {
+ switch a.Key {
+ case "public":
+ p = a.Val
+ case "system":
+ s = a.Val
+ }
+ }
+ if p != "" {
+ if _, err := w.WriteString(" PUBLIC "); err != nil {
+ return err
+ }
+ if err := writeQuoted(w, p); err != nil {
+ return err
+ }
+ if s != "" {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ if err := writeQuoted(w, s); err != nil {
+ return err
+ }
+ }
+ } else if s != "" {
+ if _, err := w.WriteString(" SYSTEM "); err != nil {
+ return err
+ }
+ if err := writeQuoted(w, s); err != nil {
+ return err
+ }
+ }
+ }
+ return w.WriteByte('>')
+ default:
+ return errors.New("html: unknown node type")
+ }
+
+ // Render the <xxx> opening tag.
+ if err := w.WriteByte('<'); err != nil {
+ return err
+ }
+ if _, err := w.WriteString(n.Data); err != nil {
+ return err
+ }
+ for _, a := range n.Attr {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ if a.Namespace != "" {
+ if _, err := w.WriteString(a.Namespace); err != nil {
+ return err
+ }
+ if err := w.WriteByte(':'); err != nil {
+ return err
+ }
+ }
+ if _, err := w.WriteString(a.Key); err != nil {
+ return err
+ }
+ if _, err := w.WriteString(`="`); err != nil {
+ return err
+ }
+ if err := escape(w, a.Val); err != nil {
+ return err
+ }
+ if err := w.WriteByte('"'); err != nil {
+ return err
+ }
+ }
+ if voidElements[n.Data] {
+ if n.FirstChild != nil {
+ return fmt.Errorf("html: void element <%s> has child nodes", n.Data)
+ }
+ _, err := w.WriteString("/>")
+ return err
+ }
+ if err := w.WriteByte('>'); err != nil {
+ return err
+ }
+
+ // Add initial newline where there is danger of a newline beging ignored.
+ if c := n.FirstChild; c != nil && c.Type == TextNode && strings.HasPrefix(c.Data, "\n") {
+ switch n.Data {
+ case "pre", "listing", "textarea":
+ if err := w.WriteByte('\n'); err != nil {
+ return err
+ }
+ }
+ }
+
+ // Render any child nodes.
+ switch n.Data {
+ case "iframe", "noembed", "noframes", "noscript", "plaintext", "script", "style", "xmp":
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
+ if c.Type == TextNode {
+ if _, err := w.WriteString(c.Data); err != nil {
+ return err
+ }
+ } else {
+ if err := render1(w, c); err != nil {
+ return err
+ }
+ }
+ }
+ if n.Data == "plaintext" {
+ // Don't render anything else. <plaintext> must be the
+ // last element in the file, with no closing tag.
+ return plaintextAbort
+ }
+ default:
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
+ if err := render1(w, c); err != nil {
+ return err
+ }
+ }
+ }
+
+ // Render the </xxx> closing tag.
+ if _, err := w.WriteString("</"); err != nil {
+ return err
+ }
+ if _, err := w.WriteString(n.Data); err != nil {
+ return err
+ }
+ return w.WriteByte('>')
+}
+
+// writeQuoted writes s to w surrounded by quotes. Normally it will use double
+// quotes, but if s contains a double quote, it will use single quotes.
+// It is used for writing the identifiers in a doctype declaration.
+// In valid HTML, they can't contain both types of quotes.
+func writeQuoted(w writer, s string) error {
+ var q byte = '"'
+ if strings.Contains(s, `"`) {
+ q = '\''
+ }
+ if err := w.WriteByte(q); err != nil {
+ return err
+ }
+ if _, err := w.WriteString(s); err != nil {
+ return err
+ }
+ if err := w.WriteByte(q); err != nil {
+ return err
+ }
+ return nil
+}
+
+// Section 12.1.2, "Elements", gives this list of void elements. Void elements
+// are those that can't have any contents.
+var voidElements = map[string]bool{
+ "area": true,
+ "base": true,
+ "br": true,
+ "col": true,
+ "command": true,
+ "embed": true,
+ "hr": true,
+ "img": true,
+ "input": true,
+ "keygen": true,
+ "link": true,
+ "meta": true,
+ "param": true,
+ "source": true,
+ "track": true,
+ "wbr": true,
+}
diff --git a/vendor/golang.org/x/net/html/token.go b/vendor/golang.org/x/net/html/token.go
new file mode 100644
index 0000000..e3c01d7
--- /dev/null
+++ b/vendor/golang.org/x/net/html/token.go
@@ -0,0 +1,1219 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "bytes"
+ "errors"
+ "io"
+ "strconv"
+ "strings"
+
+ "golang.org/x/net/html/atom"
+)
+
+// A TokenType is the type of a Token.
+type TokenType uint32
+
+const (
+ // ErrorToken means that an error occurred during tokenization.
+ ErrorToken TokenType = iota
+ // TextToken means a text node.
+ TextToken
+ // A StartTagToken looks like <a>.
+ StartTagToken
+ // An EndTagToken looks like </a>.
+ EndTagToken
+ // A SelfClosingTagToken tag looks like <br/>.
+ SelfClosingTagToken
+ // A CommentToken looks like <!--x-->.
+ CommentToken
+ // A DoctypeToken looks like <!DOCTYPE x>
+ DoctypeToken
+)
+
+// ErrBufferExceeded means that the buffering limit was exceeded.
+var ErrBufferExceeded = errors.New("max buffer exceeded")
+
+// String returns a string representation of the TokenType.
+func (t TokenType) String() string {
+ switch t {
+ case ErrorToken:
+ return "Error"
+ case TextToken:
+ return "Text"
+ case StartTagToken:
+ return "StartTag"
+ case EndTagToken:
+ return "EndTag"
+ case SelfClosingTagToken:
+ return "SelfClosingTag"
+ case CommentToken:
+ return "Comment"
+ case DoctypeToken:
+ return "Doctype"
+ }
+ return "Invalid(" + strconv.Itoa(int(t)) + ")"
+}
+
+// An Attribute is an attribute namespace-key-value triple. Namespace is
+// non-empty for foreign attributes like xlink, Key is alphabetic (and hence
+// does not contain escapable characters like '&', '<' or '>'), and Val is
+// unescaped (it looks like "a<b" rather than "a&lt;b").
+//
+// Namespace is only used by the parser, not the tokenizer.
+type Attribute struct {
+ Namespace, Key, Val string
+}
+
+// A Token consists of a TokenType and some Data (tag name for start and end
+// tags, content for text, comments and doctypes). A tag Token may also contain
+// a slice of Attributes. Data is unescaped for all Tokens (it looks like "a<b"
+// rather than "a&lt;b"). For tag Tokens, DataAtom is the atom for Data, or
+// zero if Data is not a known tag name.
+type Token struct {
+ Type TokenType
+ DataAtom atom.Atom
+ Data string
+ Attr []Attribute
+}
+
+// tagString returns a string representation of a tag Token's Data and Attr.
+func (t Token) tagString() string {
+ if len(t.Attr) == 0 {
+ return t.Data
+ }
+ buf := bytes.NewBufferString(t.Data)
+ for _, a := range t.Attr {
+ buf.WriteByte(' ')
+ buf.WriteString(a.Key)
+ buf.WriteString(`="`)
+ escape(buf, a.Val)
+ buf.WriteByte('"')
+ }
+ return buf.String()
+}
+
+// String returns a string representation of the Token.
+func (t Token) String() string {
+ switch t.Type {
+ case ErrorToken:
+ return ""
+ case TextToken:
+ return EscapeString(t.Data)
+ case StartTagToken:
+ return "<" + t.tagString() + ">"
+ case EndTagToken:
+ return "</" + t.tagString() + ">"
+ case SelfClosingTagToken:
+ return "<" + t.tagString() + "/>"
+ case CommentToken:
+ return "<!--" + t.Data + "-->"
+ case DoctypeToken:
+ return "<!DOCTYPE " + t.Data + ">"
+ }
+ return "Invalid(" + strconv.Itoa(int(t.Type)) + ")"
+}
+
+// span is a range of bytes in a Tokenizer's buffer. The start is inclusive,
+// the end is exclusive.
+type span struct {
+ start, end int
+}
+
+// A Tokenizer returns a stream of HTML Tokens.
+type Tokenizer struct {
+ // r is the source of the HTML text.
+ r io.Reader
+ // tt is the TokenType of the current token.
+ tt TokenType
+ // err is the first error encountered during tokenization. It is possible
+ // for tt != Error && err != nil to hold: this means that Next returned a
+ // valid token but the subsequent Next call will return an error token.
+ // For example, if the HTML text input was just "plain", then the first
+ // Next call would set z.err to io.EOF but return a TextToken, and all
+ // subsequent Next calls would return an ErrorToken.
+ // err is never reset. Once it becomes non-nil, it stays non-nil.
+ err error
+ // readErr is the error returned by the io.Reader r. It is separate from
+ // err because it is valid for an io.Reader to return (n int, err1 error)
+ // such that n > 0 && err1 != nil, and callers should always process the
+ // n > 0 bytes before considering the error err1.
+ readErr error
+ // buf[raw.start:raw.end] holds the raw bytes of the current token.
+ // buf[raw.end:] is buffered input that will yield future tokens.
+ raw span
+ buf []byte
+ // maxBuf limits the data buffered in buf. A value of 0 means unlimited.
+ maxBuf int
+ // buf[data.start:data.end] holds the raw bytes of the current token's data:
+ // a text token's text, a tag token's tag name, etc.
+ data span
+ // pendingAttr is the attribute key and value currently being tokenized.
+ // When complete, pendingAttr is pushed onto attr. nAttrReturned is
+ // incremented on each call to TagAttr.
+ pendingAttr [2]span
+ attr [][2]span
+ nAttrReturned int
+ // rawTag is the "script" in "</script>" that closes the next token. If
+ // non-empty, the subsequent call to Next will return a raw or RCDATA text
+ // token: one that treats "<p>" as text instead of an element.
+ // rawTag's contents are lower-cased.
+ rawTag string
+ // textIsRaw is whether the current text token's data is not escaped.
+ textIsRaw bool
+ // convertNUL is whether NUL bytes in the current token's data should
+ // be converted into \ufffd replacement characters.
+ convertNUL bool
+ // allowCDATA is whether CDATA sections are allowed in the current context.
+ allowCDATA bool
+}
+
+// AllowCDATA sets whether or not the tokenizer recognizes <![CDATA[foo]]> as
+// the text "foo". The default value is false, which means to recognize it as
+// a bogus comment "<!-- [CDATA[foo]] -->" instead.
+//
+// Strictly speaking, an HTML5 compliant tokenizer should allow CDATA if and
+// only if tokenizing foreign content, such as MathML and SVG. However,
+// tracking foreign-contentness is difficult to do purely in the tokenizer,
+// as opposed to the parser, due to HTML integration points: an <svg> element
+// can contain a <foreignObject> that is foreign-to-SVG but not foreign-to-
+// HTML. For strict compliance with the HTML5 tokenization algorithm, it is the
+// responsibility of the user of a tokenizer to call AllowCDATA as appropriate.
+// In practice, if using the tokenizer without caring whether MathML or SVG
+// CDATA is text or comments, such as tokenizing HTML to find all the anchor
+// text, it is acceptable to ignore this responsibility.
+func (z *Tokenizer) AllowCDATA(allowCDATA bool) {
+ z.allowCDATA = allowCDATA
+}
+
+// NextIsNotRawText instructs the tokenizer that the next token should not be
+// considered as 'raw text'. Some elements, such as script and title elements,
+// normally require the next token after the opening tag to be 'raw text' that
+// has no child elements. For example, tokenizing "<title>a<b>c</b>d</title>"
+// yields a start tag token for "<title>", a text token for "a<b>c</b>d", and
+// an end tag token for "</title>". There are no distinct start tag or end tag
+// tokens for the "<b>" and "</b>".
+//
+// This tokenizer implementation will generally look for raw text at the right
+// times. Strictly speaking, an HTML5 compliant tokenizer should not look for
+// raw text if in foreign content: <title> generally needs raw text, but a
+// <title> inside an <svg> does not. Another example is that a <textarea>
+// generally needs raw text, but a <textarea> is not allowed as an immediate
+// child of a <select>; in normal parsing, a <textarea> implies </select>, but
+// one cannot close the implicit element when parsing a <select>'s InnerHTML.
+// Similarly to AllowCDATA, tracking the correct moment to override raw-text-
+// ness is difficult to do purely in the tokenizer, as opposed to the parser.
+// For strict compliance with the HTML5 tokenization algorithm, it is the
+// responsibility of the user of a tokenizer to call NextIsNotRawText as
+// appropriate. In practice, like AllowCDATA, it is acceptable to ignore this
+// responsibility for basic usage.
+//
+// Note that this 'raw text' concept is different from the one offered by the
+// Tokenizer.Raw method.
+func (z *Tokenizer) NextIsNotRawText() {
+ z.rawTag = ""
+}
+
+// Err returns the error associated with the most recent ErrorToken token.
+// This is typically io.EOF, meaning the end of tokenization.
+func (z *Tokenizer) Err() error {
+ if z.tt != ErrorToken {
+ return nil
+ }
+ return z.err
+}
+
+// readByte returns the next byte from the input stream, doing a buffered read
+// from z.r into z.buf if necessary. z.buf[z.raw.start:z.raw.end] remains a contiguous byte
+// slice that holds all the bytes read so far for the current token.
+// It sets z.err if the underlying reader returns an error.
+// Pre-condition: z.err == nil.
+func (z *Tokenizer) readByte() byte {
+ if z.raw.end >= len(z.buf) {
+ // Our buffer is exhausted and we have to read from z.r. Check if the
+ // previous read resulted in an error.
+ if z.readErr != nil {
+ z.err = z.readErr
+ return 0
+ }
+ // We copy z.buf[z.raw.start:z.raw.end] to the beginning of z.buf. If the length
+ // z.raw.end - z.raw.start is more than half the capacity of z.buf, then we
+ // allocate a new buffer before the copy.
+ c := cap(z.buf)
+ d := z.raw.end - z.raw.start
+ var buf1 []byte
+ if 2*d > c {
+ buf1 = make([]byte, d, 2*c)
+ } else {
+ buf1 = z.buf[:d]
+ }
+ copy(buf1, z.buf[z.raw.start:z.raw.end])
+ if x := z.raw.start; x != 0 {
+ // Adjust the data/attr spans to refer to the same contents after the copy.
+ z.data.start -= x
+ z.data.end -= x
+ z.pendingAttr[0].start -= x
+ z.pendingAttr[0].end -= x
+ z.pendingAttr[1].start -= x
+ z.pendingAttr[1].end -= x
+ for i := range z.attr {
+ z.attr[i][0].start -= x
+ z.attr[i][0].end -= x
+ z.attr[i][1].start -= x
+ z.attr[i][1].end -= x
+ }
+ }
+ z.raw.start, z.raw.end, z.buf = 0, d, buf1[:d]
+ // Now that we have copied the live bytes to the start of the buffer,
+ // we read from z.r into the remainder.
+ var n int
+ n, z.readErr = readAtLeastOneByte(z.r, buf1[d:cap(buf1)])
+ if n == 0 {
+ z.err = z.readErr
+ return 0
+ }
+ z.buf = buf1[:d+n]
+ }
+ x := z.buf[z.raw.end]
+ z.raw.end++
+ if z.maxBuf > 0 && z.raw.end-z.raw.start >= z.maxBuf {
+ z.err = ErrBufferExceeded
+ return 0
+ }
+ return x
+}
+
+// Buffered returns a slice containing data buffered but not yet tokenized.
+func (z *Tokenizer) Buffered() []byte {
+ return z.buf[z.raw.end:]
+}
+
+// readAtLeastOneByte wraps an io.Reader so that reading cannot return (0, nil).
+// It returns io.ErrNoProgress if the underlying r.Read method returns (0, nil)
+// too many times in succession.
+func readAtLeastOneByte(r io.Reader, b []byte) (int, error) {
+ for i := 0; i < 100; i++ {
+ n, err := r.Read(b)
+ if n != 0 || err != nil {
+ return n, err
+ }
+ }
+ return 0, io.ErrNoProgress
+}
+
+// skipWhiteSpace skips past any white space.
+func (z *Tokenizer) skipWhiteSpace() {
+ if z.err != nil {
+ return
+ }
+ for {
+ c := z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case ' ', '\n', '\r', '\t', '\f':
+ // No-op.
+ default:
+ z.raw.end--
+ return
+ }
+ }
+}
+
+// readRawOrRCDATA reads until the next "</foo>", where "foo" is z.rawTag and
+// is typically something like "script" or "textarea".
+func (z *Tokenizer) readRawOrRCDATA() {
+ if z.rawTag == "script" {
+ z.readScript()
+ z.textIsRaw = true
+ z.rawTag = ""
+ return
+ }
+loop:
+ for {
+ c := z.readByte()
+ if z.err != nil {
+ break loop
+ }
+ if c != '<' {
+ continue loop
+ }
+ c = z.readByte()
+ if z.err != nil {
+ break loop
+ }
+ if c != '/' {
+ continue loop
+ }
+ if z.readRawEndTag() || z.err != nil {
+ break loop
+ }
+ }
+ z.data.end = z.raw.end
+ // A textarea's or title's RCDATA can contain escaped entities.
+ z.textIsRaw = z.rawTag != "textarea" && z.rawTag != "title"
+ z.rawTag = ""
+}
+
+// readRawEndTag attempts to read a tag like "</foo>", where "foo" is z.rawTag.
+// If it succeeds, it backs up the input position to reconsume the tag and
+// returns true. Otherwise it returns false. The opening "</" has already been
+// consumed.
+func (z *Tokenizer) readRawEndTag() bool {
+ for i := 0; i < len(z.rawTag); i++ {
+ c := z.readByte()
+ if z.err != nil {
+ return false
+ }
+ if c != z.rawTag[i] && c != z.rawTag[i]-('a'-'A') {
+ z.raw.end--
+ return false
+ }
+ }
+ c := z.readByte()
+ if z.err != nil {
+ return false
+ }
+ switch c {
+ case ' ', '\n', '\r', '\t', '\f', '/', '>':
+ // The 3 is 2 for the leading "</" plus 1 for the trailing character c.
+ z.raw.end -= 3 + len(z.rawTag)
+ return true
+ }
+ z.raw.end--
+ return false
+}
+
+// readScript reads until the next </script> tag, following the byzantine
+// rules for escaping/hiding the closing tag.
+func (z *Tokenizer) readScript() {
+ defer func() {
+ z.data.end = z.raw.end
+ }()
+ var c byte
+
+scriptData:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ if c == '<' {
+ goto scriptDataLessThanSign
+ }
+ goto scriptData
+
+scriptDataLessThanSign:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case '/':
+ goto scriptDataEndTagOpen
+ case '!':
+ goto scriptDataEscapeStart
+ }
+ z.raw.end--
+ goto scriptData
+
+scriptDataEndTagOpen:
+ if z.readRawEndTag() || z.err != nil {
+ return
+ }
+ goto scriptData
+
+scriptDataEscapeStart:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ if c == '-' {
+ goto scriptDataEscapeStartDash
+ }
+ z.raw.end--
+ goto scriptData
+
+scriptDataEscapeStartDash:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ if c == '-' {
+ goto scriptDataEscapedDashDash
+ }
+ z.raw.end--
+ goto scriptData
+
+scriptDataEscaped:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case '-':
+ goto scriptDataEscapedDash
+ case '<':
+ goto scriptDataEscapedLessThanSign
+ }
+ goto scriptDataEscaped
+
+scriptDataEscapedDash:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case '-':
+ goto scriptDataEscapedDashDash
+ case '<':
+ goto scriptDataEscapedLessThanSign
+ }
+ goto scriptDataEscaped
+
+scriptDataEscapedDashDash:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case '-':
+ goto scriptDataEscapedDashDash
+ case '<':
+ goto scriptDataEscapedLessThanSign
+ case '>':
+ goto scriptData
+ }
+ goto scriptDataEscaped
+
+scriptDataEscapedLessThanSign:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ if c == '/' {
+ goto scriptDataEscapedEndTagOpen
+ }
+ if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' {
+ goto scriptDataDoubleEscapeStart
+ }
+ z.raw.end--
+ goto scriptData
+
+scriptDataEscapedEndTagOpen:
+ if z.readRawEndTag() || z.err != nil {
+ return
+ }
+ goto scriptDataEscaped
+
+scriptDataDoubleEscapeStart:
+ z.raw.end--
+ for i := 0; i < len("script"); i++ {
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ if c != "script"[i] && c != "SCRIPT"[i] {
+ z.raw.end--
+ goto scriptDataEscaped
+ }
+ }
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case ' ', '\n', '\r', '\t', '\f', '/', '>':
+ goto scriptDataDoubleEscaped
+ }
+ z.raw.end--
+ goto scriptDataEscaped
+
+scriptDataDoubleEscaped:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case '-':
+ goto scriptDataDoubleEscapedDash
+ case '<':
+ goto scriptDataDoubleEscapedLessThanSign
+ }
+ goto scriptDataDoubleEscaped
+
+scriptDataDoubleEscapedDash:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case '-':
+ goto scriptDataDoubleEscapedDashDash
+ case '<':
+ goto scriptDataDoubleEscapedLessThanSign
+ }
+ goto scriptDataDoubleEscaped
+
+scriptDataDoubleEscapedDashDash:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch c {
+ case '-':
+ goto scriptDataDoubleEscapedDashDash
+ case '<':
+ goto scriptDataDoubleEscapedLessThanSign
+ case '>':
+ goto scriptData
+ }
+ goto scriptDataDoubleEscaped
+
+scriptDataDoubleEscapedLessThanSign:
+ c = z.readByte()
+ if z.err != nil {
+ return
+ }
+ if c == '/' {
+ goto scriptDataDoubleEscapeEnd
+ }
+ z.raw.end--
+ goto scriptDataDoubleEscaped
+
+scriptDataDoubleEscapeEnd:
+ if z.readRawEndTag() {
+ z.raw.end += len("</script>")
+ goto scriptDataEscaped
+ }
+ if z.err != nil {
+ return
+ }
+ goto scriptDataDoubleEscaped
+}
+
+// readComment reads the next comment token starting with "<!--". The opening
+// "<!--" has already been consumed.
+func (z *Tokenizer) readComment() {
+ z.data.start = z.raw.end
+ defer func() {
+ if z.data.end < z.data.start {
+ // It's a comment with no data, like <!-->.
+ z.data.end = z.data.start
+ }
+ }()
+ for dashCount := 2; ; {
+ c := z.readByte()
+ if z.err != nil {
+ // Ignore up to two dashes at EOF.
+ if dashCount > 2 {
+ dashCount = 2
+ }
+ z.data.end = z.raw.end - dashCount
+ return
+ }
+ switch c {
+ case '-':
+ dashCount++
+ continue
+ case '>':
+ if dashCount >= 2 {
+ z.data.end = z.raw.end - len("-->")
+ return
+ }
+ case '!':
+ if dashCount >= 2 {
+ c = z.readByte()
+ if z.err != nil {
+ z.data.end = z.raw.end
+ return
+ }
+ if c == '>' {
+ z.data.end = z.raw.end - len("--!>")
+ return
+ }
+ }
+ }
+ dashCount = 0
+ }
+}
+
+// readUntilCloseAngle reads until the next ">".
+func (z *Tokenizer) readUntilCloseAngle() {
+ z.data.start = z.raw.end
+ for {
+ c := z.readByte()
+ if z.err != nil {
+ z.data.end = z.raw.end
+ return
+ }
+ if c == '>' {
+ z.data.end = z.raw.end - len(">")
+ return
+ }
+ }
+}
+
+// readMarkupDeclaration reads the next token starting with "<!". It might be
+// a "<!--comment-->", a "<!DOCTYPE foo>", a "<![CDATA[section]]>" or
+// "<!a bogus comment". The opening "<!" has already been consumed.
+func (z *Tokenizer) readMarkupDeclaration() TokenType {
+ z.data.start = z.raw.end
+ var c [2]byte
+ for i := 0; i < 2; i++ {
+ c[i] = z.readByte()
+ if z.err != nil {
+ z.data.end = z.raw.end
+ return CommentToken
+ }
+ }
+ if c[0] == '-' && c[1] == '-' {
+ z.readComment()
+ return CommentToken
+ }
+ z.raw.end -= 2
+ if z.readDoctype() {
+ return DoctypeToken
+ }
+ if z.allowCDATA && z.readCDATA() {
+ z.convertNUL = true
+ return TextToken
+ }
+ // It's a bogus comment.
+ z.readUntilCloseAngle()
+ return CommentToken
+}
+
+// readDoctype attempts to read a doctype declaration and returns true if
+// successful. The opening "<!" has already been consumed.
+func (z *Tokenizer) readDoctype() bool {
+ const s = "DOCTYPE"
+ for i := 0; i < len(s); i++ {
+ c := z.readByte()
+ if z.err != nil {
+ z.data.end = z.raw.end
+ return false
+ }
+ if c != s[i] && c != s[i]+('a'-'A') {
+ // Back up to read the fragment of "DOCTYPE" again.
+ z.raw.end = z.data.start
+ return false
+ }
+ }
+ if z.skipWhiteSpace(); z.err != nil {
+ z.data.start = z.raw.end
+ z.data.end = z.raw.end
+ return true
+ }
+ z.readUntilCloseAngle()
+ return true
+}
+
+// readCDATA attempts to read a CDATA section and returns true if
+// successful. The opening "<!" has already been consumed.
+func (z *Tokenizer) readCDATA() bool {
+ const s = "[CDATA["
+ for i := 0; i < len(s); i++ {
+ c := z.readByte()
+ if z.err != nil {
+ z.data.end = z.raw.end
+ return false
+ }
+ if c != s[i] {
+ // Back up to read the fragment of "[CDATA[" again.
+ z.raw.end = z.data.start
+ return false
+ }
+ }
+ z.data.start = z.raw.end
+ brackets := 0
+ for {
+ c := z.readByte()
+ if z.err != nil {
+ z.data.end = z.raw.end
+ return true
+ }
+ switch c {
+ case ']':
+ brackets++
+ case '>':
+ if brackets >= 2 {
+ z.data.end = z.raw.end - len("]]>")
+ return true
+ }
+ brackets = 0
+ default:
+ brackets = 0
+ }
+ }
+}
+
+// startTagIn returns whether the start tag in z.buf[z.data.start:z.data.end]
+// case-insensitively matches any element of ss.
+func (z *Tokenizer) startTagIn(ss ...string) bool {
+loop:
+ for _, s := range ss {
+ if z.data.end-z.data.start != len(s) {
+ continue loop
+ }
+ for i := 0; i < len(s); i++ {
+ c := z.buf[z.data.start+i]
+ if 'A' <= c && c <= 'Z' {
+ c += 'a' - 'A'
+ }
+ if c != s[i] {
+ continue loop
+ }
+ }
+ return true
+ }
+ return false
+}
+
+// readStartTag reads the next start tag token. The opening "<a" has already
+// been consumed, where 'a' means anything in [A-Za-z].
+func (z *Tokenizer) readStartTag() TokenType {
+ z.readTag(true)
+ if z.err != nil {
+ return ErrorToken
+ }
+ // Several tags flag the tokenizer's next token as raw.
+ c, raw := z.buf[z.data.start], false
+ if 'A' <= c && c <= 'Z' {
+ c += 'a' - 'A'
+ }
+ switch c {
+ case 'i':
+ raw = z.startTagIn("iframe")
+ case 'n':
+ raw = z.startTagIn("noembed", "noframes", "noscript")
+ case 'p':
+ raw = z.startTagIn("plaintext")
+ case 's':
+ raw = z.startTagIn("script", "style")
+ case 't':
+ raw = z.startTagIn("textarea", "title")
+ case 'x':
+ raw = z.startTagIn("xmp")
+ }
+ if raw {
+ z.rawTag = strings.ToLower(string(z.buf[z.data.start:z.data.end]))
+ }
+ // Look for a self-closing token like "<br/>".
+ if z.err == nil && z.buf[z.raw.end-2] == '/' {
+ return SelfClosingTagToken
+ }
+ return StartTagToken
+}
+
+// readTag reads the next tag token and its attributes. If saveAttr, those
+// attributes are saved in z.attr, otherwise z.attr is set to an empty slice.
+// The opening "<a" or "</a" has already been consumed, where 'a' means anything
+// in [A-Za-z].
+func (z *Tokenizer) readTag(saveAttr bool) {
+ z.attr = z.attr[:0]
+ z.nAttrReturned = 0
+ // Read the tag name and attribute key/value pairs.
+ z.readTagName()
+ if z.skipWhiteSpace(); z.err != nil {
+ return
+ }
+ for {
+ c := z.readByte()
+ if z.err != nil || c == '>' {
+ break
+ }
+ z.raw.end--
+ z.readTagAttrKey()
+ z.readTagAttrVal()
+ // Save pendingAttr if saveAttr and that attribute has a non-empty key.
+ if saveAttr && z.pendingAttr[0].start != z.pendingAttr[0].end {
+ z.attr = append(z.attr, z.pendingAttr)
+ }
+ if z.skipWhiteSpace(); z.err != nil {
+ break
+ }
+ }
+}
+
+// readTagName sets z.data to the "div" in "<div k=v>". The reader (z.raw.end)
+// is positioned such that the first byte of the tag name (the "d" in "<div")
+// has already been consumed.
+func (z *Tokenizer) readTagName() {
+ z.data.start = z.raw.end - 1
+ for {
+ c := z.readByte()
+ if z.err != nil {
+ z.data.end = z.raw.end
+ return
+ }
+ switch c {
+ case ' ', '\n', '\r', '\t', '\f':
+ z.data.end = z.raw.end - 1
+ return
+ case '/', '>':
+ z.raw.end--
+ z.data.end = z.raw.end
+ return
+ }
+ }
+}
+
+// readTagAttrKey sets z.pendingAttr[0] to the "k" in "<div k=v>".
+// Precondition: z.err == nil.
+func (z *Tokenizer) readTagAttrKey() {
+ z.pendingAttr[0].start = z.raw.end
+ for {
+ c := z.readByte()
+ if z.err != nil {
+ z.pendingAttr[0].end = z.raw.end
+ return
+ }
+ switch c {
+ case ' ', '\n', '\r', '\t', '\f', '/':
+ z.pendingAttr[0].end = z.raw.end - 1
+ return
+ case '=', '>':
+ z.raw.end--
+ z.pendingAttr[0].end = z.raw.end
+ return
+ }
+ }
+}
+
+// readTagAttrVal sets z.pendingAttr[1] to the "v" in "<div k=v>".
+func (z *Tokenizer) readTagAttrVal() {
+ z.pendingAttr[1].start = z.raw.end
+ z.pendingAttr[1].end = z.raw.end
+ if z.skipWhiteSpace(); z.err != nil {
+ return
+ }
+ c := z.readByte()
+ if z.err != nil {
+ return
+ }
+ if c != '=' {
+ z.raw.end--
+ return
+ }
+ if z.skipWhiteSpace(); z.err != nil {
+ return
+ }
+ quote := z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch quote {
+ case '>':
+ z.raw.end--
+ return
+
+ case '\'', '"':
+ z.pendingAttr[1].start = z.raw.end
+ for {
+ c := z.readByte()
+ if z.err != nil {
+ z.pendingAttr[1].end = z.raw.end
+ return
+ }
+ if c == quote {
+ z.pendingAttr[1].end = z.raw.end - 1
+ return
+ }
+ }
+
+ default:
+ z.pendingAttr[1].start = z.raw.end - 1
+ for {
+ c := z.readByte()
+ if z.err != nil {
+ z.pendingAttr[1].end = z.raw.end
+ return
+ }
+ switch c {
+ case ' ', '\n', '\r', '\t', '\f':
+ z.pendingAttr[1].end = z.raw.end - 1
+ return
+ case '>':
+ z.raw.end--
+ z.pendingAttr[1].end = z.raw.end
+ return
+ }
+ }
+ }
+}
+
+// Next scans the next token and returns its type.
+func (z *Tokenizer) Next() TokenType {
+ z.raw.start = z.raw.end
+ z.data.start = z.raw.end
+ z.data.end = z.raw.end
+ if z.err != nil {
+ z.tt = ErrorToken
+ return z.tt
+ }
+ if z.rawTag != "" {
+ if z.rawTag == "plaintext" {
+ // Read everything up to EOF.
+ for z.err == nil {
+ z.readByte()
+ }
+ z.data.end = z.raw.end
+ z.textIsRaw = true
+ } else {
+ z.readRawOrRCDATA()
+ }
+ if z.data.end > z.data.start {
+ z.tt = TextToken
+ z.convertNUL = true
+ return z.tt
+ }
+ }
+ z.textIsRaw = false
+ z.convertNUL = false
+
+loop:
+ for {
+ c := z.readByte()
+ if z.err != nil {
+ break loop
+ }
+ if c != '<' {
+ continue loop
+ }
+
+ // Check if the '<' we have just read is part of a tag, comment
+ // or doctype. If not, it's part of the accumulated text token.
+ c = z.readByte()
+ if z.err != nil {
+ break loop
+ }
+ var tokenType TokenType
+ switch {
+ case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z':
+ tokenType = StartTagToken
+ case c == '/':
+ tokenType = EndTagToken
+ case c == '!' || c == '?':
+ // We use CommentToken to mean any of "<!--actual comments-->",
+ // "<!DOCTYPE declarations>" and "<?xml processing instructions?>".
+ tokenType = CommentToken
+ default:
+ // Reconsume the current character.
+ z.raw.end--
+ continue
+ }
+
+ // We have a non-text token, but we might have accumulated some text
+ // before that. If so, we return the text first, and return the non-
+ // text token on the subsequent call to Next.
+ if x := z.raw.end - len("<a"); z.raw.start < x {
+ z.raw.end = x
+ z.data.end = x
+ z.tt = TextToken
+ return z.tt
+ }
+ switch tokenType {
+ case StartTagToken:
+ z.tt = z.readStartTag()
+ return z.tt
+ case EndTagToken:
+ c = z.readByte()
+ if z.err != nil {
+ break loop
+ }
+ if c == '>' {
+ // "</>" does not generate a token at all. Generate an empty comment
+ // to allow passthrough clients to pick up the data using Raw.
+ // Reset the tokenizer state and start again.
+ z.tt = CommentToken
+ return z.tt
+ }
+ if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' {
+ z.readTag(false)
+ if z.err != nil {
+ z.tt = ErrorToken
+ } else {
+ z.tt = EndTagToken
+ }
+ return z.tt
+ }
+ z.raw.end--
+ z.readUntilCloseAngle()
+ z.tt = CommentToken
+ return z.tt
+ case CommentToken:
+ if c == '!' {
+ z.tt = z.readMarkupDeclaration()
+ return z.tt
+ }
+ z.raw.end--
+ z.readUntilCloseAngle()
+ z.tt = CommentToken
+ return z.tt
+ }
+ }
+ if z.raw.start < z.raw.end {
+ z.data.end = z.raw.end
+ z.tt = TextToken
+ return z.tt
+ }
+ z.tt = ErrorToken
+ return z.tt
+}
+
+// Raw returns the unmodified text of the current token. Calling Next, Token,
+// Text, TagName or TagAttr may change the contents of the returned slice.
+func (z *Tokenizer) Raw() []byte {
+ return z.buf[z.raw.start:z.raw.end]
+}
+
+// convertNewlines converts "\r" and "\r\n" in s to "\n".
+// The conversion happens in place, but the resulting slice may be shorter.
+func convertNewlines(s []byte) []byte {
+ for i, c := range s {
+ if c != '\r' {
+ continue
+ }
+
+ src := i + 1
+ if src >= len(s) || s[src] != '\n' {
+ s[i] = '\n'
+ continue
+ }
+
+ dst := i
+ for src < len(s) {
+ if s[src] == '\r' {
+ if src+1 < len(s) && s[src+1] == '\n' {
+ src++
+ }
+ s[dst] = '\n'
+ } else {
+ s[dst] = s[src]
+ }
+ src++
+ dst++
+ }
+ return s[:dst]
+ }
+ return s
+}
+
+var (
+ nul = []byte("\x00")
+ replacement = []byte("\ufffd")
+)
+
+// Text returns the unescaped text of a text, comment or doctype token. The
+// contents of the returned slice may change on the next call to Next.
+func (z *Tokenizer) Text() []byte {
+ switch z.tt {
+ case TextToken, CommentToken, DoctypeToken:
+ s := z.buf[z.data.start:z.data.end]
+ z.data.start = z.raw.end
+ z.data.end = z.raw.end
+ s = convertNewlines(s)
+ if (z.convertNUL || z.tt == CommentToken) && bytes.Contains(s, nul) {
+ s = bytes.Replace(s, nul, replacement, -1)
+ }
+ if !z.textIsRaw {
+ s = unescape(s, false)
+ }
+ return s
+ }
+ return nil
+}
+
+// TagName returns the lower-cased name of a tag token (the `img` out of
+// `<IMG SRC="foo">`) and whether the tag has attributes.
+// The contents of the returned slice may change on the next call to Next.
+func (z *Tokenizer) TagName() (name []byte, hasAttr bool) {
+ if z.data.start < z.data.end {
+ switch z.tt {
+ case StartTagToken, EndTagToken, SelfClosingTagToken:
+ s := z.buf[z.data.start:z.data.end]
+ z.data.start = z.raw.end
+ z.data.end = z.raw.end
+ return lower(s), z.nAttrReturned < len(z.attr)
+ }
+ }
+ return nil, false
+}
+
+// TagAttr returns the lower-cased key and unescaped value of the next unparsed
+// attribute for the current tag token and whether there are more attributes.
+// The contents of the returned slices may change on the next call to Next.
+func (z *Tokenizer) TagAttr() (key, val []byte, moreAttr bool) {
+ if z.nAttrReturned < len(z.attr) {
+ switch z.tt {
+ case StartTagToken, SelfClosingTagToken:
+ x := z.attr[z.nAttrReturned]
+ z.nAttrReturned++
+ key = z.buf[x[0].start:x[0].end]
+ val = z.buf[x[1].start:x[1].end]
+ return lower(key), unescape(convertNewlines(val), true), z.nAttrReturned < len(z.attr)
+ }
+ }
+ return nil, nil, false
+}
+
+// Token returns the current Token. The result's Data and Attr values remain
+// valid after subsequent Next calls.
+func (z *Tokenizer) Token() Token {
+ t := Token{Type: z.tt}
+ switch z.tt {
+ case TextToken, CommentToken, DoctypeToken:
+ t.Data = string(z.Text())
+ case StartTagToken, SelfClosingTagToken, EndTagToken:
+ name, moreAttr := z.TagName()
+ for moreAttr {
+ var key, val []byte
+ key, val, moreAttr = z.TagAttr()
+ t.Attr = append(t.Attr, Attribute{"", atom.String(key), string(val)})
+ }
+ if a := atom.Lookup(name); a != 0 {
+ t.DataAtom, t.Data = a, a.String()
+ } else {
+ t.DataAtom, t.Data = 0, string(name)
+ }
+ }
+ return t
+}
+
+// SetMaxBuf sets a limit on the amount of data buffered during tokenization.
+// A value of 0 means unlimited.
+func (z *Tokenizer) SetMaxBuf(n int) {
+ z.maxBuf = n
+}
+
+// NewTokenizer returns a new HTML Tokenizer for the given Reader.
+// The input is assumed to be UTF-8 encoded.
+func NewTokenizer(r io.Reader) *Tokenizer {
+ return NewTokenizerFragment(r, "")
+}
+
+// NewTokenizerFragment returns a new HTML Tokenizer for the given Reader, for
+// tokenizing an existing element's InnerHTML fragment. contextTag is that
+// element's tag, such as "div" or "iframe".
+//
+// For example, how the InnerHTML "a<b" is tokenized depends on whether it is
+// for a <p> tag or a <script> tag.
+//
+// The input is assumed to be UTF-8 encoded.
+func NewTokenizerFragment(r io.Reader, contextTag string) *Tokenizer {
+ z := &Tokenizer{
+ r: r,
+ buf: make([]byte, 0, 4096),
+ }
+ if contextTag != "" {
+ switch s := strings.ToLower(contextTag); s {
+ case "iframe", "noembed", "noframes", "noscript", "plaintext", "script", "style", "title", "textarea", "xmp":
+ z.rawTag = s
+ }
+ }
+ return z
+}
diff --git a/vendor/golang.org/x/text/AUTHORS b/vendor/golang.org/x/text/AUTHORS
new file mode 100644
index 0000000..15167cd
--- /dev/null
+++ b/vendor/golang.org/x/text/AUTHORS
@@ -0,0 +1,3 @@
+# This source code refers to The Go Authors for copyright purposes.
+# The master list of authors is in the main Go distribution,
+# visible at http://tip.golang.org/AUTHORS.
diff --git a/vendor/golang.org/x/text/CONTRIBUTORS b/vendor/golang.org/x/text/CONTRIBUTORS
new file mode 100644
index 0000000..1c4577e
--- /dev/null
+++ b/vendor/golang.org/x/text/CONTRIBUTORS
@@ -0,0 +1,3 @@
+# This source code was written by the Go contributors.
+# The master list of contributors is in the main Go distribution,
+# visible at http://tip.golang.org/CONTRIBUTORS.
diff --git a/vendor/golang.org/x/text/LICENSE b/vendor/golang.org/x/text/LICENSE
new file mode 100644
index 0000000..6a66aea
--- /dev/null
+++ b/vendor/golang.org/x/text/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/golang.org/x/text/PATENTS b/vendor/golang.org/x/text/PATENTS
new file mode 100644
index 0000000..7330990
--- /dev/null
+++ b/vendor/golang.org/x/text/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go. This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation. If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
diff --git a/vendor/golang.org/x/text/encoding/encoding.go b/vendor/golang.org/x/text/encoding/encoding.go
new file mode 100644
index 0000000..221f175
--- /dev/null
+++ b/vendor/golang.org/x/text/encoding/encoding.go
@@ -0,0 +1,335 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package encoding defines an interface for character encodings, such as Shift
+// JIS and Windows 1252, that can convert to and from UTF-8.
+//
+// Encoding implementations are provided in other packages, such as
+// golang.org/x/text/encoding/charmap and
+// golang.org/x/text/encoding/japanese.
+package encoding // import "golang.org/x/text/encoding"
+
+import (
+ "errors"
+ "io"
+ "strconv"
+ "unicode/utf8"
+
+ "golang.org/x/text/encoding/internal/identifier"
+ "golang.org/x/text/transform"
+)
+
+// TODO:
+// - There seems to be some inconsistency in when decoders return errors
+// and when not. Also documentation seems to suggest they shouldn't return
+// errors at all (except for UTF-16).
+// - Encoders seem to rely on or at least benefit from the input being in NFC
+// normal form. Perhaps add an example how users could prepare their output.
+
+// Encoding is a character set encoding that can be transformed to and from
+// UTF-8.
+type Encoding interface {
+ // NewDecoder returns a Decoder.
+ NewDecoder() *Decoder
+
+ // NewEncoder returns an Encoder.
+ NewEncoder() *Encoder
+}
+
+// A Decoder converts bytes to UTF-8. It implements transform.Transformer.
+//
+// Transforming source bytes that are not of that encoding will not result in an
+// error per se. Each byte that cannot be transcoded will be represented in the
+// output by the UTF-8 encoding of '\uFFFD', the replacement rune.
+type Decoder struct {
+ transform.Transformer
+
+ // This forces external creators of Decoders to use names in struct
+ // initializers, allowing for future extendibility without having to break
+ // code.
+ _ struct{}
+}
+
+// Bytes converts the given encoded bytes to UTF-8. It returns the converted
+// bytes or nil, err if any error occurred.
+func (d *Decoder) Bytes(b []byte) ([]byte, error) {
+ b, _, err := transform.Bytes(d, b)
+ if err != nil {
+ return nil, err
+ }
+ return b, nil
+}
+
+// String converts the given encoded string to UTF-8. It returns the converted
+// string or "", err if any error occurred.
+func (d *Decoder) String(s string) (string, error) {
+ s, _, err := transform.String(d, s)
+ if err != nil {
+ return "", err
+ }
+ return s, nil
+}
+
+// Reader wraps another Reader to decode its bytes.
+//
+// The Decoder may not be used for any other operation as long as the returned
+// Reader is in use.
+func (d *Decoder) Reader(r io.Reader) io.Reader {
+ return transform.NewReader(r, d)
+}
+
+// An Encoder converts bytes from UTF-8. It implements transform.Transformer.
+//
+// Each rune that cannot be transcoded will result in an error. In this case,
+// the transform will consume all source byte up to, not including the offending
+// rune. Transforming source bytes that are not valid UTF-8 will be replaced by
+// `\uFFFD`. To return early with an error instead, use transform.Chain to
+// preprocess the data with a UTF8Validator.
+type Encoder struct {
+ transform.Transformer
+
+ // This forces external creators of Encoders to use names in struct
+ // initializers, allowing for future extendibility without having to break
+ // code.
+ _ struct{}
+}
+
+// Bytes converts bytes from UTF-8. It returns the converted bytes or nil, err if
+// any error occurred.
+func (e *Encoder) Bytes(b []byte) ([]byte, error) {
+ b, _, err := transform.Bytes(e, b)
+ if err != nil {
+ return nil, err
+ }
+ return b, nil
+}
+
+// String converts a string from UTF-8. It returns the converted string or
+// "", err if any error occurred.
+func (e *Encoder) String(s string) (string, error) {
+ s, _, err := transform.String(e, s)
+ if err != nil {
+ return "", err
+ }
+ return s, nil
+}
+
+// Writer wraps another Writer to encode its UTF-8 output.
+//
+// The Encoder may not be used for any other operation as long as the returned
+// Writer is in use.
+func (e *Encoder) Writer(w io.Writer) io.Writer {
+ return transform.NewWriter(w, e)
+}
+
+// ASCIISub is the ASCII substitute character, as recommended by
+// http://unicode.org/reports/tr36/#Text_Comparison
+const ASCIISub = '\x1a'
+
+// Nop is the nop encoding. Its transformed bytes are the same as the source
+// bytes; it does not replace invalid UTF-8 sequences.
+var Nop Encoding = nop{}
+
+type nop struct{}
+
+func (nop) NewDecoder() *Decoder {
+ return &Decoder{Transformer: transform.Nop}
+}
+func (nop) NewEncoder() *Encoder {
+ return &Encoder{Transformer: transform.Nop}
+}
+
+// Replacement is the replacement encoding. Decoding from the replacement
+// encoding yields a single '\uFFFD' replacement rune. Encoding from UTF-8 to
+// the replacement encoding yields the same as the source bytes except that
+// invalid UTF-8 is converted to '\uFFFD'.
+//
+// It is defined at http://encoding.spec.whatwg.org/#replacement
+var Replacement Encoding = replacement{}
+
+type replacement struct{}
+
+func (replacement) NewDecoder() *Decoder {
+ return &Decoder{Transformer: replacementDecoder{}}
+}
+
+func (replacement) NewEncoder() *Encoder {
+ return &Encoder{Transformer: replacementEncoder{}}
+}
+
+func (replacement) ID() (mib identifier.MIB, other string) {
+ return identifier.Replacement, ""
+}
+
+type replacementDecoder struct{ transform.NopResetter }
+
+func (replacementDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ if len(dst) < 3 {
+ return 0, 0, transform.ErrShortDst
+ }
+ if atEOF {
+ const fffd = "\ufffd"
+ dst[0] = fffd[0]
+ dst[1] = fffd[1]
+ dst[2] = fffd[2]
+ nDst = 3
+ }
+ return nDst, len(src), nil
+}
+
+type replacementEncoder struct{ transform.NopResetter }
+
+func (replacementEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ r, size := rune(0), 0
+
+ for ; nSrc < len(src); nSrc += size {
+ r = rune(src[nSrc])
+
+ // Decode a 1-byte rune.
+ if r < utf8.RuneSelf {
+ size = 1
+
+ } else {
+ // Decode a multi-byte rune.
+ r, size = utf8.DecodeRune(src[nSrc:])
+ if size == 1 {
+ // All valid runes of size 1 (those below utf8.RuneSelf) were
+ // handled above. We have invalid UTF-8 or we haven't seen the
+ // full character yet.
+ if !atEOF && !utf8.FullRune(src[nSrc:]) {
+ err = transform.ErrShortSrc
+ break
+ }
+ r = '\ufffd'
+ }
+ }
+
+ if nDst+utf8.RuneLen(r) > len(dst) {
+ err = transform.ErrShortDst
+ break
+ }
+ nDst += utf8.EncodeRune(dst[nDst:], r)
+ }
+ return nDst, nSrc, err
+}
+
+// HTMLEscapeUnsupported wraps encoders to replace source runes outside the
+// repertoire of the destination encoding with HTML escape sequences.
+//
+// This wrapper exists to comply to URL and HTML forms requiring a
+// non-terminating legacy encoder. The produced sequences may lead to data
+// loss as they are indistinguishable from legitimate input. To avoid this
+// issue, use UTF-8 encodings whenever possible.
+func HTMLEscapeUnsupported(e *Encoder) *Encoder {
+ return &Encoder{Transformer: &errorHandler{e, errorToHTML}}
+}
+
+// ReplaceUnsupported wraps encoders to replace source runes outside the
+// repertoire of the destination encoding with an encoding-specific
+// replacement.
+//
+// This wrapper is only provided for backwards compatibility and legacy
+// handling. Its use is strongly discouraged. Use UTF-8 whenever possible.
+func ReplaceUnsupported(e *Encoder) *Encoder {
+ return &Encoder{Transformer: &errorHandler{e, errorToReplacement}}
+}
+
+type errorHandler struct {
+ *Encoder
+ handler func(dst []byte, r rune, err repertoireError) (n int, ok bool)
+}
+
+// TODO: consider making this error public in some form.
+type repertoireError interface {
+ Replacement() byte
+}
+
+func (h errorHandler) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ nDst, nSrc, err = h.Transformer.Transform(dst, src, atEOF)
+ for err != nil {
+ rerr, ok := err.(repertoireError)
+ if !ok {
+ return nDst, nSrc, err
+ }
+ r, sz := utf8.DecodeRune(src[nSrc:])
+ n, ok := h.handler(dst[nDst:], r, rerr)
+ if !ok {
+ return nDst, nSrc, transform.ErrShortDst
+ }
+ err = nil
+ nDst += n
+ if nSrc += sz; nSrc < len(src) {
+ var dn, sn int
+ dn, sn, err = h.Transformer.Transform(dst[nDst:], src[nSrc:], atEOF)
+ nDst += dn
+ nSrc += sn
+ }
+ }
+ return nDst, nSrc, err
+}
+
+func errorToHTML(dst []byte, r rune, err repertoireError) (n int, ok bool) {
+ buf := [8]byte{}
+ b := strconv.AppendUint(buf[:0], uint64(r), 10)
+ if n = len(b) + len("&#;"); n >= len(dst) {
+ return 0, false
+ }
+ dst[0] = '&'
+ dst[1] = '#'
+ dst[copy(dst[2:], b)+2] = ';'
+ return n, true
+}
+
+func errorToReplacement(dst []byte, r rune, err repertoireError) (n int, ok bool) {
+ if len(dst) == 0 {
+ return 0, false
+ }
+ dst[0] = err.Replacement()
+ return 1, true
+}
+
+// ErrInvalidUTF8 means that a transformer encountered invalid UTF-8.
+var ErrInvalidUTF8 = errors.New("encoding: invalid UTF-8")
+
+// UTF8Validator is a transformer that returns ErrInvalidUTF8 on the first
+// input byte that is not valid UTF-8.
+var UTF8Validator transform.Transformer = utf8Validator{}
+
+type utf8Validator struct{ transform.NopResetter }
+
+func (utf8Validator) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ n := len(src)
+ if n > len(dst) {
+ n = len(dst)
+ }
+ for i := 0; i < n; {
+ if c := src[i]; c < utf8.RuneSelf {
+ dst[i] = c
+ i++
+ continue
+ }
+ _, size := utf8.DecodeRune(src[i:])
+ if size == 1 {
+ // All valid runes of size 1 (those below utf8.RuneSelf) were
+ // handled above. We have invalid UTF-8 or we haven't seen the
+ // full character yet.
+ err = ErrInvalidUTF8
+ if !atEOF && !utf8.FullRune(src[i:]) {
+ err = transform.ErrShortSrc
+ }
+ return i, i, err
+ }
+ if i+size > len(dst) {
+ return i, i, transform.ErrShortDst
+ }
+ for ; size > 0; size-- {
+ dst[i] = src[i]
+ i++
+ }
+ }
+ if len(src) > len(dst) {
+ err = transform.ErrShortDst
+ }
+ return n, n, err
+}
diff --git a/vendor/golang.org/x/text/encoding/internal/identifier/gen.go b/vendor/golang.org/x/text/encoding/internal/identifier/gen.go
new file mode 100644
index 0000000..0c8eba7
--- /dev/null
+++ b/vendor/golang.org/x/text/encoding/internal/identifier/gen.go
@@ -0,0 +1,137 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+import (
+ "bytes"
+ "encoding/xml"
+ "fmt"
+ "io"
+ "log"
+ "strings"
+
+ "golang.org/x/text/internal/gen"
+)
+
+type registry struct {
+ XMLName xml.Name `xml:"registry"`
+ Updated string `xml:"updated"`
+ Registry []struct {
+ ID string `xml:"id,attr"`
+ Record []struct {
+ Name string `xml:"name"`
+ Xref []struct {
+ Type string `xml:"type,attr"`
+ Data string `xml:"data,attr"`
+ } `xml:"xref"`
+ Desc struct {
+ Data string `xml:",innerxml"`
+ // Any []struct {
+ // Data string `xml:",chardata"`
+ // } `xml:",any"`
+ // Data string `xml:",chardata"`
+ } `xml:"description,"`
+ MIB string `xml:"value"`
+ Alias []string `xml:"alias"`
+ MIME string `xml:"preferred_alias"`
+ } `xml:"record"`
+ } `xml:"registry"`
+}
+
+func main() {
+ r := gen.OpenIANAFile("assignments/character-sets/character-sets.xml")
+ reg := &registry{}
+ if err := xml.NewDecoder(r).Decode(&reg); err != nil && err != io.EOF {
+ log.Fatalf("Error decoding charset registry: %v", err)
+ }
+ if len(reg.Registry) == 0 || reg.Registry[0].ID != "character-sets-1" {
+ log.Fatalf("Unexpected ID %s", reg.Registry[0].ID)
+ }
+
+ w := &bytes.Buffer{}
+ fmt.Fprintf(w, "const (\n")
+ for _, rec := range reg.Registry[0].Record {
+ constName := ""
+ for _, a := range rec.Alias {
+ if strings.HasPrefix(a, "cs") && strings.IndexByte(a, '-') == -1 {
+ // Some of the constant definitions have comments in them. Strip those.
+ constName = strings.Title(strings.SplitN(a[2:], "\n", 2)[0])
+ }
+ }
+ if constName == "" {
+ switch rec.MIB {
+ case "2085":
+ constName = "HZGB2312" // Not listed as alias for some reason.
+ default:
+ log.Fatalf("No cs alias defined for %s.", rec.MIB)
+ }
+ }
+ if rec.MIME != "" {
+ rec.MIME = fmt.Sprintf(" (MIME: %s)", rec.MIME)
+ }
+ fmt.Fprintf(w, "// %s is the MIB identifier with IANA name %s%s.\n//\n", constName, rec.Name, rec.MIME)
+ if len(rec.Desc.Data) > 0 {
+ fmt.Fprint(w, "// ")
+ d := xml.NewDecoder(strings.NewReader(rec.Desc.Data))
+ inElem := true
+ attr := ""
+ for {
+ t, err := d.Token()
+ if err != nil {
+ if err != io.EOF {
+ log.Fatal(err)
+ }
+ break
+ }
+ switch x := t.(type) {
+ case xml.CharData:
+ attr = "" // Don't need attribute info.
+ a := bytes.Split([]byte(x), []byte("\n"))
+ for i, b := range a {
+ if b = bytes.TrimSpace(b); len(b) != 0 {
+ if !inElem && i > 0 {
+ fmt.Fprint(w, "\n// ")
+ }
+ inElem = false
+ fmt.Fprintf(w, "%s ", string(b))
+ }
+ }
+ case xml.StartElement:
+ if x.Name.Local == "xref" {
+ inElem = true
+ use := false
+ for _, a := range x.Attr {
+ if a.Name.Local == "type" {
+ use = use || a.Value != "person"
+ }
+ if a.Name.Local == "data" && use {
+ attr = a.Value + " "
+ }
+ }
+ }
+ case xml.EndElement:
+ inElem = false
+ fmt.Fprint(w, attr)
+ }
+ }
+ fmt.Fprint(w, "\n")
+ }
+ for _, x := range rec.Xref {
+ switch x.Type {
+ case "rfc":
+ fmt.Fprintf(w, "// Reference: %s\n", strings.ToUpper(x.Data))
+ case "uri":
+ fmt.Fprintf(w, "// Reference: %s\n", x.Data)
+ }
+ }
+ fmt.Fprintf(w, "%s MIB = %s\n", constName, rec.MIB)
+ fmt.Fprintln(w)
+ }
+ fmt.Fprintln(w, ")")
+
+ gen.WriteGoFile("mib.go", "identifier", w.Bytes())
+}
diff --git a/vendor/golang.org/x/text/encoding/internal/identifier/identifier.go b/vendor/golang.org/x/text/encoding/internal/identifier/identifier.go
new file mode 100644
index 0000000..7351b4e
--- /dev/null
+++ b/vendor/golang.org/x/text/encoding/internal/identifier/identifier.go
@@ -0,0 +1,81 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:generate go run gen.go
+
+// Package identifier defines the contract between implementations of Encoding
+// and Index by defining identifiers that uniquely identify standardized coded
+// character sets (CCS) and character encoding schemes (CES), which we will
+// together refer to as encodings, for which Encoding implementations provide
+// converters to and from UTF-8. This package is typically only of concern to
+// implementers of Indexes and Encodings.
+//
+// One part of the identifier is the MIB code, which is defined by IANA and
+// uniquely identifies a CCS or CES. Each code is associated with data that
+// references authorities, official documentation as well as aliases and MIME
+// names.
+//
+// Not all CESs are covered by the IANA registry. The "other" string that is
+// returned by ID can be used to identify other character sets or versions of
+// existing ones.
+//
+// It is recommended that each package that provides a set of Encodings provide
+// the All and Common variables to reference all supported encodings and
+// commonly used subset. This allows Index implementations to include all
+// available encodings without explicitly referencing or knowing about them.
+package identifier
+
+// Note: this package is internal, but could be made public if there is a need
+// for writing third-party Indexes and Encodings.
+
+// References:
+// - http://source.icu-project.org/repos/icu/icu/trunk/source/data/mappings/convrtrs.txt
+// - http://www.iana.org/assignments/character-sets/character-sets.xhtml
+// - http://www.iana.org/assignments/ianacharset-mib/ianacharset-mib
+// - http://www.ietf.org/rfc/rfc2978.txt
+// - http://www.unicode.org/reports/tr22/
+// - http://www.w3.org/TR/encoding/
+// - https://encoding.spec.whatwg.org/
+// - https://encoding.spec.whatwg.org/encodings.json
+// - https://tools.ietf.org/html/rfc6657#section-5
+
+// Interface can be implemented by Encodings to define the CCS or CES for which
+// it implements conversions.
+type Interface interface {
+ // ID returns an encoding identifier. Exactly one of the mib and other
+ // values should be non-zero.
+ //
+ // In the usual case it is only necessary to indicate the MIB code. The
+ // other string can be used to specify encodings for which there is no MIB,
+ // such as "x-mac-dingbat".
+ //
+ // The other string may only contain the characters a-z, A-Z, 0-9, - and _.
+ ID() (mib MIB, other string)
+
+ // NOTE: the restrictions on the encoding are to allow extending the syntax
+ // with additional information such as versions, vendors and other variants.
+}
+
+// A MIB identifies an encoding. It is derived from the IANA MIB codes and adds
+// some identifiers for some encodings that are not covered by the IANA
+// standard.
+//
+// See http://www.iana.org/assignments/ianacharset-mib.
+type MIB uint16
+
+// These additional MIB types are not defined in IANA. They are added because
+// they are common and defined within the text repo.
+const (
+ // Unofficial marks the start of encodings not registered by IANA.
+ Unofficial MIB = 10000 + iota
+
+ // Replacement is the WhatWG replacement encoding.
+ Replacement
+
+ // XUserDefined is the code for x-user-defined.
+ XUserDefined
+
+ // MacintoshCyrillic is the code for x-mac-cyrillic.
+ MacintoshCyrillic
+)
diff --git a/vendor/golang.org/x/text/encoding/internal/identifier/mib.go b/vendor/golang.org/x/text/encoding/internal/identifier/mib.go
new file mode 100644
index 0000000..768842b
--- /dev/null
+++ b/vendor/golang.org/x/text/encoding/internal/identifier/mib.go
@@ -0,0 +1,1621 @@
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+package identifier
+
+const (
+ // ASCII is the MIB identifier with IANA name US-ASCII (MIME: US-ASCII).
+ //
+ // ANSI X3.4-1986
+ // Reference: RFC2046
+ ASCII MIB = 3
+
+ // ISOLatin1 is the MIB identifier with IANA name ISO_8859-1:1987 (MIME: ISO-8859-1).
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISOLatin1 MIB = 4
+
+ // ISOLatin2 is the MIB identifier with IANA name ISO_8859-2:1987 (MIME: ISO-8859-2).
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISOLatin2 MIB = 5
+
+ // ISOLatin3 is the MIB identifier with IANA name ISO_8859-3:1988 (MIME: ISO-8859-3).
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISOLatin3 MIB = 6
+
+ // ISOLatin4 is the MIB identifier with IANA name ISO_8859-4:1988 (MIME: ISO-8859-4).
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISOLatin4 MIB = 7
+
+ // ISOLatinCyrillic is the MIB identifier with IANA name ISO_8859-5:1988 (MIME: ISO-8859-5).
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISOLatinCyrillic MIB = 8
+
+ // ISOLatinArabic is the MIB identifier with IANA name ISO_8859-6:1987 (MIME: ISO-8859-6).
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISOLatinArabic MIB = 9
+
+ // ISOLatinGreek is the MIB identifier with IANA name ISO_8859-7:1987 (MIME: ISO-8859-7).
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1947
+ // Reference: RFC1345
+ ISOLatinGreek MIB = 10
+
+ // ISOLatinHebrew is the MIB identifier with IANA name ISO_8859-8:1988 (MIME: ISO-8859-8).
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISOLatinHebrew MIB = 11
+
+ // ISOLatin5 is the MIB identifier with IANA name ISO_8859-9:1989 (MIME: ISO-8859-9).
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISOLatin5 MIB = 12
+
+ // ISOLatin6 is the MIB identifier with IANA name ISO-8859-10 (MIME: ISO-8859-10).
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISOLatin6 MIB = 13
+
+ // ISOTextComm is the MIB identifier with IANA name ISO_6937-2-add.
+ //
+ // ISO-IR: International Register of Escape Sequences and ISO 6937-2:1983
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISOTextComm MIB = 14
+
+ // HalfWidthKatakana is the MIB identifier with IANA name JIS_X0201.
+ //
+ // JIS X 0201-1976. One byte only, this is equivalent to
+ // JIS/Roman (similar to ASCII) plus eight-bit half-width
+ // Katakana
+ // Reference: RFC1345
+ HalfWidthKatakana MIB = 15
+
+ // JISEncoding is the MIB identifier with IANA name JIS_Encoding.
+ //
+ // JIS X 0202-1991. Uses ISO 2022 escape sequences to
+ // shift code sets as documented in JIS X 0202-1991.
+ JISEncoding MIB = 16
+
+ // ShiftJIS is the MIB identifier with IANA name Shift_JIS (MIME: Shift_JIS).
+ //
+ // This charset is an extension of csHalfWidthKatakana by
+ // adding graphic characters in JIS X 0208. The CCS's are
+ // JIS X0201:1997 and JIS X0208:1997. The
+ // complete definition is shown in Appendix 1 of JIS
+ // X0208:1997.
+ // This charset can be used for the top-level media type "text".
+ ShiftJIS MIB = 17
+
+ // EUCPkdFmtJapanese is the MIB identifier with IANA name Extended_UNIX_Code_Packed_Format_for_Japanese (MIME: EUC-JP).
+ //
+ // Standardized by OSF, UNIX International, and UNIX Systems
+ // Laboratories Pacific. Uses ISO 2022 rules to select
+ // code set 0: US-ASCII (a single 7-bit byte set)
+ // code set 1: JIS X0208-1990 (a double 8-bit byte set)
+ // restricted to A0-FF in both bytes
+ // code set 2: Half Width Katakana (a single 7-bit byte set)
+ // requiring SS2 as the character prefix
+ // code set 3: JIS X0212-1990 (a double 7-bit byte set)
+ // restricted to A0-FF in both bytes
+ // requiring SS3 as the character prefix
+ EUCPkdFmtJapanese MIB = 18
+
+ // EUCFixWidJapanese is the MIB identifier with IANA name Extended_UNIX_Code_Fixed_Width_for_Japanese.
+ //
+ // Used in Japan. Each character is 2 octets.
+ // code set 0: US-ASCII (a single 7-bit byte set)
+ // 1st byte = 00
+ // 2nd byte = 20-7E
+ // code set 1: JIS X0208-1990 (a double 7-bit byte set)
+ // restricted to A0-FF in both bytes
+ // code set 2: Half Width Katakana (a single 7-bit byte set)
+ // 1st byte = 00
+ // 2nd byte = A0-FF
+ // code set 3: JIS X0212-1990 (a double 7-bit byte set)
+ // restricted to A0-FF in
+ // the first byte
+ // and 21-7E in the second byte
+ EUCFixWidJapanese MIB = 19
+
+ // ISO4UnitedKingdom is the MIB identifier with IANA name BS_4730.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO4UnitedKingdom MIB = 20
+
+ // ISO11SwedishForNames is the MIB identifier with IANA name SEN_850200_C.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO11SwedishForNames MIB = 21
+
+ // ISO15Italian is the MIB identifier with IANA name IT.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO15Italian MIB = 22
+
+ // ISO17Spanish is the MIB identifier with IANA name ES.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO17Spanish MIB = 23
+
+ // ISO21German is the MIB identifier with IANA name DIN_66003.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO21German MIB = 24
+
+ // ISO60Norwegian1 is the MIB identifier with IANA name NS_4551-1.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO60Norwegian1 MIB = 25
+
+ // ISO69French is the MIB identifier with IANA name NF_Z_62-010.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO69French MIB = 26
+
+ // ISO10646UTF1 is the MIB identifier with IANA name ISO-10646-UTF-1.
+ //
+ // Universal Transfer Format (1), this is the multibyte
+ // encoding, that subsets ASCII-7. It does not have byte
+ // ordering issues.
+ ISO10646UTF1 MIB = 27
+
+ // ISO646basic1983 is the MIB identifier with IANA name ISO_646.basic:1983.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO646basic1983 MIB = 28
+
+ // INVARIANT is the MIB identifier with IANA name INVARIANT.
+ //
+ // Reference: RFC1345
+ INVARIANT MIB = 29
+
+ // ISO2IntlRefVersion is the MIB identifier with IANA name ISO_646.irv:1983.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO2IntlRefVersion MIB = 30
+
+ // NATSSEFI is the MIB identifier with IANA name NATS-SEFI.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ NATSSEFI MIB = 31
+
+ // NATSSEFIADD is the MIB identifier with IANA name NATS-SEFI-ADD.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ NATSSEFIADD MIB = 32
+
+ // NATSDANO is the MIB identifier with IANA name NATS-DANO.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ NATSDANO MIB = 33
+
+ // NATSDANOADD is the MIB identifier with IANA name NATS-DANO-ADD.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ NATSDANOADD MIB = 34
+
+ // ISO10Swedish is the MIB identifier with IANA name SEN_850200_B.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO10Swedish MIB = 35
+
+ // KSC56011987 is the MIB identifier with IANA name KS_C_5601-1987.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ KSC56011987 MIB = 36
+
+ // ISO2022KR is the MIB identifier with IANA name ISO-2022-KR (MIME: ISO-2022-KR).
+ //
+ // rfc1557 (see also KS_C_5601-1987)
+ // Reference: RFC1557
+ ISO2022KR MIB = 37
+
+ // EUCKR is the MIB identifier with IANA name EUC-KR (MIME: EUC-KR).
+ //
+ // rfc1557 (see also KS_C_5861-1992)
+ // Reference: RFC1557
+ EUCKR MIB = 38
+
+ // ISO2022JP is the MIB identifier with IANA name ISO-2022-JP (MIME: ISO-2022-JP).
+ //
+ // rfc1468 (see also rfc2237 )
+ // Reference: RFC1468
+ ISO2022JP MIB = 39
+
+ // ISO2022JP2 is the MIB identifier with IANA name ISO-2022-JP-2 (MIME: ISO-2022-JP-2).
+ //
+ // rfc1554
+ // Reference: RFC1554
+ ISO2022JP2 MIB = 40
+
+ // ISO13JISC6220jp is the MIB identifier with IANA name JIS_C6220-1969-jp.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO13JISC6220jp MIB = 41
+
+ // ISO14JISC6220ro is the MIB identifier with IANA name JIS_C6220-1969-ro.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO14JISC6220ro MIB = 42
+
+ // ISO16Portuguese is the MIB identifier with IANA name PT.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO16Portuguese MIB = 43
+
+ // ISO18Greek7Old is the MIB identifier with IANA name greek7-old.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO18Greek7Old MIB = 44
+
+ // ISO19LatinGreek is the MIB identifier with IANA name latin-greek.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO19LatinGreek MIB = 45
+
+ // ISO25French is the MIB identifier with IANA name NF_Z_62-010_(1973).
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO25French MIB = 46
+
+ // ISO27LatinGreek1 is the MIB identifier with IANA name Latin-greek-1.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO27LatinGreek1 MIB = 47
+
+ // ISO5427Cyrillic is the MIB identifier with IANA name ISO_5427.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO5427Cyrillic MIB = 48
+
+ // ISO42JISC62261978 is the MIB identifier with IANA name JIS_C6226-1978.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO42JISC62261978 MIB = 49
+
+ // ISO47BSViewdata is the MIB identifier with IANA name BS_viewdata.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO47BSViewdata MIB = 50
+
+ // ISO49INIS is the MIB identifier with IANA name INIS.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO49INIS MIB = 51
+
+ // ISO50INIS8 is the MIB identifier with IANA name INIS-8.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO50INIS8 MIB = 52
+
+ // ISO51INISCyrillic is the MIB identifier with IANA name INIS-cyrillic.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO51INISCyrillic MIB = 53
+
+ // ISO54271981 is the MIB identifier with IANA name ISO_5427:1981.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO54271981 MIB = 54
+
+ // ISO5428Greek is the MIB identifier with IANA name ISO_5428:1980.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO5428Greek MIB = 55
+
+ // ISO57GB1988 is the MIB identifier with IANA name GB_1988-80.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO57GB1988 MIB = 56
+
+ // ISO58GB231280 is the MIB identifier with IANA name GB_2312-80.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO58GB231280 MIB = 57
+
+ // ISO61Norwegian2 is the MIB identifier with IANA name NS_4551-2.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO61Norwegian2 MIB = 58
+
+ // ISO70VideotexSupp1 is the MIB identifier with IANA name videotex-suppl.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO70VideotexSupp1 MIB = 59
+
+ // ISO84Portuguese2 is the MIB identifier with IANA name PT2.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO84Portuguese2 MIB = 60
+
+ // ISO85Spanish2 is the MIB identifier with IANA name ES2.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO85Spanish2 MIB = 61
+
+ // ISO86Hungarian is the MIB identifier with IANA name MSZ_7795.3.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO86Hungarian MIB = 62
+
+ // ISO87JISX0208 is the MIB identifier with IANA name JIS_C6226-1983.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO87JISX0208 MIB = 63
+
+ // ISO88Greek7 is the MIB identifier with IANA name greek7.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO88Greek7 MIB = 64
+
+ // ISO89ASMO449 is the MIB identifier with IANA name ASMO_449.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO89ASMO449 MIB = 65
+
+ // ISO90 is the MIB identifier with IANA name iso-ir-90.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO90 MIB = 66
+
+ // ISO91JISC62291984a is the MIB identifier with IANA name JIS_C6229-1984-a.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO91JISC62291984a MIB = 67
+
+ // ISO92JISC62991984b is the MIB identifier with IANA name JIS_C6229-1984-b.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO92JISC62991984b MIB = 68
+
+ // ISO93JIS62291984badd is the MIB identifier with IANA name JIS_C6229-1984-b-add.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO93JIS62291984badd MIB = 69
+
+ // ISO94JIS62291984hand is the MIB identifier with IANA name JIS_C6229-1984-hand.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO94JIS62291984hand MIB = 70
+
+ // ISO95JIS62291984handadd is the MIB identifier with IANA name JIS_C6229-1984-hand-add.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO95JIS62291984handadd MIB = 71
+
+ // ISO96JISC62291984kana is the MIB identifier with IANA name JIS_C6229-1984-kana.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO96JISC62291984kana MIB = 72
+
+ // ISO2033 is the MIB identifier with IANA name ISO_2033-1983.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO2033 MIB = 73
+
+ // ISO99NAPLPS is the MIB identifier with IANA name ANSI_X3.110-1983.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO99NAPLPS MIB = 74
+
+ // ISO102T617bit is the MIB identifier with IANA name T.61-7bit.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO102T617bit MIB = 75
+
+ // ISO103T618bit is the MIB identifier with IANA name T.61-8bit.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO103T618bit MIB = 76
+
+ // ISO111ECMACyrillic is the MIB identifier with IANA name ECMA-cyrillic.
+ //
+ // ISO registry
+ // (formerly ECMA
+ // registry )
+ ISO111ECMACyrillic MIB = 77
+
+ // ISO121Canadian1 is the MIB identifier with IANA name CSA_Z243.4-1985-1.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO121Canadian1 MIB = 78
+
+ // ISO122Canadian2 is the MIB identifier with IANA name CSA_Z243.4-1985-2.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO122Canadian2 MIB = 79
+
+ // ISO123CSAZ24341985gr is the MIB identifier with IANA name CSA_Z243.4-1985-gr.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO123CSAZ24341985gr MIB = 80
+
+ // ISO88596E is the MIB identifier with IANA name ISO_8859-6-E (MIME: ISO-8859-6-E).
+ //
+ // rfc1556
+ // Reference: RFC1556
+ ISO88596E MIB = 81
+
+ // ISO88596I is the MIB identifier with IANA name ISO_8859-6-I (MIME: ISO-8859-6-I).
+ //
+ // rfc1556
+ // Reference: RFC1556
+ ISO88596I MIB = 82
+
+ // ISO128T101G2 is the MIB identifier with IANA name T.101-G2.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO128T101G2 MIB = 83
+
+ // ISO88598E is the MIB identifier with IANA name ISO_8859-8-E (MIME: ISO-8859-8-E).
+ //
+ // rfc1556
+ // Reference: RFC1556
+ ISO88598E MIB = 84
+
+ // ISO88598I is the MIB identifier with IANA name ISO_8859-8-I (MIME: ISO-8859-8-I).
+ //
+ // rfc1556
+ // Reference: RFC1556
+ ISO88598I MIB = 85
+
+ // ISO139CSN369103 is the MIB identifier with IANA name CSN_369103.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO139CSN369103 MIB = 86
+
+ // ISO141JUSIB1002 is the MIB identifier with IANA name JUS_I.B1.002.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO141JUSIB1002 MIB = 87
+
+ // ISO143IECP271 is the MIB identifier with IANA name IEC_P27-1.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO143IECP271 MIB = 88
+
+ // ISO146Serbian is the MIB identifier with IANA name JUS_I.B1.003-serb.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO146Serbian MIB = 89
+
+ // ISO147Macedonian is the MIB identifier with IANA name JUS_I.B1.003-mac.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO147Macedonian MIB = 90
+
+ // ISO150GreekCCITT is the MIB identifier with IANA name greek-ccitt.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO150GreekCCITT MIB = 91
+
+ // ISO151Cuba is the MIB identifier with IANA name NC_NC00-10:81.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO151Cuba MIB = 92
+
+ // ISO6937Add is the MIB identifier with IANA name ISO_6937-2-25.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO6937Add MIB = 93
+
+ // ISO153GOST1976874 is the MIB identifier with IANA name GOST_19768-74.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO153GOST1976874 MIB = 94
+
+ // ISO8859Supp is the MIB identifier with IANA name ISO_8859-supp.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO8859Supp MIB = 95
+
+ // ISO10367Box is the MIB identifier with IANA name ISO_10367-box.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO10367Box MIB = 96
+
+ // ISO158Lap is the MIB identifier with IANA name latin-lap.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO158Lap MIB = 97
+
+ // ISO159JISX02121990 is the MIB identifier with IANA name JIS_X0212-1990.
+ //
+ // ISO-IR: International Register of Escape Sequences
+ // Note: The current registration authority is IPSJ/ITSCJ, Japan.
+ // Reference: RFC1345
+ ISO159JISX02121990 MIB = 98
+
+ // ISO646Danish is the MIB identifier with IANA name DS_2089.
+ //
+ // Danish Standard, DS 2089, February 1974
+ // Reference: RFC1345
+ ISO646Danish MIB = 99
+
+ // USDK is the MIB identifier with IANA name us-dk.
+ //
+ // Reference: RFC1345
+ USDK MIB = 100
+
+ // DKUS is the MIB identifier with IANA name dk-us.
+ //
+ // Reference: RFC1345
+ DKUS MIB = 101
+
+ // KSC5636 is the MIB identifier with IANA name KSC5636.
+ //
+ // Reference: RFC1345
+ KSC5636 MIB = 102
+
+ // Unicode11UTF7 is the MIB identifier with IANA name UNICODE-1-1-UTF-7.
+ //
+ // rfc1642
+ // Reference: RFC1642
+ Unicode11UTF7 MIB = 103
+
+ // ISO2022CN is the MIB identifier with IANA name ISO-2022-CN.
+ //
+ // rfc1922
+ // Reference: RFC1922
+ ISO2022CN MIB = 104
+
+ // ISO2022CNEXT is the MIB identifier with IANA name ISO-2022-CN-EXT.
+ //
+ // rfc1922
+ // Reference: RFC1922
+ ISO2022CNEXT MIB = 105
+
+ // UTF8 is the MIB identifier with IANA name UTF-8.
+ //
+ // rfc3629
+ // Reference: RFC3629
+ UTF8 MIB = 106
+
+ // ISO885913 is the MIB identifier with IANA name ISO-8859-13.
+ //
+ // ISO See http://www.iana.org/assignments/charset-reg/ISO-8859-13 http://www.iana.org/assignments/charset-reg/ISO-8859-13
+ ISO885913 MIB = 109
+
+ // ISO885914 is the MIB identifier with IANA name ISO-8859-14.
+ //
+ // ISO See http://www.iana.org/assignments/charset-reg/ISO-8859-14
+ ISO885914 MIB = 110
+
+ // ISO885915 is the MIB identifier with IANA name ISO-8859-15.
+ //
+ // ISO
+ // Please see: http://www.iana.org/assignments/charset-reg/ISO-8859-15
+ ISO885915 MIB = 111
+
+ // ISO885916 is the MIB identifier with IANA name ISO-8859-16.
+ //
+ // ISO
+ ISO885916 MIB = 112
+
+ // GBK is the MIB identifier with IANA name GBK.
+ //
+ // Chinese IT Standardization Technical Committee
+ // Please see: http://www.iana.org/assignments/charset-reg/GBK
+ GBK MIB = 113
+
+ // GB18030 is the MIB identifier with IANA name GB18030.
+ //
+ // Chinese IT Standardization Technical Committee
+ // Please see: http://www.iana.org/assignments/charset-reg/GB18030
+ GB18030 MIB = 114
+
+ // OSDEBCDICDF0415 is the MIB identifier with IANA name OSD_EBCDIC_DF04_15.
+ //
+ // Fujitsu-Siemens standard mainframe EBCDIC encoding
+ // Please see: http://www.iana.org/assignments/charset-reg/OSD-EBCDIC-DF04-15
+ OSDEBCDICDF0415 MIB = 115
+
+ // OSDEBCDICDF03IRV is the MIB identifier with IANA name OSD_EBCDIC_DF03_IRV.
+ //
+ // Fujitsu-Siemens standard mainframe EBCDIC encoding
+ // Please see: http://www.iana.org/assignments/charset-reg/OSD-EBCDIC-DF03-IRV
+ OSDEBCDICDF03IRV MIB = 116
+
+ // OSDEBCDICDF041 is the MIB identifier with IANA name OSD_EBCDIC_DF04_1.
+ //
+ // Fujitsu-Siemens standard mainframe EBCDIC encoding
+ // Please see: http://www.iana.org/assignments/charset-reg/OSD-EBCDIC-DF04-1
+ OSDEBCDICDF041 MIB = 117
+
+ // ISO115481 is the MIB identifier with IANA name ISO-11548-1.
+ //
+ // See http://www.iana.org/assignments/charset-reg/ISO-11548-1
+ ISO115481 MIB = 118
+
+ // KZ1048 is the MIB identifier with IANA name KZ-1048.
+ //
+ // See http://www.iana.org/assignments/charset-reg/KZ-1048
+ KZ1048 MIB = 119
+
+ // Unicode is the MIB identifier with IANA name ISO-10646-UCS-2.
+ //
+ // the 2-octet Basic Multilingual Plane, aka Unicode
+ // this needs to specify network byte order: the standard
+ // does not specify (it is a 16-bit integer space)
+ Unicode MIB = 1000
+
+ // UCS4 is the MIB identifier with IANA name ISO-10646-UCS-4.
+ //
+ // the full code space. (same comment about byte order,
+ // these are 31-bit numbers.
+ UCS4 MIB = 1001
+
+ // UnicodeASCII is the MIB identifier with IANA name ISO-10646-UCS-Basic.
+ //
+ // ASCII subset of Unicode. Basic Latin = collection 1
+ // See ISO 10646, Appendix A
+ UnicodeASCII MIB = 1002
+
+ // UnicodeLatin1 is the MIB identifier with IANA name ISO-10646-Unicode-Latin1.
+ //
+ // ISO Latin-1 subset of Unicode. Basic Latin and Latin-1
+ // Supplement = collections 1 and 2. See ISO 10646,
+ // Appendix A. See rfc1815 .
+ UnicodeLatin1 MIB = 1003
+
+ // UnicodeJapanese is the MIB identifier with IANA name ISO-10646-J-1.
+ //
+ // ISO 10646 Japanese, see rfc1815 .
+ UnicodeJapanese MIB = 1004
+
+ // UnicodeIBM1261 is the MIB identifier with IANA name ISO-Unicode-IBM-1261.
+ //
+ // IBM Latin-2, -3, -5, Extended Presentation Set, GCSGID: 1261
+ UnicodeIBM1261 MIB = 1005
+
+ // UnicodeIBM1268 is the MIB identifier with IANA name ISO-Unicode-IBM-1268.
+ //
+ // IBM Latin-4 Extended Presentation Set, GCSGID: 1268
+ UnicodeIBM1268 MIB = 1006
+
+ // UnicodeIBM1276 is the MIB identifier with IANA name ISO-Unicode-IBM-1276.
+ //
+ // IBM Cyrillic Greek Extended Presentation Set, GCSGID: 1276
+ UnicodeIBM1276 MIB = 1007
+
+ // UnicodeIBM1264 is the MIB identifier with IANA name ISO-Unicode-IBM-1264.
+ //
+ // IBM Arabic Presentation Set, GCSGID: 1264
+ UnicodeIBM1264 MIB = 1008
+
+ // UnicodeIBM1265 is the MIB identifier with IANA name ISO-Unicode-IBM-1265.
+ //
+ // IBM Hebrew Presentation Set, GCSGID: 1265
+ UnicodeIBM1265 MIB = 1009
+
+ // Unicode11 is the MIB identifier with IANA name UNICODE-1-1.
+ //
+ // rfc1641
+ // Reference: RFC1641
+ Unicode11 MIB = 1010
+
+ // SCSU is the MIB identifier with IANA name SCSU.
+ //
+ // SCSU See http://www.iana.org/assignments/charset-reg/SCSU
+ SCSU MIB = 1011
+
+ // UTF7 is the MIB identifier with IANA name UTF-7.
+ //
+ // rfc2152
+ // Reference: RFC2152
+ UTF7 MIB = 1012
+
+ // UTF16BE is the MIB identifier with IANA name UTF-16BE.
+ //
+ // rfc2781
+ // Reference: RFC2781
+ UTF16BE MIB = 1013
+
+ // UTF16LE is the MIB identifier with IANA name UTF-16LE.
+ //
+ // rfc2781
+ // Reference: RFC2781
+ UTF16LE MIB = 1014
+
+ // UTF16 is the MIB identifier with IANA name UTF-16.
+ //
+ // rfc2781
+ // Reference: RFC2781
+ UTF16 MIB = 1015
+
+ // CESU8 is the MIB identifier with IANA name CESU-8.
+ //
+ // http://www.unicode.org/unicode/reports/tr26
+ CESU8 MIB = 1016
+
+ // UTF32 is the MIB identifier with IANA name UTF-32.
+ //
+ // http://www.unicode.org/unicode/reports/tr19/
+ UTF32 MIB = 1017
+
+ // UTF32BE is the MIB identifier with IANA name UTF-32BE.
+ //
+ // http://www.unicode.org/unicode/reports/tr19/
+ UTF32BE MIB = 1018
+
+ // UTF32LE is the MIB identifier with IANA name UTF-32LE.
+ //
+ // http://www.unicode.org/unicode/reports/tr19/
+ UTF32LE MIB = 1019
+
+ // BOCU1 is the MIB identifier with IANA name BOCU-1.
+ //
+ // http://www.unicode.org/notes/tn6/
+ BOCU1 MIB = 1020
+
+ // Windows30Latin1 is the MIB identifier with IANA name ISO-8859-1-Windows-3.0-Latin-1.
+ //
+ // Extended ISO 8859-1 Latin-1 for Windows 3.0.
+ // PCL Symbol Set id: 9U
+ Windows30Latin1 MIB = 2000
+
+ // Windows31Latin1 is the MIB identifier with IANA name ISO-8859-1-Windows-3.1-Latin-1.
+ //
+ // Extended ISO 8859-1 Latin-1 for Windows 3.1.
+ // PCL Symbol Set id: 19U
+ Windows31Latin1 MIB = 2001
+
+ // Windows31Latin2 is the MIB identifier with IANA name ISO-8859-2-Windows-Latin-2.
+ //
+ // Extended ISO 8859-2. Latin-2 for Windows 3.1.
+ // PCL Symbol Set id: 9E
+ Windows31Latin2 MIB = 2002
+
+ // Windows31Latin5 is the MIB identifier with IANA name ISO-8859-9-Windows-Latin-5.
+ //
+ // Extended ISO 8859-9. Latin-5 for Windows 3.1
+ // PCL Symbol Set id: 5T
+ Windows31Latin5 MIB = 2003
+
+ // HPRoman8 is the MIB identifier with IANA name hp-roman8.
+ //
+ // LaserJet IIP Printer User's Manual,
+ // HP part no 33471-90901, Hewlet-Packard, June 1989.
+ // Reference: RFC1345
+ HPRoman8 MIB = 2004
+
+ // AdobeStandardEncoding is the MIB identifier with IANA name Adobe-Standard-Encoding.
+ //
+ // PostScript Language Reference Manual
+ // PCL Symbol Set id: 10J
+ AdobeStandardEncoding MIB = 2005
+
+ // VenturaUS is the MIB identifier with IANA name Ventura-US.
+ //
+ // Ventura US. ASCII plus characters typically used in
+ // publishing, like pilcrow, copyright, registered, trade mark,
+ // section, dagger, and double dagger in the range A0 (hex)
+ // to FF (hex).
+ // PCL Symbol Set id: 14J
+ VenturaUS MIB = 2006
+
+ // VenturaInternational is the MIB identifier with IANA name Ventura-International.
+ //
+ // Ventura International. ASCII plus coded characters similar
+ // to Roman8.
+ // PCL Symbol Set id: 13J
+ VenturaInternational MIB = 2007
+
+ // DECMCS is the MIB identifier with IANA name DEC-MCS.
+ //
+ // VAX/VMS User's Manual,
+ // Order Number: AI-Y517A-TE, April 1986.
+ // Reference: RFC1345
+ DECMCS MIB = 2008
+
+ // PC850Multilingual is the MIB identifier with IANA name IBM850.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ PC850Multilingual MIB = 2009
+
+ // PC8DanishNorwegian is the MIB identifier with IANA name PC8-Danish-Norwegian.
+ //
+ // PC Danish Norwegian
+ // 8-bit PC set for Danish Norwegian
+ // PCL Symbol Set id: 11U
+ PC8DanishNorwegian MIB = 2012
+
+ // PC862LatinHebrew is the MIB identifier with IANA name IBM862.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ PC862LatinHebrew MIB = 2013
+
+ // PC8Turkish is the MIB identifier with IANA name PC8-Turkish.
+ //
+ // PC Latin Turkish. PCL Symbol Set id: 9T
+ PC8Turkish MIB = 2014
+
+ // IBMSymbols is the MIB identifier with IANA name IBM-Symbols.
+ //
+ // Presentation Set, CPGID: 259
+ IBMSymbols MIB = 2015
+
+ // IBMThai is the MIB identifier with IANA name IBM-Thai.
+ //
+ // Presentation Set, CPGID: 838
+ IBMThai MIB = 2016
+
+ // HPLegal is the MIB identifier with IANA name HP-Legal.
+ //
+ // PCL 5 Comparison Guide, Hewlett-Packard,
+ // HP part number 5961-0510, October 1992
+ // PCL Symbol Set id: 1U
+ HPLegal MIB = 2017
+
+ // HPPiFont is the MIB identifier with IANA name HP-Pi-font.
+ //
+ // PCL 5 Comparison Guide, Hewlett-Packard,
+ // HP part number 5961-0510, October 1992
+ // PCL Symbol Set id: 15U
+ HPPiFont MIB = 2018
+
+ // HPMath8 is the MIB identifier with IANA name HP-Math8.
+ //
+ // PCL 5 Comparison Guide, Hewlett-Packard,
+ // HP part number 5961-0510, October 1992
+ // PCL Symbol Set id: 8M
+ HPMath8 MIB = 2019
+
+ // HPPSMath is the MIB identifier with IANA name Adobe-Symbol-Encoding.
+ //
+ // PostScript Language Reference Manual
+ // PCL Symbol Set id: 5M
+ HPPSMath MIB = 2020
+
+ // HPDesktop is the MIB identifier with IANA name HP-DeskTop.
+ //
+ // PCL 5 Comparison Guide, Hewlett-Packard,
+ // HP part number 5961-0510, October 1992
+ // PCL Symbol Set id: 7J
+ HPDesktop MIB = 2021
+
+ // VenturaMath is the MIB identifier with IANA name Ventura-Math.
+ //
+ // PCL 5 Comparison Guide, Hewlett-Packard,
+ // HP part number 5961-0510, October 1992
+ // PCL Symbol Set id: 6M
+ VenturaMath MIB = 2022
+
+ // MicrosoftPublishing is the MIB identifier with IANA name Microsoft-Publishing.
+ //
+ // PCL 5 Comparison Guide, Hewlett-Packard,
+ // HP part number 5961-0510, October 1992
+ // PCL Symbol Set id: 6J
+ MicrosoftPublishing MIB = 2023
+
+ // Windows31J is the MIB identifier with IANA name Windows-31J.
+ //
+ // Windows Japanese. A further extension of Shift_JIS
+ // to include NEC special characters (Row 13), NEC
+ // selection of IBM extensions (Rows 89 to 92), and IBM
+ // extensions (Rows 115 to 119). The CCS's are
+ // JIS X0201:1997, JIS X0208:1997, and these extensions.
+ // This charset can be used for the top-level media type "text",
+ // but it is of limited or specialized use (see rfc2278 ).
+ // PCL Symbol Set id: 19K
+ Windows31J MIB = 2024
+
+ // GB2312 is the MIB identifier with IANA name GB2312 (MIME: GB2312).
+ //
+ // Chinese for People's Republic of China (PRC) mixed one byte,
+ // two byte set:
+ // 20-7E = one byte ASCII
+ // A1-FE = two byte PRC Kanji
+ // See GB 2312-80
+ // PCL Symbol Set Id: 18C
+ GB2312 MIB = 2025
+
+ // Big5 is the MIB identifier with IANA name Big5 (MIME: Big5).
+ //
+ // Chinese for Taiwan Multi-byte set.
+ // PCL Symbol Set Id: 18T
+ Big5 MIB = 2026
+
+ // Macintosh is the MIB identifier with IANA name macintosh.
+ //
+ // The Unicode Standard ver1.0, ISBN 0-201-56788-1, Oct 1991
+ // Reference: RFC1345
+ Macintosh MIB = 2027
+
+ // IBM037 is the MIB identifier with IANA name IBM037.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM037 MIB = 2028
+
+ // IBM038 is the MIB identifier with IANA name IBM038.
+ //
+ // IBM 3174 Character Set Ref, GA27-3831-02, March 1990
+ // Reference: RFC1345
+ IBM038 MIB = 2029
+
+ // IBM273 is the MIB identifier with IANA name IBM273.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM273 MIB = 2030
+
+ // IBM274 is the MIB identifier with IANA name IBM274.
+ //
+ // IBM 3174 Character Set Ref, GA27-3831-02, March 1990
+ // Reference: RFC1345
+ IBM274 MIB = 2031
+
+ // IBM275 is the MIB identifier with IANA name IBM275.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM275 MIB = 2032
+
+ // IBM277 is the MIB identifier with IANA name IBM277.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM277 MIB = 2033
+
+ // IBM278 is the MIB identifier with IANA name IBM278.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM278 MIB = 2034
+
+ // IBM280 is the MIB identifier with IANA name IBM280.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM280 MIB = 2035
+
+ // IBM281 is the MIB identifier with IANA name IBM281.
+ //
+ // IBM 3174 Character Set Ref, GA27-3831-02, March 1990
+ // Reference: RFC1345
+ IBM281 MIB = 2036
+
+ // IBM284 is the MIB identifier with IANA name IBM284.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM284 MIB = 2037
+
+ // IBM285 is the MIB identifier with IANA name IBM285.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM285 MIB = 2038
+
+ // IBM290 is the MIB identifier with IANA name IBM290.
+ //
+ // IBM 3174 Character Set Ref, GA27-3831-02, March 1990
+ // Reference: RFC1345
+ IBM290 MIB = 2039
+
+ // IBM297 is the MIB identifier with IANA name IBM297.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM297 MIB = 2040
+
+ // IBM420 is the MIB identifier with IANA name IBM420.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990,
+ // IBM NLS RM p 11-11
+ // Reference: RFC1345
+ IBM420 MIB = 2041
+
+ // IBM423 is the MIB identifier with IANA name IBM423.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM423 MIB = 2042
+
+ // IBM424 is the MIB identifier with IANA name IBM424.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM424 MIB = 2043
+
+ // PC8CodePage437 is the MIB identifier with IANA name IBM437.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ PC8CodePage437 MIB = 2011
+
+ // IBM500 is the MIB identifier with IANA name IBM500.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM500 MIB = 2044
+
+ // IBM851 is the MIB identifier with IANA name IBM851.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM851 MIB = 2045
+
+ // PCp852 is the MIB identifier with IANA name IBM852.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ PCp852 MIB = 2010
+
+ // IBM855 is the MIB identifier with IANA name IBM855.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM855 MIB = 2046
+
+ // IBM857 is the MIB identifier with IANA name IBM857.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM857 MIB = 2047
+
+ // IBM860 is the MIB identifier with IANA name IBM860.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM860 MIB = 2048
+
+ // IBM861 is the MIB identifier with IANA name IBM861.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM861 MIB = 2049
+
+ // IBM863 is the MIB identifier with IANA name IBM863.
+ //
+ // IBM Keyboard layouts and code pages, PN 07G4586 June 1991
+ // Reference: RFC1345
+ IBM863 MIB = 2050
+
+ // IBM864 is the MIB identifier with IANA name IBM864.
+ //
+ // IBM Keyboard layouts and code pages, PN 07G4586 June 1991
+ // Reference: RFC1345
+ IBM864 MIB = 2051
+
+ // IBM865 is the MIB identifier with IANA name IBM865.
+ //
+ // IBM DOS 3.3 Ref (Abridged), 94X9575 (Feb 1987)
+ // Reference: RFC1345
+ IBM865 MIB = 2052
+
+ // IBM868 is the MIB identifier with IANA name IBM868.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM868 MIB = 2053
+
+ // IBM869 is the MIB identifier with IANA name IBM869.
+ //
+ // IBM Keyboard layouts and code pages, PN 07G4586 June 1991
+ // Reference: RFC1345
+ IBM869 MIB = 2054
+
+ // IBM870 is the MIB identifier with IANA name IBM870.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM870 MIB = 2055
+
+ // IBM871 is the MIB identifier with IANA name IBM871.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM871 MIB = 2056
+
+ // IBM880 is the MIB identifier with IANA name IBM880.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM880 MIB = 2057
+
+ // IBM891 is the MIB identifier with IANA name IBM891.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM891 MIB = 2058
+
+ // IBM903 is the MIB identifier with IANA name IBM903.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM903 MIB = 2059
+
+ // IBBM904 is the MIB identifier with IANA name IBM904.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBBM904 MIB = 2060
+
+ // IBM905 is the MIB identifier with IANA name IBM905.
+ //
+ // IBM 3174 Character Set Ref, GA27-3831-02, March 1990
+ // Reference: RFC1345
+ IBM905 MIB = 2061
+
+ // IBM918 is the MIB identifier with IANA name IBM918.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM918 MIB = 2062
+
+ // IBM1026 is the MIB identifier with IANA name IBM1026.
+ //
+ // IBM NLS RM Vol2 SE09-8002-01, March 1990
+ // Reference: RFC1345
+ IBM1026 MIB = 2063
+
+ // IBMEBCDICATDE is the MIB identifier with IANA name EBCDIC-AT-DE.
+ //
+ // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987
+ // Reference: RFC1345
+ IBMEBCDICATDE MIB = 2064
+
+ // EBCDICATDEA is the MIB identifier with IANA name EBCDIC-AT-DE-A.
+ //
+ // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987
+ // Reference: RFC1345
+ EBCDICATDEA MIB = 2065
+
+ // EBCDICCAFR is the MIB identifier with IANA name EBCDIC-CA-FR.
+ //
+ // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987
+ // Reference: RFC1345
+ EBCDICCAFR MIB = 2066
+
+ // EBCDICDKNO is the MIB identifier with IANA name EBCDIC-DK-NO.
+ //
+ // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987
+ // Reference: RFC1345
+ EBCDICDKNO MIB = 2067
+
+ // EBCDICDKNOA is the MIB identifier with IANA name EBCDIC-DK-NO-A.
+ //
+ // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987
+ // Reference: RFC1345
+ EBCDICDKNOA MIB = 2068
+
+ // EBCDICFISE is the MIB identifier with IANA name EBCDIC-FI-SE.
+ //
+ // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987
+ // Reference: RFC1345
+ EBCDICFISE MIB = 2069
+
+ // EBCDICFISEA is the MIB identifier with IANA name EBCDIC-FI-SE-A.
+ //
+ // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987
+ // Reference: RFC1345
+ EBCDICFISEA MIB = 2070
+
+ // EBCDICFR is the MIB identifier with IANA name EBCDIC-FR.
+ //
+ // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987
+ // Reference: RFC1345
+ EBCDICFR MIB = 2071
+
+ // EBCDICIT is the MIB identifier with IANA name EBCDIC-IT.
+ //
+ // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987
+ // Reference: RFC1345
+ EBCDICIT MIB = 2072
+
+ // EBCDICPT is the MIB identifier with IANA name EBCDIC-PT.
+ //
+ // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987
+ // Reference: RFC1345
+ EBCDICPT MIB = 2073
+
+ // EBCDICES is the MIB identifier with IANA name EBCDIC-ES.
+ //
+ // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987
+ // Reference: RFC1345
+ EBCDICES MIB = 2074
+
+ // EBCDICESA is the MIB identifier with IANA name EBCDIC-ES-A.
+ //
+ // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987
+ // Reference: RFC1345
+ EBCDICESA MIB = 2075
+
+ // EBCDICESS is the MIB identifier with IANA name EBCDIC-ES-S.
+ //
+ // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987
+ // Reference: RFC1345
+ EBCDICESS MIB = 2076
+
+ // EBCDICUK is the MIB identifier with IANA name EBCDIC-UK.
+ //
+ // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987
+ // Reference: RFC1345
+ EBCDICUK MIB = 2077
+
+ // EBCDICUS is the MIB identifier with IANA name EBCDIC-US.
+ //
+ // IBM 3270 Char Set Ref Ch 10, GA27-2837-9, April 1987
+ // Reference: RFC1345
+ EBCDICUS MIB = 2078
+
+ // Unknown8BiT is the MIB identifier with IANA name UNKNOWN-8BIT.
+ //
+ // Reference: RFC1428
+ Unknown8BiT MIB = 2079
+
+ // Mnemonic is the MIB identifier with IANA name MNEMONIC.
+ //
+ // rfc1345 , also known as "mnemonic+ascii+38"
+ // Reference: RFC1345
+ Mnemonic MIB = 2080
+
+ // Mnem is the MIB identifier with IANA name MNEM.
+ //
+ // rfc1345 , also known as "mnemonic+ascii+8200"
+ // Reference: RFC1345
+ Mnem MIB = 2081
+
+ // VISCII is the MIB identifier with IANA name VISCII.
+ //
+ // rfc1456
+ // Reference: RFC1456
+ VISCII MIB = 2082
+
+ // VIQR is the MIB identifier with IANA name VIQR.
+ //
+ // rfc1456
+ // Reference: RFC1456
+ VIQR MIB = 2083
+
+ // KOI8R is the MIB identifier with IANA name KOI8-R (MIME: KOI8-R).
+ //
+ // rfc1489 , based on GOST-19768-74, ISO-6937/8,
+ // INIS-Cyrillic, ISO-5427.
+ // Reference: RFC1489
+ KOI8R MIB = 2084
+
+ // HZGB2312 is the MIB identifier with IANA name HZ-GB-2312.
+ //
+ // rfc1842 , rfc1843 rfc1843 rfc1842
+ HZGB2312 MIB = 2085
+
+ // IBM866 is the MIB identifier with IANA name IBM866.
+ //
+ // IBM NLDG Volume 2 (SE09-8002-03) August 1994
+ IBM866 MIB = 2086
+
+ // PC775Baltic is the MIB identifier with IANA name IBM775.
+ //
+ // HP PCL 5 Comparison Guide (P/N 5021-0329) pp B-13, 1996
+ PC775Baltic MIB = 2087
+
+ // KOI8U is the MIB identifier with IANA name KOI8-U.
+ //
+ // rfc2319
+ // Reference: RFC2319
+ KOI8U MIB = 2088
+
+ // IBM00858 is the MIB identifier with IANA name IBM00858.
+ //
+ // IBM See http://www.iana.org/assignments/charset-reg/IBM00858
+ IBM00858 MIB = 2089
+
+ // IBM00924 is the MIB identifier with IANA name IBM00924.
+ //
+ // IBM See http://www.iana.org/assignments/charset-reg/IBM00924
+ IBM00924 MIB = 2090
+
+ // IBM01140 is the MIB identifier with IANA name IBM01140.
+ //
+ // IBM See http://www.iana.org/assignments/charset-reg/IBM01140
+ IBM01140 MIB = 2091
+
+ // IBM01141 is the MIB identifier with IANA name IBM01141.
+ //
+ // IBM See http://www.iana.org/assignments/charset-reg/IBM01141
+ IBM01141 MIB = 2092
+
+ // IBM01142 is the MIB identifier with IANA name IBM01142.
+ //
+ // IBM See http://www.iana.org/assignments/charset-reg/IBM01142
+ IBM01142 MIB = 2093
+
+ // IBM01143 is the MIB identifier with IANA name IBM01143.
+ //
+ // IBM See http://www.iana.org/assignments/charset-reg/IBM01143
+ IBM01143 MIB = 2094
+
+ // IBM01144 is the MIB identifier with IANA name IBM01144.
+ //
+ // IBM See http://www.iana.org/assignments/charset-reg/IBM01144
+ IBM01144 MIB = 2095
+
+ // IBM01145 is the MIB identifier with IANA name IBM01145.
+ //
+ // IBM See http://www.iana.org/assignments/charset-reg/IBM01145
+ IBM01145 MIB = 2096
+
+ // IBM01146 is the MIB identifier with IANA name IBM01146.
+ //
+ // IBM See http://www.iana.org/assignments/charset-reg/IBM01146
+ IBM01146 MIB = 2097
+
+ // IBM01147 is the MIB identifier with IANA name IBM01147.
+ //
+ // IBM See http://www.iana.org/assignments/charset-reg/IBM01147
+ IBM01147 MIB = 2098
+
+ // IBM01148 is the MIB identifier with IANA name IBM01148.
+ //
+ // IBM See http://www.iana.org/assignments/charset-reg/IBM01148
+ IBM01148 MIB = 2099
+
+ // IBM01149 is the MIB identifier with IANA name IBM01149.
+ //
+ // IBM See http://www.iana.org/assignments/charset-reg/IBM01149
+ IBM01149 MIB = 2100
+
+ // Big5HKSCS is the MIB identifier with IANA name Big5-HKSCS.
+ //
+ // See http://www.iana.org/assignments/charset-reg/Big5-HKSCS
+ Big5HKSCS MIB = 2101
+
+ // IBM1047 is the MIB identifier with IANA name IBM1047.
+ //
+ // IBM1047 (EBCDIC Latin 1/Open Systems) http://www-1.ibm.com/servers/eserver/iseries/software/globalization/pdf/cp01047z.pdf
+ IBM1047 MIB = 2102
+
+ // PTCP154 is the MIB identifier with IANA name PTCP154.
+ //
+ // See http://www.iana.org/assignments/charset-reg/PTCP154
+ PTCP154 MIB = 2103
+
+ // Amiga1251 is the MIB identifier with IANA name Amiga-1251.
+ //
+ // See http://www.amiga.ultranet.ru/Amiga-1251.html
+ Amiga1251 MIB = 2104
+
+ // KOI7switched is the MIB identifier with IANA name KOI7-switched.
+ //
+ // See http://www.iana.org/assignments/charset-reg/KOI7-switched
+ KOI7switched MIB = 2105
+
+ // BRF is the MIB identifier with IANA name BRF.
+ //
+ // See http://www.iana.org/assignments/charset-reg/BRF
+ BRF MIB = 2106
+
+ // TSCII is the MIB identifier with IANA name TSCII.
+ //
+ // See http://www.iana.org/assignments/charset-reg/TSCII
+ TSCII MIB = 2107
+
+ // CP51932 is the MIB identifier with IANA name CP51932.
+ //
+ // See http://www.iana.org/assignments/charset-reg/CP51932
+ CP51932 MIB = 2108
+
+ // Windows874 is the MIB identifier with IANA name windows-874.
+ //
+ // See http://www.iana.org/assignments/charset-reg/windows-874
+ Windows874 MIB = 2109
+
+ // Windows1250 is the MIB identifier with IANA name windows-1250.
+ //
+ // Microsoft http://www.iana.org/assignments/charset-reg/windows-1250
+ Windows1250 MIB = 2250
+
+ // Windows1251 is the MIB identifier with IANA name windows-1251.
+ //
+ // Microsoft http://www.iana.org/assignments/charset-reg/windows-1251
+ Windows1251 MIB = 2251
+
+ // Windows1252 is the MIB identifier with IANA name windows-1252.
+ //
+ // Microsoft http://www.iana.org/assignments/charset-reg/windows-1252
+ Windows1252 MIB = 2252
+
+ // Windows1253 is the MIB identifier with IANA name windows-1253.
+ //
+ // Microsoft http://www.iana.org/assignments/charset-reg/windows-1253
+ Windows1253 MIB = 2253
+
+ // Windows1254 is the MIB identifier with IANA name windows-1254.
+ //
+ // Microsoft http://www.iana.org/assignments/charset-reg/windows-1254
+ Windows1254 MIB = 2254
+
+ // Windows1255 is the MIB identifier with IANA name windows-1255.
+ //
+ // Microsoft http://www.iana.org/assignments/charset-reg/windows-1255
+ Windows1255 MIB = 2255
+
+ // Windows1256 is the MIB identifier with IANA name windows-1256.
+ //
+ // Microsoft http://www.iana.org/assignments/charset-reg/windows-1256
+ Windows1256 MIB = 2256
+
+ // Windows1257 is the MIB identifier with IANA name windows-1257.
+ //
+ // Microsoft http://www.iana.org/assignments/charset-reg/windows-1257
+ Windows1257 MIB = 2257
+
+ // Windows1258 is the MIB identifier with IANA name windows-1258.
+ //
+ // Microsoft http://www.iana.org/assignments/charset-reg/windows-1258
+ Windows1258 MIB = 2258
+
+ // TIS620 is the MIB identifier with IANA name TIS-620.
+ //
+ // Thai Industrial Standards Institute (TISI)
+ TIS620 MIB = 2259
+
+ // CP50220 is the MIB identifier with IANA name CP50220.
+ //
+ // See http://www.iana.org/assignments/charset-reg/CP50220
+ CP50220 MIB = 2260
+)
diff --git a/vendor/golang.org/x/text/internal/gen/code.go b/vendor/golang.org/x/text/internal/gen/code.go
new file mode 100644
index 0000000..0389509
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/gen/code.go
@@ -0,0 +1,369 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gen
+
+import (
+ "bytes"
+ "encoding/gob"
+ "fmt"
+ "hash"
+ "hash/fnv"
+ "io"
+ "log"
+ "os"
+ "reflect"
+ "strings"
+ "unicode"
+ "unicode/utf8"
+)
+
+// This file contains utilities for generating code.
+
+// TODO: other write methods like:
+// - slices, maps, types, etc.
+
+// CodeWriter is a utility for writing structured code. It computes the content
+// hash and size of written content. It ensures there are newlines between
+// written code blocks.
+type CodeWriter struct {
+ buf bytes.Buffer
+ Size int
+ Hash hash.Hash32 // content hash
+ gob *gob.Encoder
+ // For comments we skip the usual one-line separator if they are followed by
+ // a code block.
+ skipSep bool
+}
+
+func (w *CodeWriter) Write(p []byte) (n int, err error) {
+ return w.buf.Write(p)
+}
+
+// NewCodeWriter returns a new CodeWriter.
+func NewCodeWriter() *CodeWriter {
+ h := fnv.New32()
+ return &CodeWriter{Hash: h, gob: gob.NewEncoder(h)}
+}
+
+// WriteGoFile appends the buffer with the total size of all created structures
+// and writes it as a Go file to the the given file with the given package name.
+func (w *CodeWriter) WriteGoFile(filename, pkg string) {
+ f, err := os.Create(filename)
+ if err != nil {
+ log.Fatalf("Could not create file %s: %v", filename, err)
+ }
+ defer f.Close()
+ if _, err = w.WriteGo(f, pkg, ""); err != nil {
+ log.Fatalf("Error writing file %s: %v", filename, err)
+ }
+}
+
+// WriteVersionedGoFile appends the buffer with the total size of all created
+// structures and writes it as a Go file to the the given file with the given
+// package name and build tags for the current Unicode version,
+func (w *CodeWriter) WriteVersionedGoFile(filename, pkg string) {
+ tags := buildTags()
+ if tags != "" {
+ filename = insertVersion(filename, UnicodeVersion())
+ }
+ f, err := os.Create(filename)
+ if err != nil {
+ log.Fatalf("Could not create file %s: %v", filename, err)
+ }
+ defer f.Close()
+ if _, err = w.WriteGo(f, pkg, tags); err != nil {
+ log.Fatalf("Error writing file %s: %v", filename, err)
+ }
+}
+
+// WriteGo appends the buffer with the total size of all created structures and
+// writes it as a Go file to the the given writer with the given package name.
+func (w *CodeWriter) WriteGo(out io.Writer, pkg, tags string) (n int, err error) {
+ sz := w.Size
+ w.WriteComment("Total table size %d bytes (%dKiB); checksum: %X\n", sz, sz/1024, w.Hash.Sum32())
+ defer w.buf.Reset()
+ return WriteGo(out, pkg, tags, w.buf.Bytes())
+}
+
+func (w *CodeWriter) printf(f string, x ...interface{}) {
+ fmt.Fprintf(w, f, x...)
+}
+
+func (w *CodeWriter) insertSep() {
+ if w.skipSep {
+ w.skipSep = false
+ return
+ }
+ // Use at least two newlines to ensure a blank space between the previous
+ // block. WriteGoFile will remove extraneous newlines.
+ w.printf("\n\n")
+}
+
+// WriteComment writes a comment block. All line starts are prefixed with "//".
+// Initial empty lines are gobbled. The indentation for the first line is
+// stripped from consecutive lines.
+func (w *CodeWriter) WriteComment(comment string, args ...interface{}) {
+ s := fmt.Sprintf(comment, args...)
+ s = strings.Trim(s, "\n")
+
+ // Use at least two newlines to ensure a blank space between the previous
+ // block. WriteGoFile will remove extraneous newlines.
+ w.printf("\n\n// ")
+ w.skipSep = true
+
+ // strip first indent level.
+ sep := "\n"
+ for ; len(s) > 0 && (s[0] == '\t' || s[0] == ' '); s = s[1:] {
+ sep += s[:1]
+ }
+
+ strings.NewReplacer(sep, "\n// ", "\n", "\n// ").WriteString(w, s)
+
+ w.printf("\n")
+}
+
+func (w *CodeWriter) writeSizeInfo(size int) {
+ w.printf("// Size: %d bytes\n", size)
+}
+
+// WriteConst writes a constant of the given name and value.
+func (w *CodeWriter) WriteConst(name string, x interface{}) {
+ w.insertSep()
+ v := reflect.ValueOf(x)
+
+ switch v.Type().Kind() {
+ case reflect.String:
+ w.printf("const %s %s = ", name, typeName(x))
+ w.WriteString(v.String())
+ w.printf("\n")
+ default:
+ w.printf("const %s = %#v\n", name, x)
+ }
+}
+
+// WriteVar writes a variable of the given name and value.
+func (w *CodeWriter) WriteVar(name string, x interface{}) {
+ w.insertSep()
+ v := reflect.ValueOf(x)
+ oldSize := w.Size
+ sz := int(v.Type().Size())
+ w.Size += sz
+
+ switch v.Type().Kind() {
+ case reflect.String:
+ w.printf("var %s %s = ", name, typeName(x))
+ w.WriteString(v.String())
+ case reflect.Struct:
+ w.gob.Encode(x)
+ fallthrough
+ case reflect.Slice, reflect.Array:
+ w.printf("var %s = ", name)
+ w.writeValue(v)
+ w.writeSizeInfo(w.Size - oldSize)
+ default:
+ w.printf("var %s %s = ", name, typeName(x))
+ w.gob.Encode(x)
+ w.writeValue(v)
+ w.writeSizeInfo(w.Size - oldSize)
+ }
+ w.printf("\n")
+}
+
+func (w *CodeWriter) writeValue(v reflect.Value) {
+ x := v.Interface()
+ switch v.Kind() {
+ case reflect.String:
+ w.WriteString(v.String())
+ case reflect.Array:
+ // Don't double count: callers of WriteArray count on the size being
+ // added, so we need to discount it here.
+ w.Size -= int(v.Type().Size())
+ w.writeSlice(x, true)
+ case reflect.Slice:
+ w.writeSlice(x, false)
+ case reflect.Struct:
+ w.printf("%s{\n", typeName(v.Interface()))
+ t := v.Type()
+ for i := 0; i < v.NumField(); i++ {
+ w.printf("%s: ", t.Field(i).Name)
+ w.writeValue(v.Field(i))
+ w.printf(",\n")
+ }
+ w.printf("}")
+ default:
+ w.printf("%#v", x)
+ }
+}
+
+// WriteString writes a string literal.
+func (w *CodeWriter) WriteString(s string) {
+ s = strings.Replace(s, `\`, `\\`, -1)
+ io.WriteString(w.Hash, s) // content hash
+ w.Size += len(s)
+
+ const maxInline = 40
+ if len(s) <= maxInline {
+ w.printf("%q", s)
+ return
+ }
+
+ // We will render the string as a multi-line string.
+ const maxWidth = 80 - 4 - len(`"`) - len(`" +`)
+
+ // When starting on its own line, go fmt indents line 2+ an extra level.
+ n, max := maxWidth, maxWidth-4
+
+ // As per https://golang.org/issue/18078, the compiler has trouble
+ // compiling the concatenation of many strings, s0 + s1 + s2 + ... + sN,
+ // for large N. We insert redundant, explicit parentheses to work around
+ // that, lowering the N at any given step: (s0 + s1 + ... + s63) + (s64 +
+ // ... + s127) + etc + (etc + ... + sN).
+ explicitParens, extraComment := len(s) > 128*1024, ""
+ if explicitParens {
+ w.printf(`(`)
+ extraComment = "; the redundant, explicit parens are for https://golang.org/issue/18078"
+ }
+
+ // Print "" +\n, if a string does not start on its own line.
+ b := w.buf.Bytes()
+ if p := len(bytes.TrimRight(b, " \t")); p > 0 && b[p-1] != '\n' {
+ w.printf("\"\" + // Size: %d bytes%s\n", len(s), extraComment)
+ n, max = maxWidth, maxWidth
+ }
+
+ w.printf(`"`)
+
+ for sz, p, nLines := 0, 0, 0; p < len(s); {
+ var r rune
+ r, sz = utf8.DecodeRuneInString(s[p:])
+ out := s[p : p+sz]
+ chars := 1
+ if !unicode.IsPrint(r) || r == utf8.RuneError || r == '"' {
+ switch sz {
+ case 1:
+ out = fmt.Sprintf("\\x%02x", s[p])
+ case 2, 3:
+ out = fmt.Sprintf("\\u%04x", r)
+ case 4:
+ out = fmt.Sprintf("\\U%08x", r)
+ }
+ chars = len(out)
+ }
+ if n -= chars; n < 0 {
+ nLines++
+ if explicitParens && nLines&63 == 63 {
+ w.printf("\") + (\"")
+ }
+ w.printf("\" +\n\"")
+ n = max - len(out)
+ }
+ w.printf("%s", out)
+ p += sz
+ }
+ w.printf(`"`)
+ if explicitParens {
+ w.printf(`)`)
+ }
+}
+
+// WriteSlice writes a slice value.
+func (w *CodeWriter) WriteSlice(x interface{}) {
+ w.writeSlice(x, false)
+}
+
+// WriteArray writes an array value.
+func (w *CodeWriter) WriteArray(x interface{}) {
+ w.writeSlice(x, true)
+}
+
+func (w *CodeWriter) writeSlice(x interface{}, isArray bool) {
+ v := reflect.ValueOf(x)
+ w.gob.Encode(v.Len())
+ w.Size += v.Len() * int(v.Type().Elem().Size())
+ name := typeName(x)
+ if isArray {
+ name = fmt.Sprintf("[%d]%s", v.Len(), name[strings.Index(name, "]")+1:])
+ }
+ if isArray {
+ w.printf("%s{\n", name)
+ } else {
+ w.printf("%s{ // %d elements\n", name, v.Len())
+ }
+
+ switch kind := v.Type().Elem().Kind(); kind {
+ case reflect.String:
+ for _, s := range x.([]string) {
+ w.WriteString(s)
+ w.printf(",\n")
+ }
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+ reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ // nLine and nBlock are the number of elements per line and block.
+ nLine, nBlock, format := 8, 64, "%d,"
+ switch kind {
+ case reflect.Uint8:
+ format = "%#02x,"
+ case reflect.Uint16:
+ format = "%#04x,"
+ case reflect.Uint32:
+ nLine, nBlock, format = 4, 32, "%#08x,"
+ case reflect.Uint, reflect.Uint64:
+ nLine, nBlock, format = 4, 32, "%#016x,"
+ case reflect.Int8:
+ nLine = 16
+ }
+ n := nLine
+ for i := 0; i < v.Len(); i++ {
+ if i%nBlock == 0 && v.Len() > nBlock {
+ w.printf("// Entry %X - %X\n", i, i+nBlock-1)
+ }
+ x := v.Index(i).Interface()
+ w.gob.Encode(x)
+ w.printf(format, x)
+ if n--; n == 0 {
+ n = nLine
+ w.printf("\n")
+ }
+ }
+ w.printf("\n")
+ case reflect.Struct:
+ zero := reflect.Zero(v.Type().Elem()).Interface()
+ for i := 0; i < v.Len(); i++ {
+ x := v.Index(i).Interface()
+ w.gob.EncodeValue(v)
+ if !reflect.DeepEqual(zero, x) {
+ line := fmt.Sprintf("%#v,\n", x)
+ line = line[strings.IndexByte(line, '{'):]
+ w.printf("%d: ", i)
+ w.printf(line)
+ }
+ }
+ case reflect.Array:
+ for i := 0; i < v.Len(); i++ {
+ w.printf("%d: %#v,\n", i, v.Index(i).Interface())
+ }
+ default:
+ panic("gen: slice elem type not supported")
+ }
+ w.printf("}")
+}
+
+// WriteType writes a definition of the type of the given value and returns the
+// type name.
+func (w *CodeWriter) WriteType(x interface{}) string {
+ t := reflect.TypeOf(x)
+ w.printf("type %s struct {\n", t.Name())
+ for i := 0; i < t.NumField(); i++ {
+ w.printf("\t%s %s\n", t.Field(i).Name, t.Field(i).Type)
+ }
+ w.printf("}\n")
+ return t.Name()
+}
+
+// typeName returns the name of the go type of x.
+func typeName(x interface{}) string {
+ t := reflect.ValueOf(x).Type()
+ return strings.Replace(fmt.Sprint(t), "main.", "", 1)
+}
diff --git a/vendor/golang.org/x/text/internal/gen/gen.go b/vendor/golang.org/x/text/internal/gen/gen.go
new file mode 100644
index 0000000..4c3f760
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/gen/gen.go
@@ -0,0 +1,333 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package gen contains common code for the various code generation tools in the
+// text repository. Its usage ensures consistency between tools.
+//
+// This package defines command line flags that are common to most generation
+// tools. The flags allow for specifying specific Unicode and CLDR versions
+// in the public Unicode data repository (http://www.unicode.org/Public).
+//
+// A local Unicode data mirror can be set through the flag -local or the
+// environment variable UNICODE_DIR. The former takes precedence. The local
+// directory should follow the same structure as the public repository.
+//
+// IANA data can also optionally be mirrored by putting it in the iana directory
+// rooted at the top of the local mirror. Beware, though, that IANA data is not
+// versioned. So it is up to the developer to use the right version.
+package gen // import "golang.org/x/text/internal/gen"
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "go/build"
+ "go/format"
+ "io"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "os"
+ "path"
+ "path/filepath"
+ "strings"
+ "sync"
+ "unicode"
+
+ "golang.org/x/text/unicode/cldr"
+)
+
+var (
+ url = flag.String("url",
+ "http://www.unicode.org/Public",
+ "URL of Unicode database directory")
+ iana = flag.String("iana",
+ "http://www.iana.org",
+ "URL of the IANA repository")
+ unicodeVersion = flag.String("unicode",
+ getEnv("UNICODE_VERSION", unicode.Version),
+ "unicode version to use")
+ cldrVersion = flag.String("cldr",
+ getEnv("CLDR_VERSION", cldr.Version),
+ "cldr version to use")
+)
+
+func getEnv(name, def string) string {
+ if v := os.Getenv(name); v != "" {
+ return v
+ }
+ return def
+}
+
+// Init performs common initialization for a gen command. It parses the flags
+// and sets up the standard logging parameters.
+func Init() {
+ log.SetPrefix("")
+ log.SetFlags(log.Lshortfile)
+ flag.Parse()
+}
+
+const header = `// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+`
+
+// UnicodeVersion reports the requested Unicode version.
+func UnicodeVersion() string {
+ return *unicodeVersion
+}
+
+// CLDRVersion reports the requested CLDR version.
+func CLDRVersion() string {
+ return *cldrVersion
+}
+
+var tags = []struct{ version, buildTags string }{
+ {"10.0.0", "go1.10"},
+ {"", "!go1.10"},
+}
+
+// buildTags reports the build tags used for the current Unicode version.
+func buildTags() string {
+ v := UnicodeVersion()
+ for _, x := range tags {
+ // We should do a numeric comparison, but including the collate package
+ // would create an import cycle. We approximate it by assuming that
+ // longer version strings are later.
+ if len(x.version) <= len(v) {
+ return x.buildTags
+ }
+ if len(x.version) == len(v) && x.version <= v {
+ return x.buildTags
+ }
+ }
+ return tags[0].buildTags
+}
+
+// IsLocal reports whether data files are available locally.
+func IsLocal() bool {
+ dir, err := localReadmeFile()
+ if err != nil {
+ return false
+ }
+ if _, err = os.Stat(dir); err != nil {
+ return false
+ }
+ return true
+}
+
+// OpenUCDFile opens the requested UCD file. The file is specified relative to
+// the public Unicode root directory. It will call log.Fatal if there are any
+// errors.
+func OpenUCDFile(file string) io.ReadCloser {
+ return openUnicode(path.Join(*unicodeVersion, "ucd", file))
+}
+
+// OpenCLDRCoreZip opens the CLDR core zip file. It will call log.Fatal if there
+// are any errors.
+func OpenCLDRCoreZip() io.ReadCloser {
+ return OpenUnicodeFile("cldr", *cldrVersion, "core.zip")
+}
+
+// OpenUnicodeFile opens the requested file of the requested category from the
+// root of the Unicode data archive. The file is specified relative to the
+// public Unicode root directory. If version is "", it will use the default
+// Unicode version. It will call log.Fatal if there are any errors.
+func OpenUnicodeFile(category, version, file string) io.ReadCloser {
+ if version == "" {
+ version = UnicodeVersion()
+ }
+ return openUnicode(path.Join(category, version, file))
+}
+
+// OpenIANAFile opens the requested IANA file. The file is specified relative
+// to the IANA root, which is typically either http://www.iana.org or the
+// iana directory in the local mirror. It will call log.Fatal if there are any
+// errors.
+func OpenIANAFile(path string) io.ReadCloser {
+ return Open(*iana, "iana", path)
+}
+
+var (
+ dirMutex sync.Mutex
+ localDir string
+)
+
+const permissions = 0755
+
+func localReadmeFile() (string, error) {
+ p, err := build.Import("golang.org/x/text", "", build.FindOnly)
+ if err != nil {
+ return "", fmt.Errorf("Could not locate package: %v", err)
+ }
+ return filepath.Join(p.Dir, "DATA", "README"), nil
+}
+
+func getLocalDir() string {
+ dirMutex.Lock()
+ defer dirMutex.Unlock()
+
+ readme, err := localReadmeFile()
+ if err != nil {
+ log.Fatal(err)
+ }
+ dir := filepath.Dir(readme)
+ if _, err := os.Stat(readme); err != nil {
+ if err := os.MkdirAll(dir, permissions); err != nil {
+ log.Fatalf("Could not create directory: %v", err)
+ }
+ ioutil.WriteFile(readme, []byte(readmeTxt), permissions)
+ }
+ return dir
+}
+
+const readmeTxt = `Generated by golang.org/x/text/internal/gen. DO NOT EDIT.
+
+This directory contains downloaded files used to generate the various tables
+in the golang.org/x/text subrepo.
+
+Note that the language subtag repo (iana/assignments/language-subtag-registry)
+and all other times in the iana subdirectory are not versioned and will need
+to be periodically manually updated. The easiest way to do this is to remove
+the entire iana directory. This is mostly of concern when updating the language
+package.
+`
+
+// Open opens subdir/path if a local directory is specified and the file exists,
+// where subdir is a directory relative to the local root, or fetches it from
+// urlRoot/path otherwise. It will call log.Fatal if there are any errors.
+func Open(urlRoot, subdir, path string) io.ReadCloser {
+ file := filepath.Join(getLocalDir(), subdir, filepath.FromSlash(path))
+ return open(file, urlRoot, path)
+}
+
+func openUnicode(path string) io.ReadCloser {
+ file := filepath.Join(getLocalDir(), filepath.FromSlash(path))
+ return open(file, *url, path)
+}
+
+// TODO: automatically periodically update non-versioned files.
+
+func open(file, urlRoot, path string) io.ReadCloser {
+ if f, err := os.Open(file); err == nil {
+ return f
+ }
+ r := get(urlRoot, path)
+ defer r.Close()
+ b, err := ioutil.ReadAll(r)
+ if err != nil {
+ log.Fatalf("Could not download file: %v", err)
+ }
+ os.MkdirAll(filepath.Dir(file), permissions)
+ if err := ioutil.WriteFile(file, b, permissions); err != nil {
+ log.Fatalf("Could not create file: %v", err)
+ }
+ return ioutil.NopCloser(bytes.NewReader(b))
+}
+
+func get(root, path string) io.ReadCloser {
+ url := root + "/" + path
+ fmt.Printf("Fetching %s...", url)
+ defer fmt.Println(" done.")
+ resp, err := http.Get(url)
+ if err != nil {
+ log.Fatalf("HTTP GET: %v", err)
+ }
+ if resp.StatusCode != 200 {
+ log.Fatalf("Bad GET status for %q: %q", url, resp.Status)
+ }
+ return resp.Body
+}
+
+// TODO: use Write*Version in all applicable packages.
+
+// WriteUnicodeVersion writes a constant for the Unicode version from which the
+// tables are generated.
+func WriteUnicodeVersion(w io.Writer) {
+ fmt.Fprintf(w, "// UnicodeVersion is the Unicode version from which the tables in this package are derived.\n")
+ fmt.Fprintf(w, "const UnicodeVersion = %q\n\n", UnicodeVersion())
+}
+
+// WriteCLDRVersion writes a constant for the CLDR version from which the
+// tables are generated.
+func WriteCLDRVersion(w io.Writer) {
+ fmt.Fprintf(w, "// CLDRVersion is the CLDR version from which the tables in this package are derived.\n")
+ fmt.Fprintf(w, "const CLDRVersion = %q\n\n", CLDRVersion())
+}
+
+// WriteGoFile prepends a standard file comment and package statement to the
+// given bytes, applies gofmt, and writes them to a file with the given name.
+// It will call log.Fatal if there are any errors.
+func WriteGoFile(filename, pkg string, b []byte) {
+ w, err := os.Create(filename)
+ if err != nil {
+ log.Fatalf("Could not create file %s: %v", filename, err)
+ }
+ defer w.Close()
+ if _, err = WriteGo(w, pkg, "", b); err != nil {
+ log.Fatalf("Error writing file %s: %v", filename, err)
+ }
+}
+
+func insertVersion(filename, version string) string {
+ suffix := ".go"
+ if strings.HasSuffix(filename, "_test.go") {
+ suffix = "_test.go"
+ }
+ return fmt.Sprint(filename[:len(filename)-len(suffix)], version, suffix)
+}
+
+// WriteVersionedGoFile prepends a standard file comment, adds build tags to
+// version the file for the current Unicode version, and package statement to
+// the given bytes, applies gofmt, and writes them to a file with the given
+// name. It will call log.Fatal if there are any errors.
+func WriteVersionedGoFile(filename, pkg string, b []byte) {
+ tags := buildTags()
+ if tags != "" {
+ filename = insertVersion(filename, UnicodeVersion())
+ }
+ w, err := os.Create(filename)
+ if err != nil {
+ log.Fatalf("Could not create file %s: %v", filename, err)
+ }
+ defer w.Close()
+ if _, err = WriteGo(w, pkg, tags, b); err != nil {
+ log.Fatalf("Error writing file %s: %v", filename, err)
+ }
+}
+
+// WriteGo prepends a standard file comment and package statement to the given
+// bytes, applies gofmt, and writes them to w.
+func WriteGo(w io.Writer, pkg, tags string, b []byte) (n int, err error) {
+ src := []byte(header)
+ if tags != "" {
+ src = append(src, fmt.Sprintf("// +build %s\n\n", tags)...)
+ }
+ src = append(src, fmt.Sprintf("package %s\n\n", pkg)...)
+ src = append(src, b...)
+ formatted, err := format.Source(src)
+ if err != nil {
+ // Print the generated code even in case of an error so that the
+ // returned error can be meaningfully interpreted.
+ n, _ = w.Write(src)
+ return n, err
+ }
+ return w.Write(formatted)
+}
+
+// Repackage rewrites a Go file from belonging to package main to belonging to
+// the given package.
+func Repackage(inFile, outFile, pkg string) {
+ src, err := ioutil.ReadFile(inFile)
+ if err != nil {
+ log.Fatalf("reading %s: %v", inFile, err)
+ }
+ const toDelete = "package main\n\n"
+ i := bytes.Index(src, []byte(toDelete))
+ if i < 0 {
+ log.Fatalf("Could not find %q in %s.", toDelete, inFile)
+ }
+ w := &bytes.Buffer{}
+ w.Write(src[i+len(toDelete):])
+ WriteGoFile(outFile, pkg, w.Bytes())
+}
diff --git a/vendor/golang.org/x/text/transform/transform.go b/vendor/golang.org/x/text/transform/transform.go
new file mode 100644
index 0000000..fe47b9b
--- /dev/null
+++ b/vendor/golang.org/x/text/transform/transform.go
@@ -0,0 +1,705 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package transform provides reader and writer wrappers that transform the
+// bytes passing through as well as various transformations. Example
+// transformations provided by other packages include normalization and
+// conversion between character sets.
+package transform // import "golang.org/x/text/transform"
+
+import (
+ "bytes"
+ "errors"
+ "io"
+ "unicode/utf8"
+)
+
+var (
+ // ErrShortDst means that the destination buffer was too short to
+ // receive all of the transformed bytes.
+ ErrShortDst = errors.New("transform: short destination buffer")
+
+ // ErrShortSrc means that the source buffer has insufficient data to
+ // complete the transformation.
+ ErrShortSrc = errors.New("transform: short source buffer")
+
+ // ErrEndOfSpan means that the input and output (the transformed input)
+ // are not identical.
+ ErrEndOfSpan = errors.New("transform: input and output are not identical")
+
+ // errInconsistentByteCount means that Transform returned success (nil
+ // error) but also returned nSrc inconsistent with the src argument.
+ errInconsistentByteCount = errors.New("transform: inconsistent byte count returned")
+
+ // errShortInternal means that an internal buffer is not large enough
+ // to make progress and the Transform operation must be aborted.
+ errShortInternal = errors.New("transform: short internal buffer")
+)
+
+// Transformer transforms bytes.
+type Transformer interface {
+ // Transform writes to dst the transformed bytes read from src, and
+ // returns the number of dst bytes written and src bytes read. The
+ // atEOF argument tells whether src represents the last bytes of the
+ // input.
+ //
+ // Callers should always process the nDst bytes produced and account
+ // for the nSrc bytes consumed before considering the error err.
+ //
+ // A nil error means that all of the transformed bytes (whether freshly
+ // transformed from src or left over from previous Transform calls)
+ // were written to dst. A nil error can be returned regardless of
+ // whether atEOF is true. If err is nil then nSrc must equal len(src);
+ // the converse is not necessarily true.
+ //
+ // ErrShortDst means that dst was too short to receive all of the
+ // transformed bytes. ErrShortSrc means that src had insufficient data
+ // to complete the transformation. If both conditions apply, then
+ // either error may be returned. Other than the error conditions listed
+ // here, implementations are free to report other errors that arise.
+ Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error)
+
+ // Reset resets the state and allows a Transformer to be reused.
+ Reset()
+}
+
+// SpanningTransformer extends the Transformer interface with a Span method
+// that determines how much of the input already conforms to the Transformer.
+type SpanningTransformer interface {
+ Transformer
+
+ // Span returns a position in src such that transforming src[:n] results in
+ // identical output src[:n] for these bytes. It does not necessarily return
+ // the largest such n. The atEOF argument tells whether src represents the
+ // last bytes of the input.
+ //
+ // Callers should always account for the n bytes consumed before
+ // considering the error err.
+ //
+ // A nil error means that all input bytes are known to be identical to the
+ // output produced by the Transformer. A nil error can be be returned
+ // regardless of whether atEOF is true. If err is nil, then then n must
+ // equal len(src); the converse is not necessarily true.
+ //
+ // ErrEndOfSpan means that the Transformer output may differ from the
+ // input after n bytes. Note that n may be len(src), meaning that the output
+ // would contain additional bytes after otherwise identical output.
+ // ErrShortSrc means that src had insufficient data to determine whether the
+ // remaining bytes would change. Other than the error conditions listed
+ // here, implementations are free to report other errors that arise.
+ //
+ // Calling Span can modify the Transformer state as a side effect. In
+ // effect, it does the transformation just as calling Transform would, only
+ // without copying to a destination buffer and only up to a point it can
+ // determine the input and output bytes are the same. This is obviously more
+ // limited than calling Transform, but can be more efficient in terms of
+ // copying and allocating buffers. Calls to Span and Transform may be
+ // interleaved.
+ Span(src []byte, atEOF bool) (n int, err error)
+}
+
+// NopResetter can be embedded by implementations of Transformer to add a nop
+// Reset method.
+type NopResetter struct{}
+
+// Reset implements the Reset method of the Transformer interface.
+func (NopResetter) Reset() {}
+
+// Reader wraps another io.Reader by transforming the bytes read.
+type Reader struct {
+ r io.Reader
+ t Transformer
+ err error
+
+ // dst[dst0:dst1] contains bytes that have been transformed by t but
+ // not yet copied out via Read.
+ dst []byte
+ dst0, dst1 int
+
+ // src[src0:src1] contains bytes that have been read from r but not
+ // yet transformed through t.
+ src []byte
+ src0, src1 int
+
+ // transformComplete is whether the transformation is complete,
+ // regardless of whether or not it was successful.
+ transformComplete bool
+}
+
+const defaultBufSize = 4096
+
+// NewReader returns a new Reader that wraps r by transforming the bytes read
+// via t. It calls Reset on t.
+func NewReader(r io.Reader, t Transformer) *Reader {
+ t.Reset()
+ return &Reader{
+ r: r,
+ t: t,
+ dst: make([]byte, defaultBufSize),
+ src: make([]byte, defaultBufSize),
+ }
+}
+
+// Read implements the io.Reader interface.
+func (r *Reader) Read(p []byte) (int, error) {
+ n, err := 0, error(nil)
+ for {
+ // Copy out any transformed bytes and return the final error if we are done.
+ if r.dst0 != r.dst1 {
+ n = copy(p, r.dst[r.dst0:r.dst1])
+ r.dst0 += n
+ if r.dst0 == r.dst1 && r.transformComplete {
+ return n, r.err
+ }
+ return n, nil
+ } else if r.transformComplete {
+ return 0, r.err
+ }
+
+ // Try to transform some source bytes, or to flush the transformer if we
+ // are out of source bytes. We do this even if r.r.Read returned an error.
+ // As the io.Reader documentation says, "process the n > 0 bytes returned
+ // before considering the error".
+ if r.src0 != r.src1 || r.err != nil {
+ r.dst0 = 0
+ r.dst1, n, err = r.t.Transform(r.dst, r.src[r.src0:r.src1], r.err == io.EOF)
+ r.src0 += n
+
+ switch {
+ case err == nil:
+ if r.src0 != r.src1 {
+ r.err = errInconsistentByteCount
+ }
+ // The Transform call was successful; we are complete if we
+ // cannot read more bytes into src.
+ r.transformComplete = r.err != nil
+ continue
+ case err == ErrShortDst && (r.dst1 != 0 || n != 0):
+ // Make room in dst by copying out, and try again.
+ continue
+ case err == ErrShortSrc && r.src1-r.src0 != len(r.src) && r.err == nil:
+ // Read more bytes into src via the code below, and try again.
+ default:
+ r.transformComplete = true
+ // The reader error (r.err) takes precedence over the
+ // transformer error (err) unless r.err is nil or io.EOF.
+ if r.err == nil || r.err == io.EOF {
+ r.err = err
+ }
+ continue
+ }
+ }
+
+ // Move any untransformed source bytes to the start of the buffer
+ // and read more bytes.
+ if r.src0 != 0 {
+ r.src0, r.src1 = 0, copy(r.src, r.src[r.src0:r.src1])
+ }
+ n, r.err = r.r.Read(r.src[r.src1:])
+ r.src1 += n
+ }
+}
+
+// TODO: implement ReadByte (and ReadRune??).
+
+// Writer wraps another io.Writer by transforming the bytes read.
+// The user needs to call Close to flush unwritten bytes that may
+// be buffered.
+type Writer struct {
+ w io.Writer
+ t Transformer
+ dst []byte
+
+ // src[:n] contains bytes that have not yet passed through t.
+ src []byte
+ n int
+}
+
+// NewWriter returns a new Writer that wraps w by transforming the bytes written
+// via t. It calls Reset on t.
+func NewWriter(w io.Writer, t Transformer) *Writer {
+ t.Reset()
+ return &Writer{
+ w: w,
+ t: t,
+ dst: make([]byte, defaultBufSize),
+ src: make([]byte, defaultBufSize),
+ }
+}
+
+// Write implements the io.Writer interface. If there are not enough
+// bytes available to complete a Transform, the bytes will be buffered
+// for the next write. Call Close to convert the remaining bytes.
+func (w *Writer) Write(data []byte) (n int, err error) {
+ src := data
+ if w.n > 0 {
+ // Append bytes from data to the last remainder.
+ // TODO: limit the amount copied on first try.
+ n = copy(w.src[w.n:], data)
+ w.n += n
+ src = w.src[:w.n]
+ }
+ for {
+ nDst, nSrc, err := w.t.Transform(w.dst, src, false)
+ if _, werr := w.w.Write(w.dst[:nDst]); werr != nil {
+ return n, werr
+ }
+ src = src[nSrc:]
+ if w.n == 0 {
+ n += nSrc
+ } else if len(src) <= n {
+ // Enough bytes from w.src have been consumed. We make src point
+ // to data instead to reduce the copying.
+ w.n = 0
+ n -= len(src)
+ src = data[n:]
+ if n < len(data) && (err == nil || err == ErrShortSrc) {
+ continue
+ }
+ }
+ switch err {
+ case ErrShortDst:
+ // This error is okay as long as we are making progress.
+ if nDst > 0 || nSrc > 0 {
+ continue
+ }
+ case ErrShortSrc:
+ if len(src) < len(w.src) {
+ m := copy(w.src, src)
+ // If w.n > 0, bytes from data were already copied to w.src and n
+ // was already set to the number of bytes consumed.
+ if w.n == 0 {
+ n += m
+ }
+ w.n = m
+ err = nil
+ } else if nDst > 0 || nSrc > 0 {
+ // Not enough buffer to store the remainder. Keep processing as
+ // long as there is progress. Without this case, transforms that
+ // require a lookahead larger than the buffer may result in an
+ // error. This is not something one may expect to be common in
+ // practice, but it may occur when buffers are set to small
+ // sizes during testing.
+ continue
+ }
+ case nil:
+ if w.n > 0 {
+ err = errInconsistentByteCount
+ }
+ }
+ return n, err
+ }
+}
+
+// Close implements the io.Closer interface.
+func (w *Writer) Close() error {
+ src := w.src[:w.n]
+ for {
+ nDst, nSrc, err := w.t.Transform(w.dst, src, true)
+ if _, werr := w.w.Write(w.dst[:nDst]); werr != nil {
+ return werr
+ }
+ if err != ErrShortDst {
+ return err
+ }
+ src = src[nSrc:]
+ }
+}
+
+type nop struct{ NopResetter }
+
+func (nop) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ n := copy(dst, src)
+ if n < len(src) {
+ err = ErrShortDst
+ }
+ return n, n, err
+}
+
+func (nop) Span(src []byte, atEOF bool) (n int, err error) {
+ return len(src), nil
+}
+
+type discard struct{ NopResetter }
+
+func (discard) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ return 0, len(src), nil
+}
+
+var (
+ // Discard is a Transformer for which all Transform calls succeed
+ // by consuming all bytes and writing nothing.
+ Discard Transformer = discard{}
+
+ // Nop is a SpanningTransformer that copies src to dst.
+ Nop SpanningTransformer = nop{}
+)
+
+// chain is a sequence of links. A chain with N Transformers has N+1 links and
+// N+1 buffers. Of those N+1 buffers, the first and last are the src and dst
+// buffers given to chain.Transform and the middle N-1 buffers are intermediate
+// buffers owned by the chain. The i'th link transforms bytes from the i'th
+// buffer chain.link[i].b at read offset chain.link[i].p to the i+1'th buffer
+// chain.link[i+1].b at write offset chain.link[i+1].n, for i in [0, N).
+type chain struct {
+ link []link
+ err error
+ // errStart is the index at which the error occurred plus 1. Processing
+ // errStart at this level at the next call to Transform. As long as
+ // errStart > 0, chain will not consume any more source bytes.
+ errStart int
+}
+
+func (c *chain) fatalError(errIndex int, err error) {
+ if i := errIndex + 1; i > c.errStart {
+ c.errStart = i
+ c.err = err
+ }
+}
+
+type link struct {
+ t Transformer
+ // b[p:n] holds the bytes to be transformed by t.
+ b []byte
+ p int
+ n int
+}
+
+func (l *link) src() []byte {
+ return l.b[l.p:l.n]
+}
+
+func (l *link) dst() []byte {
+ return l.b[l.n:]
+}
+
+// Chain returns a Transformer that applies t in sequence.
+func Chain(t ...Transformer) Transformer {
+ if len(t) == 0 {
+ return nop{}
+ }
+ c := &chain{link: make([]link, len(t)+1)}
+ for i, tt := range t {
+ c.link[i].t = tt
+ }
+ // Allocate intermediate buffers.
+ b := make([][defaultBufSize]byte, len(t)-1)
+ for i := range b {
+ c.link[i+1].b = b[i][:]
+ }
+ return c
+}
+
+// Reset resets the state of Chain. It calls Reset on all the Transformers.
+func (c *chain) Reset() {
+ for i, l := range c.link {
+ if l.t != nil {
+ l.t.Reset()
+ }
+ c.link[i].p, c.link[i].n = 0, 0
+ }
+}
+
+// TODO: make chain use Span (is going to be fun to implement!)
+
+// Transform applies the transformers of c in sequence.
+func (c *chain) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ // Set up src and dst in the chain.
+ srcL := &c.link[0]
+ dstL := &c.link[len(c.link)-1]
+ srcL.b, srcL.p, srcL.n = src, 0, len(src)
+ dstL.b, dstL.n = dst, 0
+ var lastFull, needProgress bool // for detecting progress
+
+ // i is the index of the next Transformer to apply, for i in [low, high].
+ // low is the lowest index for which c.link[low] may still produce bytes.
+ // high is the highest index for which c.link[high] has a Transformer.
+ // The error returned by Transform determines whether to increase or
+ // decrease i. We try to completely fill a buffer before converting it.
+ for low, i, high := c.errStart, c.errStart, len(c.link)-2; low <= i && i <= high; {
+ in, out := &c.link[i], &c.link[i+1]
+ nDst, nSrc, err0 := in.t.Transform(out.dst(), in.src(), atEOF && low == i)
+ out.n += nDst
+ in.p += nSrc
+ if i > 0 && in.p == in.n {
+ in.p, in.n = 0, 0
+ }
+ needProgress, lastFull = lastFull, false
+ switch err0 {
+ case ErrShortDst:
+ // Process the destination buffer next. Return if we are already
+ // at the high index.
+ if i == high {
+ return dstL.n, srcL.p, ErrShortDst
+ }
+ if out.n != 0 {
+ i++
+ // If the Transformer at the next index is not able to process any
+ // source bytes there is nothing that can be done to make progress
+ // and the bytes will remain unprocessed. lastFull is used to
+ // detect this and break out of the loop with a fatal error.
+ lastFull = true
+ continue
+ }
+ // The destination buffer was too small, but is completely empty.
+ // Return a fatal error as this transformation can never complete.
+ c.fatalError(i, errShortInternal)
+ case ErrShortSrc:
+ if i == 0 {
+ // Save ErrShortSrc in err. All other errors take precedence.
+ err = ErrShortSrc
+ break
+ }
+ // Source bytes were depleted before filling up the destination buffer.
+ // Verify we made some progress, move the remaining bytes to the errStart
+ // and try to get more source bytes.
+ if needProgress && nSrc == 0 || in.n-in.p == len(in.b) {
+ // There were not enough source bytes to proceed while the source
+ // buffer cannot hold any more bytes. Return a fatal error as this
+ // transformation can never complete.
+ c.fatalError(i, errShortInternal)
+ break
+ }
+ // in.b is an internal buffer and we can make progress.
+ in.p, in.n = 0, copy(in.b, in.src())
+ fallthrough
+ case nil:
+ // if i == low, we have depleted the bytes at index i or any lower levels.
+ // In that case we increase low and i. In all other cases we decrease i to
+ // fetch more bytes before proceeding to the next index.
+ if i > low {
+ i--
+ continue
+ }
+ default:
+ c.fatalError(i, err0)
+ }
+ // Exhausted level low or fatal error: increase low and continue
+ // to process the bytes accepted so far.
+ i++
+ low = i
+ }
+
+ // If c.errStart > 0, this means we found a fatal error. We will clear
+ // all upstream buffers. At this point, no more progress can be made
+ // downstream, as Transform would have bailed while handling ErrShortDst.
+ if c.errStart > 0 {
+ for i := 1; i < c.errStart; i++ {
+ c.link[i].p, c.link[i].n = 0, 0
+ }
+ err, c.errStart, c.err = c.err, 0, nil
+ }
+ return dstL.n, srcL.p, err
+}
+
+// Deprecated: use runes.Remove instead.
+func RemoveFunc(f func(r rune) bool) Transformer {
+ return removeF(f)
+}
+
+type removeF func(r rune) bool
+
+func (removeF) Reset() {}
+
+// Transform implements the Transformer interface.
+func (t removeF) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ for r, sz := rune(0), 0; len(src) > 0; src = src[sz:] {
+
+ if r = rune(src[0]); r < utf8.RuneSelf {
+ sz = 1
+ } else {
+ r, sz = utf8.DecodeRune(src)
+
+ if sz == 1 {
+ // Invalid rune.
+ if !atEOF && !utf8.FullRune(src) {
+ err = ErrShortSrc
+ break
+ }
+ // We replace illegal bytes with RuneError. Not doing so might
+ // otherwise turn a sequence of invalid UTF-8 into valid UTF-8.
+ // The resulting byte sequence may subsequently contain runes
+ // for which t(r) is true that were passed unnoticed.
+ if !t(r) {
+ if nDst+3 > len(dst) {
+ err = ErrShortDst
+ break
+ }
+ nDst += copy(dst[nDst:], "\uFFFD")
+ }
+ nSrc++
+ continue
+ }
+ }
+
+ if !t(r) {
+ if nDst+sz > len(dst) {
+ err = ErrShortDst
+ break
+ }
+ nDst += copy(dst[nDst:], src[:sz])
+ }
+ nSrc += sz
+ }
+ return
+}
+
+// grow returns a new []byte that is longer than b, and copies the first n bytes
+// of b to the start of the new slice.
+func grow(b []byte, n int) []byte {
+ m := len(b)
+ if m <= 32 {
+ m = 64
+ } else if m <= 256 {
+ m *= 2
+ } else {
+ m += m >> 1
+ }
+ buf := make([]byte, m)
+ copy(buf, b[:n])
+ return buf
+}
+
+const initialBufSize = 128
+
+// String returns a string with the result of converting s[:n] using t, where
+// n <= len(s). If err == nil, n will be len(s). It calls Reset on t.
+func String(t Transformer, s string) (result string, n int, err error) {
+ t.Reset()
+ if s == "" {
+ // Fast path for the common case for empty input. Results in about a
+ // 86% reduction of running time for BenchmarkStringLowerEmpty.
+ if _, _, err := t.Transform(nil, nil, true); err == nil {
+ return "", 0, nil
+ }
+ }
+
+ // Allocate only once. Note that both dst and src escape when passed to
+ // Transform.
+ buf := [2 * initialBufSize]byte{}
+ dst := buf[:initialBufSize:initialBufSize]
+ src := buf[initialBufSize : 2*initialBufSize]
+
+ // The input string s is transformed in multiple chunks (starting with a
+ // chunk size of initialBufSize). nDst and nSrc are per-chunk (or
+ // per-Transform-call) indexes, pDst and pSrc are overall indexes.
+ nDst, nSrc := 0, 0
+ pDst, pSrc := 0, 0
+
+ // pPrefix is the length of a common prefix: the first pPrefix bytes of the
+ // result will equal the first pPrefix bytes of s. It is not guaranteed to
+ // be the largest such value, but if pPrefix, len(result) and len(s) are
+ // all equal after the final transform (i.e. calling Transform with atEOF
+ // being true returned nil error) then we don't need to allocate a new
+ // result string.
+ pPrefix := 0
+ for {
+ // Invariant: pDst == pPrefix && pSrc == pPrefix.
+
+ n := copy(src, s[pSrc:])
+ nDst, nSrc, err = t.Transform(dst, src[:n], pSrc+n == len(s))
+ pDst += nDst
+ pSrc += nSrc
+
+ // TODO: let transformers implement an optional Spanner interface, akin
+ // to norm's QuickSpan. This would even allow us to avoid any allocation.
+ if !bytes.Equal(dst[:nDst], src[:nSrc]) {
+ break
+ }
+ pPrefix = pSrc
+ if err == ErrShortDst {
+ // A buffer can only be short if a transformer modifies its input.
+ break
+ } else if err == ErrShortSrc {
+ if nSrc == 0 {
+ // No progress was made.
+ break
+ }
+ // Equal so far and !atEOF, so continue checking.
+ } else if err != nil || pPrefix == len(s) {
+ return string(s[:pPrefix]), pPrefix, err
+ }
+ }
+ // Post-condition: pDst == pPrefix + nDst && pSrc == pPrefix + nSrc.
+
+ // We have transformed the first pSrc bytes of the input s to become pDst
+ // transformed bytes. Those transformed bytes are discontiguous: the first
+ // pPrefix of them equal s[:pPrefix] and the last nDst of them equal
+ // dst[:nDst]. We copy them around, into a new dst buffer if necessary, so
+ // that they become one contiguous slice: dst[:pDst].
+ if pPrefix != 0 {
+ newDst := dst
+ if pDst > len(newDst) {
+ newDst = make([]byte, len(s)+nDst-nSrc)
+ }
+ copy(newDst[pPrefix:pDst], dst[:nDst])
+ copy(newDst[:pPrefix], s[:pPrefix])
+ dst = newDst
+ }
+
+ // Prevent duplicate Transform calls with atEOF being true at the end of
+ // the input. Also return if we have an unrecoverable error.
+ if (err == nil && pSrc == len(s)) ||
+ (err != nil && err != ErrShortDst && err != ErrShortSrc) {
+ return string(dst[:pDst]), pSrc, err
+ }
+
+ // Transform the remaining input, growing dst and src buffers as necessary.
+ for {
+ n := copy(src, s[pSrc:])
+ nDst, nSrc, err := t.Transform(dst[pDst:], src[:n], pSrc+n == len(s))
+ pDst += nDst
+ pSrc += nSrc
+
+ // If we got ErrShortDst or ErrShortSrc, do not grow as long as we can
+ // make progress. This may avoid excessive allocations.
+ if err == ErrShortDst {
+ if nDst == 0 {
+ dst = grow(dst, pDst)
+ }
+ } else if err == ErrShortSrc {
+ if nSrc == 0 {
+ src = grow(src, 0)
+ }
+ } else if err != nil || pSrc == len(s) {
+ return string(dst[:pDst]), pSrc, err
+ }
+ }
+}
+
+// Bytes returns a new byte slice with the result of converting b[:n] using t,
+// where n <= len(b). If err == nil, n will be len(b). It calls Reset on t.
+func Bytes(t Transformer, b []byte) (result []byte, n int, err error) {
+ return doAppend(t, 0, make([]byte, len(b)), b)
+}
+
+// Append appends the result of converting src[:n] using t to dst, where
+// n <= len(src), If err == nil, n will be len(src). It calls Reset on t.
+func Append(t Transformer, dst, src []byte) (result []byte, n int, err error) {
+ if len(dst) == cap(dst) {
+ n := len(src) + len(dst) // It is okay for this to be 0.
+ b := make([]byte, n)
+ dst = b[:copy(b, dst)]
+ }
+ return doAppend(t, len(dst), dst[:cap(dst)], src)
+}
+
+func doAppend(t Transformer, pDst int, dst, src []byte) (result []byte, n int, err error) {
+ t.Reset()
+ pSrc := 0
+ for {
+ nDst, nSrc, err := t.Transform(dst[pDst:], src[pSrc:], true)
+ pDst += nDst
+ pSrc += nSrc
+ if err != ErrShortDst {
+ return dst[:pDst], pSrc, err
+ }
+
+ // Grow the destination buffer, but do not grow as long as we can make
+ // progress. This may avoid excessive allocations.
+ if nDst == 0 {
+ dst = grow(dst, pDst)
+ }
+ }
+}
diff --git a/vendor/golang.org/x/text/unicode/cldr/base.go b/vendor/golang.org/x/text/unicode/cldr/base.go
new file mode 100644
index 0000000..63cdc16
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/cldr/base.go
@@ -0,0 +1,105 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cldr
+
+import (
+ "encoding/xml"
+ "regexp"
+ "strconv"
+)
+
+// Elem is implemented by every XML element.
+type Elem interface {
+ setEnclosing(Elem)
+ setName(string)
+ enclosing() Elem
+
+ GetCommon() *Common
+}
+
+type hidden struct {
+ CharData string `xml:",chardata"`
+ Alias *struct {
+ Common
+ Source string `xml:"source,attr"`
+ Path string `xml:"path,attr"`
+ } `xml:"alias"`
+ Def *struct {
+ Common
+ Choice string `xml:"choice,attr,omitempty"`
+ Type string `xml:"type,attr,omitempty"`
+ } `xml:"default"`
+}
+
+// Common holds several of the most common attributes and sub elements
+// of an XML element.
+type Common struct {
+ XMLName xml.Name
+ name string
+ enclElem Elem
+ Type string `xml:"type,attr,omitempty"`
+ Reference string `xml:"reference,attr,omitempty"`
+ Alt string `xml:"alt,attr,omitempty"`
+ ValidSubLocales string `xml:"validSubLocales,attr,omitempty"`
+ Draft string `xml:"draft,attr,omitempty"`
+ hidden
+}
+
+// Default returns the default type to select from the enclosed list
+// or "" if no default value is specified.
+func (e *Common) Default() string {
+ if e.Def == nil {
+ return ""
+ }
+ if e.Def.Choice != "" {
+ return e.Def.Choice
+ } else if e.Def.Type != "" {
+ // Type is still used by the default element in collation.
+ return e.Def.Type
+ }
+ return ""
+}
+
+// Element returns the XML element name.
+func (e *Common) Element() string {
+ return e.name
+}
+
+// GetCommon returns e. It is provided such that Common implements Elem.
+func (e *Common) GetCommon() *Common {
+ return e
+}
+
+// Data returns the character data accumulated for this element.
+func (e *Common) Data() string {
+ e.CharData = charRe.ReplaceAllStringFunc(e.CharData, replaceUnicode)
+ return e.CharData
+}
+
+func (e *Common) setName(s string) {
+ e.name = s
+}
+
+func (e *Common) enclosing() Elem {
+ return e.enclElem
+}
+
+func (e *Common) setEnclosing(en Elem) {
+ e.enclElem = en
+}
+
+// Escape characters that can be escaped without further escaping the string.
+var charRe = regexp.MustCompile(`&#x[0-9a-fA-F]*;|\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8}|\\x[0-9a-fA-F]{2}|\\[0-7]{3}|\\[abtnvfr]`)
+
+// replaceUnicode converts hexadecimal Unicode codepoint notations to a one-rune string.
+// It assumes the input string is correctly formatted.
+func replaceUnicode(s string) string {
+ if s[1] == '#' {
+ r, _ := strconv.ParseInt(s[3:len(s)-1], 16, 32)
+ return string(r)
+ }
+ r, _, _, _ := strconv.UnquoteChar(s, 0)
+ return string(r)
+}
diff --git a/vendor/golang.org/x/text/unicode/cldr/cldr.go b/vendor/golang.org/x/text/unicode/cldr/cldr.go
new file mode 100644
index 0000000..2197f8a
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/cldr/cldr.go
@@ -0,0 +1,130 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:generate go run makexml.go -output xml.go
+
+// Package cldr provides a parser for LDML and related XML formats.
+// This package is intended to be used by the table generation tools
+// for the various internationalization-related packages.
+// As the XML types are generated from the CLDR DTD, and as the CLDR standard
+// is periodically amended, this package may change considerably over time.
+// This mostly means that data may appear and disappear between versions.
+// That is, old code should keep compiling for newer versions, but data
+// may have moved or changed.
+// CLDR version 22 is the first version supported by this package.
+// Older versions may not work.
+package cldr // import "golang.org/x/text/unicode/cldr"
+
+import (
+ "fmt"
+ "sort"
+)
+
+// CLDR provides access to parsed data of the Unicode Common Locale Data Repository.
+type CLDR struct {
+ parent map[string][]string
+ locale map[string]*LDML
+ resolved map[string]*LDML
+ bcp47 *LDMLBCP47
+ supp *SupplementalData
+}
+
+func makeCLDR() *CLDR {
+ return &CLDR{
+ parent: make(map[string][]string),
+ locale: make(map[string]*LDML),
+ resolved: make(map[string]*LDML),
+ bcp47: &LDMLBCP47{},
+ supp: &SupplementalData{},
+ }
+}
+
+// BCP47 returns the parsed BCP47 LDML data. If no such data was parsed, nil is returned.
+func (cldr *CLDR) BCP47() *LDMLBCP47 {
+ return nil
+}
+
+// Draft indicates the draft level of an element.
+type Draft int
+
+const (
+ Approved Draft = iota
+ Contributed
+ Provisional
+ Unconfirmed
+)
+
+var drafts = []string{"unconfirmed", "provisional", "contributed", "approved", ""}
+
+// ParseDraft returns the Draft value corresponding to the given string. The
+// empty string corresponds to Approved.
+func ParseDraft(level string) (Draft, error) {
+ if level == "" {
+ return Approved, nil
+ }
+ for i, s := range drafts {
+ if level == s {
+ return Unconfirmed - Draft(i), nil
+ }
+ }
+ return Approved, fmt.Errorf("cldr: unknown draft level %q", level)
+}
+
+func (d Draft) String() string {
+ return drafts[len(drafts)-1-int(d)]
+}
+
+// SetDraftLevel sets which draft levels to include in the evaluated LDML.
+// Any draft element for which the draft level is higher than lev will be excluded.
+// If multiple draft levels are available for a single element, the one with the
+// lowest draft level will be selected, unless preferDraft is true, in which case
+// the highest draft will be chosen.
+// It is assumed that the underlying LDML is canonicalized.
+func (cldr *CLDR) SetDraftLevel(lev Draft, preferDraft bool) {
+ // TODO: implement
+ cldr.resolved = make(map[string]*LDML)
+}
+
+// RawLDML returns the LDML XML for id in unresolved form.
+// id must be one of the strings returned by Locales.
+func (cldr *CLDR) RawLDML(loc string) *LDML {
+ return cldr.locale[loc]
+}
+
+// LDML returns the fully resolved LDML XML for loc, which must be one of
+// the strings returned by Locales.
+func (cldr *CLDR) LDML(loc string) (*LDML, error) {
+ return cldr.resolve(loc)
+}
+
+// Supplemental returns the parsed supplemental data. If no such data was parsed,
+// nil is returned.
+func (cldr *CLDR) Supplemental() *SupplementalData {
+ return cldr.supp
+}
+
+// Locales returns the locales for which there exist files.
+// Valid sublocales for which there is no file are not included.
+// The root locale is always sorted first.
+func (cldr *CLDR) Locales() []string {
+ loc := []string{"root"}
+ hasRoot := false
+ for l, _ := range cldr.locale {
+ if l == "root" {
+ hasRoot = true
+ continue
+ }
+ loc = append(loc, l)
+ }
+ sort.Strings(loc[1:])
+ if !hasRoot {
+ return loc[1:]
+ }
+ return loc
+}
+
+// Get fills in the fields of x based on the XPath path.
+func Get(e Elem, path string) (res Elem, err error) {
+ return walkXPath(e, path)
+}
diff --git a/vendor/golang.org/x/text/unicode/cldr/collate.go b/vendor/golang.org/x/text/unicode/cldr/collate.go
new file mode 100644
index 0000000..80ee28d
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/cldr/collate.go
@@ -0,0 +1,359 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cldr
+
+import (
+ "bufio"
+ "encoding/xml"
+ "errors"
+ "fmt"
+ "strconv"
+ "strings"
+ "unicode"
+ "unicode/utf8"
+)
+
+// RuleProcessor can be passed to Collator's Process method, which
+// parses the rules and calls the respective method for each rule found.
+type RuleProcessor interface {
+ Reset(anchor string, before int) error
+ Insert(level int, str, context, extend string) error
+ Index(id string)
+}
+
+const (
+ // cldrIndex is a Unicode-reserved sentinel value used to mark the start
+ // of a grouping within an index.
+ // We ignore any rule that starts with this rune.
+ // See http://unicode.org/reports/tr35/#Collation_Elements for details.
+ cldrIndex = "\uFDD0"
+
+ // specialAnchor is the format in which to represent logical reset positions,
+ // such as "first tertiary ignorable".
+ specialAnchor = "<%s/>"
+)
+
+// Process parses the rules for the tailorings of this collation
+// and calls the respective methods of p for each rule found.
+func (c Collation) Process(p RuleProcessor) (err error) {
+ if len(c.Cr) > 0 {
+ if len(c.Cr) > 1 {
+ return fmt.Errorf("multiple cr elements, want 0 or 1")
+ }
+ return processRules(p, c.Cr[0].Data())
+ }
+ if c.Rules.Any != nil {
+ return c.processXML(p)
+ }
+ return errors.New("no tailoring data")
+}
+
+// processRules parses rules in the Collation Rule Syntax defined in
+// http://www.unicode.org/reports/tr35/tr35-collation.html#Collation_Tailorings.
+func processRules(p RuleProcessor, s string) (err error) {
+ chk := func(s string, e error) string {
+ if err == nil {
+ err = e
+ }
+ return s
+ }
+ i := 0 // Save the line number for use after the loop.
+ scanner := bufio.NewScanner(strings.NewReader(s))
+ for ; scanner.Scan() && err == nil; i++ {
+ for s := skipSpace(scanner.Text()); s != "" && s[0] != '#'; s = skipSpace(s) {
+ level := 5
+ var ch byte
+ switch ch, s = s[0], s[1:]; ch {
+ case '&': // followed by <anchor> or '[' <key> ']'
+ if s = skipSpace(s); consume(&s, '[') {
+ s = chk(parseSpecialAnchor(p, s))
+ } else {
+ s = chk(parseAnchor(p, 0, s))
+ }
+ case '<': // sort relation '<'{1,4}, optionally followed by '*'.
+ for level = 1; consume(&s, '<'); level++ {
+ }
+ if level > 4 {
+ err = fmt.Errorf("level %d > 4", level)
+ }
+ fallthrough
+ case '=': // identity relation, optionally followed by *.
+ if consume(&s, '*') {
+ s = chk(parseSequence(p, level, s))
+ } else {
+ s = chk(parseOrder(p, level, s))
+ }
+ default:
+ chk("", fmt.Errorf("illegal operator %q", ch))
+ break
+ }
+ }
+ }
+ if chk("", scanner.Err()); err != nil {
+ return fmt.Errorf("%d: %v", i, err)
+ }
+ return nil
+}
+
+// parseSpecialAnchor parses the anchor syntax which is either of the form
+// ['before' <level>] <anchor>
+// or
+// [<label>]
+// The starting should already be consumed.
+func parseSpecialAnchor(p RuleProcessor, s string) (tail string, err error) {
+ i := strings.IndexByte(s, ']')
+ if i == -1 {
+ return "", errors.New("unmatched bracket")
+ }
+ a := strings.TrimSpace(s[:i])
+ s = s[i+1:]
+ if strings.HasPrefix(a, "before ") {
+ l, err := strconv.ParseUint(skipSpace(a[len("before "):]), 10, 3)
+ if err != nil {
+ return s, err
+ }
+ return parseAnchor(p, int(l), s)
+ }
+ return s, p.Reset(fmt.Sprintf(specialAnchor, a), 0)
+}
+
+func parseAnchor(p RuleProcessor, level int, s string) (tail string, err error) {
+ anchor, s, err := scanString(s)
+ if err != nil {
+ return s, err
+ }
+ return s, p.Reset(anchor, level)
+}
+
+func parseOrder(p RuleProcessor, level int, s string) (tail string, err error) {
+ var value, context, extend string
+ if value, s, err = scanString(s); err != nil {
+ return s, err
+ }
+ if strings.HasPrefix(value, cldrIndex) {
+ p.Index(value[len(cldrIndex):])
+ return
+ }
+ if consume(&s, '|') {
+ if context, s, err = scanString(s); err != nil {
+ return s, errors.New("missing string after context")
+ }
+ }
+ if consume(&s, '/') {
+ if extend, s, err = scanString(s); err != nil {
+ return s, errors.New("missing string after extension")
+ }
+ }
+ return s, p.Insert(level, value, context, extend)
+}
+
+// scanString scans a single input string.
+func scanString(s string) (str, tail string, err error) {
+ if s = skipSpace(s); s == "" {
+ return s, s, errors.New("missing string")
+ }
+ buf := [16]byte{} // small but enough to hold most cases.
+ value := buf[:0]
+ for s != "" {
+ if consume(&s, '\'') {
+ i := strings.IndexByte(s, '\'')
+ if i == -1 {
+ return "", "", errors.New(`unmatched single quote`)
+ }
+ if i == 0 {
+ value = append(value, '\'')
+ } else {
+ value = append(value, s[:i]...)
+ }
+ s = s[i+1:]
+ continue
+ }
+ r, sz := utf8.DecodeRuneInString(s)
+ if unicode.IsSpace(r) || strings.ContainsRune("&<=#", r) {
+ break
+ }
+ value = append(value, s[:sz]...)
+ s = s[sz:]
+ }
+ return string(value), skipSpace(s), nil
+}
+
+func parseSequence(p RuleProcessor, level int, s string) (tail string, err error) {
+ if s = skipSpace(s); s == "" {
+ return s, errors.New("empty sequence")
+ }
+ last := rune(0)
+ for s != "" {
+ r, sz := utf8.DecodeRuneInString(s)
+ s = s[sz:]
+
+ if r == '-' {
+ // We have a range. The first element was already written.
+ if last == 0 {
+ return s, errors.New("range without starter value")
+ }
+ r, sz = utf8.DecodeRuneInString(s)
+ s = s[sz:]
+ if r == utf8.RuneError || r < last {
+ return s, fmt.Errorf("invalid range %q-%q", last, r)
+ }
+ for i := last + 1; i <= r; i++ {
+ if err := p.Insert(level, string(i), "", ""); err != nil {
+ return s, err
+ }
+ }
+ last = 0
+ continue
+ }
+
+ if unicode.IsSpace(r) || unicode.IsPunct(r) {
+ break
+ }
+
+ // normal case
+ if err := p.Insert(level, string(r), "", ""); err != nil {
+ return s, err
+ }
+ last = r
+ }
+ return s, nil
+}
+
+func skipSpace(s string) string {
+ return strings.TrimLeftFunc(s, unicode.IsSpace)
+}
+
+// consumes returns whether the next byte is ch. If so, it gobbles it by
+// updating s.
+func consume(s *string, ch byte) (ok bool) {
+ if *s == "" || (*s)[0] != ch {
+ return false
+ }
+ *s = (*s)[1:]
+ return true
+}
+
+// The following code parses Collation rules of CLDR version 24 and before.
+
+var lmap = map[byte]int{
+ 'p': 1,
+ 's': 2,
+ 't': 3,
+ 'i': 5,
+}
+
+type rulesElem struct {
+ Rules struct {
+ Common
+ Any []*struct {
+ XMLName xml.Name
+ rule
+ } `xml:",any"`
+ } `xml:"rules"`
+}
+
+type rule struct {
+ Value string `xml:",chardata"`
+ Before string `xml:"before,attr"`
+ Any []*struct {
+ XMLName xml.Name
+ rule
+ } `xml:",any"`
+}
+
+var emptyValueError = errors.New("cldr: empty rule value")
+
+func (r *rule) value() (string, error) {
+ // Convert hexadecimal Unicode codepoint notation to a string.
+ s := charRe.ReplaceAllStringFunc(r.Value, replaceUnicode)
+ r.Value = s
+ if s == "" {
+ if len(r.Any) != 1 {
+ return "", emptyValueError
+ }
+ r.Value = fmt.Sprintf(specialAnchor, r.Any[0].XMLName.Local)
+ r.Any = nil
+ } else if len(r.Any) != 0 {
+ return "", fmt.Errorf("cldr: XML elements found in collation rule: %v", r.Any)
+ }
+ return r.Value, nil
+}
+
+func (r rule) process(p RuleProcessor, name, context, extend string) error {
+ v, err := r.value()
+ if err != nil {
+ return err
+ }
+ switch name {
+ case "p", "s", "t", "i":
+ if strings.HasPrefix(v, cldrIndex) {
+ p.Index(v[len(cldrIndex):])
+ return nil
+ }
+ if err := p.Insert(lmap[name[0]], v, context, extend); err != nil {
+ return err
+ }
+ case "pc", "sc", "tc", "ic":
+ level := lmap[name[0]]
+ for _, s := range v {
+ if err := p.Insert(level, string(s), context, extend); err != nil {
+ return err
+ }
+ }
+ default:
+ return fmt.Errorf("cldr: unsupported tag: %q", name)
+ }
+ return nil
+}
+
+// processXML parses the format of CLDR versions 24 and older.
+func (c Collation) processXML(p RuleProcessor) (err error) {
+ // Collation is generated and defined in xml.go.
+ var v string
+ for _, r := range c.Rules.Any {
+ switch r.XMLName.Local {
+ case "reset":
+ level := 0
+ switch r.Before {
+ case "primary", "1":
+ level = 1
+ case "secondary", "2":
+ level = 2
+ case "tertiary", "3":
+ level = 3
+ case "":
+ default:
+ return fmt.Errorf("cldr: unknown level %q", r.Before)
+ }
+ v, err = r.value()
+ if err == nil {
+ err = p.Reset(v, level)
+ }
+ case "x":
+ var context, extend string
+ for _, r1 := range r.Any {
+ v, err = r1.value()
+ switch r1.XMLName.Local {
+ case "context":
+ context = v
+ case "extend":
+ extend = v
+ }
+ }
+ for _, r1 := range r.Any {
+ if t := r1.XMLName.Local; t == "context" || t == "extend" {
+ continue
+ }
+ r1.rule.process(p, r1.XMLName.Local, context, extend)
+ }
+ default:
+ err = r.rule.process(p, r.XMLName.Local, "", "")
+ }
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/vendor/golang.org/x/text/unicode/cldr/decode.go b/vendor/golang.org/x/text/unicode/cldr/decode.go
new file mode 100644
index 0000000..094d431
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/cldr/decode.go
@@ -0,0 +1,171 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cldr
+
+import (
+ "archive/zip"
+ "bytes"
+ "encoding/xml"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+ "path/filepath"
+ "regexp"
+)
+
+// A Decoder loads an archive of CLDR data.
+type Decoder struct {
+ dirFilter []string
+ sectionFilter []string
+ loader Loader
+ cldr *CLDR
+ curLocale string
+}
+
+// SetSectionFilter takes a list top-level LDML element names to which
+// evaluation of LDML should be limited. It automatically calls SetDirFilter.
+func (d *Decoder) SetSectionFilter(filter ...string) {
+ d.sectionFilter = filter
+ // TODO: automatically set dir filter
+}
+
+// SetDirFilter limits the loading of LDML XML files of the specied directories.
+// Note that sections may be split across directories differently for different CLDR versions.
+// For more robust code, use SetSectionFilter.
+func (d *Decoder) SetDirFilter(dir ...string) {
+ d.dirFilter = dir
+}
+
+// A Loader provides access to the files of a CLDR archive.
+type Loader interface {
+ Len() int
+ Path(i int) string
+ Reader(i int) (io.ReadCloser, error)
+}
+
+var fileRe = regexp.MustCompile(`.*[/\\](.*)[/\\](.*)\.xml`)
+
+// Decode loads and decodes the files represented by l.
+func (d *Decoder) Decode(l Loader) (cldr *CLDR, err error) {
+ d.cldr = makeCLDR()
+ for i := 0; i < l.Len(); i++ {
+ fname := l.Path(i)
+ if m := fileRe.FindStringSubmatch(fname); m != nil {
+ if len(d.dirFilter) > 0 && !in(d.dirFilter, m[1]) {
+ continue
+ }
+ var r io.Reader
+ if r, err = l.Reader(i); err == nil {
+ err = d.decode(m[1], m[2], r)
+ }
+ if err != nil {
+ return nil, err
+ }
+ }
+ }
+ d.cldr.finalize(d.sectionFilter)
+ return d.cldr, nil
+}
+
+func (d *Decoder) decode(dir, id string, r io.Reader) error {
+ var v interface{}
+ var l *LDML
+ cldr := d.cldr
+ switch {
+ case dir == "supplemental":
+ v = cldr.supp
+ case dir == "transforms":
+ return nil
+ case dir == "bcp47":
+ v = cldr.bcp47
+ case dir == "validity":
+ return nil
+ default:
+ ok := false
+ if v, ok = cldr.locale[id]; !ok {
+ l = &LDML{}
+ v, cldr.locale[id] = l, l
+ }
+ }
+ x := xml.NewDecoder(r)
+ if err := x.Decode(v); err != nil {
+ log.Printf("%s/%s: %v", dir, id, err)
+ return err
+ }
+ if l != nil {
+ if l.Identity == nil {
+ return fmt.Errorf("%s/%s: missing identity element", dir, id)
+ }
+ // TODO: verify when CLDR bug http://unicode.org/cldr/trac/ticket/8970
+ // is resolved.
+ // path := strings.Split(id, "_")
+ // if lang := l.Identity.Language.Type; lang != path[0] {
+ // return fmt.Errorf("%s/%s: language was %s; want %s", dir, id, lang, path[0])
+ // }
+ }
+ return nil
+}
+
+type pathLoader []string
+
+func makePathLoader(path string) (pl pathLoader, err error) {
+ err = filepath.Walk(path, func(path string, _ os.FileInfo, err error) error {
+ pl = append(pl, path)
+ return err
+ })
+ return pl, err
+}
+
+func (pl pathLoader) Len() int {
+ return len(pl)
+}
+
+func (pl pathLoader) Path(i int) string {
+ return pl[i]
+}
+
+func (pl pathLoader) Reader(i int) (io.ReadCloser, error) {
+ return os.Open(pl[i])
+}
+
+// DecodePath loads CLDR data from the given path.
+func (d *Decoder) DecodePath(path string) (cldr *CLDR, err error) {
+ loader, err := makePathLoader(path)
+ if err != nil {
+ return nil, err
+ }
+ return d.Decode(loader)
+}
+
+type zipLoader struct {
+ r *zip.Reader
+}
+
+func (zl zipLoader) Len() int {
+ return len(zl.r.File)
+}
+
+func (zl zipLoader) Path(i int) string {
+ return zl.r.File[i].Name
+}
+
+func (zl zipLoader) Reader(i int) (io.ReadCloser, error) {
+ return zl.r.File[i].Open()
+}
+
+// DecodeZip loads CLDR data from the zip archive for which r is the source.
+func (d *Decoder) DecodeZip(r io.Reader) (cldr *CLDR, err error) {
+ buffer, err := ioutil.ReadAll(r)
+ if err != nil {
+ return nil, err
+ }
+ archive, err := zip.NewReader(bytes.NewReader(buffer), int64(len(buffer)))
+ if err != nil {
+ return nil, err
+ }
+ return d.Decode(zipLoader{archive})
+}
diff --git a/vendor/golang.org/x/text/unicode/cldr/makexml.go b/vendor/golang.org/x/text/unicode/cldr/makexml.go
new file mode 100644
index 0000000..6114d01
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/cldr/makexml.go
@@ -0,0 +1,400 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+// This tool generates types for the various XML formats of CLDR.
+package main
+
+import (
+ "archive/zip"
+ "bytes"
+ "encoding/xml"
+ "flag"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+ "regexp"
+ "strings"
+
+ "golang.org/x/text/internal/gen"
+)
+
+var outputFile = flag.String("output", "xml.go", "output file name")
+
+func main() {
+ flag.Parse()
+
+ r := gen.OpenCLDRCoreZip()
+ buffer, err := ioutil.ReadAll(r)
+ if err != nil {
+ log.Fatal("Could not read zip file")
+ }
+ r.Close()
+ z, err := zip.NewReader(bytes.NewReader(buffer), int64(len(buffer)))
+ if err != nil {
+ log.Fatalf("Could not read zip archive: %v", err)
+ }
+
+ var buf bytes.Buffer
+
+ version := gen.CLDRVersion()
+
+ for _, dtd := range files {
+ for _, f := range z.File {
+ if strings.HasSuffix(f.Name, dtd.file+".dtd") {
+ r, err := f.Open()
+ failOnError(err)
+
+ b := makeBuilder(&buf, dtd)
+ b.parseDTD(r)
+ b.resolve(b.index[dtd.top[0]])
+ b.write()
+ if b.version != "" && version != b.version {
+ println(f.Name)
+ log.Fatalf("main: inconsistent versions: found %s; want %s", b.version, version)
+ }
+ break
+ }
+ }
+ }
+ fmt.Fprintln(&buf, "// Version is the version of CLDR from which the XML definitions are generated.")
+ fmt.Fprintf(&buf, "const Version = %q\n", version)
+
+ gen.WriteGoFile(*outputFile, "cldr", buf.Bytes())
+}
+
+func failOnError(err error) {
+ if err != nil {
+ log.New(os.Stderr, "", log.Lshortfile).Output(2, err.Error())
+ os.Exit(1)
+ }
+}
+
+// configuration data per DTD type
+type dtd struct {
+ file string // base file name
+ root string // Go name of the root XML element
+ top []string // create a different type for this section
+
+ skipElem []string // hard-coded or deprecated elements
+ skipAttr []string // attributes to exclude
+ predefined []string // hard-coded elements exist of the form <name>Elem
+ forceRepeat []string // elements to make slices despite DTD
+}
+
+var files = []dtd{
+ {
+ file: "ldmlBCP47",
+ root: "LDMLBCP47",
+ top: []string{"ldmlBCP47"},
+ skipElem: []string{
+ "cldrVersion", // deprecated, not used
+ },
+ },
+ {
+ file: "ldmlSupplemental",
+ root: "SupplementalData",
+ top: []string{"supplementalData"},
+ skipElem: []string{
+ "cldrVersion", // deprecated, not used
+ },
+ forceRepeat: []string{
+ "plurals", // data defined in plurals.xml and ordinals.xml
+ },
+ },
+ {
+ file: "ldml",
+ root: "LDML",
+ top: []string{
+ "ldml", "collation", "calendar", "timeZoneNames", "localeDisplayNames", "numbers",
+ },
+ skipElem: []string{
+ "cp", // not used anywhere
+ "special", // not used anywhere
+ "fallback", // deprecated, not used
+ "alias", // in Common
+ "default", // in Common
+ },
+ skipAttr: []string{
+ "hiraganaQuarternary", // typo in DTD, correct version included as well
+ },
+ predefined: []string{"rules"},
+ },
+}
+
+var comments = map[string]string{
+ "ldmlBCP47": `
+// LDMLBCP47 holds information on allowable values for various variables in LDML.
+`,
+ "supplementalData": `
+// SupplementalData holds information relevant for internationalization
+// and proper use of CLDR, but that is not contained in the locale hierarchy.
+`,
+ "ldml": `
+// LDML is the top-level type for locale-specific data.
+`,
+ "collation": `
+// Collation contains rules that specify a certain sort-order,
+// as a tailoring of the root order.
+// The parsed rules are obtained by passing a RuleProcessor to Collation's
+// Process method.
+`,
+ "calendar": `
+// Calendar specifies the fields used for formatting and parsing dates and times.
+// The month and quarter names are identified numerically, starting at 1.
+// The day (of the week) names are identified with short strings, since there is
+// no universally-accepted numeric designation.
+`,
+ "dates": `
+// Dates contains information regarding the format and parsing of dates and times.
+`,
+ "localeDisplayNames": `
+// LocaleDisplayNames specifies localized display names for for scripts, languages,
+// countries, currencies, and variants.
+`,
+ "numbers": `
+// Numbers supplies information for formatting and parsing numbers and currencies.
+`,
+}
+
+type element struct {
+ name string // XML element name
+ category string // elements contained by this element
+ signature string // category + attrKey*
+
+ attr []*attribute // attributes supported by this element.
+ sub []struct { // parsed and evaluated sub elements of this element.
+ e *element
+ repeat bool // true if the element needs to be a slice
+ }
+
+ resolved bool // prevent multiple resolutions of this element.
+}
+
+type attribute struct {
+ name string
+ key string
+ list []string
+
+ tag string // Go tag
+}
+
+var (
+ reHead = regexp.MustCompile(` *(\w+) +([\w\-]+)`)
+ reAttr = regexp.MustCompile(` *(\w+) *(?:(\w+)|\(([\w\- \|]+)\)) *(?:#([A-Z]*) *(?:\"([\.\d+])\")?)? *("[\w\-:]*")?`)
+ reElem = regexp.MustCompile(`^ *(EMPTY|ANY|\(.*\)[\*\+\?]?) *$`)
+ reToken = regexp.MustCompile(`\w\-`)
+)
+
+// builder is used to read in the DTD files from CLDR and generate Go code
+// to be used with the encoding/xml package.
+type builder struct {
+ w io.Writer
+ index map[string]*element
+ elem []*element
+ info dtd
+ version string
+}
+
+func makeBuilder(w io.Writer, d dtd) builder {
+ return builder{
+ w: w,
+ index: make(map[string]*element),
+ elem: []*element{},
+ info: d,
+ }
+}
+
+// parseDTD parses a DTD file.
+func (b *builder) parseDTD(r io.Reader) {
+ for d := xml.NewDecoder(r); ; {
+ t, err := d.Token()
+ if t == nil {
+ break
+ }
+ failOnError(err)
+ dir, ok := t.(xml.Directive)
+ if !ok {
+ continue
+ }
+ m := reHead.FindSubmatch(dir)
+ dir = dir[len(m[0]):]
+ ename := string(m[2])
+ el, elementFound := b.index[ename]
+ switch string(m[1]) {
+ case "ELEMENT":
+ if elementFound {
+ log.Fatal("parseDTD: duplicate entry for element %q", ename)
+ }
+ m := reElem.FindSubmatch(dir)
+ if m == nil {
+ log.Fatalf("parseDTD: invalid element %q", string(dir))
+ }
+ if len(m[0]) != len(dir) {
+ log.Fatal("parseDTD: invalid element %q", string(dir), len(dir), len(m[0]), string(m[0]))
+ }
+ s := string(m[1])
+ el = &element{
+ name: ename,
+ category: s,
+ }
+ b.index[ename] = el
+ case "ATTLIST":
+ if !elementFound {
+ log.Fatalf("parseDTD: unknown element %q", ename)
+ }
+ s := string(dir)
+ m := reAttr.FindStringSubmatch(s)
+ if m == nil {
+ log.Fatal(fmt.Errorf("parseDTD: invalid attribute %q", string(dir)))
+ }
+ if m[4] == "FIXED" {
+ b.version = m[5]
+ } else {
+ switch m[1] {
+ case "draft", "references", "alt", "validSubLocales", "standard" /* in Common */ :
+ case "type", "choice":
+ default:
+ el.attr = append(el.attr, &attribute{
+ name: m[1],
+ key: s,
+ list: reToken.FindAllString(m[3], -1),
+ })
+ el.signature = fmt.Sprintf("%s=%s+%s", el.signature, m[1], m[2])
+ }
+ }
+ }
+ }
+}
+
+var reCat = regexp.MustCompile(`[ ,\|]*(?:(\(|\)|\#?[\w_-]+)([\*\+\?]?))?`)
+
+// resolve takes a parsed element and converts it into structured data
+// that can be used to generate the XML code.
+func (b *builder) resolve(e *element) {
+ if e.resolved {
+ return
+ }
+ b.elem = append(b.elem, e)
+ e.resolved = true
+ s := e.category
+ found := make(map[string]bool)
+ sequenceStart := []int{}
+ for len(s) > 0 {
+ m := reCat.FindStringSubmatch(s)
+ if m == nil {
+ log.Fatalf("%s: invalid category string %q", e.name, s)
+ }
+ repeat := m[2] == "*" || m[2] == "+" || in(b.info.forceRepeat, m[1])
+ switch m[1] {
+ case "":
+ case "(":
+ sequenceStart = append(sequenceStart, len(e.sub))
+ case ")":
+ if len(sequenceStart) == 0 {
+ log.Fatalf("%s: unmatched closing parenthesis", e.name)
+ }
+ for i := sequenceStart[len(sequenceStart)-1]; i < len(e.sub); i++ {
+ e.sub[i].repeat = e.sub[i].repeat || repeat
+ }
+ sequenceStart = sequenceStart[:len(sequenceStart)-1]
+ default:
+ if in(b.info.skipElem, m[1]) {
+ } else if sub, ok := b.index[m[1]]; ok {
+ if !found[sub.name] {
+ e.sub = append(e.sub, struct {
+ e *element
+ repeat bool
+ }{sub, repeat})
+ found[sub.name] = true
+ b.resolve(sub)
+ }
+ } else if m[1] == "#PCDATA" || m[1] == "ANY" {
+ } else if m[1] != "EMPTY" {
+ log.Fatalf("resolve:%s: element %q not found", e.name, m[1])
+ }
+ }
+ s = s[len(m[0]):]
+ }
+}
+
+// return true if s is contained in set.
+func in(set []string, s string) bool {
+ for _, v := range set {
+ if v == s {
+ return true
+ }
+ }
+ return false
+}
+
+var repl = strings.NewReplacer("-", " ", "_", " ")
+
+// title puts the first character or each character following '_' in title case and
+// removes all occurrences of '_'.
+func title(s string) string {
+ return strings.Replace(strings.Title(repl.Replace(s)), " ", "", -1)
+}
+
+// writeElem generates Go code for a single element, recursively.
+func (b *builder) writeElem(tab int, e *element) {
+ p := func(f string, x ...interface{}) {
+ f = strings.Replace(f, "\n", "\n"+strings.Repeat("\t", tab), -1)
+ fmt.Fprintf(b.w, f, x...)
+ }
+ if len(e.sub) == 0 && len(e.attr) == 0 {
+ p("Common")
+ return
+ }
+ p("struct {")
+ tab++
+ p("\nCommon")
+ for _, attr := range e.attr {
+ if !in(b.info.skipAttr, attr.name) {
+ p("\n%s string `xml:\"%s,attr\"`", title(attr.name), attr.name)
+ }
+ }
+ for _, sub := range e.sub {
+ if in(b.info.predefined, sub.e.name) {
+ p("\n%sElem", sub.e.name)
+ continue
+ }
+ if in(b.info.skipElem, sub.e.name) {
+ continue
+ }
+ p("\n%s ", title(sub.e.name))
+ if sub.repeat {
+ p("[]")
+ }
+ p("*")
+ if in(b.info.top, sub.e.name) {
+ p(title(sub.e.name))
+ } else {
+ b.writeElem(tab, sub.e)
+ }
+ p(" `xml:\"%s\"`", sub.e.name)
+ }
+ tab--
+ p("\n}")
+}
+
+// write generates the Go XML code.
+func (b *builder) write() {
+ for i, name := range b.info.top {
+ e := b.index[name]
+ if e != nil {
+ fmt.Fprintf(b.w, comments[name])
+ name := title(e.name)
+ if i == 0 {
+ name = b.info.root
+ }
+ fmt.Fprintf(b.w, "type %s ", name)
+ b.writeElem(0, e)
+ fmt.Fprint(b.w, "\n")
+ }
+ }
+}
diff --git a/vendor/golang.org/x/text/unicode/cldr/resolve.go b/vendor/golang.org/x/text/unicode/cldr/resolve.go
new file mode 100644
index 0000000..691b590
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/cldr/resolve.go
@@ -0,0 +1,602 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cldr
+
+// This file implements the various inheritance constructs defined by LDML.
+// See http://www.unicode.org/reports/tr35/#Inheritance_and_Validity
+// for more details.
+
+import (
+ "fmt"
+ "log"
+ "reflect"
+ "regexp"
+ "sort"
+ "strings"
+)
+
+// fieldIter iterates over fields in a struct. It includes
+// fields of embedded structs.
+type fieldIter struct {
+ v reflect.Value
+ index, n []int
+}
+
+func iter(v reflect.Value) fieldIter {
+ if v.Kind() != reflect.Struct {
+ log.Panicf("value %v must be a struct", v)
+ }
+ i := fieldIter{
+ v: v,
+ index: []int{0},
+ n: []int{v.NumField()},
+ }
+ i.descent()
+ return i
+}
+
+func (i *fieldIter) descent() {
+ for f := i.field(); f.Anonymous && f.Type.NumField() > 0; f = i.field() {
+ i.index = append(i.index, 0)
+ i.n = append(i.n, f.Type.NumField())
+ }
+}
+
+func (i *fieldIter) done() bool {
+ return len(i.index) == 1 && i.index[0] >= i.n[0]
+}
+
+func skip(f reflect.StructField) bool {
+ return !f.Anonymous && (f.Name[0] < 'A' || f.Name[0] > 'Z')
+}
+
+func (i *fieldIter) next() {
+ for {
+ k := len(i.index) - 1
+ i.index[k]++
+ if i.index[k] < i.n[k] {
+ if !skip(i.field()) {
+ break
+ }
+ } else {
+ if k == 0 {
+ return
+ }
+ i.index = i.index[:k]
+ i.n = i.n[:k]
+ }
+ }
+ i.descent()
+}
+
+func (i *fieldIter) value() reflect.Value {
+ return i.v.FieldByIndex(i.index)
+}
+
+func (i *fieldIter) field() reflect.StructField {
+ return i.v.Type().FieldByIndex(i.index)
+}
+
+type visitor func(v reflect.Value) error
+
+var stopDescent = fmt.Errorf("do not recurse")
+
+func (f visitor) visit(x interface{}) error {
+ return f.visitRec(reflect.ValueOf(x))
+}
+
+// visit recursively calls f on all nodes in v.
+func (f visitor) visitRec(v reflect.Value) error {
+ if v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ return nil
+ }
+ return f.visitRec(v.Elem())
+ }
+ if err := f(v); err != nil {
+ if err == stopDescent {
+ return nil
+ }
+ return err
+ }
+ switch v.Kind() {
+ case reflect.Struct:
+ for i := iter(v); !i.done(); i.next() {
+ if err := f.visitRec(i.value()); err != nil {
+ return err
+ }
+ }
+ case reflect.Slice:
+ for i := 0; i < v.Len(); i++ {
+ if err := f.visitRec(v.Index(i)); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+// getPath is used for error reporting purposes only.
+func getPath(e Elem) string {
+ if e == nil {
+ return "<nil>"
+ }
+ if e.enclosing() == nil {
+ return e.GetCommon().name
+ }
+ if e.GetCommon().Type == "" {
+ return fmt.Sprintf("%s.%s", getPath(e.enclosing()), e.GetCommon().name)
+ }
+ return fmt.Sprintf("%s.%s[type=%s]", getPath(e.enclosing()), e.GetCommon().name, e.GetCommon().Type)
+}
+
+// xmlName returns the xml name of the element or attribute
+func xmlName(f reflect.StructField) (name string, attr bool) {
+ tags := strings.Split(f.Tag.Get("xml"), ",")
+ for _, s := range tags {
+ attr = attr || s == "attr"
+ }
+ return tags[0], attr
+}
+
+func findField(v reflect.Value, key string) (reflect.Value, error) {
+ v = reflect.Indirect(v)
+ for i := iter(v); !i.done(); i.next() {
+ if n, _ := xmlName(i.field()); n == key {
+ return i.value(), nil
+ }
+ }
+ return reflect.Value{}, fmt.Errorf("cldr: no field %q in element %#v", key, v.Interface())
+}
+
+var xpathPart = regexp.MustCompile(`(\pL+)(?:\[@(\pL+)='([\w-]+)'\])?`)
+
+func walkXPath(e Elem, path string) (res Elem, err error) {
+ for _, c := range strings.Split(path, "/") {
+ if c == ".." {
+ if e = e.enclosing(); e == nil {
+ panic("path ..")
+ return nil, fmt.Errorf(`cldr: ".." moves past root in path %q`, path)
+ }
+ continue
+ } else if c == "" {
+ continue
+ }
+ m := xpathPart.FindStringSubmatch(c)
+ if len(m) == 0 || len(m[0]) != len(c) {
+ return nil, fmt.Errorf("cldr: syntax error in path component %q", c)
+ }
+ v, err := findField(reflect.ValueOf(e), m[1])
+ if err != nil {
+ return nil, err
+ }
+ switch v.Kind() {
+ case reflect.Slice:
+ i := 0
+ if m[2] != "" || v.Len() > 1 {
+ if m[2] == "" {
+ m[2] = "type"
+ if m[3] = e.GetCommon().Default(); m[3] == "" {
+ return nil, fmt.Errorf("cldr: type selector or default value needed for element %s", m[1])
+ }
+ }
+ for ; i < v.Len(); i++ {
+ vi := v.Index(i)
+ key, err := findField(vi.Elem(), m[2])
+ if err != nil {
+ return nil, err
+ }
+ key = reflect.Indirect(key)
+ if key.Kind() == reflect.String && key.String() == m[3] {
+ break
+ }
+ }
+ }
+ if i == v.Len() || v.Index(i).IsNil() {
+ return nil, fmt.Errorf("no %s found with %s==%s", m[1], m[2], m[3])
+ }
+ e = v.Index(i).Interface().(Elem)
+ case reflect.Ptr:
+ if v.IsNil() {
+ return nil, fmt.Errorf("cldr: element %q not found within element %q", m[1], e.GetCommon().name)
+ }
+ var ok bool
+ if e, ok = v.Interface().(Elem); !ok {
+ return nil, fmt.Errorf("cldr: %q is not an XML element", m[1])
+ } else if m[2] != "" || m[3] != "" {
+ return nil, fmt.Errorf("cldr: no type selector allowed for element %s", m[1])
+ }
+ default:
+ return nil, fmt.Errorf("cldr: %q is not an XML element", m[1])
+ }
+ }
+ return e, nil
+}
+
+const absPrefix = "//ldml/"
+
+func (cldr *CLDR) resolveAlias(e Elem, src, path string) (res Elem, err error) {
+ if src != "locale" {
+ if !strings.HasPrefix(path, absPrefix) {
+ return nil, fmt.Errorf("cldr: expected absolute path, found %q", path)
+ }
+ path = path[len(absPrefix):]
+ if e, err = cldr.resolve(src); err != nil {
+ return nil, err
+ }
+ }
+ return walkXPath(e, path)
+}
+
+func (cldr *CLDR) resolveAndMergeAlias(e Elem) error {
+ alias := e.GetCommon().Alias
+ if alias == nil {
+ return nil
+ }
+ a, err := cldr.resolveAlias(e, alias.Source, alias.Path)
+ if err != nil {
+ return fmt.Errorf("%v: error evaluating path %q: %v", getPath(e), alias.Path, err)
+ }
+ // Ensure alias node was already evaluated. TODO: avoid double evaluation.
+ err = cldr.resolveAndMergeAlias(a)
+ v := reflect.ValueOf(e).Elem()
+ for i := iter(reflect.ValueOf(a).Elem()); !i.done(); i.next() {
+ if vv := i.value(); vv.Kind() != reflect.Ptr || !vv.IsNil() {
+ if _, attr := xmlName(i.field()); !attr {
+ v.FieldByIndex(i.index).Set(vv)
+ }
+ }
+ }
+ return err
+}
+
+func (cldr *CLDR) aliasResolver() visitor {
+ return func(v reflect.Value) (err error) {
+ if e, ok := v.Addr().Interface().(Elem); ok {
+ err = cldr.resolveAndMergeAlias(e)
+ if err == nil && blocking[e.GetCommon().name] {
+ return stopDescent
+ }
+ }
+ return err
+ }
+}
+
+// elements within blocking elements do not inherit.
+// Taken from CLDR's supplementalMetaData.xml.
+var blocking = map[string]bool{
+ "identity": true,
+ "supplementalData": true,
+ "cldrTest": true,
+ "collation": true,
+ "transform": true,
+}
+
+// Distinguishing attributes affect inheritance; two elements with different
+// distinguishing attributes are treated as different for purposes of inheritance,
+// except when such attributes occur in the indicated elements.
+// Taken from CLDR's supplementalMetaData.xml.
+var distinguishing = map[string][]string{
+ "key": nil,
+ "request_id": nil,
+ "id": nil,
+ "registry": nil,
+ "alt": nil,
+ "iso4217": nil,
+ "iso3166": nil,
+ "mzone": nil,
+ "from": nil,
+ "to": nil,
+ "type": []string{
+ "abbreviationFallback",
+ "default",
+ "mapping",
+ "measurementSystem",
+ "preferenceOrdering",
+ },
+ "numberSystem": nil,
+}
+
+func in(set []string, s string) bool {
+ for _, v := range set {
+ if v == s {
+ return true
+ }
+ }
+ return false
+}
+
+// attrKey computes a key based on the distinguishable attributes of
+// an element and it's values.
+func attrKey(v reflect.Value, exclude ...string) string {
+ parts := []string{}
+ ename := v.Interface().(Elem).GetCommon().name
+ v = v.Elem()
+ for i := iter(v); !i.done(); i.next() {
+ if name, attr := xmlName(i.field()); attr {
+ if except, ok := distinguishing[name]; ok && !in(exclude, name) && !in(except, ename) {
+ v := i.value()
+ if v.Kind() == reflect.Ptr {
+ v = v.Elem()
+ }
+ if v.IsValid() {
+ parts = append(parts, fmt.Sprintf("%s=%s", name, v.String()))
+ }
+ }
+ }
+ }
+ sort.Strings(parts)
+ return strings.Join(parts, ";")
+}
+
+// Key returns a key for e derived from all distinguishing attributes
+// except those specified by exclude.
+func Key(e Elem, exclude ...string) string {
+ return attrKey(reflect.ValueOf(e), exclude...)
+}
+
+// linkEnclosing sets the enclosing element as well as the name
+// for all sub-elements of child, recursively.
+func linkEnclosing(parent, child Elem) {
+ child.setEnclosing(parent)
+ v := reflect.ValueOf(child).Elem()
+ for i := iter(v); !i.done(); i.next() {
+ vf := i.value()
+ if vf.Kind() == reflect.Slice {
+ for j := 0; j < vf.Len(); j++ {
+ linkEnclosing(child, vf.Index(j).Interface().(Elem))
+ }
+ } else if vf.Kind() == reflect.Ptr && !vf.IsNil() && vf.Elem().Kind() == reflect.Struct {
+ linkEnclosing(child, vf.Interface().(Elem))
+ }
+ }
+}
+
+func setNames(e Elem, name string) {
+ e.setName(name)
+ v := reflect.ValueOf(e).Elem()
+ for i := iter(v); !i.done(); i.next() {
+ vf := i.value()
+ name, _ = xmlName(i.field())
+ if vf.Kind() == reflect.Slice {
+ for j := 0; j < vf.Len(); j++ {
+ setNames(vf.Index(j).Interface().(Elem), name)
+ }
+ } else if vf.Kind() == reflect.Ptr && !vf.IsNil() && vf.Elem().Kind() == reflect.Struct {
+ setNames(vf.Interface().(Elem), name)
+ }
+ }
+}
+
+// deepCopy copies elements of v recursively. All elements of v that may
+// be modified by inheritance are explicitly copied.
+func deepCopy(v reflect.Value) reflect.Value {
+ switch v.Kind() {
+ case reflect.Ptr:
+ if v.IsNil() || v.Elem().Kind() != reflect.Struct {
+ return v
+ }
+ nv := reflect.New(v.Elem().Type())
+ nv.Elem().Set(v.Elem())
+ deepCopyRec(nv.Elem(), v.Elem())
+ return nv
+ case reflect.Slice:
+ nv := reflect.MakeSlice(v.Type(), v.Len(), v.Len())
+ for i := 0; i < v.Len(); i++ {
+ deepCopyRec(nv.Index(i), v.Index(i))
+ }
+ return nv
+ }
+ panic("deepCopy: must be called with pointer or slice")
+}
+
+// deepCopyRec is only called by deepCopy.
+func deepCopyRec(nv, v reflect.Value) {
+ if v.Kind() == reflect.Struct {
+ t := v.Type()
+ for i := 0; i < v.NumField(); i++ {
+ if name, attr := xmlName(t.Field(i)); name != "" && !attr {
+ deepCopyRec(nv.Field(i), v.Field(i))
+ }
+ }
+ } else {
+ nv.Set(deepCopy(v))
+ }
+}
+
+// newNode is used to insert a missing node during inheritance.
+func (cldr *CLDR) newNode(v, enc reflect.Value) reflect.Value {
+ n := reflect.New(v.Type())
+ for i := iter(v); !i.done(); i.next() {
+ if name, attr := xmlName(i.field()); name == "" || attr {
+ n.Elem().FieldByIndex(i.index).Set(i.value())
+ }
+ }
+ n.Interface().(Elem).GetCommon().setEnclosing(enc.Addr().Interface().(Elem))
+ return n
+}
+
+// v, parent must be pointers to struct
+func (cldr *CLDR) inheritFields(v, parent reflect.Value) (res reflect.Value, err error) {
+ t := v.Type()
+ nv := reflect.New(t)
+ nv.Elem().Set(v)
+ for i := iter(v); !i.done(); i.next() {
+ vf := i.value()
+ f := i.field()
+ name, attr := xmlName(f)
+ if name == "" || attr {
+ continue
+ }
+ pf := parent.FieldByIndex(i.index)
+ if blocking[name] {
+ if vf.IsNil() {
+ vf = pf
+ }
+ nv.Elem().FieldByIndex(i.index).Set(deepCopy(vf))
+ continue
+ }
+ switch f.Type.Kind() {
+ case reflect.Ptr:
+ if f.Type.Elem().Kind() == reflect.Struct {
+ if !vf.IsNil() {
+ if vf, err = cldr.inheritStructPtr(vf, pf); err != nil {
+ return reflect.Value{}, err
+ }
+ vf.Interface().(Elem).setEnclosing(nv.Interface().(Elem))
+ nv.Elem().FieldByIndex(i.index).Set(vf)
+ } else if !pf.IsNil() {
+ n := cldr.newNode(pf.Elem(), v)
+ if vf, err = cldr.inheritStructPtr(n, pf); err != nil {
+ return reflect.Value{}, err
+ }
+ vf.Interface().(Elem).setEnclosing(nv.Interface().(Elem))
+ nv.Elem().FieldByIndex(i.index).Set(vf)
+ }
+ }
+ case reflect.Slice:
+ vf, err := cldr.inheritSlice(nv.Elem(), vf, pf)
+ if err != nil {
+ return reflect.Zero(t), err
+ }
+ nv.Elem().FieldByIndex(i.index).Set(vf)
+ }
+ }
+ return nv, nil
+}
+
+func root(e Elem) *LDML {
+ for ; e.enclosing() != nil; e = e.enclosing() {
+ }
+ return e.(*LDML)
+}
+
+// inheritStructPtr first merges possible aliases in with v and then inherits
+// any underspecified elements from parent.
+func (cldr *CLDR) inheritStructPtr(v, parent reflect.Value) (r reflect.Value, err error) {
+ if !v.IsNil() {
+ e := v.Interface().(Elem).GetCommon()
+ alias := e.Alias
+ if alias == nil && !parent.IsNil() {
+ alias = parent.Interface().(Elem).GetCommon().Alias
+ }
+ if alias != nil {
+ a, err := cldr.resolveAlias(v.Interface().(Elem), alias.Source, alias.Path)
+ if a != nil {
+ if v, err = cldr.inheritFields(v.Elem(), reflect.ValueOf(a).Elem()); err != nil {
+ return reflect.Value{}, err
+ }
+ }
+ }
+ if !parent.IsNil() {
+ return cldr.inheritFields(v.Elem(), parent.Elem())
+ }
+ } else if parent.IsNil() {
+ panic("should not reach here")
+ }
+ return v, nil
+}
+
+// Must be slice of struct pointers.
+func (cldr *CLDR) inheritSlice(enc, v, parent reflect.Value) (res reflect.Value, err error) {
+ t := v.Type()
+ index := make(map[string]reflect.Value)
+ if !v.IsNil() {
+ for i := 0; i < v.Len(); i++ {
+ vi := v.Index(i)
+ key := attrKey(vi)
+ index[key] = vi
+ }
+ }
+ if !parent.IsNil() {
+ for i := 0; i < parent.Len(); i++ {
+ vi := parent.Index(i)
+ key := attrKey(vi)
+ if w, ok := index[key]; ok {
+ index[key], err = cldr.inheritStructPtr(w, vi)
+ } else {
+ n := cldr.newNode(vi.Elem(), enc)
+ index[key], err = cldr.inheritStructPtr(n, vi)
+ }
+ index[key].Interface().(Elem).setEnclosing(enc.Addr().Interface().(Elem))
+ if err != nil {
+ return v, err
+ }
+ }
+ }
+ keys := make([]string, 0, len(index))
+ for k, _ := range index {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+ sl := reflect.MakeSlice(t, len(index), len(index))
+ for i, k := range keys {
+ sl.Index(i).Set(index[k])
+ }
+ return sl, nil
+}
+
+func parentLocale(loc string) string {
+ parts := strings.Split(loc, "_")
+ if len(parts) == 1 {
+ return "root"
+ }
+ parts = parts[:len(parts)-1]
+ key := strings.Join(parts, "_")
+ return key
+}
+
+func (cldr *CLDR) resolve(loc string) (res *LDML, err error) {
+ if r := cldr.resolved[loc]; r != nil {
+ return r, nil
+ }
+ x := cldr.RawLDML(loc)
+ if x == nil {
+ return nil, fmt.Errorf("cldr: unknown locale %q", loc)
+ }
+ var v reflect.Value
+ if loc == "root" {
+ x = deepCopy(reflect.ValueOf(x)).Interface().(*LDML)
+ linkEnclosing(nil, x)
+ err = cldr.aliasResolver().visit(x)
+ } else {
+ key := parentLocale(loc)
+ var parent *LDML
+ for ; cldr.locale[key] == nil; key = parentLocale(key) {
+ }
+ if parent, err = cldr.resolve(key); err != nil {
+ return nil, err
+ }
+ v, err = cldr.inheritFields(reflect.ValueOf(x).Elem(), reflect.ValueOf(parent).Elem())
+ x = v.Interface().(*LDML)
+ linkEnclosing(nil, x)
+ }
+ if err != nil {
+ return nil, err
+ }
+ cldr.resolved[loc] = x
+ return x, err
+}
+
+// finalize finalizes the initialization of the raw LDML structs. It also
+// removed unwanted fields, as specified by filter, so that they will not
+// be unnecessarily evaluated.
+func (cldr *CLDR) finalize(filter []string) {
+ for _, x := range cldr.locale {
+ if filter != nil {
+ v := reflect.ValueOf(x).Elem()
+ t := v.Type()
+ for i := 0; i < v.NumField(); i++ {
+ f := t.Field(i)
+ name, _ := xmlName(f)
+ if name != "" && name != "identity" && !in(filter, name) {
+ v.Field(i).Set(reflect.Zero(f.Type))
+ }
+ }
+ }
+ linkEnclosing(nil, x) // for resolving aliases and paths
+ setNames(x, "ldml")
+ }
+}
diff --git a/vendor/golang.org/x/text/unicode/cldr/slice.go b/vendor/golang.org/x/text/unicode/cldr/slice.go
new file mode 100644
index 0000000..388c983
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/cldr/slice.go
@@ -0,0 +1,144 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cldr
+
+import (
+ "fmt"
+ "reflect"
+ "sort"
+)
+
+// Slice provides utilities for modifying slices of elements.
+// It can be wrapped around any slice of which the element type implements
+// interface Elem.
+type Slice struct {
+ ptr reflect.Value
+ typ reflect.Type
+}
+
+// Value returns the reflect.Value of the underlying slice.
+func (s *Slice) Value() reflect.Value {
+ return s.ptr.Elem()
+}
+
+// MakeSlice wraps a pointer to a slice of Elems.
+// It replaces the array pointed to by the slice so that subsequent modifications
+// do not alter the data in a CLDR type.
+// It panics if an incorrect type is passed.
+func MakeSlice(slicePtr interface{}) Slice {
+ ptr := reflect.ValueOf(slicePtr)
+ if ptr.Kind() != reflect.Ptr {
+ panic(fmt.Sprintf("MakeSlice: argument must be pointer to slice, found %v", ptr.Type()))
+ }
+ sl := ptr.Elem()
+ if sl.Kind() != reflect.Slice {
+ panic(fmt.Sprintf("MakeSlice: argument must point to a slice, found %v", sl.Type()))
+ }
+ intf := reflect.TypeOf((*Elem)(nil)).Elem()
+ if !sl.Type().Elem().Implements(intf) {
+ panic(fmt.Sprintf("MakeSlice: element type of slice (%v) does not implement Elem", sl.Type().Elem()))
+ }
+ nsl := reflect.MakeSlice(sl.Type(), sl.Len(), sl.Len())
+ reflect.Copy(nsl, sl)
+ sl.Set(nsl)
+ return Slice{
+ ptr: ptr,
+ typ: sl.Type().Elem().Elem(),
+ }
+}
+
+func (s Slice) indexForAttr(a string) []int {
+ for i := iter(reflect.Zero(s.typ)); !i.done(); i.next() {
+ if n, _ := xmlName(i.field()); n == a {
+ return i.index
+ }
+ }
+ panic(fmt.Sprintf("MakeSlice: no attribute %q for type %v", a, s.typ))
+}
+
+// Filter filters s to only include elements for which fn returns true.
+func (s Slice) Filter(fn func(e Elem) bool) {
+ k := 0
+ sl := s.Value()
+ for i := 0; i < sl.Len(); i++ {
+ vi := sl.Index(i)
+ if fn(vi.Interface().(Elem)) {
+ sl.Index(k).Set(vi)
+ k++
+ }
+ }
+ sl.Set(sl.Slice(0, k))
+}
+
+// Group finds elements in s for which fn returns the same value and groups
+// them in a new Slice.
+func (s Slice) Group(fn func(e Elem) string) []Slice {
+ m := make(map[string][]reflect.Value)
+ sl := s.Value()
+ for i := 0; i < sl.Len(); i++ {
+ vi := sl.Index(i)
+ key := fn(vi.Interface().(Elem))
+ m[key] = append(m[key], vi)
+ }
+ keys := []string{}
+ for k, _ := range m {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+ res := []Slice{}
+ for _, k := range keys {
+ nsl := reflect.New(sl.Type())
+ nsl.Elem().Set(reflect.Append(nsl.Elem(), m[k]...))
+ res = append(res, MakeSlice(nsl.Interface()))
+ }
+ return res
+}
+
+// SelectAnyOf filters s to contain only elements for which attr matches
+// any of the values.
+func (s Slice) SelectAnyOf(attr string, values ...string) {
+ index := s.indexForAttr(attr)
+ s.Filter(func(e Elem) bool {
+ vf := reflect.ValueOf(e).Elem().FieldByIndex(index)
+ return in(values, vf.String())
+ })
+}
+
+// SelectOnePerGroup filters s to include at most one element e per group of
+// elements matching Key(attr), where e has an attribute a that matches any
+// the values in v.
+// If more than one element in a group matches a value in v preference
+// is given to the element that matches the first value in v.
+func (s Slice) SelectOnePerGroup(a string, v []string) {
+ index := s.indexForAttr(a)
+ grouped := s.Group(func(e Elem) string { return Key(e, a) })
+ sl := s.Value()
+ sl.Set(sl.Slice(0, 0))
+ for _, g := range grouped {
+ e := reflect.Value{}
+ found := len(v)
+ gsl := g.Value()
+ for i := 0; i < gsl.Len(); i++ {
+ vi := gsl.Index(i).Elem().FieldByIndex(index)
+ j := 0
+ for ; j < len(v) && v[j] != vi.String(); j++ {
+ }
+ if j < found {
+ found = j
+ e = gsl.Index(i)
+ }
+ }
+ if found < len(v) {
+ sl.Set(reflect.Append(sl, e))
+ }
+ }
+}
+
+// SelectDraft drops all elements from the list with a draft level smaller than d
+// and selects the highest draft level of the remaining.
+// This method assumes that the input CLDR is canonicalized.
+func (s Slice) SelectDraft(d Draft) {
+ s.SelectOnePerGroup("draft", drafts[len(drafts)-2-int(d):])
+}
diff --git a/vendor/golang.org/x/text/unicode/cldr/xml.go b/vendor/golang.org/x/text/unicode/cldr/xml.go
new file mode 100644
index 0000000..f847663
--- /dev/null
+++ b/vendor/golang.org/x/text/unicode/cldr/xml.go
@@ -0,0 +1,1494 @@
+// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
+
+package cldr
+
+// LDMLBCP47 holds information on allowable values for various variables in LDML.
+type LDMLBCP47 struct {
+ Common
+ Version *struct {
+ Common
+ Number string `xml:"number,attr"`
+ } `xml:"version"`
+ Generation *struct {
+ Common
+ Date string `xml:"date,attr"`
+ } `xml:"generation"`
+ Keyword []*struct {
+ Common
+ Key []*struct {
+ Common
+ Extension string `xml:"extension,attr"`
+ Name string `xml:"name,attr"`
+ Description string `xml:"description,attr"`
+ Deprecated string `xml:"deprecated,attr"`
+ Preferred string `xml:"preferred,attr"`
+ Alias string `xml:"alias,attr"`
+ ValueType string `xml:"valueType,attr"`
+ Since string `xml:"since,attr"`
+ Type []*struct {
+ Common
+ Name string `xml:"name,attr"`
+ Description string `xml:"description,attr"`
+ Deprecated string `xml:"deprecated,attr"`
+ Preferred string `xml:"preferred,attr"`
+ Alias string `xml:"alias,attr"`
+ Since string `xml:"since,attr"`
+ } `xml:"type"`
+ } `xml:"key"`
+ } `xml:"keyword"`
+ Attribute []*struct {
+ Common
+ Name string `xml:"name,attr"`
+ Description string `xml:"description,attr"`
+ Deprecated string `xml:"deprecated,attr"`
+ Preferred string `xml:"preferred,attr"`
+ Since string `xml:"since,attr"`
+ } `xml:"attribute"`
+}
+
+// SupplementalData holds information relevant for internationalization
+// and proper use of CLDR, but that is not contained in the locale hierarchy.
+type SupplementalData struct {
+ Common
+ Version *struct {
+ Common
+ Number string `xml:"number,attr"`
+ } `xml:"version"`
+ Generation *struct {
+ Common
+ Date string `xml:"date,attr"`
+ } `xml:"generation"`
+ CurrencyData *struct {
+ Common
+ Fractions []*struct {
+ Common
+ Info []*struct {
+ Common
+ Iso4217 string `xml:"iso4217,attr"`
+ Digits string `xml:"digits,attr"`
+ Rounding string `xml:"rounding,attr"`
+ CashDigits string `xml:"cashDigits,attr"`
+ CashRounding string `xml:"cashRounding,attr"`
+ } `xml:"info"`
+ } `xml:"fractions"`
+ Region []*struct {
+ Common
+ Iso3166 string `xml:"iso3166,attr"`
+ Currency []*struct {
+ Common
+ Before string `xml:"before,attr"`
+ From string `xml:"from,attr"`
+ To string `xml:"to,attr"`
+ Iso4217 string `xml:"iso4217,attr"`
+ Digits string `xml:"digits,attr"`
+ Rounding string `xml:"rounding,attr"`
+ CashRounding string `xml:"cashRounding,attr"`
+ Tender string `xml:"tender,attr"`
+ Alternate []*struct {
+ Common
+ Iso4217 string `xml:"iso4217,attr"`
+ } `xml:"alternate"`
+ } `xml:"currency"`
+ } `xml:"region"`
+ } `xml:"currencyData"`
+ TerritoryContainment *struct {
+ Common
+ Group []*struct {
+ Common
+ Contains string `xml:"contains,attr"`
+ Grouping string `xml:"grouping,attr"`
+ Status string `xml:"status,attr"`
+ } `xml:"group"`
+ } `xml:"territoryContainment"`
+ SubdivisionContainment *struct {
+ Common
+ Subgroup []*struct {
+ Common
+ Subtype string `xml:"subtype,attr"`
+ Contains string `xml:"contains,attr"`
+ } `xml:"subgroup"`
+ } `xml:"subdivisionContainment"`
+ LanguageData *struct {
+ Common
+ Language []*struct {
+ Common
+ Scripts string `xml:"scripts,attr"`
+ Territories string `xml:"territories,attr"`
+ Variants string `xml:"variants,attr"`
+ } `xml:"language"`
+ } `xml:"languageData"`
+ TerritoryInfo *struct {
+ Common
+ Territory []*struct {
+ Common
+ Gdp string `xml:"gdp,attr"`
+ LiteracyPercent string `xml:"literacyPercent,attr"`
+ Population string `xml:"population,attr"`
+ LanguagePopulation []*struct {
+ Common
+ LiteracyPercent string `xml:"literacyPercent,attr"`
+ WritingPercent string `xml:"writingPercent,attr"`
+ PopulationPercent string `xml:"populationPercent,attr"`
+ OfficialStatus string `xml:"officialStatus,attr"`
+ } `xml:"languagePopulation"`
+ } `xml:"territory"`
+ } `xml:"territoryInfo"`
+ PostalCodeData *struct {
+ Common
+ PostCodeRegex []*struct {
+ Common
+ TerritoryId string `xml:"territoryId,attr"`
+ } `xml:"postCodeRegex"`
+ } `xml:"postalCodeData"`
+ CalendarData *struct {
+ Common
+ Calendar []*struct {
+ Common
+ Territories string `xml:"territories,attr"`
+ CalendarSystem *Common `xml:"calendarSystem"`
+ Eras *struct {
+ Common
+ Era []*struct {
+ Common
+ Start string `xml:"start,attr"`
+ End string `xml:"end,attr"`
+ } `xml:"era"`
+ } `xml:"eras"`
+ } `xml:"calendar"`
+ } `xml:"calendarData"`
+ CalendarPreferenceData *struct {
+ Common
+ CalendarPreference []*struct {
+ Common
+ Territories string `xml:"territories,attr"`
+ Ordering string `xml:"ordering,attr"`
+ } `xml:"calendarPreference"`
+ } `xml:"calendarPreferenceData"`
+ WeekData *struct {
+ Common
+ MinDays []*struct {
+ Common
+ Count string `xml:"count,attr"`
+ Territories string `xml:"territories,attr"`
+ } `xml:"minDays"`
+ FirstDay []*struct {
+ Common
+ Day string `xml:"day,attr"`
+ Territories string `xml:"territories,attr"`
+ } `xml:"firstDay"`
+ WeekendStart []*struct {
+ Common
+ Day string `xml:"day,attr"`
+ Territories string `xml:"territories,attr"`
+ } `xml:"weekendStart"`
+ WeekendEnd []*struct {
+ Common
+ Day string `xml:"day,attr"`
+ Territories string `xml:"territories,attr"`
+ } `xml:"weekendEnd"`
+ WeekOfPreference []*struct {
+ Common
+ Locales string `xml:"locales,attr"`
+ Ordering string `xml:"ordering,attr"`
+ } `xml:"weekOfPreference"`
+ } `xml:"weekData"`
+ TimeData *struct {
+ Common
+ Hours []*struct {
+ Common
+ Allowed string `xml:"allowed,attr"`
+ Preferred string `xml:"preferred,attr"`
+ Regions string `xml:"regions,attr"`
+ } `xml:"hours"`
+ } `xml:"timeData"`
+ MeasurementData *struct {
+ Common
+ MeasurementSystem []*struct {
+ Common
+ Category string `xml:"category,attr"`
+ Territories string `xml:"territories,attr"`
+ } `xml:"measurementSystem"`
+ PaperSize []*struct {
+ Common
+ Territories string `xml:"territories,attr"`
+ } `xml:"paperSize"`
+ } `xml:"measurementData"`
+ UnitPreferenceData *struct {
+ Common
+ UnitPreferences []*struct {
+ Common
+ Category string `xml:"category,attr"`
+ Usage string `xml:"usage,attr"`
+ Scope string `xml:"scope,attr"`
+ UnitPreference []*struct {
+ Common
+ Regions string `xml:"regions,attr"`
+ } `xml:"unitPreference"`
+ } `xml:"unitPreferences"`
+ } `xml:"unitPreferenceData"`
+ TimezoneData *struct {
+ Common
+ MapTimezones []*struct {
+ Common
+ OtherVersion string `xml:"otherVersion,attr"`
+ TypeVersion string `xml:"typeVersion,attr"`
+ MapZone []*struct {
+ Common
+ Other string `xml:"other,attr"`
+ Territory string `xml:"territory,attr"`
+ } `xml:"mapZone"`
+ } `xml:"mapTimezones"`
+ ZoneFormatting []*struct {
+ Common
+ Multizone string `xml:"multizone,attr"`
+ TzidVersion string `xml:"tzidVersion,attr"`
+ ZoneItem []*struct {
+ Common
+ Territory string `xml:"territory,attr"`
+ Aliases string `xml:"aliases,attr"`
+ } `xml:"zoneItem"`
+ } `xml:"zoneFormatting"`
+ } `xml:"timezoneData"`
+ Characters *struct {
+ Common
+ CharacterFallback []*struct {
+ Common
+ Character []*struct {
+ Common
+ Value string `xml:"value,attr"`
+ Substitute []*Common `xml:"substitute"`
+ } `xml:"character"`
+ } `xml:"character-fallback"`
+ } `xml:"characters"`
+ Transforms *struct {
+ Common
+ Transform []*struct {
+ Common
+ Source string `xml:"source,attr"`
+ Target string `xml:"target,attr"`
+ Variant string `xml:"variant,attr"`
+ Direction string `xml:"direction,attr"`
+ Alias string `xml:"alias,attr"`
+ BackwardAlias string `xml:"backwardAlias,attr"`
+ Visibility string `xml:"visibility,attr"`
+ Comment []*Common `xml:"comment"`
+ TRule []*Common `xml:"tRule"`
+ } `xml:"transform"`
+ } `xml:"transforms"`
+ Metadata *struct {
+ Common
+ AttributeOrder *Common `xml:"attributeOrder"`
+ ElementOrder *Common `xml:"elementOrder"`
+ SerialElements *Common `xml:"serialElements"`
+ Suppress *struct {
+ Common
+ Attributes []*struct {
+ Common
+ Element string `xml:"element,attr"`
+ Attribute string `xml:"attribute,attr"`
+ AttributeValue string `xml:"attributeValue,attr"`
+ } `xml:"attributes"`
+ } `xml:"suppress"`
+ Validity *struct {
+ Common
+ Variable []*struct {
+ Common
+ Id string `xml:"id,attr"`
+ } `xml:"variable"`
+ AttributeValues []*struct {
+ Common
+ Dtds string `xml:"dtds,attr"`
+ Elements string `xml:"elements,attr"`
+ Attributes string `xml:"attributes,attr"`
+ Order string `xml:"order,attr"`
+ } `xml:"attributeValues"`
+ } `xml:"validity"`
+ Alias *struct {
+ Common
+ LanguageAlias []*struct {
+ Common
+ Replacement string `xml:"replacement,attr"`
+ Reason string `xml:"reason,attr"`
+ } `xml:"languageAlias"`
+ ScriptAlias []*struct {
+ Common
+ Replacement string `xml:"replacement,attr"`
+ Reason string `xml:"reason,attr"`
+ } `xml:"scriptAlias"`
+ TerritoryAlias []*struct {
+ Common
+ Replacement string `xml:"replacement,attr"`
+ Reason string `xml:"reason,attr"`
+ } `xml:"territoryAlias"`
+ SubdivisionAlias []*struct {
+ Common
+ Replacement string `xml:"replacement,attr"`
+ Reason string `xml:"reason,attr"`
+ } `xml:"subdivisionAlias"`
+ VariantAlias []*struct {
+ Common
+ Replacement string `xml:"replacement,attr"`
+ Reason string `xml:"reason,attr"`
+ } `xml:"variantAlias"`
+ ZoneAlias []*struct {
+ Common
+ Replacement string `xml:"replacement,attr"`
+ Reason string `xml:"reason,attr"`
+ } `xml:"zoneAlias"`
+ } `xml:"alias"`
+ Deprecated *struct {
+ Common
+ DeprecatedItems []*struct {
+ Common
+ Elements string `xml:"elements,attr"`
+ Attributes string `xml:"attributes,attr"`
+ Values string `xml:"values,attr"`
+ } `xml:"deprecatedItems"`
+ } `xml:"deprecated"`
+ Distinguishing *struct {
+ Common
+ DistinguishingItems []*struct {
+ Common
+ Exclude string `xml:"exclude,attr"`
+ Elements string `xml:"elements,attr"`
+ Attributes string `xml:"attributes,attr"`
+ } `xml:"distinguishingItems"`
+ } `xml:"distinguishing"`
+ Blocking *struct {
+ Common
+ BlockingItems []*struct {
+ Common
+ Elements string `xml:"elements,attr"`
+ } `xml:"blockingItems"`
+ } `xml:"blocking"`
+ CoverageAdditions *struct {
+ Common
+ LanguageCoverage []*struct {
+ Common
+ Values string `xml:"values,attr"`
+ } `xml:"languageCoverage"`
+ ScriptCoverage []*struct {
+ Common
+ Values string `xml:"values,attr"`
+ } `xml:"scriptCoverage"`
+ TerritoryCoverage []*struct {
+ Common
+ Values string `xml:"values,attr"`
+ } `xml:"territoryCoverage"`
+ CurrencyCoverage []*struct {
+ Common
+ Values string `xml:"values,attr"`
+ } `xml:"currencyCoverage"`
+ TimezoneCoverage []*struct {
+ Common
+ Values string `xml:"values,attr"`
+ } `xml:"timezoneCoverage"`
+ } `xml:"coverageAdditions"`
+ SkipDefaultLocale *struct {
+ Common
+ Services string `xml:"services,attr"`
+ } `xml:"skipDefaultLocale"`
+ DefaultContent *struct {
+ Common
+ Locales string `xml:"locales,attr"`
+ } `xml:"defaultContent"`
+ } `xml:"metadata"`
+ CodeMappings *struct {
+ Common
+ LanguageCodes []*struct {
+ Common
+ Alpha3 string `xml:"alpha3,attr"`
+ } `xml:"languageCodes"`
+ TerritoryCodes []*struct {
+ Common
+ Numeric string `xml:"numeric,attr"`
+ Alpha3 string `xml:"alpha3,attr"`
+ Fips10 string `xml:"fips10,attr"`
+ Internet string `xml:"internet,attr"`
+ } `xml:"territoryCodes"`
+ CurrencyCodes []*struct {
+ Common
+ Numeric string `xml:"numeric,attr"`
+ } `xml:"currencyCodes"`
+ } `xml:"codeMappings"`
+ ParentLocales *struct {
+ Common
+ ParentLocale []*struct {
+ Common
+ Parent string `xml:"parent,attr"`
+ Locales string `xml:"locales,attr"`
+ } `xml:"parentLocale"`
+ } `xml:"parentLocales"`
+ LikelySubtags *struct {
+ Common
+ LikelySubtag []*struct {
+ Common
+ From string `xml:"from,attr"`
+ To string `xml:"to,attr"`
+ } `xml:"likelySubtag"`
+ } `xml:"likelySubtags"`
+ MetazoneInfo *struct {
+ Common
+ Timezone []*struct {
+ Common
+ UsesMetazone []*struct {
+ Common
+ From string `xml:"from,attr"`
+ To string `xml:"to,attr"`
+ Mzone string `xml:"mzone,attr"`
+ } `xml:"usesMetazone"`
+ } `xml:"timezone"`
+ } `xml:"metazoneInfo"`
+ Plurals []*struct {
+ Common
+ PluralRules []*struct {
+ Common
+ Locales string `xml:"locales,attr"`
+ PluralRule []*struct {
+ Common
+ Count string `xml:"count,attr"`
+ } `xml:"pluralRule"`
+ } `xml:"pluralRules"`
+ PluralRanges []*struct {
+ Common
+ Locales string `xml:"locales,attr"`
+ PluralRange []*struct {
+ Common
+ Start string `xml:"start,attr"`
+ End string `xml:"end,attr"`
+ Result string `xml:"result,attr"`
+ } `xml:"pluralRange"`
+ } `xml:"pluralRanges"`
+ } `xml:"plurals"`
+ TelephoneCodeData *struct {
+ Common
+ CodesByTerritory []*struct {
+ Common
+ Territory string `xml:"territory,attr"`
+ TelephoneCountryCode []*struct {
+ Common
+ Code string `xml:"code,attr"`
+ From string `xml:"from,attr"`
+ To string `xml:"to,attr"`
+ } `xml:"telephoneCountryCode"`
+ } `xml:"codesByTerritory"`
+ } `xml:"telephoneCodeData"`
+ NumberingSystems *struct {
+ Common
+ NumberingSystem []*struct {
+ Common
+ Id string `xml:"id,attr"`
+ Radix string `xml:"radix,attr"`
+ Digits string `xml:"digits,attr"`
+ Rules string `xml:"rules,attr"`
+ } `xml:"numberingSystem"`
+ } `xml:"numberingSystems"`
+ Bcp47KeywordMappings *struct {
+ Common
+ MapKeys *struct {
+ Common
+ KeyMap []*struct {
+ Common
+ Bcp47 string `xml:"bcp47,attr"`
+ } `xml:"keyMap"`
+ } `xml:"mapKeys"`
+ MapTypes []*struct {
+ Common
+ TypeMap []*struct {
+ Common
+ Bcp47 string `xml:"bcp47,attr"`
+ } `xml:"typeMap"`
+ } `xml:"mapTypes"`
+ } `xml:"bcp47KeywordMappings"`
+ Gender *struct {
+ Common
+ PersonList []*struct {
+ Common
+ Locales string `xml:"locales,attr"`
+ } `xml:"personList"`
+ } `xml:"gender"`
+ References *struct {
+ Common
+ Reference []*struct {
+ Common
+ Uri string `xml:"uri,attr"`
+ } `xml:"reference"`
+ } `xml:"references"`
+ LanguageMatching *struct {
+ Common
+ LanguageMatches []*struct {
+ Common
+ ParadigmLocales []*struct {
+ Common
+ Locales string `xml:"locales,attr"`
+ } `xml:"paradigmLocales"`
+ MatchVariable []*struct {
+ Common
+ Id string `xml:"id,attr"`
+ Value string `xml:"value,attr"`
+ } `xml:"matchVariable"`
+ LanguageMatch []*struct {
+ Common
+ Desired string `xml:"desired,attr"`
+ Supported string `xml:"supported,attr"`
+ Percent string `xml:"percent,attr"`
+ Distance string `xml:"distance,attr"`
+ Oneway string `xml:"oneway,attr"`
+ } `xml:"languageMatch"`
+ } `xml:"languageMatches"`
+ } `xml:"languageMatching"`
+ DayPeriodRuleSet []*struct {
+ Common
+ DayPeriodRules []*struct {
+ Common
+ Locales string `xml:"locales,attr"`
+ DayPeriodRule []*struct {
+ Common
+ At string `xml:"at,attr"`
+ After string `xml:"after,attr"`
+ Before string `xml:"before,attr"`
+ From string `xml:"from,attr"`
+ To string `xml:"to,attr"`
+ } `xml:"dayPeriodRule"`
+ } `xml:"dayPeriodRules"`
+ } `xml:"dayPeriodRuleSet"`
+ MetaZones *struct {
+ Common
+ MetazoneInfo *struct {
+ Common
+ Timezone []*struct {
+ Common
+ UsesMetazone []*struct {
+ Common
+ From string `xml:"from,attr"`
+ To string `xml:"to,attr"`
+ Mzone string `xml:"mzone,attr"`
+ } `xml:"usesMetazone"`
+ } `xml:"timezone"`
+ } `xml:"metazoneInfo"`
+ MapTimezones *struct {
+ Common
+ OtherVersion string `xml:"otherVersion,attr"`
+ TypeVersion string `xml:"typeVersion,attr"`
+ MapZone []*struct {
+ Common
+ Other string `xml:"other,attr"`
+ Territory string `xml:"territory,attr"`
+ } `xml:"mapZone"`
+ } `xml:"mapTimezones"`
+ } `xml:"metaZones"`
+ PrimaryZones *struct {
+ Common
+ PrimaryZone []*struct {
+ Common
+ Iso3166 string `xml:"iso3166,attr"`
+ } `xml:"primaryZone"`
+ } `xml:"primaryZones"`
+ WindowsZones *struct {
+ Common
+ MapTimezones *struct {
+ Common
+ OtherVersion string `xml:"otherVersion,attr"`
+ TypeVersion string `xml:"typeVersion,attr"`
+ MapZone []*struct {
+ Common
+ Other string `xml:"other,attr"`
+ Territory string `xml:"territory,attr"`
+ } `xml:"mapZone"`
+ } `xml:"mapTimezones"`
+ } `xml:"windowsZones"`
+ CoverageLevels *struct {
+ Common
+ ApprovalRequirements *struct {
+ Common
+ ApprovalRequirement []*struct {
+ Common
+ Votes string `xml:"votes,attr"`
+ Locales string `xml:"locales,attr"`
+ Paths string `xml:"paths,attr"`
+ } `xml:"approvalRequirement"`
+ } `xml:"approvalRequirements"`
+ CoverageVariable []*struct {
+ Common
+ Key string `xml:"key,attr"`
+ Value string `xml:"value,attr"`
+ } `xml:"coverageVariable"`
+ CoverageLevel []*struct {
+ Common
+ InLanguage string `xml:"inLanguage,attr"`
+ InScript string `xml:"inScript,attr"`
+ InTerritory string `xml:"inTerritory,attr"`
+ Value string `xml:"value,attr"`
+ Match string `xml:"match,attr"`
+ } `xml:"coverageLevel"`
+ } `xml:"coverageLevels"`
+ IdValidity *struct {
+ Common
+ Id []*struct {
+ Common
+ IdStatus string `xml:"idStatus,attr"`
+ } `xml:"id"`
+ } `xml:"idValidity"`
+ RgScope *struct {
+ Common
+ RgPath []*struct {
+ Common
+ Path string `xml:"path,attr"`
+ } `xml:"rgPath"`
+ } `xml:"rgScope"`
+ LanguageGroups *struct {
+ Common
+ LanguageGroup []*struct {
+ Common
+ Parent string `xml:"parent,attr"`
+ } `xml:"languageGroup"`
+ } `xml:"languageGroups"`
+}
+
+// LDML is the top-level type for locale-specific data.
+type LDML struct {
+ Common
+ Version string `xml:"version,attr"`
+ Identity *struct {
+ Common
+ Version *struct {
+ Common
+ Number string `xml:"number,attr"`
+ } `xml:"version"`
+ Generation *struct {
+ Common
+ Date string `xml:"date,attr"`
+ } `xml:"generation"`
+ Language *Common `xml:"language"`
+ Script *Common `xml:"script"`
+ Territory *Common `xml:"territory"`
+ Variant *Common `xml:"variant"`
+ } `xml:"identity"`
+ LocaleDisplayNames *LocaleDisplayNames `xml:"localeDisplayNames"`
+ Layout *struct {
+ Common
+ Orientation []*struct {
+ Common
+ Characters string `xml:"characters,attr"`
+ Lines string `xml:"lines,attr"`
+ CharacterOrder []*Common `xml:"characterOrder"`
+ LineOrder []*Common `xml:"lineOrder"`
+ } `xml:"orientation"`
+ InList []*struct {
+ Common
+ Casing string `xml:"casing,attr"`
+ } `xml:"inList"`
+ InText []*Common `xml:"inText"`
+ } `xml:"layout"`
+ ContextTransforms *struct {
+ Common
+ ContextTransformUsage []*struct {
+ Common
+ ContextTransform []*Common `xml:"contextTransform"`
+ } `xml:"contextTransformUsage"`
+ } `xml:"contextTransforms"`
+ Characters *struct {
+ Common
+ ExemplarCharacters []*Common `xml:"exemplarCharacters"`
+ Ellipsis []*Common `xml:"ellipsis"`
+ MoreInformation []*Common `xml:"moreInformation"`
+ Stopwords []*struct {
+ Common
+ StopwordList []*Common `xml:"stopwordList"`
+ } `xml:"stopwords"`
+ IndexLabels []*struct {
+ Common
+ IndexSeparator []*Common `xml:"indexSeparator"`
+ CompressedIndexSeparator []*Common `xml:"compressedIndexSeparator"`
+ IndexRangePattern []*Common `xml:"indexRangePattern"`
+ IndexLabelBefore []*Common `xml:"indexLabelBefore"`
+ IndexLabelAfter []*Common `xml:"indexLabelAfter"`
+ IndexLabel []*struct {
+ Common
+ IndexSource string `xml:"indexSource,attr"`
+ Priority string `xml:"priority,attr"`
+ } `xml:"indexLabel"`
+ } `xml:"indexLabels"`
+ Mapping []*struct {
+ Common
+ Registry string `xml:"registry,attr"`
+ } `xml:"mapping"`
+ ParseLenients []*struct {
+ Common
+ Scope string `xml:"scope,attr"`
+ Level string `xml:"level,attr"`
+ ParseLenient []*struct {
+ Common
+ Sample string `xml:"sample,attr"`
+ } `xml:"parseLenient"`
+ } `xml:"parseLenients"`
+ } `xml:"characters"`
+ Delimiters *struct {
+ Common
+ QuotationStart []*Common `xml:"quotationStart"`
+ QuotationEnd []*Common `xml:"quotationEnd"`
+ AlternateQuotationStart []*Common `xml:"alternateQuotationStart"`
+ AlternateQuotationEnd []*Common `xml:"alternateQuotationEnd"`
+ } `xml:"delimiters"`
+ Measurement *struct {
+ Common
+ MeasurementSystem []*Common `xml:"measurementSystem"`
+ PaperSize []*struct {
+ Common
+ Height []*Common `xml:"height"`
+ Width []*Common `xml:"width"`
+ } `xml:"paperSize"`
+ } `xml:"measurement"`
+ Dates *struct {
+ Common
+ LocalizedPatternChars []*Common `xml:"localizedPatternChars"`
+ DateRangePattern []*Common `xml:"dateRangePattern"`
+ Calendars *struct {
+ Common
+ Calendar []*Calendar `xml:"calendar"`
+ } `xml:"calendars"`
+ Fields *struct {
+ Common
+ Field []*struct {
+ Common
+ DisplayName []*struct {
+ Common
+ Count string `xml:"count,attr"`
+ } `xml:"displayName"`
+ Relative []*Common `xml:"relative"`
+ RelativeTime []*struct {
+ Common
+ RelativeTimePattern []*struct {
+ Common
+ Count string `xml:"count,attr"`
+ } `xml:"relativeTimePattern"`
+ } `xml:"relativeTime"`
+ RelativePeriod []*Common `xml:"relativePeriod"`
+ } `xml:"field"`
+ } `xml:"fields"`
+ TimeZoneNames *TimeZoneNames `xml:"timeZoneNames"`
+ } `xml:"dates"`
+ Numbers *Numbers `xml:"numbers"`
+ Units *struct {
+ Common
+ Unit []*struct {
+ Common
+ DisplayName []*struct {
+ Common
+ Count string `xml:"count,attr"`
+ } `xml:"displayName"`
+ UnitPattern []*struct {
+ Common
+ Count string `xml:"count,attr"`
+ } `xml:"unitPattern"`
+ PerUnitPattern []*Common `xml:"perUnitPattern"`
+ } `xml:"unit"`
+ UnitLength []*struct {
+ Common
+ CompoundUnit []*struct {
+ Common
+ CompoundUnitPattern []*Common `xml:"compoundUnitPattern"`
+ } `xml:"compoundUnit"`
+ Unit []*struct {
+ Common
+ DisplayName []*struct {
+ Common
+ Count string `xml:"count,attr"`
+ } `xml:"displayName"`
+ UnitPattern []*struct {
+ Common
+ Count string `xml:"count,attr"`
+ } `xml:"unitPattern"`
+ PerUnitPattern []*Common `xml:"perUnitPattern"`
+ } `xml:"unit"`
+ CoordinateUnit []*struct {
+ Common
+ CoordinateUnitPattern []*Common `xml:"coordinateUnitPattern"`
+ } `xml:"coordinateUnit"`
+ } `xml:"unitLength"`
+ DurationUnit []*struct {
+ Common
+ DurationUnitPattern []*Common `xml:"durationUnitPattern"`
+ } `xml:"durationUnit"`
+ } `xml:"units"`
+ ListPatterns *struct {
+ Common
+ ListPattern []*struct {
+ Common
+ ListPatternPart []*Common `xml:"listPatternPart"`
+ } `xml:"listPattern"`
+ } `xml:"listPatterns"`
+ Collations *struct {
+ Common
+ Version string `xml:"version,attr"`
+ DefaultCollation *Common `xml:"defaultCollation"`
+ Collation []*Collation `xml:"collation"`
+ } `xml:"collations"`
+ Posix *struct {
+ Common
+ Messages []*struct {
+ Common
+ Yesstr []*Common `xml:"yesstr"`
+ Nostr []*Common `xml:"nostr"`
+ Yesexpr []*Common `xml:"yesexpr"`
+ Noexpr []*Common `xml:"noexpr"`
+ } `xml:"messages"`
+ } `xml:"posix"`
+ CharacterLabels *struct {
+ Common
+ CharacterLabelPattern []*struct {
+ Common
+ Count string `xml:"count,attr"`
+ } `xml:"characterLabelPattern"`
+ CharacterLabel []*Common `xml:"characterLabel"`
+ } `xml:"characterLabels"`
+ Segmentations *struct {
+ Common
+ Segmentation []*struct {
+ Common
+ Variables *struct {
+ Common
+ Variable []*struct {
+ Common
+ Id string `xml:"id,attr"`
+ } `xml:"variable"`
+ } `xml:"variables"`
+ SegmentRules *struct {
+ Common
+ Rule []*struct {
+ Common
+ Id string `xml:"id,attr"`
+ } `xml:"rule"`
+ } `xml:"segmentRules"`
+ Exceptions *struct {
+ Common
+ Exception []*Common `xml:"exception"`
+ } `xml:"exceptions"`
+ Suppressions *struct {
+ Common
+ Suppression []*Common `xml:"suppression"`
+ } `xml:"suppressions"`
+ } `xml:"segmentation"`
+ } `xml:"segmentations"`
+ Rbnf *struct {
+ Common
+ RulesetGrouping []*struct {
+ Common
+ Ruleset []*struct {
+ Common
+ Access string `xml:"access,attr"`
+ AllowsParsing string `xml:"allowsParsing,attr"`
+ Rbnfrule []*struct {
+ Common
+ Value string `xml:"value,attr"`
+ Radix string `xml:"radix,attr"`
+ Decexp string `xml:"decexp,attr"`
+ } `xml:"rbnfrule"`
+ } `xml:"ruleset"`
+ } `xml:"rulesetGrouping"`
+ } `xml:"rbnf"`
+ Annotations *struct {
+ Common
+ Annotation []*struct {
+ Common
+ Cp string `xml:"cp,attr"`
+ Tts string `xml:"tts,attr"`
+ } `xml:"annotation"`
+ } `xml:"annotations"`
+ Metadata *struct {
+ Common
+ CasingData *struct {
+ Common
+ CasingItem []*struct {
+ Common
+ Override string `xml:"override,attr"`
+ ForceError string `xml:"forceError,attr"`
+ } `xml:"casingItem"`
+ } `xml:"casingData"`
+ } `xml:"metadata"`
+ References *struct {
+ Common
+ Reference []*struct {
+ Common
+ Uri string `xml:"uri,attr"`
+ } `xml:"reference"`
+ } `xml:"references"`
+}
+
+// Collation contains rules that specify a certain sort-order,
+// as a tailoring of the root order.
+// The parsed rules are obtained by passing a RuleProcessor to Collation's
+// Process method.
+type Collation struct {
+ Common
+ Visibility string `xml:"visibility,attr"`
+ Base *Common `xml:"base"`
+ Import []*struct {
+ Common
+ Source string `xml:"source,attr"`
+ } `xml:"import"`
+ Settings *struct {
+ Common
+ Strength string `xml:"strength,attr"`
+ Alternate string `xml:"alternate,attr"`
+ Backwards string `xml:"backwards,attr"`
+ Normalization string `xml:"normalization,attr"`
+ CaseLevel string `xml:"caseLevel,attr"`
+ CaseFirst string `xml:"caseFirst,attr"`
+ HiraganaQuaternary string `xml:"hiraganaQuaternary,attr"`
+ MaxVariable string `xml:"maxVariable,attr"`
+ Numeric string `xml:"numeric,attr"`
+ Private string `xml:"private,attr"`
+ VariableTop string `xml:"variableTop,attr"`
+ Reorder string `xml:"reorder,attr"`
+ } `xml:"settings"`
+ SuppressContractions *Common `xml:"suppress_contractions"`
+ Optimize *Common `xml:"optimize"`
+ Cr []*Common `xml:"cr"`
+ rulesElem
+}
+
+// Calendar specifies the fields used for formatting and parsing dates and times.
+// The month and quarter names are identified numerically, starting at 1.
+// The day (of the week) names are identified with short strings, since there is
+// no universally-accepted numeric designation.
+type Calendar struct {
+ Common
+ Months *struct {
+ Common
+ MonthContext []*struct {
+ Common
+ MonthWidth []*struct {
+ Common
+ Month []*struct {
+ Common
+ Yeartype string `xml:"yeartype,attr"`
+ } `xml:"month"`
+ } `xml:"monthWidth"`
+ } `xml:"monthContext"`
+ } `xml:"months"`
+ MonthNames *struct {
+ Common
+ Month []*struct {
+ Common
+ Yeartype string `xml:"yeartype,attr"`
+ } `xml:"month"`
+ } `xml:"monthNames"`
+ MonthAbbr *struct {
+ Common
+ Month []*struct {
+ Common
+ Yeartype string `xml:"yeartype,attr"`
+ } `xml:"month"`
+ } `xml:"monthAbbr"`
+ MonthPatterns *struct {
+ Common
+ MonthPatternContext []*struct {
+ Common
+ MonthPatternWidth []*struct {
+ Common
+ MonthPattern []*Common `xml:"monthPattern"`
+ } `xml:"monthPatternWidth"`
+ } `xml:"monthPatternContext"`
+ } `xml:"monthPatterns"`
+ Days *struct {
+ Common
+ DayContext []*struct {
+ Common
+ DayWidth []*struct {
+ Common
+ Day []*Common `xml:"day"`
+ } `xml:"dayWidth"`
+ } `xml:"dayContext"`
+ } `xml:"days"`
+ DayNames *struct {
+ Common
+ Day []*Common `xml:"day"`
+ } `xml:"dayNames"`
+ DayAbbr *struct {
+ Common
+ Day []*Common `xml:"day"`
+ } `xml:"dayAbbr"`
+ Quarters *struct {
+ Common
+ QuarterContext []*struct {
+ Common
+ QuarterWidth []*struct {
+ Common
+ Quarter []*Common `xml:"quarter"`
+ } `xml:"quarterWidth"`
+ } `xml:"quarterContext"`
+ } `xml:"quarters"`
+ Week *struct {
+ Common
+ MinDays []*struct {
+ Common
+ Count string `xml:"count,attr"`
+ } `xml:"minDays"`
+ FirstDay []*struct {
+ Common
+ Day string `xml:"day,attr"`
+ } `xml:"firstDay"`
+ WeekendStart []*struct {
+ Common
+ Day string `xml:"day,attr"`
+ Time string `xml:"time,attr"`
+ } `xml:"weekendStart"`
+ WeekendEnd []*struct {
+ Common
+ Day string `xml:"day,attr"`
+ Time string `xml:"time,attr"`
+ } `xml:"weekendEnd"`
+ } `xml:"week"`
+ Am []*Common `xml:"am"`
+ Pm []*Common `xml:"pm"`
+ DayPeriods *struct {
+ Common
+ DayPeriodContext []*struct {
+ Common
+ DayPeriodWidth []*struct {
+ Common
+ DayPeriod []*Common `xml:"dayPeriod"`
+ } `xml:"dayPeriodWidth"`
+ } `xml:"dayPeriodContext"`
+ } `xml:"dayPeriods"`
+ Eras *struct {
+ Common
+ EraNames *struct {
+ Common
+ Era []*Common `xml:"era"`
+ } `xml:"eraNames"`
+ EraAbbr *struct {
+ Common
+ Era []*Common `xml:"era"`
+ } `xml:"eraAbbr"`
+ EraNarrow *struct {
+ Common
+ Era []*Common `xml:"era"`
+ } `xml:"eraNarrow"`
+ } `xml:"eras"`
+ CyclicNameSets *struct {
+ Common
+ CyclicNameSet []*struct {
+ Common
+ CyclicNameContext []*struct {
+ Common
+ CyclicNameWidth []*struct {
+ Common
+ CyclicName []*Common `xml:"cyclicName"`
+ } `xml:"cyclicNameWidth"`
+ } `xml:"cyclicNameContext"`
+ } `xml:"cyclicNameSet"`
+ } `xml:"cyclicNameSets"`
+ DateFormats *struct {
+ Common
+ DateFormatLength []*struct {
+ Common
+ DateFormat []*struct {
+ Common
+ Pattern []*struct {
+ Common
+ Numbers string `xml:"numbers,attr"`
+ Count string `xml:"count,attr"`
+ } `xml:"pattern"`
+ DisplayName []*struct {
+ Common
+ Count string `xml:"count,attr"`
+ } `xml:"displayName"`
+ } `xml:"dateFormat"`
+ } `xml:"dateFormatLength"`
+ } `xml:"dateFormats"`
+ TimeFormats *struct {
+ Common
+ TimeFormatLength []*struct {
+ Common
+ TimeFormat []*struct {
+ Common
+ Pattern []*struct {
+ Common
+ Numbers string `xml:"numbers,attr"`
+ Count string `xml:"count,attr"`
+ } `xml:"pattern"`
+ DisplayName []*struct {
+ Common
+ Count string `xml:"count,attr"`
+ } `xml:"displayName"`
+ } `xml:"timeFormat"`
+ } `xml:"timeFormatLength"`
+ } `xml:"timeFormats"`
+ DateTimeFormats *struct {
+ Common
+ DateTimeFormatLength []*struct {
+ Common
+ DateTimeFormat []*struct {
+ Common
+ Pattern []*struct {
+ Common
+ Numbers string `xml:"numbers,attr"`
+ Count string `xml:"count,attr"`
+ } `xml:"pattern"`
+ DisplayName []*struct {
+ Common
+ Count string `xml:"count,attr"`
+ } `xml:"displayName"`
+ } `xml:"dateTimeFormat"`
+ } `xml:"dateTimeFormatLength"`
+ AvailableFormats []*struct {
+ Common
+ DateFormatItem []*struct {
+ Common
+ Id string `xml:"id,attr"`
+ Count string `xml:"count,attr"`
+ } `xml:"dateFormatItem"`
+ } `xml:"availableFormats"`
+ AppendItems []*struct {
+ Common
+ AppendItem []*struct {
+ Common
+ Request string `xml:"request,attr"`
+ } `xml:"appendItem"`
+ } `xml:"appendItems"`
+ IntervalFormats []*struct {
+ Common
+ IntervalFormatFallback []*Common `xml:"intervalFormatFallback"`
+ IntervalFormatItem []*struct {
+ Common
+ Id string `xml:"id,attr"`
+ GreatestDifference []*struct {
+ Common
+ Id string `xml:"id,attr"`
+ } `xml:"greatestDifference"`
+ } `xml:"intervalFormatItem"`
+ } `xml:"intervalFormats"`
+ } `xml:"dateTimeFormats"`
+ Fields []*struct {
+ Common
+ Field []*struct {
+ Common
+ DisplayName []*struct {
+ Common
+ Count string `xml:"count,attr"`
+ } `xml:"displayName"`
+ Relative []*Common `xml:"relative"`
+ RelativeTime []*struct {
+ Common
+ RelativeTimePattern []*struct {
+ Common
+ Count string `xml:"count,attr"`
+ } `xml:"relativeTimePattern"`
+ } `xml:"relativeTime"`
+ RelativePeriod []*Common `xml:"relativePeriod"`
+ } `xml:"field"`
+ } `xml:"fields"`
+}
+type TimeZoneNames struct {
+ Common
+ HourFormat []*Common `xml:"hourFormat"`
+ HoursFormat []*Common `xml:"hoursFormat"`
+ GmtFormat []*Common `xml:"gmtFormat"`
+ GmtZeroFormat []*Common `xml:"gmtZeroFormat"`
+ RegionFormat []*Common `xml:"regionFormat"`
+ FallbackFormat []*Common `xml:"fallbackFormat"`
+ FallbackRegionFormat []*Common `xml:"fallbackRegionFormat"`
+ AbbreviationFallback []*Common `xml:"abbreviationFallback"`
+ PreferenceOrdering []*Common `xml:"preferenceOrdering"`
+ SingleCountries []*struct {
+ Common
+ List string `xml:"list,attr"`
+ } `xml:"singleCountries"`
+ Zone []*struct {
+ Common
+ Long []*struct {
+ Common
+ Generic []*Common `xml:"generic"`
+ Standard []*Common `xml:"standard"`
+ Daylight []*Common `xml:"daylight"`
+ } `xml:"long"`
+ Short []*struct {
+ Common
+ Generic []*Common `xml:"generic"`
+ Standard []*Common `xml:"standard"`
+ Daylight []*Common `xml:"daylight"`
+ } `xml:"short"`
+ CommonlyUsed []*struct {
+ Common
+ Used string `xml:"used,attr"`
+ } `xml:"commonlyUsed"`
+ ExemplarCity []*Common `xml:"exemplarCity"`
+ } `xml:"zone"`
+ Metazone []*struct {
+ Common
+ Long []*struct {
+ Common
+ Generic []*Common `xml:"generic"`
+ Standard []*Common `xml:"standard"`
+ Daylight []*Common `xml:"daylight"`
+ } `xml:"long"`
+ Short []*struct {
+ Common
+ Generic []*Common `xml:"generic"`
+ Standard []*Common `xml:"standard"`
+ Daylight []*Common `xml:"daylight"`
+ } `xml:"short"`
+ CommonlyUsed []*struct {
+ Common
+ Used string `xml:"used,attr"`
+ } `xml:"commonlyUsed"`
+ } `xml:"metazone"`
+}
+
+// LocaleDisplayNames specifies localized display names for for scripts, languages,
+// countries, currencies, and variants.
+type LocaleDisplayNames struct {
+ Common
+ LocaleDisplayPattern *struct {
+ Common
+ LocalePattern []*Common `xml:"localePattern"`
+ LocaleSeparator []*Common `xml:"localeSeparator"`
+ LocaleKeyTypePattern []*Common `xml:"localeKeyTypePattern"`
+ } `xml:"localeDisplayPattern"`
+ Languages *struct {
+ Common
+ Language []*Common `xml:"language"`
+ } `xml:"languages"`
+ Scripts *struct {
+ Common
+ Script []*Common `xml:"script"`
+ } `xml:"scripts"`
+ Territories *struct {
+ Common
+ Territory []*Common `xml:"territory"`
+ } `xml:"territories"`
+ Subdivisions *struct {
+ Common
+ Subdivision []*Common `xml:"subdivision"`
+ } `xml:"subdivisions"`
+ Variants *struct {
+ Common
+ Variant []*Common `xml:"variant"`
+ } `xml:"variants"`
+ Keys *struct {
+ Common
+ Key []*Common `xml:"key"`
+ } `xml:"keys"`
+ Types *struct {
+ Common
+ Type []*struct {
+ Common
+ Key string `xml:"key,attr"`
+ } `xml:"type"`
+ } `xml:"types"`
+ TransformNames *struct {
+ Common
+ TransformName []*Common `xml:"transformName"`
+ } `xml:"transformNames"`
+ MeasurementSystemNames *struct {
+ Common
+ MeasurementSystemName []*Common `xml:"measurementSystemName"`
+ } `xml:"measurementSystemNames"`
+ CodePatterns *struct {
+ Common
+ CodePattern []*Common `xml:"codePattern"`
+ } `xml:"codePatterns"`
+}
+
+// Numbers supplies information for formatting and parsing numbers and currencies.
+type Numbers struct {
+ Common
+ DefaultNumberingSystem []*Common `xml:"defaultNumberingSystem"`
+ OtherNumberingSystems []*struct {
+ Common
+ Native []*Common `xml:"native"`
+ Traditional []*Common `xml:"traditional"`
+ Finance []*Common `xml:"finance"`
+ } `xml:"otherNumberingSystems"`
+ MinimumGroupingDigits []*Common `xml:"minimumGroupingDigits"`
+ Symbols []*struct {
+ Common
+ NumberSystem string `xml:"numberSystem,attr"`
+ Decimal []*struct {
+ Common
+ NumberSystem string `xml:"numberSystem,attr"`
+ } `xml:"decimal"`
+ Group []*struct {
+ Common
+ NumberSystem string `xml:"numberSystem,attr"`
+ } `xml:"group"`
+ List []*struct {
+ Common
+ NumberSystem string `xml:"numberSystem,attr"`
+ } `xml:"list"`
+ PercentSign []*struct {
+ Common
+ NumberSystem string `xml:"numberSystem,attr"`
+ } `xml:"percentSign"`
+ NativeZeroDigit []*struct {
+ Common
+ NumberSystem string `xml:"numberSystem,attr"`
+ } `xml:"nativeZeroDigit"`
+ PatternDigit []*struct {
+ Common
+ NumberSystem string `xml:"numberSystem,attr"`
+ } `xml:"patternDigit"`
+ PlusSign []*struct {
+ Common
+ NumberSystem string `xml:"numberSystem,attr"`
+ } `xml:"plusSign"`
+ MinusSign []*struct {
+ Common
+ NumberSystem string `xml:"numberSystem,attr"`
+ } `xml:"minusSign"`
+ Exponential []*struct {
+ Common
+ NumberSystem string `xml:"numberSystem,attr"`
+ } `xml:"exponential"`
+ SuperscriptingExponent []*Common `xml:"superscriptingExponent"`
+ PerMille []*struct {
+ Common
+ NumberSystem string `xml:"numberSystem,attr"`
+ } `xml:"perMille"`
+ Infinity []*struct {
+ Common
+ NumberSystem string `xml:"numberSystem,attr"`
+ } `xml:"infinity"`
+ Nan []*struct {
+ Common
+ NumberSystem string `xml:"numberSystem,attr"`
+ } `xml:"nan"`
+ CurrencyDecimal []*struct {
+ Common
+ NumberSystem string `xml:"numberSystem,attr"`
+ } `xml:"currencyDecimal"`
+ CurrencyGroup []*struct {
+ Common
+ NumberSystem string `xml:"numberSystem,attr"`
+ } `xml:"currencyGroup"`
+ TimeSeparator []*Common `xml:"timeSeparator"`
+ } `xml:"symbols"`
+ DecimalFormats []*struct {
+ Common
+ NumberSystem string `xml:"numberSystem,attr"`
+ DecimalFormatLength []*struct {
+ Common
+ DecimalFormat []*struct {
+ Common
+ Pattern []*struct {
+ Common
+ Numbers string `xml:"numbers,attr"`
+ Count string `xml:"count,attr"`
+ } `xml:"pattern"`
+ } `xml:"decimalFormat"`
+ } `xml:"decimalFormatLength"`
+ } `xml:"decimalFormats"`
+ ScientificFormats []*struct {
+ Common
+ NumberSystem string `xml:"numberSystem,attr"`
+ ScientificFormatLength []*struct {
+ Common
+ ScientificFormat []*struct {
+ Common
+ Pattern []*struct {
+ Common
+ Numbers string `xml:"numbers,attr"`
+ Count string `xml:"count,attr"`
+ } `xml:"pattern"`
+ } `xml:"scientificFormat"`
+ } `xml:"scientificFormatLength"`
+ } `xml:"scientificFormats"`
+ PercentFormats []*struct {
+ Common
+ NumberSystem string `xml:"numberSystem,attr"`
+ PercentFormatLength []*struct {
+ Common
+ PercentFormat []*struct {
+ Common
+ Pattern []*struct {
+ Common
+ Numbers string `xml:"numbers,attr"`
+ Count string `xml:"count,attr"`
+ } `xml:"pattern"`
+ } `xml:"percentFormat"`
+ } `xml:"percentFormatLength"`
+ } `xml:"percentFormats"`
+ CurrencyFormats []*struct {
+ Common
+ NumberSystem string `xml:"numberSystem,attr"`
+ CurrencySpacing []*struct {
+ Common
+ BeforeCurrency []*struct {
+ Common
+ CurrencyMatch []*Common `xml:"currencyMatch"`
+ SurroundingMatch []*Common `xml:"surroundingMatch"`
+ InsertBetween []*Common `xml:"insertBetween"`
+ } `xml:"beforeCurrency"`
+ AfterCurrency []*struct {
+ Common
+ CurrencyMatch []*Common `xml:"currencyMatch"`
+ SurroundingMatch []*Common `xml:"surroundingMatch"`
+ InsertBetween []*Common `xml:"insertBetween"`
+ } `xml:"afterCurrency"`
+ } `xml:"currencySpacing"`
+ CurrencyFormatLength []*struct {
+ Common
+ CurrencyFormat []*struct {
+ Common
+ Pattern []*struct {
+ Common
+ Numbers string `xml:"numbers,attr"`
+ Count string `xml:"count,attr"`
+ } `xml:"pattern"`
+ } `xml:"currencyFormat"`
+ } `xml:"currencyFormatLength"`
+ UnitPattern []*struct {
+ Common
+ Count string `xml:"count,attr"`
+ } `xml:"unitPattern"`
+ } `xml:"currencyFormats"`
+ Currencies *struct {
+ Common
+ Currency []*struct {
+ Common
+ Pattern []*struct {
+ Common
+ Numbers string `xml:"numbers,attr"`
+ Count string `xml:"count,attr"`
+ } `xml:"pattern"`
+ DisplayName []*struct {
+ Common
+ Count string `xml:"count,attr"`
+ } `xml:"displayName"`
+ Symbol []*Common `xml:"symbol"`
+ Decimal []*struct {
+ Common
+ NumberSystem string `xml:"numberSystem,attr"`
+ } `xml:"decimal"`
+ Group []*struct {
+ Common
+ NumberSystem string `xml:"numberSystem,attr"`
+ } `xml:"group"`
+ } `xml:"currency"`
+ } `xml:"currencies"`
+ MiscPatterns []*struct {
+ Common
+ NumberSystem string `xml:"numberSystem,attr"`
+ Pattern []*struct {
+ Common
+ Numbers string `xml:"numbers,attr"`
+ Count string `xml:"count,attr"`
+ } `xml:"pattern"`
+ } `xml:"miscPatterns"`
+ MinimalPairs []*struct {
+ Common
+ PluralMinimalPairs []*struct {
+ Common
+ Count string `xml:"count,attr"`
+ } `xml:"pluralMinimalPairs"`
+ OrdinalMinimalPairs []*struct {
+ Common
+ Ordinal string `xml:"ordinal,attr"`
+ } `xml:"ordinalMinimalPairs"`
+ } `xml:"minimalPairs"`
+}
+
+// Version is the version of CLDR from which the XML definitions are generated.
+const Version = "32"