diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
new file mode 100644
index 0000000000000000000000000000000000000000..38d846171c0a152dd2056f24d1fd76eee8de88d7
--- /dev/null
+++ b/Godeps/Godeps.json
@@ -0,0 +1,86 @@
+{
+	"ImportPath": "git.autistici.org/ale/djrandom",
+	"GoVersion": "go1.4",
+	"Packages": [
+		"./..."
+	],
+	"Deps": [
+		{
+			"ImportPath": "code.google.com/p/go.crypto/pbkdf2",
+			"Comment": "null-218",
+			"Rev": "f3cebac2bd11c2bf03c15bfa4c66688ad02a0a40"
+		},
+		{
+			"ImportPath": "code.google.com/p/go.crypto/scrypt",
+			"Comment": "null-218",
+			"Rev": "f3cebac2bd11c2bf03c15bfa4c66688ad02a0a40"
+		},
+		{
+			"ImportPath": "code.google.com/p/go.text/unicode/norm",
+			"Comment": "null-116",
+			"Rev": "5b2527008a4c8988ca9dc6f010ebfb9dae67150b"
+		},
+		{
+			"ImportPath": "code.google.com/p/portaudio-go/portaudio",
+			"Comment": "null-23",
+			"Rev": "8728fce2d74b17b775b5607d8068f6070ab094b0"
+		},
+		{
+			"ImportPath": "code.google.com/p/xsrftoken",
+			"Comment": "null-3",
+			"Rev": "f842d34f33840dbbe5487f1cb77bc5596a94c7ea"
+		},
+		{
+			"ImportPath": "git.autistici.org/ale/gompd",
+			"Rev": "5003e65346abb72a64bdaf9f0d795defbb3b7741"
+		},
+		{
+			"ImportPath": "git.autistici.org/ale/imms/imms-go",
+			"Rev": "ccc6be2dd369e67bbdb95396b749570359b7f71a"
+		},
+		{
+			"ImportPath": "git.autistici.org/ale/rrpc",
+			"Rev": "919ef3e52e3ad09b1dbd36e4095e57bd22da592a"
+		},
+		{
+			"ImportPath": "github.com/cactus/go-statsd-client/statsd",
+			"Rev": "a99092dcd2d2f2a604a6f2502ba9ebba6a1165e5"
+		},
+		{
+			"ImportPath": "github.com/dgryski/dmrgo",
+			"Rev": "6ced6b9098ca85822203953415d808fa8aa35186"
+		},
+		{
+			"ImportPath": "github.com/dustin/go-id3",
+			"Rev": "ba3c7f075a2651675ec0c42d4d4feea290a960b0"
+		},
+		{
+			"ImportPath": "github.com/gorilla/context",
+			"Rev": "708054d61e5a2918b9f4e9700000ee611dcf03f5"
+		},
+		{
+			"ImportPath": "github.com/gorilla/mux",
+			"Rev": "9b36453141c35697401168b07f2c09fcff7721ce"
+		},
+		{
+			"ImportPath": "github.com/gorilla/securecookie",
+			"Rev": "1b0c7f6e9ab3d7f500fd7d50c7ad835ff428139b"
+		},
+		{
+			"ImportPath": "github.com/gorilla/sessions",
+			"Rev": "92e8e64f2e1f8915884b48701e1faa0d2eee0853"
+		},
+		{
+			"ImportPath": "github.com/jmhodges/levigo",
+			"Rev": "2c43dde93d0e056173706534afd514fcbc1dd578"
+		},
+		{
+			"ImportPath": "github.com/mewkiz/pkg/readerutil",
+			"Rev": "94f179fceed13dd6234230593ff7be45fbb770a8"
+		},
+		{
+			"ImportPath": "golang.org/x/text/transform",
+			"Rev": "c980adc4a823548817b9c47d38c6ca6b7d7d8b6a"
+		}
+	]
+}
diff --git a/Godeps/Readme b/Godeps/Readme
new file mode 100644
index 0000000000000000000000000000000000000000..4cdaa53d56d71d3ec11dc34a2811ca57cb6fa35b
--- /dev/null
+++ b/Godeps/Readme
@@ -0,0 +1,5 @@
+This directory tree is generated automatically by godep.
+
+Please do not edit.
+
+See https://github.com/tools/godep for more information.
diff --git a/Godeps/_workspace/.gitignore b/Godeps/_workspace/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..f037d684ef2bd64c0ed8a87d7e85977324b277de
--- /dev/null
+++ b/Godeps/_workspace/.gitignore
@@ -0,0 +1,2 @@
+/pkg
+/bin
diff --git a/Godeps/_workspace/src/code.google.com/p/go.crypto/pbkdf2/pbkdf2.go b/Godeps/_workspace/src/code.google.com/p/go.crypto/pbkdf2/pbkdf2.go
new file mode 100644
index 0000000000000000000000000000000000000000..c02b4d5a70e0b7fd86a90177c4e717b7c8bcf065
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.crypto/pbkdf2/pbkdf2.go
@@ -0,0 +1,77 @@
+// 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 pbkdf2 implements the key derivation function PBKDF2 as defined in RFC
+2898 / PKCS #5 v2.0.
+
+A key derivation function is useful when encrypting data based on a password
+or any other not-fully-random data. It uses a pseudorandom function to derive
+a secure encryption key based on the password.
+
+While v2.0 of the standard defines only one pseudorandom function to use,
+HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved
+Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To
+choose, you can pass the `New` functions from the different SHA packages to
+pbkdf2.Key.
+*/
+package pbkdf2
+
+import (
+	"crypto/hmac"
+	"hash"
+)
+
+// Key derives a key from the password, salt and iteration count, returning a
+// []byte of length keylen that can be used as cryptographic key. The key is
+// derived based on the method described as PBKDF2 with the HMAC variant using
+// the supplied hash function.
+//
+// For example, to use a HMAC-SHA-1 based PBKDF2 key derivation function, you
+// can get a derived key for e.g. AES-256 (which needs a 32-byte key) by
+// doing:
+//
+// 	dk := pbkdf2.Key([]byte("some password"), salt, 4096, 32, sha1.New)
+//
+// Remember to get a good random salt. At least 8 bytes is recommended by the
+// RFC.
+//
+// Using a higher iteration count will increase the cost of an exhaustive
+// search but will also make derivation proportionally slower.
+func Key(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte {
+	prf := hmac.New(h, password)
+	hashLen := prf.Size()
+	numBlocks := (keyLen + hashLen - 1) / hashLen
+
+	var buf [4]byte
+	dk := make([]byte, 0, numBlocks*hashLen)
+	U := make([]byte, hashLen)
+	for block := 1; block <= numBlocks; block++ {
+		// N.B.: || means concatenation, ^ means XOR
+		// for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
+		// U_1 = PRF(password, salt || uint(i))
+		prf.Reset()
+		prf.Write(salt)
+		buf[0] = byte(block >> 24)
+		buf[1] = byte(block >> 16)
+		buf[2] = byte(block >> 8)
+		buf[3] = byte(block)
+		prf.Write(buf[:4])
+		dk = prf.Sum(dk)
+		T := dk[len(dk)-hashLen:]
+		copy(U, T)
+
+		// U_n = PRF(password, U_(n-1))
+		for n := 2; n <= iter; n++ {
+			prf.Reset()
+			prf.Write(U)
+			U = U[:0]
+			U = prf.Sum(U)
+			for x := range U {
+				T[x] ^= U[x]
+			}
+		}
+	}
+	return dk[:keyLen]
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/go.crypto/pbkdf2/pbkdf2_test.go b/Godeps/_workspace/src/code.google.com/p/go.crypto/pbkdf2/pbkdf2_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..1379240610b456556f376f53abf5a2ddc2bc882f
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.crypto/pbkdf2/pbkdf2_test.go
@@ -0,0 +1,157 @@
+// 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 pbkdf2
+
+import (
+	"bytes"
+	"crypto/sha1"
+	"crypto/sha256"
+	"hash"
+	"testing"
+)
+
+type testVector struct {
+	password string
+	salt     string
+	iter     int
+	output   []byte
+}
+
+// Test vectors from RFC 6070, http://tools.ietf.org/html/rfc6070
+var sha1TestVectors = []testVector{
+	{
+		"password",
+		"salt",
+		1,
+		[]byte{
+			0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
+			0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
+			0x2f, 0xe0, 0x37, 0xa6,
+		},
+	},
+	{
+		"password",
+		"salt",
+		2,
+		[]byte{
+			0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,
+			0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,
+			0xd8, 0xde, 0x89, 0x57,
+		},
+	},
+	{
+		"password",
+		"salt",
+		4096,
+		[]byte{
+			0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,
+			0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,
+			0x65, 0xa4, 0x29, 0xc1,
+		},
+	},
+	// // This one takes too long
+	// {
+	// 	"password",
+	// 	"salt",
+	// 	16777216,
+	// 	[]byte{
+	// 		0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4,
+	// 		0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c,
+	// 		0x26, 0x34, 0xe9, 0x84,
+	// 	},
+	// },
+	{
+		"passwordPASSWORDpassword",
+		"saltSALTsaltSALTsaltSALTsaltSALTsalt",
+		4096,
+		[]byte{
+			0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,
+			0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,
+			0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,
+			0x38,
+		},
+	},
+	{
+		"pass\000word",
+		"sa\000lt",
+		4096,
+		[]byte{
+			0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
+			0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3,
+		},
+	},
+}
+
+// Test vectors from
+// http://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors
+var sha256TestVectors = []testVector{
+	{
+		"password",
+		"salt",
+		1,
+		[]byte{
+			0x12, 0x0f, 0xb6, 0xcf, 0xfc, 0xf8, 0xb3, 0x2c,
+			0x43, 0xe7, 0x22, 0x52, 0x56, 0xc4, 0xf8, 0x37,
+			0xa8, 0x65, 0x48, 0xc9,
+		},
+	},
+	{
+		"password",
+		"salt",
+		2,
+		[]byte{
+			0xae, 0x4d, 0x0c, 0x95, 0xaf, 0x6b, 0x46, 0xd3,
+			0x2d, 0x0a, 0xdf, 0xf9, 0x28, 0xf0, 0x6d, 0xd0,
+			0x2a, 0x30, 0x3f, 0x8e,
+		},
+	},
+	{
+		"password",
+		"salt",
+		4096,
+		[]byte{
+			0xc5, 0xe4, 0x78, 0xd5, 0x92, 0x88, 0xc8, 0x41,
+			0xaa, 0x53, 0x0d, 0xb6, 0x84, 0x5c, 0x4c, 0x8d,
+			0x96, 0x28, 0x93, 0xa0,
+		},
+	},
+	{
+		"passwordPASSWORDpassword",
+		"saltSALTsaltSALTsaltSALTsaltSALTsalt",
+		4096,
+		[]byte{
+			0x34, 0x8c, 0x89, 0xdb, 0xcb, 0xd3, 0x2b, 0x2f,
+			0x32, 0xd8, 0x14, 0xb8, 0x11, 0x6e, 0x84, 0xcf,
+			0x2b, 0x17, 0x34, 0x7e, 0xbc, 0x18, 0x00, 0x18,
+			0x1c,
+		},
+	},
+	{
+		"pass\000word",
+		"sa\000lt",
+		4096,
+		[]byte{
+			0x89, 0xb6, 0x9d, 0x05, 0x16, 0xf8, 0x29, 0x89,
+			0x3c, 0x69, 0x62, 0x26, 0x65, 0x0a, 0x86, 0x87,
+		},
+	},
+}
+
+func testHash(t *testing.T, h func() hash.Hash, hashName string, vectors []testVector) {
+	for i, v := range vectors {
+		o := Key([]byte(v.password), []byte(v.salt), v.iter, len(v.output), h)
+		if !bytes.Equal(o, v.output) {
+			t.Errorf("%s %d: expected %x, got %x", hashName, i, v.output, o)
+		}
+	}
+}
+
+func TestWithHMACSHA1(t *testing.T) {
+	testHash(t, sha1.New, "SHA1", sha1TestVectors)
+}
+
+func TestWithHMACSHA256(t *testing.T) {
+	testHash(t, sha256.New, "SHA256", sha256TestVectors)
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/go.crypto/scrypt/scrypt.go b/Godeps/_workspace/src/code.google.com/p/go.crypto/scrypt/scrypt.go
new file mode 100644
index 0000000000000000000000000000000000000000..f7a9fe1a0dd42eed21e1c7bb29cf15c55b232db4
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.crypto/scrypt/scrypt.go
@@ -0,0 +1,243 @@
+// 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 scrypt implements the scrypt key derivation function as defined in
+// Colin Percival's paper "Stronger Key Derivation via Sequential Memory-Hard
+// Functions" (http://www.tarsnap.com/scrypt/scrypt.pdf).
+package scrypt
+
+import (
+	"crypto/sha256"
+	"errors"
+
+	"code.google.com/p/go.crypto/pbkdf2"
+)
+
+const maxInt = int(^uint(0) >> 1)
+
+// blockCopy copies n numbers from src into dst.
+func blockCopy(dst, src []uint32, n int) {
+	copy(dst, src[:n])
+}
+
+// blockXOR XORs numbers from dst with n numbers from src.
+func blockXOR(dst, src []uint32, n int) {
+	for i, v := range src[:n] {
+		dst[i] ^= v
+	}
+}
+
+// salsaXOR applies Salsa20/8 to the XOR of 16 numbers from tmp and in,
+// and puts the result into both both tmp and out.
+func salsaXOR(tmp *[16]uint32, in, out []uint32) {
+	w0 := tmp[0] ^ in[0]
+	w1 := tmp[1] ^ in[1]
+	w2 := tmp[2] ^ in[2]
+	w3 := tmp[3] ^ in[3]
+	w4 := tmp[4] ^ in[4]
+	w5 := tmp[5] ^ in[5]
+	w6 := tmp[6] ^ in[6]
+	w7 := tmp[7] ^ in[7]
+	w8 := tmp[8] ^ in[8]
+	w9 := tmp[9] ^ in[9]
+	w10 := tmp[10] ^ in[10]
+	w11 := tmp[11] ^ in[11]
+	w12 := tmp[12] ^ in[12]
+	w13 := tmp[13] ^ in[13]
+	w14 := tmp[14] ^ in[14]
+	w15 := tmp[15] ^ in[15]
+
+	x0, x1, x2, x3, x4, x5, x6, x7, x8 := w0, w1, w2, w3, w4, w5, w6, w7, w8
+	x9, x10, x11, x12, x13, x14, x15 := w9, w10, w11, w12, w13, w14, w15
+
+	for i := 0; i < 8; i += 2 {
+		u := x0 + x12
+		x4 ^= u<<7 | u>>(32-7)
+		u = x4 + x0
+		x8 ^= u<<9 | u>>(32-9)
+		u = x8 + x4
+		x12 ^= u<<13 | u>>(32-13)
+		u = x12 + x8
+		x0 ^= u<<18 | u>>(32-18)
+
+		u = x5 + x1
+		x9 ^= u<<7 | u>>(32-7)
+		u = x9 + x5
+		x13 ^= u<<9 | u>>(32-9)
+		u = x13 + x9
+		x1 ^= u<<13 | u>>(32-13)
+		u = x1 + x13
+		x5 ^= u<<18 | u>>(32-18)
+
+		u = x10 + x6
+		x14 ^= u<<7 | u>>(32-7)
+		u = x14 + x10
+		x2 ^= u<<9 | u>>(32-9)
+		u = x2 + x14
+		x6 ^= u<<13 | u>>(32-13)
+		u = x6 + x2
+		x10 ^= u<<18 | u>>(32-18)
+
+		u = x15 + x11
+		x3 ^= u<<7 | u>>(32-7)
+		u = x3 + x15
+		x7 ^= u<<9 | u>>(32-9)
+		u = x7 + x3
+		x11 ^= u<<13 | u>>(32-13)
+		u = x11 + x7
+		x15 ^= u<<18 | u>>(32-18)
+
+		u = x0 + x3
+		x1 ^= u<<7 | u>>(32-7)
+		u = x1 + x0
+		x2 ^= u<<9 | u>>(32-9)
+		u = x2 + x1
+		x3 ^= u<<13 | u>>(32-13)
+		u = x3 + x2
+		x0 ^= u<<18 | u>>(32-18)
+
+		u = x5 + x4
+		x6 ^= u<<7 | u>>(32-7)
+		u = x6 + x5
+		x7 ^= u<<9 | u>>(32-9)
+		u = x7 + x6
+		x4 ^= u<<13 | u>>(32-13)
+		u = x4 + x7
+		x5 ^= u<<18 | u>>(32-18)
+
+		u = x10 + x9
+		x11 ^= u<<7 | u>>(32-7)
+		u = x11 + x10
+		x8 ^= u<<9 | u>>(32-9)
+		u = x8 + x11
+		x9 ^= u<<13 | u>>(32-13)
+		u = x9 + x8
+		x10 ^= u<<18 | u>>(32-18)
+
+		u = x15 + x14
+		x12 ^= u<<7 | u>>(32-7)
+		u = x12 + x15
+		x13 ^= u<<9 | u>>(32-9)
+		u = x13 + x12
+		x14 ^= u<<13 | u>>(32-13)
+		u = x14 + x13
+		x15 ^= u<<18 | u>>(32-18)
+	}
+	x0 += w0
+	x1 += w1
+	x2 += w2
+	x3 += w3
+	x4 += w4
+	x5 += w5
+	x6 += w6
+	x7 += w7
+	x8 += w8
+	x9 += w9
+	x10 += w10
+	x11 += w11
+	x12 += w12
+	x13 += w13
+	x14 += w14
+	x15 += w15
+
+	out[0], tmp[0] = x0, x0
+	out[1], tmp[1] = x1, x1
+	out[2], tmp[2] = x2, x2
+	out[3], tmp[3] = x3, x3
+	out[4], tmp[4] = x4, x4
+	out[5], tmp[5] = x5, x5
+	out[6], tmp[6] = x6, x6
+	out[7], tmp[7] = x7, x7
+	out[8], tmp[8] = x8, x8
+	out[9], tmp[9] = x9, x9
+	out[10], tmp[10] = x10, x10
+	out[11], tmp[11] = x11, x11
+	out[12], tmp[12] = x12, x12
+	out[13], tmp[13] = x13, x13
+	out[14], tmp[14] = x14, x14
+	out[15], tmp[15] = x15, x15
+}
+
+func blockMix(tmp *[16]uint32, in, out []uint32, r int) {
+	blockCopy(tmp[:], in[(2*r-1)*16:], 16)
+	for i := 0; i < 2*r; i += 2 {
+		salsaXOR(tmp, in[i*16:], out[i*8:])
+		salsaXOR(tmp, in[i*16+16:], out[i*8+r*16:])
+	}
+}
+
+func integer(b []uint32, r int) uint64 {
+	j := (2*r - 1) * 16
+	return uint64(b[j]) | uint64(b[j+1])<<32
+}
+
+func smix(b []byte, r, N int, v, xy []uint32) {
+	var tmp [16]uint32
+	x := xy
+	y := xy[32*r:]
+
+	j := 0
+	for i := 0; i < 32*r; i++ {
+		x[i] = uint32(b[j]) | uint32(b[j+1])<<8 | uint32(b[j+2])<<16 | uint32(b[j+3])<<24
+		j += 4
+	}
+	for i := 0; i < N; i += 2 {
+		blockCopy(v[i*(32*r):], x, 32*r)
+		blockMix(&tmp, x, y, r)
+
+		blockCopy(v[(i+1)*(32*r):], y, 32*r)
+		blockMix(&tmp, y, x, r)
+	}
+	for i := 0; i < N; i += 2 {
+		j := int(integer(x, r) & uint64(N-1))
+		blockXOR(x, v[j*(32*r):], 32*r)
+		blockMix(&tmp, x, y, r)
+
+		j = int(integer(y, r) & uint64(N-1))
+		blockXOR(y, v[j*(32*r):], 32*r)
+		blockMix(&tmp, y, x, r)
+	}
+	j = 0
+	for _, v := range x[:32*r] {
+		b[j+0] = byte(v >> 0)
+		b[j+1] = byte(v >> 8)
+		b[j+2] = byte(v >> 16)
+		b[j+3] = byte(v >> 24)
+		j += 4
+	}
+}
+
+// Key derives a key from the password, salt, and cost parameters, returning
+// a byte slice of length keyLen that can be used as cryptographic key.
+//
+// N is a CPU/memory cost parameter, which must be a power of two greater than 1.
+// r and p must satisfy r * p < 2³⁰. If the parameters do not satisfy the
+// limits, the function returns a nil byte slice and an error.
+//
+// For example, you can get a derived key for e.g. AES-256 (which needs a
+// 32-byte key) by doing:
+//
+//      dk := scrypt.Key([]byte("some password"), salt, 16384, 8, 1, 32)
+//
+// The recommended parameters for interactive logins as of 2009 are N=16384,
+// r=8, p=1. They should be increased as memory latency and CPU parallelism
+// increases. Remember to get a good random salt.
+func Key(password, salt []byte, N, r, p, keyLen int) ([]byte, error) {
+	if N <= 1 || N&(N-1) != 0 {
+		return nil, errors.New("scrypt: N must be > 1 and a power of 2")
+	}
+	if uint64(r)*uint64(p) >= 1<<30 || r > maxInt/128/p || r > maxInt/256 || N > maxInt/128/r {
+		return nil, errors.New("scrypt: parameters are too large")
+	}
+
+	xy := make([]uint32, 64*r)
+	v := make([]uint32, 32*N*r)
+	b := pbkdf2.Key(password, salt, 1, p*128*r, sha256.New)
+
+	for i := 0; i < p; i++ {
+		smix(b[i*128*r:], r, N, v, xy)
+	}
+
+	return pbkdf2.Key(password, b, 1, keyLen, sha256.New), nil
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/go.crypto/scrypt/scrypt_test.go b/Godeps/_workspace/src/code.google.com/p/go.crypto/scrypt/scrypt_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..e096c3a31ab6ab757296c7b32293d62fab8eea96
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.crypto/scrypt/scrypt_test.go
@@ -0,0 +1,160 @@
+// 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 scrypt
+
+import (
+	"bytes"
+	"testing"
+)
+
+type testVector struct {
+	password string
+	salt     string
+	N, r, p  int
+	output   []byte
+}
+
+var good = []testVector{
+	{
+		"password",
+		"salt",
+		2, 10, 10,
+		[]byte{
+			0x48, 0x2c, 0x85, 0x8e, 0x22, 0x90, 0x55, 0xe6, 0x2f,
+			0x41, 0xe0, 0xec, 0x81, 0x9a, 0x5e, 0xe1, 0x8b, 0xdb,
+			0x87, 0x25, 0x1a, 0x53, 0x4f, 0x75, 0xac, 0xd9, 0x5a,
+			0xc5, 0xe5, 0xa, 0xa1, 0x5f,
+		},
+	},
+	{
+		"password",
+		"salt",
+		16, 100, 100,
+		[]byte{
+			0x88, 0xbd, 0x5e, 0xdb, 0x52, 0xd1, 0xdd, 0x0, 0x18,
+			0x87, 0x72, 0xad, 0x36, 0x17, 0x12, 0x90, 0x22, 0x4e,
+			0x74, 0x82, 0x95, 0x25, 0xb1, 0x8d, 0x73, 0x23, 0xa5,
+			0x7f, 0x91, 0x96, 0x3c, 0x37,
+		},
+	},
+	{
+		"this is a long \000 password",
+		"and this is a long \000 salt",
+		16384, 8, 1,
+		[]byte{
+			0xc3, 0xf1, 0x82, 0xee, 0x2d, 0xec, 0x84, 0x6e, 0x70,
+			0xa6, 0x94, 0x2f, 0xb5, 0x29, 0x98, 0x5a, 0x3a, 0x09,
+			0x76, 0x5e, 0xf0, 0x4c, 0x61, 0x29, 0x23, 0xb1, 0x7f,
+			0x18, 0x55, 0x5a, 0x37, 0x07, 0x6d, 0xeb, 0x2b, 0x98,
+			0x30, 0xd6, 0x9d, 0xe5, 0x49, 0x26, 0x51, 0xe4, 0x50,
+			0x6a, 0xe5, 0x77, 0x6d, 0x96, 0xd4, 0x0f, 0x67, 0xaa,
+			0xee, 0x37, 0xe1, 0x77, 0x7b, 0x8a, 0xd5, 0xc3, 0x11,
+			0x14, 0x32, 0xbb, 0x3b, 0x6f, 0x7e, 0x12, 0x64, 0x40,
+			0x18, 0x79, 0xe6, 0x41, 0xae,
+		},
+	},
+	{
+		"p",
+		"s",
+		2, 1, 1,
+		[]byte{
+			0x48, 0xb0, 0xd2, 0xa8, 0xa3, 0x27, 0x26, 0x11, 0x98,
+			0x4c, 0x50, 0xeb, 0xd6, 0x30, 0xaf, 0x52,
+		},
+	},
+
+	{
+		"",
+		"",
+		16, 1, 1,
+		[]byte{
+			0x77, 0xd6, 0x57, 0x62, 0x38, 0x65, 0x7b, 0x20, 0x3b,
+			0x19, 0xca, 0x42, 0xc1, 0x8a, 0x04, 0x97, 0xf1, 0x6b,
+			0x48, 0x44, 0xe3, 0x07, 0x4a, 0xe8, 0xdf, 0xdf, 0xfa,
+			0x3f, 0xed, 0xe2, 0x14, 0x42, 0xfc, 0xd0, 0x06, 0x9d,
+			0xed, 0x09, 0x48, 0xf8, 0x32, 0x6a, 0x75, 0x3a, 0x0f,
+			0xc8, 0x1f, 0x17, 0xe8, 0xd3, 0xe0, 0xfb, 0x2e, 0x0d,
+			0x36, 0x28, 0xcf, 0x35, 0xe2, 0x0c, 0x38, 0xd1, 0x89,
+			0x06,
+		},
+	},
+	{
+		"password",
+		"NaCl",
+		1024, 8, 16,
+		[]byte{
+			0xfd, 0xba, 0xbe, 0x1c, 0x9d, 0x34, 0x72, 0x00, 0x78,
+			0x56, 0xe7, 0x19, 0x0d, 0x01, 0xe9, 0xfe, 0x7c, 0x6a,
+			0xd7, 0xcb, 0xc8, 0x23, 0x78, 0x30, 0xe7, 0x73, 0x76,
+			0x63, 0x4b, 0x37, 0x31, 0x62, 0x2e, 0xaf, 0x30, 0xd9,
+			0x2e, 0x22, 0xa3, 0x88, 0x6f, 0xf1, 0x09, 0x27, 0x9d,
+			0x98, 0x30, 0xda, 0xc7, 0x27, 0xaf, 0xb9, 0x4a, 0x83,
+			0xee, 0x6d, 0x83, 0x60, 0xcb, 0xdf, 0xa2, 0xcc, 0x06,
+			0x40,
+		},
+	},
+	{
+		"pleaseletmein", "SodiumChloride",
+		16384, 8, 1,
+		[]byte{
+			0x70, 0x23, 0xbd, 0xcb, 0x3a, 0xfd, 0x73, 0x48, 0x46,
+			0x1c, 0x06, 0xcd, 0x81, 0xfd, 0x38, 0xeb, 0xfd, 0xa8,
+			0xfb, 0xba, 0x90, 0x4f, 0x8e, 0x3e, 0xa9, 0xb5, 0x43,
+			0xf6, 0x54, 0x5d, 0xa1, 0xf2, 0xd5, 0x43, 0x29, 0x55,
+			0x61, 0x3f, 0x0f, 0xcf, 0x62, 0xd4, 0x97, 0x05, 0x24,
+			0x2a, 0x9a, 0xf9, 0xe6, 0x1e, 0x85, 0xdc, 0x0d, 0x65,
+			0x1e, 0x40, 0xdf, 0xcf, 0x01, 0x7b, 0x45, 0x57, 0x58,
+			0x87,
+		},
+	},
+	/*
+		// Disabled: needs 1 GiB RAM and takes too long for a simple test.
+		{
+			"pleaseletmein", "SodiumChloride",
+			1048576, 8, 1,
+			[]byte{
+				0x21, 0x01, 0xcb, 0x9b, 0x6a, 0x51, 0x1a, 0xae, 0xad,
+				0xdb, 0xbe, 0x09, 0xcf, 0x70, 0xf8, 0x81, 0xec, 0x56,
+				0x8d, 0x57, 0x4a, 0x2f, 0xfd, 0x4d, 0xab, 0xe5, 0xee,
+				0x98, 0x20, 0xad, 0xaa, 0x47, 0x8e, 0x56, 0xfd, 0x8f,
+				0x4b, 0xa5, 0xd0, 0x9f, 0xfa, 0x1c, 0x6d, 0x92, 0x7c,
+				0x40, 0xf4, 0xc3, 0x37, 0x30, 0x40, 0x49, 0xe8, 0xa9,
+				0x52, 0xfb, 0xcb, 0xf4, 0x5c, 0x6f, 0xa7, 0x7a, 0x41,
+				0xa4,
+			},
+		},
+	*/
+}
+
+var bad = []testVector{
+	{"p", "s", 0, 1, 1, nil},                    // N == 0
+	{"p", "s", 1, 1, 1, nil},                    // N == 1
+	{"p", "s", 7, 8, 1, nil},                    // N is not power of 2
+	{"p", "s", 16, maxInt / 2, maxInt / 2, nil}, // p * r too large
+}
+
+func TestKey(t *testing.T) {
+	for i, v := range good {
+		k, err := Key([]byte(v.password), []byte(v.salt), v.N, v.r, v.p, len(v.output))
+		if err != nil {
+			t.Errorf("%d: got unexpected error: %s", i, err)
+		}
+		if !bytes.Equal(k, v.output) {
+			t.Errorf("%d: expected %x, got %x", i, v.output, k)
+		}
+	}
+	for i, v := range bad {
+		_, err := Key([]byte(v.password), []byte(v.salt), v.N, v.r, v.p, 32)
+		if err == nil {
+			t.Errorf("%d: expected error, got nil", i)
+		}
+	}
+}
+
+func BenchmarkKey(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Key([]byte("password"), []byte("salt"), 16384, 8, 1, 64)
+	}
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/Makefile b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..b4f5d359077589b5351f0310562d6b03862f233a
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/Makefile
@@ -0,0 +1,23 @@
+# 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.
+
+maketables: maketables.go triegen.go
+	go build $^
+
+normregtest: normregtest.go
+	go build $^
+
+tables:	maketables
+	./maketables > tables.go
+	gofmt -w tables.go
+
+# Downloads from www.unicode.org, so not part
+# of standard test scripts.
+test: testtables regtest
+
+testtables: maketables
+	./maketables -test > data_test.go && go test -tags=test
+
+regtest: normregtest
+	./normregtest
diff --git a/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/composition.go b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/composition.go
new file mode 100644
index 0000000000000000000000000000000000000000..d17b278adc347b5b61b2c3e2784e3e2b4841721c
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/composition.go
@@ -0,0 +1,514 @@
+// 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 norm
+
+import "unicode/utf8"
+
+const (
+	maxNonStarters = 30
+	// The maximum number of characters needed for a buffer is
+	// maxNonStarters + 1 for the starter + 1 for the GCJ
+	maxBufferSize    = maxNonStarters + 2
+	maxNFCExpansion  = 3  // NFC(0x1D160)
+	maxNFKCExpansion = 18 // NFKC(0xFDFA)
+
+	maxByteBufferSize = utf8.UTFMax * maxBufferSize // 128
+)
+
+// ssState is used for reporting the segment state after inserting a rune.
+// It is returned by streamSafe.next.
+type ssState int
+
+const (
+	// Indicates a rune was successfully added to the segment.
+	ssSuccess ssState = iota
+	// Indicates a rune starts a new segment and should not be added.
+	ssStarter
+	// Indicates a rune caused a segment overflow and a CGJ should be inserted.
+	ssOverflow
+)
+
+// streamSafe implements the policy of when a CGJ should be inserted.
+type streamSafe uint8
+
+// mkStreamSafe is a shorthand for declaring a streamSafe var and calling
+// first on it.
+func mkStreamSafe(p Properties) streamSafe {
+	return streamSafe(p.nTrailingNonStarters())
+}
+
+// first inserts the first rune of a segment.
+func (ss *streamSafe) first(p Properties) {
+	if *ss != 0 {
+		panic("!= 0")
+	}
+	*ss = streamSafe(p.nTrailingNonStarters())
+}
+
+// insert returns a ssState value to indicate whether a rune represented by p
+// can be inserted.
+func (ss *streamSafe) next(p Properties) ssState {
+	if *ss > maxNonStarters {
+		panic("streamSafe was not reset")
+	}
+	n := p.nLeadingNonStarters()
+	if *ss += streamSafe(n); *ss > maxNonStarters {
+		*ss = 0
+		return ssOverflow
+	}
+	// The Stream-Safe Text Processing prescribes that the counting can stop
+	// as soon as a starter is encountered. However, there are some starters,
+	// like Jamo V and T, that can combine with other runes, leaving their
+	// successive non-starters appended to the previous, possibly causing an
+	// overflow. We will therefore consider any rune with a non-zero nLead to
+	// be a non-starter. Note that it always hold that if nLead > 0 then
+	// nLead == nTrail.
+	if n == 0 {
+		*ss = 0
+		return ssStarter
+	}
+	return ssSuccess
+}
+
+// backwards is used for checking for overflow and segment starts
+// when traversing a string backwards. Users do not need to call first
+// for the first rune. The state of the streamSafe retains the count of
+// the non-starters loaded.
+func (ss *streamSafe) backwards(p Properties) ssState {
+	if *ss > maxNonStarters {
+		panic("streamSafe was not reset")
+	}
+	c := *ss + streamSafe(p.nTrailingNonStarters())
+	if c > maxNonStarters {
+		return ssOverflow
+	}
+	*ss = c
+	if p.nLeadingNonStarters() == 0 {
+		return ssStarter
+	}
+	return ssSuccess
+}
+
+func (ss streamSafe) isMax() bool {
+	return ss == maxNonStarters
+}
+
+// GraphemeJoiner is inserted after maxNonStarters non-starter runes.
+const GraphemeJoiner = "\u034F"
+
+// reorderBuffer is used to normalize a single segment.  Characters inserted with
+// insert are decomposed and reordered based on CCC. The compose method can
+// be used to recombine characters.  Note that the byte buffer does not hold
+// the UTF-8 characters in order.  Only the rune array is maintained in sorted
+// order. flush writes the resulting segment to a byte array.
+type reorderBuffer struct {
+	rune  [maxBufferSize]Properties // Per character info.
+	byte  [maxByteBufferSize]byte   // UTF-8 buffer. Referenced by runeInfo.pos.
+	nbyte uint8                     // Number or bytes.
+	ss    streamSafe                // For limiting length of non-starter sequence.
+	nrune int                       // Number of runeInfos.
+	f     formInfo
+
+	src      input
+	nsrc     int
+	tmpBytes input
+
+	out    []byte
+	flushF func(*reorderBuffer) bool
+}
+
+func (rb *reorderBuffer) init(f Form, src []byte) {
+	rb.f = *formTable[f]
+	rb.src.setBytes(src)
+	rb.nsrc = len(src)
+	rb.ss = 0
+}
+
+func (rb *reorderBuffer) initString(f Form, src string) {
+	rb.f = *formTable[f]
+	rb.src.setString(src)
+	rb.nsrc = len(src)
+	rb.ss = 0
+}
+
+func (rb *reorderBuffer) setFlusher(out []byte, f func(*reorderBuffer) bool) {
+	rb.out = out
+	rb.flushF = f
+}
+
+// reset discards all characters from the buffer.
+func (rb *reorderBuffer) reset() {
+	rb.nrune = 0
+	rb.nbyte = 0
+	rb.ss = 0
+}
+
+func (rb *reorderBuffer) doFlush() bool {
+	if rb.f.composing {
+		rb.compose()
+	}
+	res := rb.flushF(rb)
+	rb.reset()
+	return res
+}
+
+// appendFlush appends the normalized segment to rb.out.
+func appendFlush(rb *reorderBuffer) bool {
+	for i := 0; i < rb.nrune; i++ {
+		start := rb.rune[i].pos
+		end := start + rb.rune[i].size
+		rb.out = append(rb.out, rb.byte[start:end]...)
+	}
+	return true
+}
+
+// flush appends the normalized segment to out and resets rb.
+func (rb *reorderBuffer) flush(out []byte) []byte {
+	for i := 0; i < rb.nrune; i++ {
+		start := rb.rune[i].pos
+		end := start + rb.rune[i].size
+		out = append(out, rb.byte[start:end]...)
+	}
+	rb.reset()
+	return out
+}
+
+// flushCopy copies the normalized segment to buf and resets rb.
+// It returns the number of bytes written to buf.
+func (rb *reorderBuffer) flushCopy(buf []byte) int {
+	p := 0
+	for i := 0; i < rb.nrune; i++ {
+		runep := rb.rune[i]
+		p += copy(buf[p:], rb.byte[runep.pos:runep.pos+runep.size])
+	}
+	rb.reset()
+	return p
+}
+
+// insertOrdered inserts a rune in the buffer, ordered by Canonical Combining Class.
+// It returns false if the buffer is not large enough to hold the rune.
+// It is used internally by insert and insertString only.
+func (rb *reorderBuffer) insertOrdered(info Properties) {
+	n := rb.nrune
+	b := rb.rune[:]
+	cc := info.ccc
+	if cc > 0 {
+		// Find insertion position + move elements to make room.
+		for ; n > 0; n-- {
+			if b[n-1].ccc <= cc {
+				break
+			}
+			b[n] = b[n-1]
+		}
+	}
+	rb.nrune += 1
+	pos := uint8(rb.nbyte)
+	rb.nbyte += utf8.UTFMax
+	info.pos = pos
+	b[n] = info
+}
+
+// insertErr is an error code returned by insert. Using this type instead
+// of error improves performance up to 20% for many of the benchmarks.
+type insertErr int
+
+const (
+	iSuccess insertErr = -iota
+	iShortDst
+	iShortSrc
+)
+
+// insertFlush inserts the given rune in the buffer ordered by CCC.
+// If a decomposition with multiple segments are encountered, they leading
+// ones are flushed.
+// It returns a non-zero error code if the rune was not inserted.
+func (rb *reorderBuffer) insertFlush(src input, i int, info Properties) insertErr {
+	if rune := src.hangul(i); rune != 0 {
+		rb.decomposeHangul(rune)
+		return iSuccess
+	}
+	if info.hasDecomposition() {
+		return rb.insertDecomposed(info.Decomposition())
+	}
+	rb.insertSingle(src, i, info)
+	return iSuccess
+}
+
+// insertUnsafe inserts the given rune in the buffer ordered by CCC.
+// It is assumed there is sufficient space to hold the runes. It is the
+// responsibility of the caller to ensure this. This can be done by checking
+// the state returned by the streamSafe type.
+func (rb *reorderBuffer) insertUnsafe(src input, i int, info Properties) {
+	if rune := src.hangul(i); rune != 0 {
+		rb.decomposeHangul(rune)
+	}
+	if info.hasDecomposition() {
+		// TODO: inline.
+		rb.insertDecomposed(info.Decomposition())
+	} else {
+		rb.insertSingle(src, i, info)
+	}
+}
+
+// insertDecomposed inserts an entry in to the reorderBuffer for each rune
+// in dcomp. dcomp must be a sequence of decomposed UTF-8-encoded runes.
+// It flushes the buffer on each new segment start.
+func (rb *reorderBuffer) insertDecomposed(dcomp []byte) insertErr {
+	rb.tmpBytes.setBytes(dcomp)
+	for i := 0; i < len(dcomp); {
+		info := rb.f.info(rb.tmpBytes, i)
+		if info.BoundaryBefore() && rb.nrune > 0 && !rb.doFlush() {
+			return iShortDst
+		}
+		i += copy(rb.byte[rb.nbyte:], dcomp[i:i+int(info.size)])
+		rb.insertOrdered(info)
+	}
+	return iSuccess
+}
+
+// insertSingle inserts an entry in the reorderBuffer for the rune at
+// position i. info is the runeInfo for the rune at position i.
+func (rb *reorderBuffer) insertSingle(src input, i int, info Properties) {
+	src.copySlice(rb.byte[rb.nbyte:], i, i+int(info.size))
+	rb.insertOrdered(info)
+}
+
+// insertCGJ inserts a Combining Grapheme Joiner (0x034f) into rb.
+func (rb *reorderBuffer) insertCGJ() {
+	rb.insertSingle(input{str: GraphemeJoiner}, 0, Properties{size: uint8(len(GraphemeJoiner))})
+}
+
+// appendRune inserts a rune at the end of the buffer. It is used for Hangul.
+func (rb *reorderBuffer) appendRune(r rune) {
+	bn := rb.nbyte
+	sz := utf8.EncodeRune(rb.byte[bn:], rune(r))
+	rb.nbyte += utf8.UTFMax
+	rb.rune[rb.nrune] = Properties{pos: bn, size: uint8(sz)}
+	rb.nrune++
+}
+
+// assignRune sets a rune at position pos. It is used for Hangul and recomposition.
+func (rb *reorderBuffer) assignRune(pos int, r rune) {
+	bn := rb.rune[pos].pos
+	sz := utf8.EncodeRune(rb.byte[bn:], rune(r))
+	rb.rune[pos] = Properties{pos: bn, size: uint8(sz)}
+}
+
+// runeAt returns the rune at position n. It is used for Hangul and recomposition.
+func (rb *reorderBuffer) runeAt(n int) rune {
+	inf := rb.rune[n]
+	r, _ := utf8.DecodeRune(rb.byte[inf.pos : inf.pos+inf.size])
+	return r
+}
+
+// bytesAt returns the UTF-8 encoding of the rune at position n.
+// It is used for Hangul and recomposition.
+func (rb *reorderBuffer) bytesAt(n int) []byte {
+	inf := rb.rune[n]
+	return rb.byte[inf.pos : int(inf.pos)+int(inf.size)]
+}
+
+// For Hangul we combine algorithmically, instead of using tables.
+const (
+	hangulBase  = 0xAC00 // UTF-8(hangulBase) -> EA B0 80
+	hangulBase0 = 0xEA
+	hangulBase1 = 0xB0
+	hangulBase2 = 0x80
+
+	hangulEnd  = hangulBase + jamoLVTCount // UTF-8(0xD7A4) -> ED 9E A4
+	hangulEnd0 = 0xED
+	hangulEnd1 = 0x9E
+	hangulEnd2 = 0xA4
+
+	jamoLBase  = 0x1100 // UTF-8(jamoLBase) -> E1 84 00
+	jamoLBase0 = 0xE1
+	jamoLBase1 = 0x84
+	jamoLEnd   = 0x1113
+	jamoVBase  = 0x1161
+	jamoVEnd   = 0x1176
+	jamoTBase  = 0x11A7
+	jamoTEnd   = 0x11C3
+
+	jamoTCount   = 28
+	jamoVCount   = 21
+	jamoVTCount  = 21 * 28
+	jamoLVTCount = 19 * 21 * 28
+)
+
+const hangulUTF8Size = 3
+
+func isHangul(b []byte) bool {
+	if len(b) < hangulUTF8Size {
+		return false
+	}
+	b0 := b[0]
+	if b0 < hangulBase0 {
+		return false
+	}
+	b1 := b[1]
+	switch {
+	case b0 == hangulBase0:
+		return b1 >= hangulBase1
+	case b0 < hangulEnd0:
+		return true
+	case b0 > hangulEnd0:
+		return false
+	case b1 < hangulEnd1:
+		return true
+	}
+	return b1 == hangulEnd1 && b[2] < hangulEnd2
+}
+
+func isHangulString(b string) bool {
+	if len(b) < hangulUTF8Size {
+		return false
+	}
+	b0 := b[0]
+	if b0 < hangulBase0 {
+		return false
+	}
+	b1 := b[1]
+	switch {
+	case b0 == hangulBase0:
+		return b1 >= hangulBase1
+	case b0 < hangulEnd0:
+		return true
+	case b0 > hangulEnd0:
+		return false
+	case b1 < hangulEnd1:
+		return true
+	}
+	return b1 == hangulEnd1 && b[2] < hangulEnd2
+}
+
+// Caller must ensure len(b) >= 2.
+func isJamoVT(b []byte) bool {
+	// True if (rune & 0xff00) == jamoLBase
+	return b[0] == jamoLBase0 && (b[1]&0xFC) == jamoLBase1
+}
+
+func isHangulWithoutJamoT(b []byte) bool {
+	c, _ := utf8.DecodeRune(b)
+	c -= hangulBase
+	return c < jamoLVTCount && c%jamoTCount == 0
+}
+
+// decomposeHangul writes the decomposed Hangul to buf and returns the number
+// of bytes written.  len(buf) should be at least 9.
+func decomposeHangul(buf []byte, r rune) int {
+	const JamoUTF8Len = 3
+	r -= hangulBase
+	x := r % jamoTCount
+	r /= jamoTCount
+	utf8.EncodeRune(buf, jamoLBase+r/jamoVCount)
+	utf8.EncodeRune(buf[JamoUTF8Len:], jamoVBase+r%jamoVCount)
+	if x != 0 {
+		utf8.EncodeRune(buf[2*JamoUTF8Len:], jamoTBase+x)
+		return 3 * JamoUTF8Len
+	}
+	return 2 * JamoUTF8Len
+}
+
+// decomposeHangul algorithmically decomposes a Hangul rune into
+// its Jamo components.
+// See http://unicode.org/reports/tr15/#Hangul for details on decomposing Hangul.
+func (rb *reorderBuffer) decomposeHangul(r rune) {
+	r -= hangulBase
+	x := r % jamoTCount
+	r /= jamoTCount
+	rb.appendRune(jamoLBase + r/jamoVCount)
+	rb.appendRune(jamoVBase + r%jamoVCount)
+	if x != 0 {
+		rb.appendRune(jamoTBase + x)
+	}
+}
+
+// combineHangul algorithmically combines Jamo character components into Hangul.
+// See http://unicode.org/reports/tr15/#Hangul for details on combining Hangul.
+func (rb *reorderBuffer) combineHangul(s, i, k int) {
+	b := rb.rune[:]
+	bn := rb.nrune
+	for ; i < bn; i++ {
+		cccB := b[k-1].ccc
+		cccC := b[i].ccc
+		if cccB == 0 {
+			s = k - 1
+		}
+		if s != k-1 && cccB >= cccC {
+			// b[i] is blocked by greater-equal cccX below it
+			b[k] = b[i]
+			k++
+		} else {
+			l := rb.runeAt(s) // also used to compare to hangulBase
+			v := rb.runeAt(i) // also used to compare to jamoT
+			switch {
+			case jamoLBase <= l && l < jamoLEnd &&
+				jamoVBase <= v && v < jamoVEnd:
+				// 11xx plus 116x to LV
+				rb.assignRune(s, hangulBase+
+					(l-jamoLBase)*jamoVTCount+(v-jamoVBase)*jamoTCount)
+			case hangulBase <= l && l < hangulEnd &&
+				jamoTBase < v && v < jamoTEnd &&
+				((l-hangulBase)%jamoTCount) == 0:
+				// ACxx plus 11Ax to LVT
+				rb.assignRune(s, l+v-jamoTBase)
+			default:
+				b[k] = b[i]
+				k++
+			}
+		}
+	}
+	rb.nrune = k
+}
+
+// compose recombines the runes in the buffer.
+// It should only be used to recompose a single segment, as it will not
+// handle alternations between Hangul and non-Hangul characters correctly.
+func (rb *reorderBuffer) compose() {
+	// UAX #15, section X5 , including Corrigendum #5
+	// "In any character sequence beginning with starter S, a character C is
+	//  blocked from S if and only if there is some character B between S
+	//  and C, and either B is a starter or it has the same or higher
+	//  combining class as C."
+	bn := rb.nrune
+	if bn == 0 {
+		return
+	}
+	k := 1
+	b := rb.rune[:]
+	for s, i := 0, 1; i < bn; i++ {
+		if isJamoVT(rb.bytesAt(i)) {
+			// Redo from start in Hangul mode. Necessary to support
+			// U+320E..U+321E in NFKC mode.
+			rb.combineHangul(s, i, k)
+			return
+		}
+		ii := b[i]
+		// We can only use combineForward as a filter if we later
+		// get the info for the combined character. This is more
+		// expensive than using the filter. Using combinesBackward()
+		// is safe.
+		if ii.combinesBackward() {
+			cccB := b[k-1].ccc
+			cccC := ii.ccc
+			blocked := false // b[i] blocked by starter or greater or equal CCC?
+			if cccB == 0 {
+				s = k - 1
+			} else {
+				blocked = s != k-1 && cccB >= cccC
+			}
+			if !blocked {
+				combined := combine(rb.runeAt(s), rb.runeAt(i))
+				if combined != 0 {
+					rb.assignRune(s, combined)
+					continue
+				}
+			}
+		}
+		b[k] = b[i]
+		k++
+	}
+	rb.nrune = k
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/composition_test.go b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/composition_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..11684069d3386db2858336a509f85255cbeb523e
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/composition_test.go
@@ -0,0 +1,130 @@
+// 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 norm
+
+import "testing"
+
+// TestCase is used for most tests.
+type TestCase struct {
+	in  []rune
+	out []rune
+}
+
+func runTests(t *testing.T, name string, fm Form, tests []TestCase) {
+	rb := reorderBuffer{}
+	rb.init(fm, nil)
+	for i, test := range tests {
+		rb.setFlusher(nil, appendFlush)
+		for j, rune := range test.in {
+			b := []byte(string(rune))
+			src := inputBytes(b)
+			info := rb.f.info(src, 0)
+			if j == 0 {
+				rb.ss.first(info)
+			} else {
+				rb.ss.next(info)
+			}
+			if rb.insertFlush(src, 0, info) < 0 {
+				t.Errorf("%s:%d: insert failed for rune %d", name, i, j)
+			}
+		}
+		rb.doFlush()
+		was := string(rb.out)
+		want := string(test.out)
+		if len(was) != len(want) {
+			t.Errorf("%s:%d: length = %d; want %d", name, i, len(was), len(want))
+		}
+		if was != want {
+			k, pfx := pidx(was, want)
+			t.Errorf("%s:%d: \nwas  %s%+q; \nwant %s%+q", name, i, pfx, was[k:], pfx, want[k:])
+		}
+	}
+}
+
+func TestFlush(t *testing.T) {
+	const (
+		hello = "Hello "
+		world = "world!"
+	)
+	buf := make([]byte, maxByteBufferSize)
+	p := copy(buf, hello)
+	out := buf[p:]
+	rb := reorderBuffer{}
+	rb.initString(NFC, world)
+	if i := rb.flushCopy(out); i != 0 {
+		t.Errorf("wrote bytes on flush of empty buffer. (len(out) = %d)", i)
+	}
+
+	for i := range world {
+		// No need to set streamSafe values for this test.
+		rb.insertFlush(rb.src, i, rb.f.info(rb.src, i))
+		n := rb.flushCopy(out)
+		out = out[n:]
+		p += n
+	}
+
+	was := buf[:p]
+	want := hello + world
+	if string(was) != want {
+		t.Errorf(`output after flush was "%s"; want "%s"`, string(was), want)
+	}
+	if rb.nrune != 0 {
+		t.Errorf("non-null size of info buffer (rb.nrune == %d)", rb.nrune)
+	}
+	if rb.nbyte != 0 {
+		t.Errorf("non-null size of byte buffer (rb.nbyte == %d)", rb.nbyte)
+	}
+}
+
+var insertTests = []TestCase{
+	{[]rune{'a'}, []rune{'a'}},
+	{[]rune{0x300}, []rune{0x300}},
+	{[]rune{0x300, 0x316}, []rune{0x316, 0x300}}, // CCC(0x300)==230; CCC(0x316)==220
+	{[]rune{0x316, 0x300}, []rune{0x316, 0x300}},
+	{[]rune{0x41, 0x316, 0x300}, []rune{0x41, 0x316, 0x300}},
+	{[]rune{0x41, 0x300, 0x316}, []rune{0x41, 0x316, 0x300}},
+	{[]rune{0x300, 0x316, 0x41}, []rune{0x316, 0x300, 0x41}},
+	{[]rune{0x41, 0x300, 0x40, 0x316}, []rune{0x41, 0x300, 0x40, 0x316}},
+}
+
+func TestInsert(t *testing.T) {
+	runTests(t, "TestInsert", NFD, insertTests)
+}
+
+var decompositionNFDTest = []TestCase{
+	{[]rune{0xC0}, []rune{0x41, 0x300}},
+	{[]rune{0xAC00}, []rune{0x1100, 0x1161}},
+	{[]rune{0x01C4}, []rune{0x01C4}},
+	{[]rune{0x320E}, []rune{0x320E}},
+	{[]rune("음ẻ과"), []rune{0x110B, 0x1173, 0x11B7, 0x65, 0x309, 0x1100, 0x116A}},
+}
+
+var decompositionNFKDTest = []TestCase{
+	{[]rune{0xC0}, []rune{0x41, 0x300}},
+	{[]rune{0xAC00}, []rune{0x1100, 0x1161}},
+	{[]rune{0x01C4}, []rune{0x44, 0x5A, 0x030C}},
+	{[]rune{0x320E}, []rune{0x28, 0x1100, 0x1161, 0x29}},
+}
+
+func TestDecomposition(t *testing.T) {
+	runTests(t, "TestDecompositionNFD", NFD, decompositionNFDTest)
+	runTests(t, "TestDecompositionNFKD", NFKD, decompositionNFKDTest)
+}
+
+var compositionTest = []TestCase{
+	{[]rune{0x41, 0x300}, []rune{0xC0}},
+	{[]rune{0x41, 0x316}, []rune{0x41, 0x316}},
+	{[]rune{0x41, 0x300, 0x35D}, []rune{0xC0, 0x35D}},
+	{[]rune{0x41, 0x316, 0x300}, []rune{0xC0, 0x316}},
+	// blocking starter
+	{[]rune{0x41, 0x316, 0x40, 0x300}, []rune{0x41, 0x316, 0x40, 0x300}},
+	{[]rune{0x1100, 0x1161}, []rune{0xAC00}},
+	// parenthesized Hangul, alternate between ASCII and Hangul.
+	{[]rune{0x28, 0x1100, 0x1161, 0x29}, []rune{0x28, 0xAC00, 0x29}},
+}
+
+func TestComposition(t *testing.T) {
+	runTests(t, "TestComposition", NFC, compositionTest)
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/example_iter_test.go b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/example_iter_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..82df89c7bf73811564f8a9acb571011777bfec37
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/example_iter_test.go
@@ -0,0 +1,82 @@
+// 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 norm_test
+
+import (
+	"bytes"
+	"fmt"
+	"unicode/utf8"
+
+	"golang.org/x/text/unicode/norm"
+)
+
+// EqualSimple uses a norm.Iter to compare two non-normalized
+// strings for equivalence.
+func EqualSimple(a, b string) bool {
+	var ia, ib norm.Iter
+	ia.InitString(norm.NFKD, a)
+	ib.InitString(norm.NFKD, b)
+	for !ia.Done() && !ib.Done() {
+		if !bytes.Equal(ia.Next(), ib.Next()) {
+			return false
+		}
+	}
+	return ia.Done() && ib.Done()
+}
+
+// FindPrefix finds the longest common prefix of ASCII characters
+// of a and b.
+func FindPrefix(a, b string) int {
+	i := 0
+	for ; i < len(a) && i < len(b) && a[i] < utf8.RuneSelf && a[i] == b[i]; i++ {
+	}
+	return i
+}
+
+// EqualOpt is like EqualSimple, but optimizes the special
+// case for ASCII characters.
+func EqualOpt(a, b string) bool {
+	n := FindPrefix(a, b)
+	a, b = a[n:], b[n:]
+	var ia, ib norm.Iter
+	ia.InitString(norm.NFKD, a)
+	ib.InitString(norm.NFKD, b)
+	for !ia.Done() && !ib.Done() {
+		if !bytes.Equal(ia.Next(), ib.Next()) {
+			return false
+		}
+		if n := int64(FindPrefix(a[ia.Pos():], b[ib.Pos():])); n != 0 {
+			ia.Seek(n, 1)
+			ib.Seek(n, 1)
+		}
+	}
+	return ia.Done() && ib.Done()
+}
+
+var compareTests = []struct{ a, b string }{
+	{"aaa", "aaa"},
+	{"aaa", "aab"},
+	{"a\u0300a", "\u00E0a"},
+	{"a\u0300\u0320b", "a\u0320\u0300b"},
+	{"\u1E0A\u0323", "\x44\u0323\u0307"},
+	// A character that decomposes into multiple segments
+	// spans several iterations.
+	{"\u3304", "\u30A4\u30CB\u30F3\u30AF\u3099"},
+}
+
+func ExampleIter() {
+	for i, t := range compareTests {
+		r0 := EqualSimple(t.a, t.b)
+		r1 := EqualOpt(t.a, t.b)
+		fmt.Printf("%d: %v %v\n", i, r0, r1)
+	}
+	// Output:
+	// 0: true true
+	// 1: false false
+	// 2: true true
+	// 3: true true
+	// 4: true true
+	// 5: true true
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/forminfo.go b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/forminfo.go
new file mode 100644
index 0000000000000000000000000000000000000000..15a67c653a3557fd21396b08f95bf3fb64cd5be6
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/forminfo.go
@@ -0,0 +1,256 @@
+// 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 norm
+
+// This file contains Form-specific logic and wrappers for data in tables.go.
+
+// Rune info is stored in a separate trie per composing form. A composing form
+// and its corresponding decomposing form share the same trie.  Each trie maps
+// a rune to a uint16. The values take two forms.  For v >= 0x8000:
+//   bits
+//   15:    1 (inverse of NFD_QD bit of qcInfo)
+//   13..7: qcInfo (see below). isYesD is always true (no decompostion).
+//    6..0: ccc (compressed CCC value).
+// For v < 0x8000, the respective rune has a decomposition and v is an index
+// into a byte array of UTF-8 decomposition sequences and additional info and
+// has the form:
+//    <header> <decomp_byte>* [<tccc> [<lccc>]]
+// The header contains the number of bytes in the decomposition (excluding this
+// length byte). The two most significant bits of this length byte correspond
+// to bit 5 and 4 of qcInfo (see below).  The byte sequence itself starts at v+1.
+// The byte sequence is followed by a trailing and leading CCC if the values
+// for these are not zero.  The value of v determines which ccc are appended
+// to the sequences.  For v < firstCCC, there are none, for v >= firstCCC,
+// the sequence is followed by a trailing ccc, and for v >= firstLeadingCC
+// there is an additional leading ccc. The value of tccc itself is the
+// trailing CCC shifted left 2 bits. The two least-significant bits of tccc
+// are the number of trailing non-starters.
+
+const (
+	qcInfoMask      = 0x3F // to clear all but the relevant bits in a qcInfo
+	headerLenMask   = 0x3F // extract the length value from the header byte
+	headerFlagsMask = 0xC0 // extract the qcInfo bits from the header byte
+)
+
+// Properties provides access to normalization properties of a rune.
+type Properties struct {
+	pos   uint8  // start position in reorderBuffer; used in composition.go
+	size  uint8  // length of UTF-8 encoding of this rune
+	ccc   uint8  // leading canonical combining class (ccc if not decomposition)
+	tccc  uint8  // trailing canonical combining class (ccc if not decomposition)
+	nLead uint8  // number of leading non-starters.
+	flags qcInfo // quick check flags
+	index uint16
+}
+
+// functions dispatchable per form
+type lookupFunc func(b input, i int) Properties
+
+// formInfo holds Form-specific functions and tables.
+type formInfo struct {
+	form                     Form
+	composing, compatibility bool // form type
+	info                     lookupFunc
+	nextMain                 iterFunc
+}
+
+var formTable []*formInfo
+
+func init() {
+	formTable = make([]*formInfo, 4)
+
+	for i := range formTable {
+		f := &formInfo{}
+		formTable[i] = f
+		f.form = Form(i)
+		if Form(i) == NFKD || Form(i) == NFKC {
+			f.compatibility = true
+			f.info = lookupInfoNFKC
+		} else {
+			f.info = lookupInfoNFC
+		}
+		f.nextMain = nextDecomposed
+		if Form(i) == NFC || Form(i) == NFKC {
+			f.nextMain = nextComposed
+			f.composing = true
+		}
+	}
+}
+
+// We do not distinguish between boundaries for NFC, NFD, etc. to avoid
+// unexpected behavior for the user.  For example, in NFD, there is a boundary
+// after 'a'.  However, 'a' might combine with modifiers, so from the application's
+// perspective it is not a good boundary. We will therefore always use the
+// boundaries for the combining variants.
+
+// BoundaryBefore returns true if this rune starts a new segment and
+// cannot combine with any rune on the left.
+func (p Properties) BoundaryBefore() bool {
+	if p.ccc == 0 && !p.combinesBackward() {
+		return true
+	}
+	// We assume that the CCC of the first character in a decomposition
+	// is always non-zero if different from info.ccc and that we can return
+	// false at this point. This is verified by maketables.
+	return false
+}
+
+// BoundaryAfter returns true if runes cannot combine with or otherwise
+// interact with this or previous runes.
+func (p Properties) BoundaryAfter() bool {
+	// TODO: loosen these conditions.
+	return p.isInert()
+}
+
+// We pack quick check data in 4 bits:
+//   5:    Combines forward  (0 == false, 1 == true)
+//   4..3: NFC_QC Yes(00), No (10), or Maybe (11)
+//   2:    NFD_QC Yes (0) or No (1). No also means there is a decomposition.
+//   1..0: Number of trailing non-starters.
+//
+// When all 4 bits are zero, the character is inert, meaning it is never
+// influenced by normalization.
+type qcInfo uint8
+
+func (p Properties) isYesC() bool { return p.flags&0x10 == 0 }
+func (p Properties) isYesD() bool { return p.flags&0x4 == 0 }
+
+func (p Properties) combinesForward() bool  { return p.flags&0x20 != 0 }
+func (p Properties) combinesBackward() bool { return p.flags&0x8 != 0 } // == isMaybe
+func (p Properties) hasDecomposition() bool { return p.flags&0x4 != 0 } // == isNoD
+
+func (p Properties) isInert() bool {
+	return p.flags&qcInfoMask == 0 && p.ccc == 0
+}
+
+func (p Properties) multiSegment() bool {
+	return p.index >= firstMulti && p.index < endMulti
+}
+
+func (p Properties) nLeadingNonStarters() uint8 {
+	return p.nLead
+}
+
+func (p Properties) nTrailingNonStarters() uint8 {
+	return uint8(p.flags & 0x03)
+}
+
+// Decomposition returns the decomposition for the underlying rune
+// or nil if there is none.
+func (p Properties) Decomposition() []byte {
+	// TODO: create the decomposition for Hangul?
+	if p.index == 0 {
+		return nil
+	}
+	i := p.index
+	n := decomps[i] & headerLenMask
+	i++
+	return decomps[i : i+uint16(n)]
+}
+
+// Size returns the length of UTF-8 encoding of the rune.
+func (p Properties) Size() int {
+	return int(p.size)
+}
+
+// CCC returns the canonical combining class of the underlying rune.
+func (p Properties) CCC() uint8 {
+	if p.index >= firstCCCZeroExcept {
+		return 0
+	}
+	return ccc[p.ccc]
+}
+
+// LeadCCC returns the CCC of the first rune in the decomposition.
+// If there is no decomposition, LeadCCC equals CCC.
+func (p Properties) LeadCCC() uint8 {
+	return ccc[p.ccc]
+}
+
+// TrailCCC returns the CCC of the last rune in the decomposition.
+// If there is no decomposition, TrailCCC equals CCC.
+func (p Properties) TrailCCC() uint8 {
+	return ccc[p.tccc]
+}
+
+// Recomposition
+// We use 32-bit keys instead of 64-bit for the two codepoint keys.
+// This clips off the bits of three entries, but we know this will not
+// result in a collision. In the unlikely event that changes to
+// UnicodeData.txt introduce collisions, the compiler will catch it.
+// Note that the recomposition map for NFC and NFKC are identical.
+
+// combine returns the combined rune or 0 if it doesn't exist.
+func combine(a, b rune) rune {
+	key := uint32(uint16(a))<<16 + uint32(uint16(b))
+	return recompMap[key]
+}
+
+func lookupInfoNFC(b input, i int) Properties {
+	v, sz := b.charinfoNFC(i)
+	return compInfo(v, sz)
+}
+
+func lookupInfoNFKC(b input, i int) Properties {
+	v, sz := b.charinfoNFKC(i)
+	return compInfo(v, sz)
+}
+
+// Properties returns properties for the first rune in s.
+func (f Form) Properties(s []byte) Properties {
+	if f == NFC || f == NFD {
+		return compInfo(nfcData.lookup(s))
+	}
+	return compInfo(nfkcData.lookup(s))
+}
+
+// PropertiesString returns properties for the first rune in s.
+func (f Form) PropertiesString(s string) Properties {
+	if f == NFC || f == NFD {
+		return compInfo(nfcData.lookupString(s))
+	}
+	return compInfo(nfkcData.lookupString(s))
+}
+
+// compInfo converts the information contained in v and sz
+// to a Properties.  See the comment at the top of the file
+// for more information on the format.
+func compInfo(v uint16, sz int) Properties {
+	if v == 0 {
+		return Properties{size: uint8(sz)}
+	} else if v >= 0x8000 {
+		p := Properties{
+			size:  uint8(sz),
+			ccc:   uint8(v),
+			tccc:  uint8(v),
+			flags: qcInfo(v >> 8),
+		}
+		if p.ccc > 0 || p.combinesBackward() {
+			p.nLead = uint8(p.flags & 0x3)
+		}
+		return p
+	}
+	// has decomposition
+	h := decomps[v]
+	f := (qcInfo(h&headerFlagsMask) >> 2) | 0x4
+	p := Properties{size: uint8(sz), flags: f, index: v}
+	if v >= firstCCC {
+		v += uint16(h&headerLenMask) + 1
+		c := decomps[v]
+		p.tccc = c >> 2
+		p.flags |= qcInfo(c & 0x3)
+		if v >= firstLeadingCCC {
+			p.nLead = c & 0x3
+			if v >= firstStarterWithNLead {
+				// We were tricked. Remove the decomposition.
+				p.flags &= 0x03
+				p.index = 0
+				return p
+			}
+			p.ccc = decomps[v+1]
+		}
+	}
+	return p
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/forminfo_test.go b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/forminfo_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..e15ba9bee67ae03b18e65f2bd2189e5321d2ace3
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/forminfo_test.go
@@ -0,0 +1,54 @@
+// 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 test
+
+package norm
+
+import "testing"
+
+func TestProperties(t *testing.T) {
+	var d runeData
+	CK := [2]string{"C", "K"}
+	for k, r := 1, rune(0); r < 0x2ffff; r++ {
+		if k < len(testData) && r == testData[k].r {
+			d = testData[k]
+			k++
+		}
+		s := string(r)
+		for j, p := range []Properties{NFC.PropertiesString(s), NFKC.PropertiesString(s)} {
+			f := d.f[j]
+			if p.CCC() != d.ccc {
+				t.Errorf("%U: ccc(%s): was %d; want %d %X", r, CK[j], p.CCC(), d.ccc, p.index)
+			}
+			if p.isYesC() != (f.qc == Yes) {
+				t.Errorf("%U: YesC(%s): was %v; want %v", r, CK[j], p.isYesC(), f.qc == Yes)
+			}
+			if p.combinesBackward() != (f.qc == Maybe) {
+				t.Errorf("%U: combines backwards(%s): was %v; want %v", r, CK[j], p.combinesBackward(), f.qc == Maybe)
+			}
+			if p.nLeadingNonStarters() != d.nLead {
+				t.Errorf("%U: nLead(%s): was %d; want %d %#v %#v", r, CK[j], p.nLeadingNonStarters(), d.nLead, p, d)
+			}
+			if p.nTrailingNonStarters() != d.nTrail {
+				t.Errorf("%U: nTrail(%s): was %d; want %d %#v %#v", r, CK[j], p.nTrailingNonStarters(), d.nTrail, p, d)
+			}
+			if p.combinesForward() != f.combinesForward {
+				t.Errorf("%U: combines forward(%s): was %v; want %v %#v", r, CK[j], p.combinesForward(), f.combinesForward, p)
+			}
+			// Skip Hangul as it is algorithmically computed.
+			if r >= hangulBase && r < hangulEnd {
+				continue
+			}
+			if p.hasDecomposition() {
+				if has := f.decomposition != ""; !has {
+					t.Errorf("%U: hasDecomposition(%s): was %v; want %v", r, CK[j], p.hasDecomposition(), has)
+				}
+				if string(p.Decomposition()) != f.decomposition {
+					t.Errorf("%U: decomp(%s): was %+q; want %+q", r, CK[j], p.Decomposition(), f.decomposition)
+				}
+			}
+		}
+	}
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/input.go b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/input.go
new file mode 100644
index 0000000000000000000000000000000000000000..045d4ccce2ee1cf4824517d9cdc85eaa96228e9e
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/input.go
@@ -0,0 +1,105 @@
+// 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 norm
+
+import "unicode/utf8"
+
+type input struct {
+	str   string
+	bytes []byte
+}
+
+func inputBytes(str []byte) input {
+	return input{bytes: str}
+}
+
+func inputString(str string) input {
+	return input{str: str}
+}
+
+func (in *input) setBytes(str []byte) {
+	in.str = ""
+	in.bytes = str
+}
+
+func (in *input) setString(str string) {
+	in.str = str
+	in.bytes = nil
+}
+
+func (in *input) _byte(p int) byte {
+	if in.bytes == nil {
+		return in.str[p]
+	}
+	return in.bytes[p]
+}
+
+func (in *input) skipASCII(p, max int) int {
+	if in.bytes == nil {
+		for ; p < max && in.str[p] < utf8.RuneSelf; p++ {
+		}
+	} else {
+		for ; p < max && in.bytes[p] < utf8.RuneSelf; p++ {
+		}
+	}
+	return p
+}
+
+func (in *input) skipContinuationBytes(p int) int {
+	if in.bytes == nil {
+		for ; p < len(in.str) && !utf8.RuneStart(in.str[p]); p++ {
+		}
+	} else {
+		for ; p < len(in.bytes) && !utf8.RuneStart(in.bytes[p]); p++ {
+		}
+	}
+	return p
+}
+
+func (in *input) appendSlice(buf []byte, b, e int) []byte {
+	if in.bytes != nil {
+		return append(buf, in.bytes[b:e]...)
+	}
+	for i := b; i < e; i++ {
+		buf = append(buf, in.str[i])
+	}
+	return buf
+}
+
+func (in *input) copySlice(buf []byte, b, e int) int {
+	if in.bytes == nil {
+		return copy(buf, in.str[b:e])
+	}
+	return copy(buf, in.bytes[b:e])
+}
+
+func (in *input) charinfoNFC(p int) (uint16, int) {
+	if in.bytes == nil {
+		return nfcData.lookupString(in.str[p:])
+	}
+	return nfcData.lookup(in.bytes[p:])
+}
+
+func (in *input) charinfoNFKC(p int) (uint16, int) {
+	if in.bytes == nil {
+		return nfkcData.lookupString(in.str[p:])
+	}
+	return nfkcData.lookup(in.bytes[p:])
+}
+
+func (in *input) hangul(p int) (r rune) {
+	if in.bytes == nil {
+		if !isHangulString(in.str[p:]) {
+			return 0
+		}
+		r, _ = utf8.DecodeRuneInString(in.str[p:])
+	} else {
+		if !isHangul(in.bytes[p:]) {
+			return 0
+		}
+		r, _ = utf8.DecodeRune(in.bytes[p:])
+	}
+	return r
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/iter.go b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/iter.go
new file mode 100644
index 0000000000000000000000000000000000000000..0a42a72de81c0119995307f39f8a9183063389fb
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/iter.go
@@ -0,0 +1,450 @@
+// 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 norm
+
+import (
+	"fmt"
+	"unicode/utf8"
+)
+
+// MaxSegmentSize is the maximum size of a byte buffer needed to consider any
+// sequence of starter and non-starter runes for the purpose of normalization.
+const MaxSegmentSize = maxByteBufferSize
+
+// An Iter iterates over a string or byte slice, while normalizing it
+// to a given Form.
+type Iter struct {
+	rb     reorderBuffer
+	buf    [maxByteBufferSize]byte
+	info   Properties // first character saved from previous iteration
+	next   iterFunc   // implementation of next depends on form
+	asciiF iterFunc
+
+	p        int    // current position in input source
+	multiSeg []byte // remainder of multi-segment decomposition
+}
+
+type iterFunc func(*Iter) []byte
+
+// Init initializes i to iterate over src after normalizing it to Form f.
+func (i *Iter) Init(f Form, src []byte) {
+	i.p = 0
+	if len(src) == 0 {
+		i.setDone()
+		i.rb.nsrc = 0
+		return
+	}
+	i.multiSeg = nil
+	i.rb.init(f, src)
+	i.next = i.rb.f.nextMain
+	i.asciiF = nextASCIIBytes
+	i.info = i.rb.f.info(i.rb.src, i.p)
+}
+
+// InitString initializes i to iterate over src after normalizing it to Form f.
+func (i *Iter) InitString(f Form, src string) {
+	i.p = 0
+	if len(src) == 0 {
+		i.setDone()
+		i.rb.nsrc = 0
+		return
+	}
+	i.multiSeg = nil
+	i.rb.initString(f, src)
+	i.next = i.rb.f.nextMain
+	i.asciiF = nextASCIIString
+	i.info = i.rb.f.info(i.rb.src, i.p)
+}
+
+// Seek sets the segment to be returned by the next call to Next to start
+// at position p.  It is the responsibility of the caller to set p to the
+// start of a UTF8 rune.
+func (i *Iter) Seek(offset int64, whence int) (int64, error) {
+	var abs int64
+	switch whence {
+	case 0:
+		abs = offset
+	case 1:
+		abs = int64(i.p) + offset
+	case 2:
+		abs = int64(i.rb.nsrc) + offset
+	default:
+		return 0, fmt.Errorf("norm: invalid whence")
+	}
+	if abs < 0 {
+		return 0, fmt.Errorf("norm: negative position")
+	}
+	if int(abs) >= i.rb.nsrc {
+		i.setDone()
+		return int64(i.p), nil
+	}
+	i.p = int(abs)
+	i.multiSeg = nil
+	i.next = i.rb.f.nextMain
+	i.info = i.rb.f.info(i.rb.src, i.p)
+	return abs, nil
+}
+
+// returnSlice returns a slice of the underlying input type as a byte slice.
+// If the underlying is of type []byte, it will simply return a slice.
+// If the underlying is of type string, it will copy the slice to the buffer
+// and return that.
+func (i *Iter) returnSlice(a, b int) []byte {
+	if i.rb.src.bytes == nil {
+		return i.buf[:copy(i.buf[:], i.rb.src.str[a:b])]
+	}
+	return i.rb.src.bytes[a:b]
+}
+
+// Pos returns the byte position at which the next call to Next will commence processing.
+func (i *Iter) Pos() int {
+	return i.p
+}
+
+func (i *Iter) setDone() {
+	i.next = nextDone
+	i.p = i.rb.nsrc
+}
+
+// Done returns true if there is no more input to process.
+func (i *Iter) Done() bool {
+	return i.p >= i.rb.nsrc
+}
+
+// Next returns f(i.input[i.Pos():n]), where n is a boundary of i.input.
+// For any input a and b for which f(a) == f(b), subsequent calls
+// to Next will return the same segments.
+// Modifying runes are grouped together with the preceding starter, if such a starter exists.
+// Although not guaranteed, n will typically be the smallest possible n.
+func (i *Iter) Next() []byte {
+	return i.next(i)
+}
+
+func nextASCIIBytes(i *Iter) []byte {
+	p := i.p + 1
+	if p >= i.rb.nsrc {
+		i.setDone()
+		return i.rb.src.bytes[i.p:p]
+	}
+	if i.rb.src.bytes[p] < utf8.RuneSelf {
+		p0 := i.p
+		i.p = p
+		return i.rb.src.bytes[p0:p]
+	}
+	i.info = i.rb.f.info(i.rb.src, i.p)
+	i.next = i.rb.f.nextMain
+	return i.next(i)
+}
+
+func nextASCIIString(i *Iter) []byte {
+	p := i.p + 1
+	if p >= i.rb.nsrc {
+		i.buf[0] = i.rb.src.str[i.p]
+		i.setDone()
+		return i.buf[:1]
+	}
+	if i.rb.src.str[p] < utf8.RuneSelf {
+		i.buf[0] = i.rb.src.str[i.p]
+		i.p = p
+		return i.buf[:1]
+	}
+	i.info = i.rb.f.info(i.rb.src, i.p)
+	i.next = i.rb.f.nextMain
+	return i.next(i)
+}
+
+func nextHangul(i *Iter) []byte {
+	p := i.p
+	next := p + hangulUTF8Size
+	if next >= i.rb.nsrc {
+		i.setDone()
+	} else if i.rb.src.hangul(next) == 0 {
+		i.info = i.rb.f.info(i.rb.src, i.p)
+		i.next = i.rb.f.nextMain
+		return i.next(i)
+	}
+	i.p = next
+	return i.buf[:decomposeHangul(i.buf[:], i.rb.src.hangul(p))]
+}
+
+func nextDone(i *Iter) []byte {
+	return nil
+}
+
+// nextMulti is used for iterating over multi-segment decompositions
+// for decomposing normal forms.
+func nextMulti(i *Iter) []byte {
+	j := 0
+	d := i.multiSeg
+	// skip first rune
+	for j = 1; j < len(d) && !utf8.RuneStart(d[j]); j++ {
+	}
+	for j < len(d) {
+		info := i.rb.f.info(input{bytes: d}, j)
+		if info.BoundaryBefore() {
+			i.multiSeg = d[j:]
+			return d[:j]
+		}
+		j += int(info.size)
+	}
+	// treat last segment as normal decomposition
+	i.next = i.rb.f.nextMain
+	return i.next(i)
+}
+
+// nextMultiNorm is used for iterating over multi-segment decompositions
+// for composing normal forms.
+func nextMultiNorm(i *Iter) []byte {
+	j := 0
+	d := i.multiSeg
+	for j < len(d) {
+		info := i.rb.f.info(input{bytes: d}, j)
+		if info.BoundaryBefore() {
+			i.rb.compose()
+			seg := i.buf[:i.rb.flushCopy(i.buf[:])]
+			i.rb.ss.first(info)
+			i.rb.insertUnsafe(input{bytes: d}, j, info)
+			i.multiSeg = d[j+int(info.size):]
+			return seg
+		}
+		i.rb.ss.next(info)
+		i.rb.insertUnsafe(input{bytes: d}, j, info)
+		j += int(info.size)
+	}
+	i.multiSeg = nil
+	i.next = nextComposed
+	return doNormComposed(i)
+}
+
+// nextDecomposed is the implementation of Next for forms NFD and NFKD.
+func nextDecomposed(i *Iter) (next []byte) {
+	outp := 0
+	inCopyStart, outCopyStart := i.p, 0
+	ss := mkStreamSafe(i.info)
+	for {
+		if sz := int(i.info.size); sz <= 1 {
+			p := i.p
+			i.p++ // ASCII or illegal byte.  Either way, advance by 1.
+			if i.p >= i.rb.nsrc {
+				i.setDone()
+				return i.returnSlice(p, i.p)
+			} else if i.rb.src._byte(i.p) < utf8.RuneSelf {
+				i.next = i.asciiF
+				return i.returnSlice(p, i.p)
+			}
+			outp++
+		} else if d := i.info.Decomposition(); d != nil {
+			// Note: If leading CCC != 0, then len(d) == 2 and last is also non-zero.
+			// Case 1: there is a leftover to copy.  In this case the decomposition
+			// must begin with a modifier and should always be appended.
+			// Case 2: no leftover. Simply return d if followed by a ccc == 0 value.
+			p := outp + len(d)
+			if outp > 0 {
+				i.rb.src.copySlice(i.buf[outCopyStart:], inCopyStart, i.p)
+				if p > len(i.buf) {
+					return i.buf[:outp]
+				}
+			} else if i.info.multiSegment() {
+				// outp must be 0 as multi-segment decompositions always
+				// start a new segment.
+				if i.multiSeg == nil {
+					i.multiSeg = d
+					i.next = nextMulti
+					return nextMulti(i)
+				}
+				// We are in the last segment.  Treat as normal decomposition.
+				d = i.multiSeg
+				i.multiSeg = nil
+				p = len(d)
+			}
+			prevCC := i.info.tccc
+			if i.p += sz; i.p >= i.rb.nsrc {
+				i.setDone()
+				i.info = Properties{} // Force BoundaryBefore to succeed.
+			} else {
+				i.info = i.rb.f.info(i.rb.src, i.p)
+			}
+			switch ss.next(i.info) {
+			case ssOverflow:
+				i.next = nextCGJDecompose
+				fallthrough
+			case ssStarter:
+				if outp > 0 {
+					copy(i.buf[outp:], d)
+					return i.buf[:p]
+				}
+				return d
+			}
+			copy(i.buf[outp:], d)
+			outp = p
+			inCopyStart, outCopyStart = i.p, outp
+			if i.info.ccc < prevCC {
+				goto doNorm
+			}
+			continue
+		} else if r := i.rb.src.hangul(i.p); r != 0 {
+			outp = decomposeHangul(i.buf[:], r)
+			i.p += hangulUTF8Size
+			inCopyStart, outCopyStart = i.p, outp
+			if i.p >= i.rb.nsrc {
+				i.setDone()
+				break
+			} else if i.rb.src.hangul(i.p) != 0 {
+				i.next = nextHangul
+				return i.buf[:outp]
+			}
+		} else {
+			p := outp + sz
+			if p > len(i.buf) {
+				break
+			}
+			outp = p
+			i.p += sz
+		}
+		if i.p >= i.rb.nsrc {
+			i.setDone()
+			break
+		}
+		prevCC := i.info.tccc
+		i.info = i.rb.f.info(i.rb.src, i.p)
+		if v := ss.next(i.info); v == ssStarter {
+			break
+		} else if v == ssOverflow {
+			i.next = nextCGJDecompose
+			break
+		}
+		if i.info.ccc < prevCC {
+			goto doNorm
+		}
+	}
+	if outCopyStart == 0 {
+		return i.returnSlice(inCopyStart, i.p)
+	} else if inCopyStart < i.p {
+		i.rb.src.copySlice(i.buf[outCopyStart:], inCopyStart, i.p)
+	}
+	return i.buf[:outp]
+doNorm:
+	// Insert what we have decomposed so far in the reorderBuffer.
+	// As we will only reorder, there will always be enough room.
+	i.rb.src.copySlice(i.buf[outCopyStart:], inCopyStart, i.p)
+	i.rb.insertDecomposed(i.buf[0:outp])
+	return doNormDecomposed(i)
+}
+
+func doNormDecomposed(i *Iter) []byte {
+	for {
+		if s := i.rb.ss.next(i.info); s == ssOverflow {
+			i.next = nextCGJDecompose
+			break
+		}
+		i.rb.insertUnsafe(i.rb.src, i.p, i.info)
+		if i.p += int(i.info.size); i.p >= i.rb.nsrc {
+			i.setDone()
+			break
+		}
+		i.info = i.rb.f.info(i.rb.src, i.p)
+		if i.info.ccc == 0 {
+			break
+		}
+	}
+	// new segment or too many combining characters: exit normalization
+	return i.buf[:i.rb.flushCopy(i.buf[:])]
+}
+
+func nextCGJDecompose(i *Iter) []byte {
+	i.rb.ss = 0
+	i.rb.insertCGJ()
+	i.next = nextDecomposed
+	buf := doNormDecomposed(i)
+	return buf
+}
+
+// nextComposed is the implementation of Next for forms NFC and NFKC.
+func nextComposed(i *Iter) []byte {
+	outp, startp := 0, i.p
+	var prevCC uint8
+	ss := mkStreamSafe(i.info)
+	for {
+		if !i.info.isYesC() {
+			goto doNorm
+		}
+		prevCC = i.info.tccc
+		sz := int(i.info.size)
+		if sz == 0 {
+			sz = 1 // illegal rune: copy byte-by-byte
+		}
+		p := outp + sz
+		if p > len(i.buf) {
+			break
+		}
+		outp = p
+		i.p += sz
+		if i.p >= i.rb.nsrc {
+			i.setDone()
+			break
+		} else if i.rb.src._byte(i.p) < utf8.RuneSelf {
+			i.next = i.asciiF
+			break
+		}
+		i.info = i.rb.f.info(i.rb.src, i.p)
+		if v := ss.next(i.info); v == ssStarter {
+			break
+		} else if v == ssOverflow {
+			i.next = nextCGJCompose
+			break
+		}
+		if i.info.ccc < prevCC {
+			goto doNorm
+		}
+	}
+	return i.returnSlice(startp, i.p)
+doNorm:
+	i.p = startp
+	i.info = i.rb.f.info(i.rb.src, i.p)
+	if i.info.multiSegment() {
+		d := i.info.Decomposition()
+		info := i.rb.f.info(input{bytes: d}, 0)
+		i.rb.insertUnsafe(input{bytes: d}, 0, info)
+		i.multiSeg = d[int(info.size):]
+		i.next = nextMultiNorm
+		return nextMultiNorm(i)
+	}
+	i.rb.ss.first(i.info)
+	i.rb.insertUnsafe(i.rb.src, i.p, i.info)
+	return doNormComposed(i)
+}
+
+func doNormComposed(i *Iter) []byte {
+	// First rune should already be inserted.
+	for {
+		if i.p += int(i.info.size); i.p >= i.rb.nsrc {
+			i.setDone()
+			break
+		}
+		i.info = i.rb.f.info(i.rb.src, i.p)
+		if s := i.rb.ss.next(i.info); s == ssStarter {
+			break
+		} else if s == ssOverflow {
+			i.next = nextCGJCompose
+			break
+		}
+		i.rb.insertUnsafe(i.rb.src, i.p, i.info)
+	}
+	i.rb.compose()
+	seg := i.buf[:i.rb.flushCopy(i.buf[:])]
+	return seg
+}
+
+func nextCGJCompose(i *Iter) []byte {
+	i.rb.ss = 0 // instead of first
+	i.rb.insertCGJ()
+	i.next = nextComposed
+	// Note that we treat any rune with nLeadingNonStarters > 0 as a non-starter,
+	// even if they are not. This is particularly dubious for U+FF9E and UFF9A.
+	// If we ever change that, insert a check here.
+	i.rb.ss.first(i.info)
+	i.rb.insertUnsafe(i.rb.src, i.p, i.info)
+	return doNormComposed(i)
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/iter_test.go b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/iter_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..e2aa6f2515ce4d1640ccad0c6836b2876d54a738
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/iter_test.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 norm
+
+import (
+	"strings"
+	"testing"
+)
+
+func doIterNorm(f Form, s string) []byte {
+	acc := []byte{}
+	i := Iter{}
+	i.InitString(f, s)
+	for !i.Done() {
+		acc = append(acc, i.Next()...)
+	}
+	return acc
+}
+
+func TestIterNext(t *testing.T) {
+	runNormTests(t, "IterNext", func(f Form, out []byte, s string) []byte {
+		return doIterNorm(f, string(append(out, s...)))
+	})
+}
+
+type SegmentTest struct {
+	in  string
+	out []string
+}
+
+var segmentTests = []SegmentTest{
+	{"\u1E0A\u0323a", []string{"\x44\u0323\u0307", "a", ""}},
+	{rep('a', segSize), append(strings.Split(rep('a', segSize), ""), "")},
+	{rep('a', segSize+2), append(strings.Split(rep('a', segSize+2), ""), "")},
+	{rep('a', segSize) + "\u0300aa",
+		append(strings.Split(rep('a', segSize-1), ""), "a\u0300", "a", "a", "")},
+
+	// U+0f73 is NOT treated as a starter as it is a modifier
+	{"a" + grave(29) + "\u0f73", []string{"a" + grave(29), cgj + "\u0f73"}},
+	{"a\u0f73", []string{"a\u0f73"}},
+
+	// U+ff9e is treated as a non-starter.
+	// TODO: should we? Note that this will only affect iteration, as whether
+	// or not we do so does not affect the normalization output and will either
+	// way result in consistent iteration output.
+	{"a" + grave(30) + "\uff9e", []string{"a" + grave(30), cgj + "\uff9e"}},
+	{"a\uff9e", []string{"a\uff9e"}},
+}
+
+var segmentTestsK = []SegmentTest{
+	{"\u3332", []string{"\u30D5", "\u30A1", "\u30E9", "\u30C3", "\u30C8\u3099", ""}},
+	// last segment of multi-segment decomposition needs normalization
+	{"\u3332\u093C", []string{"\u30D5", "\u30A1", "\u30E9", "\u30C3", "\u30C8\u093C\u3099", ""}},
+	{"\u320E", []string{"\x28", "\uAC00", "\x29"}},
+
+	// last segment should be copied to start of buffer.
+	{"\ufdfa", []string{"\u0635", "\u0644", "\u0649", " ", "\u0627", "\u0644", "\u0644", "\u0647", " ", "\u0639", "\u0644", "\u064a", "\u0647", " ", "\u0648", "\u0633", "\u0644", "\u0645", ""}},
+	{"\ufdfa" + grave(30), []string{"\u0635", "\u0644", "\u0649", " ", "\u0627", "\u0644", "\u0644", "\u0647", " ", "\u0639", "\u0644", "\u064a", "\u0647", " ", "\u0648", "\u0633", "\u0644", "\u0645" + grave(30), ""}},
+	{"\uFDFA" + grave(64), []string{"\u0635", "\u0644", "\u0649", " ", "\u0627", "\u0644", "\u0644", "\u0647", " ", "\u0639", "\u0644", "\u064a", "\u0647", " ", "\u0648", "\u0633", "\u0644", "\u0645" + grave(30), cgj + grave(30), cgj + grave(4), ""}},
+
+	// Hangul and Jamo are grouped togeter.
+	{"\uAC00", []string{"\u1100\u1161", ""}},
+	{"\uAC01", []string{"\u1100\u1161\u11A8", ""}},
+	{"\u1100\u1161", []string{"\u1100\u1161", ""}},
+}
+
+// Note that, by design, segmentation is equal for composing and decomposing forms.
+func TestIterSegmentation(t *testing.T) {
+	segmentTest(t, "SegmentTestD", NFD, segmentTests)
+	segmentTest(t, "SegmentTestC", NFC, segmentTests)
+	segmentTest(t, "SegmentTestKD", NFKD, segmentTestsK)
+	segmentTest(t, "SegmentTestKC", NFKC, segmentTestsK)
+}
+
+func segmentTest(t *testing.T, name string, f Form, tests []SegmentTest) {
+	iter := Iter{}
+	for i, tt := range tests {
+		iter.InitString(f, tt.in)
+		for j, seg := range tt.out {
+			if seg == "" {
+				if !iter.Done() {
+					res := string(iter.Next())
+					t.Errorf(`%s:%d:%d: expected Done()==true, found segment %+q`, name, i, j, res)
+				}
+				continue
+			}
+			if iter.Done() {
+				t.Errorf("%s:%d:%d: Done()==true, want false", name, i, j)
+			}
+			seg = f.String(seg)
+			if res := string(iter.Next()); res != seg {
+				t.Errorf(`%s:%d:%d" segment was %+q (%d); want %+q (%d)`, name, i, j, pc(res), len(res), pc(seg), len(seg))
+			}
+		}
+	}
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/maketables.go b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/maketables.go
new file mode 100644
index 0000000000000000000000000000000000000000..3524e8c0c7e27faaf73974cc63c5239f646d58dd
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/maketables.go
@@ -0,0 +1,1033 @@
+// 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 ignore
+
+// Normalization table generator.
+// Data read from the web.
+// See forminfo.go for a description of the trie values associated with each rune.
+
+package main
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"io"
+	"log"
+	"net/http"
+	"os"
+	"regexp"
+	"sort"
+	"strconv"
+	"strings"
+	"unicode"
+
+	"golang.org/x/text/internal/triegen"
+	"golang.org/x/text/internal/ucd"
+)
+
+func main() {
+	flag.Parse()
+	loadUnicodeData()
+	compactCCC()
+	loadCompositionExclusions()
+	completeCharFields(FCanonical)
+	completeCharFields(FCompatibility)
+	computeNonStarterCounts()
+	verifyComputed()
+	printChars()
+	if *test {
+		testDerived()
+		printTestdata()
+	} else {
+		makeTables()
+	}
+}
+
+var url = flag.String("url",
+	"http://www.unicode.org/Public/"+unicode.Version+"/ucd/",
+	"URL of Unicode database directory")
+var tablelist = flag.String("tables",
+	"all",
+	"comma-separated list of which tables to generate; "+
+		"can be 'decomp', 'recomp', 'info' and 'all'")
+var test = flag.Bool("test",
+	false,
+	"test existing tables against DerivedNormalizationProps and generate test data for regression testing")
+var verbose = flag.Bool("verbose",
+	false,
+	"write data to stdout as it is parsed")
+var localFiles = flag.Bool("local",
+	false,
+	"data files have been copied to the current directory; for debugging only")
+
+var logger = log.New(os.Stderr, "", log.Lshortfile)
+
+const MaxChar = 0x10FFFF // anything above this shouldn't exist
+
+// Quick Check properties of runes allow us to quickly
+// determine whether a rune may occur in a normal form.
+// For a given normal form, a rune may be guaranteed to occur
+// verbatim (QC=Yes), may or may not combine with another
+// rune (QC=Maybe), or may not occur (QC=No).
+type QCResult int
+
+const (
+	QCUnknown QCResult = iota
+	QCYes
+	QCNo
+	QCMaybe
+)
+
+func (r QCResult) String() string {
+	switch r {
+	case QCYes:
+		return "Yes"
+	case QCNo:
+		return "No"
+	case QCMaybe:
+		return "Maybe"
+	}
+	return "***UNKNOWN***"
+}
+
+const (
+	FCanonical     = iota // NFC or NFD
+	FCompatibility        // NFKC or NFKD
+	FNumberOfFormTypes
+)
+
+const (
+	MComposed   = iota // NFC or NFKC
+	MDecomposed        // NFD or NFKD
+	MNumberOfModes
+)
+
+// This contains only the properties we're interested in.
+type Char struct {
+	name          string
+	codePoint     rune  // if zero, this index is not a valid code point.
+	ccc           uint8 // canonical combining class
+	origCCC       uint8
+	excludeInComp bool // from CompositionExclusions.txt
+	compatDecomp  bool // it has a compatibility expansion
+
+	nTrailingNonStarters uint8
+	nLeadingNonStarters  uint8 // must be equal to trailing if non-zero
+
+	forms [FNumberOfFormTypes]FormInfo // For FCanonical and FCompatibility
+
+	state State
+}
+
+var chars = make([]Char, MaxChar+1)
+var cccMap = make(map[uint8]uint8)
+
+func (c Char) String() string {
+	buf := new(bytes.Buffer)
+
+	fmt.Fprintf(buf, "%U [%s]:\n", c.codePoint, c.name)
+	fmt.Fprintf(buf, "  ccc: %v\n", c.ccc)
+	fmt.Fprintf(buf, "  excludeInComp: %v\n", c.excludeInComp)
+	fmt.Fprintf(buf, "  compatDecomp: %v\n", c.compatDecomp)
+	fmt.Fprintf(buf, "  state: %v\n", c.state)
+	fmt.Fprintf(buf, "  NFC:\n")
+	fmt.Fprint(buf, c.forms[FCanonical])
+	fmt.Fprintf(buf, "  NFKC:\n")
+	fmt.Fprint(buf, c.forms[FCompatibility])
+
+	return buf.String()
+}
+
+// In UnicodeData.txt, some ranges are marked like this:
+//	3400;<CJK Ideograph Extension A, First>;Lo;0;L;;;;;N;;;;;
+//	4DB5;<CJK Ideograph Extension A, Last>;Lo;0;L;;;;;N;;;;;
+// parseCharacter keeps a state variable indicating the weirdness.
+type State int
+
+const (
+	SNormal State = iota // known to be zero for the type
+	SFirst
+	SLast
+	SMissing
+)
+
+var lastChar = rune('\u0000')
+
+func (c Char) isValid() bool {
+	return c.codePoint != 0 && c.state != SMissing
+}
+
+type FormInfo struct {
+	quickCheck [MNumberOfModes]QCResult // index: MComposed or MDecomposed
+	verified   [MNumberOfModes]bool     // index: MComposed or MDecomposed
+
+	combinesForward  bool // May combine with rune on the right
+	combinesBackward bool // May combine with rune on the left
+	isOneWay         bool // Never appears in result
+	inDecomp         bool // Some decompositions result in this char.
+	decomp           Decomposition
+	expandedDecomp   Decomposition
+}
+
+func (f FormInfo) String() string {
+	buf := bytes.NewBuffer(make([]byte, 0))
+
+	fmt.Fprintf(buf, "    quickCheck[C]: %v\n", f.quickCheck[MComposed])
+	fmt.Fprintf(buf, "    quickCheck[D]: %v\n", f.quickCheck[MDecomposed])
+	fmt.Fprintf(buf, "    cmbForward: %v\n", f.combinesForward)
+	fmt.Fprintf(buf, "    cmbBackward: %v\n", f.combinesBackward)
+	fmt.Fprintf(buf, "    isOneWay: %v\n", f.isOneWay)
+	fmt.Fprintf(buf, "    inDecomp: %v\n", f.inDecomp)
+	fmt.Fprintf(buf, "    decomposition: %X\n", f.decomp)
+	fmt.Fprintf(buf, "    expandedDecomp: %X\n", f.expandedDecomp)
+
+	return buf.String()
+}
+
+type Decomposition []rune
+
+func openReader(file string) (input io.ReadCloser) {
+	if *localFiles {
+		f, err := os.Open(file)
+		if err != nil {
+			logger.Fatal(err)
+		}
+		input = f
+	} else {
+		path := *url + file
+		resp, err := http.Get(path)
+		if err != nil {
+			logger.Fatal(err)
+		}
+		if resp.StatusCode != 200 {
+			logger.Fatal("bad GET status for "+file, resp.Status)
+		}
+		input = resp.Body
+	}
+	return
+}
+
+func parseDecomposition(s string, skipfirst bool) (a []rune, err error) {
+	decomp := strings.Split(s, " ")
+	if len(decomp) > 0 && skipfirst {
+		decomp = decomp[1:]
+	}
+	for _, d := range decomp {
+		point, err := strconv.ParseUint(d, 16, 64)
+		if err != nil {
+			return a, err
+		}
+		a = append(a, rune(point))
+	}
+	return a, nil
+}
+
+func loadUnicodeData() {
+	f := openReader("UnicodeData.txt")
+	defer f.Close()
+	p := ucd.New(f)
+	for p.Next() {
+		r := p.Rune(ucd.CodePoint)
+		char := &chars[r]
+
+		char.ccc = uint8(p.Uint(ucd.CanonicalCombiningClass))
+		decmap := p.String(ucd.DecompMapping)
+
+		exp, err := parseDecomposition(decmap, false)
+		isCompat := false
+		if err != nil {
+			if len(decmap) > 0 {
+				exp, err = parseDecomposition(decmap, true)
+				if err != nil {
+					logger.Fatalf(`%U: bad decomp |%v|: "%s"`, r, decmap, err)
+				}
+				isCompat = true
+			}
+		}
+
+		char.name = p.String(ucd.Name)
+		char.codePoint = r
+		char.forms[FCompatibility].decomp = exp
+		if !isCompat {
+			char.forms[FCanonical].decomp = exp
+		} else {
+			char.compatDecomp = true
+		}
+		if len(decmap) > 0 {
+			char.forms[FCompatibility].decomp = exp
+		}
+	}
+	if err := p.Err(); err != nil {
+		logger.Fatal(err)
+	}
+}
+
+// compactCCC converts the sparse set of CCC values to a continguous one,
+// reducing the number of bits needed from 8 to 6.
+func compactCCC() {
+	m := make(map[uint8]uint8)
+	for i := range chars {
+		c := &chars[i]
+		m[c.ccc] = 0
+	}
+	cccs := []int{}
+	for v, _ := range m {
+		cccs = append(cccs, int(v))
+	}
+	sort.Ints(cccs)
+	for i, c := range cccs {
+		cccMap[uint8(i)] = uint8(c)
+		m[uint8(c)] = uint8(i)
+	}
+	for i := range chars {
+		c := &chars[i]
+		c.origCCC = c.ccc
+		c.ccc = m[c.ccc]
+	}
+	if len(m) >= 1<<6 {
+		log.Fatalf("too many difference CCC values: %d >= 64", len(m))
+	}
+}
+
+// CompositionExclusions.txt has form:
+// 0958    # ...
+// See http://unicode.org/reports/tr44/ for full explanation
+func loadCompositionExclusions() {
+	f := openReader("CompositionExclusions.txt")
+	defer f.Close()
+	p := ucd.New(f)
+	for p.Next() {
+		c := &chars[p.Rune(0)]
+		if c.excludeInComp {
+			logger.Fatalf("%U: Duplicate entry in exclusions.", c.codePoint)
+		}
+		c.excludeInComp = true
+	}
+	if e := p.Err(); e != nil {
+		logger.Fatal(e)
+	}
+}
+
+// hasCompatDecomp returns true if any of the recursive
+// decompositions contains a compatibility expansion.
+// In this case, the character may not occur in NFK*.
+func hasCompatDecomp(r rune) bool {
+	c := &chars[r]
+	if c.compatDecomp {
+		return true
+	}
+	for _, d := range c.forms[FCompatibility].decomp {
+		if hasCompatDecomp(d) {
+			return true
+		}
+	}
+	return false
+}
+
+// Hangul related constants.
+const (
+	HangulBase = 0xAC00
+	HangulEnd  = 0xD7A4 // hangulBase + Jamo combinations (19 * 21 * 28)
+
+	JamoLBase = 0x1100
+	JamoLEnd  = 0x1113
+	JamoVBase = 0x1161
+	JamoVEnd  = 0x1176
+	JamoTBase = 0x11A8
+	JamoTEnd  = 0x11C3
+
+	JamoLVTCount = 19 * 21 * 28
+	JamoTCount   = 28
+)
+
+func isHangul(r rune) bool {
+	return HangulBase <= r && r < HangulEnd
+}
+
+func isHangulWithoutJamoT(r rune) bool {
+	if !isHangul(r) {
+		return false
+	}
+	r -= HangulBase
+	return r < JamoLVTCount && r%JamoTCount == 0
+}
+
+func ccc(r rune) uint8 {
+	return chars[r].ccc
+}
+
+// Insert a rune in a buffer, ordered by Canonical Combining Class.
+func insertOrdered(b Decomposition, r rune) Decomposition {
+	n := len(b)
+	b = append(b, 0)
+	cc := ccc(r)
+	if cc > 0 {
+		// Use bubble sort.
+		for ; n > 0; n-- {
+			if ccc(b[n-1]) <= cc {
+				break
+			}
+			b[n] = b[n-1]
+		}
+	}
+	b[n] = r
+	return b
+}
+
+// Recursively decompose.
+func decomposeRecursive(form int, r rune, d Decomposition) Decomposition {
+	dcomp := chars[r].forms[form].decomp
+	if len(dcomp) == 0 {
+		return insertOrdered(d, r)
+	}
+	for _, c := range dcomp {
+		d = decomposeRecursive(form, c, d)
+	}
+	return d
+}
+
+func completeCharFields(form int) {
+	// Phase 0: pre-expand decomposition.
+	for i := range chars {
+		f := &chars[i].forms[form]
+		if len(f.decomp) == 0 {
+			continue
+		}
+		exp := make(Decomposition, 0)
+		for _, c := range f.decomp {
+			exp = decomposeRecursive(form, c, exp)
+		}
+		f.expandedDecomp = exp
+	}
+
+	// Phase 1: composition exclusion, mark decomposition.
+	for i := range chars {
+		c := &chars[i]
+		f := &c.forms[form]
+
+		// Marks script-specific exclusions and version restricted.
+		f.isOneWay = c.excludeInComp
+
+		// Singletons
+		f.isOneWay = f.isOneWay || len(f.decomp) == 1
+
+		// Non-starter decompositions
+		if len(f.decomp) > 1 {
+			chk := c.ccc != 0 || chars[f.decomp[0]].ccc != 0
+			f.isOneWay = f.isOneWay || chk
+		}
+
+		// Runes that decompose into more than two runes.
+		f.isOneWay = f.isOneWay || len(f.decomp) > 2
+
+		if form == FCompatibility {
+			f.isOneWay = f.isOneWay || hasCompatDecomp(c.codePoint)
+		}
+
+		for _, r := range f.decomp {
+			chars[r].forms[form].inDecomp = true
+		}
+	}
+
+	// Phase 2: forward and backward combining.
+	for i := range chars {
+		c := &chars[i]
+		f := &c.forms[form]
+
+		if !f.isOneWay && len(f.decomp) == 2 {
+			f0 := &chars[f.decomp[0]].forms[form]
+			f1 := &chars[f.decomp[1]].forms[form]
+			if !f0.isOneWay {
+				f0.combinesForward = true
+			}
+			if !f1.isOneWay {
+				f1.combinesBackward = true
+			}
+		}
+		if isHangulWithoutJamoT(rune(i)) {
+			f.combinesForward = true
+		}
+	}
+
+	// Phase 3: quick check values.
+	for i := range chars {
+		c := &chars[i]
+		f := &c.forms[form]
+
+		switch {
+		case len(f.decomp) > 0:
+			f.quickCheck[MDecomposed] = QCNo
+		case isHangul(rune(i)):
+			f.quickCheck[MDecomposed] = QCNo
+		default:
+			f.quickCheck[MDecomposed] = QCYes
+		}
+		switch {
+		case f.isOneWay:
+			f.quickCheck[MComposed] = QCNo
+		case (i & 0xffff00) == JamoLBase:
+			f.quickCheck[MComposed] = QCYes
+			if JamoLBase <= i && i < JamoLEnd {
+				f.combinesForward = true
+			}
+			if JamoVBase <= i && i < JamoVEnd {
+				f.quickCheck[MComposed] = QCMaybe
+				f.combinesBackward = true
+				f.combinesForward = true
+			}
+			if JamoTBase <= i && i < JamoTEnd {
+				f.quickCheck[MComposed] = QCMaybe
+				f.combinesBackward = true
+			}
+		case !f.combinesBackward:
+			f.quickCheck[MComposed] = QCYes
+		default:
+			f.quickCheck[MComposed] = QCMaybe
+		}
+	}
+}
+
+func computeNonStarterCounts() {
+	// Phase 4: leading and trailing non-starter count
+	for i := range chars {
+		c := &chars[i]
+
+		runes := []rune{rune(i)}
+		// We always use FCompatibility so that the CGJ insertion points do not
+		// change for repeated normalizations with different forms.
+		if exp := c.forms[FCompatibility].expandedDecomp; len(exp) > 0 {
+			runes = exp
+		}
+		for _, r := range runes {
+			if chars[r].ccc == 0 {
+				break
+			}
+			c.nLeadingNonStarters++
+		}
+		for i := len(runes) - 1; i >= 0; i-- {
+			if chars[runes[i]].ccc == 0 {
+				break
+			}
+			c.nTrailingNonStarters++
+		}
+
+		// We consider runes that combine backwards to be non-starters for the
+		// purpose of Stream-Safe Text Processing.
+		for _, f := range c.forms {
+			if c.ccc == 0 && f.combinesBackward {
+				if len(c.forms[FCompatibility].expandedDecomp) > 0 {
+					log.Fatalf("%U: CCC==0 modifier with an expansion is not supported.", i)
+				}
+				c.nTrailingNonStarters = 1
+				c.nLeadingNonStarters = 1
+			}
+		}
+
+		if isHangul(rune(i)) {
+			c.nTrailingNonStarters = 2
+			if isHangulWithoutJamoT(rune(i)) {
+				c.nTrailingNonStarters = 1
+			}
+		}
+
+		if l, t := c.nLeadingNonStarters, c.nTrailingNonStarters; l > 0 && l != t {
+			log.Fatalf("%U: number of leading and trailing non-starters should be equal (%d vs %d)", i, l, t)
+		}
+		if t := c.nTrailingNonStarters; t > 3 {
+			log.Fatalf("%U: number of trailing non-starters is %d > 3", t)
+		}
+	}
+}
+
+func printBytes(b []byte, name string) {
+	fmt.Printf("// %s: %d bytes\n", name, len(b))
+	fmt.Printf("var %s = [...]byte {", name)
+	for i, c := range b {
+		switch {
+		case i%64 == 0:
+			fmt.Printf("\n// Bytes %x - %x\n", i, i+63)
+		case i%8 == 0:
+			fmt.Printf("\n")
+		}
+		fmt.Printf("0x%.2X, ", c)
+	}
+	fmt.Print("\n}\n\n")
+}
+
+// See forminfo.go for format.
+func makeEntry(f *FormInfo, c *Char) uint16 {
+	e := uint16(0)
+	if r := c.codePoint; HangulBase <= r && r < HangulEnd {
+		e |= 0x40
+	}
+	if f.combinesForward {
+		e |= 0x20
+	}
+	if f.quickCheck[MDecomposed] == QCNo {
+		e |= 0x4
+	}
+	switch f.quickCheck[MComposed] {
+	case QCYes:
+	case QCNo:
+		e |= 0x10
+	case QCMaybe:
+		e |= 0x18
+	default:
+		log.Fatalf("Illegal quickcheck value %v.", f.quickCheck[MComposed])
+	}
+	e |= uint16(c.nTrailingNonStarters)
+	return e
+}
+
+// decompSet keeps track of unique decompositions, grouped by whether
+// the decomposition is followed by a trailing and/or leading CCC.
+type decompSet [7]map[string]bool
+
+const (
+	normalDecomp = iota
+	firstMulti
+	firstCCC
+	endMulti
+	firstLeadingCCC
+	firstCCCZeroExcept
+	firstStarterWithNLead
+	lastDecomp
+)
+
+var cname = []string{"firstMulti", "firstCCC", "endMulti", "firstLeadingCCC", "firstCCCZeroExcept", "firstStarterWithNLead", "lastDecomp"}
+
+func makeDecompSet() decompSet {
+	m := decompSet{}
+	for i := range m {
+		m[i] = make(map[string]bool)
+	}
+	return m
+}
+func (m *decompSet) insert(key int, s string) {
+	m[key][s] = true
+}
+
+func printCharInfoTables() int {
+	mkstr := func(r rune, f *FormInfo) (int, string) {
+		d := f.expandedDecomp
+		s := string([]rune(d))
+		if max := 1 << 6; len(s) >= max {
+			const msg = "%U: too many bytes in decomposition: %d >= %d"
+			logger.Fatalf(msg, r, len(s), max)
+		}
+		head := uint8(len(s))
+		if f.quickCheck[MComposed] != QCYes {
+			head |= 0x40
+		}
+		if f.combinesForward {
+			head |= 0x80
+		}
+		s = string([]byte{head}) + s
+
+		lccc := ccc(d[0])
+		tccc := ccc(d[len(d)-1])
+		cc := ccc(r)
+		if cc != 0 && lccc == 0 && tccc == 0 {
+			logger.Fatalf("%U: trailing and leading ccc are 0 for non-zero ccc %d", r, cc)
+		}
+		if tccc < lccc && lccc != 0 {
+			const msg = "%U: lccc (%d) must be <= tcc (%d)"
+			logger.Fatalf(msg, r, lccc, tccc)
+		}
+		index := normalDecomp
+		nTrail := chars[r].nTrailingNonStarters
+		if tccc > 0 || lccc > 0 || nTrail > 0 {
+			tccc <<= 2
+			tccc |= nTrail
+			s += string([]byte{tccc})
+			index = endMulti
+			for _, r := range d[1:] {
+				if ccc(r) == 0 {
+					index = firstCCC
+				}
+			}
+			if lccc > 0 {
+				s += string([]byte{lccc})
+				if index == firstCCC {
+					logger.Fatalf("%U: multi-segment decomposition not supported for decompositions with leading CCC != 0", r)
+				}
+				index = firstLeadingCCC
+			}
+			if cc != lccc {
+				if cc != 0 {
+					logger.Fatalf("%U: for lccc != ccc, expected ccc to be 0; was %d", r, cc)
+				}
+				index = firstCCCZeroExcept
+			}
+		} else if len(d) > 1 {
+			index = firstMulti
+		}
+		return index, s
+	}
+
+	decompSet := makeDecompSet()
+	const nLeadStr = "\x00\x01" // 0-byte length and tccc with nTrail.
+	decompSet.insert(firstStarterWithNLead, nLeadStr)
+
+	// Store the uniqued decompositions in a byte buffer,
+	// preceded by their byte length.
+	for _, c := range chars {
+		for _, f := range c.forms {
+			if len(f.expandedDecomp) == 0 {
+				continue
+			}
+			if f.combinesBackward {
+				logger.Fatalf("%U: combinesBackward and decompose", c.codePoint)
+			}
+			index, s := mkstr(c.codePoint, &f)
+			decompSet.insert(index, s)
+		}
+	}
+
+	decompositions := bytes.NewBuffer(make([]byte, 0, 10000))
+	size := 0
+	positionMap := make(map[string]uint16)
+	decompositions.WriteString("\000")
+	fmt.Println("const (")
+	for i, m := range decompSet {
+		sa := []string{}
+		for s := range m {
+			sa = append(sa, s)
+		}
+		sort.Strings(sa)
+		for _, s := range sa {
+			p := decompositions.Len()
+			decompositions.WriteString(s)
+			positionMap[s] = uint16(p)
+		}
+		if cname[i] != "" {
+			fmt.Printf("%s = 0x%X\n", cname[i], decompositions.Len())
+		}
+	}
+	fmt.Println("maxDecomp = 0x8000")
+	fmt.Println(")")
+	b := decompositions.Bytes()
+	printBytes(b, "decomps")
+	size += len(b)
+
+	varnames := []string{"nfc", "nfkc"}
+	for i := 0; i < FNumberOfFormTypes; i++ {
+		trie := triegen.NewTrie(varnames[i])
+
+		for r, c := range chars {
+			f := c.forms[i]
+			d := f.expandedDecomp
+			if len(d) != 0 {
+				_, key := mkstr(c.codePoint, &f)
+				trie.Insert(rune(r), uint64(positionMap[key]))
+				if c.ccc != ccc(d[0]) {
+					// We assume the lead ccc of a decomposition !=0 in this case.
+					if ccc(d[0]) == 0 {
+						logger.Fatalf("Expected leading CCC to be non-zero; ccc is %d", c.ccc)
+					}
+				}
+			} else if c.nLeadingNonStarters > 0 && len(f.expandedDecomp) == 0 && c.ccc == 0 && !f.combinesBackward {
+				// Handle cases where it can't be detected that the nLead should be equal
+				// to nTrail.
+				trie.Insert(c.codePoint, uint64(positionMap[nLeadStr]))
+			} else if v := makeEntry(&f, &c)<<8 | uint16(c.ccc); v != 0 {
+				trie.Insert(c.codePoint, uint64(0x8000|v))
+			}
+		}
+		sz, err := trie.Gen(os.Stdout, triegen.Compact(&normCompacter{name: varnames[i]}))
+		if err != nil {
+			logger.Fatal(err)
+		}
+		size += sz
+	}
+	return size
+}
+
+func contains(sa []string, s string) bool {
+	for _, a := range sa {
+		if a == s {
+			return true
+		}
+	}
+	return false
+}
+
+// Extract the version number from the URL.
+func version() string {
+	// From http://www.unicode.org/standard/versions/#Version_Numbering:
+	// for the later Unicode versions, data files are located in
+	// versioned directories.
+	fields := strings.Split(*url, "/")
+	for _, f := range fields {
+		if match, _ := regexp.MatchString(`[0-9]\.[0-9]\.[0-9]`, f); match {
+			return f
+		}
+	}
+	logger.Fatal("unknown version")
+	return "Unknown"
+}
+
+const fileHeader = `// Generated by running
+//	maketables --tables=%s --url=%s
+// DO NOT EDIT
+
+package norm
+
+`
+
+func makeTables() {
+	size := 0
+	if *tablelist == "" {
+		return
+	}
+	list := strings.Split(*tablelist, ",")
+	if *tablelist == "all" {
+		list = []string{"recomp", "info"}
+	}
+	fmt.Printf(fileHeader, *tablelist, *url)
+
+	// Compute maximum decomposition size.
+	max := 0
+	for _, c := range chars {
+		if n := len(string(c.forms[FCompatibility].expandedDecomp)); n > max {
+			max = n
+		}
+	}
+
+	fmt.Println("const (")
+	fmt.Println("\t// Version is the Unicode edition from which the tables are derived.")
+	fmt.Printf("\tVersion = %q\n", version())
+	fmt.Println()
+	fmt.Println("\t// MaxTransformChunkSize indicates the maximum number of bytes that Transform")
+	fmt.Println("\t// may need to write atomically for any Form. Making a destination buffer at")
+	fmt.Println("\t// least this size ensures that Transform can always make progress and that")
+	fmt.Println("\t// the user does not need to grow the buffer on an ErrShortDst.")
+	fmt.Printf("\tMaxTransformChunkSize = %d+maxNonStarters*4\n", len(string(0x034F))+max)
+	fmt.Println(")\n")
+
+	// Print the CCC remap table.
+	size += len(cccMap)
+	fmt.Printf("var ccc = [%d]uint8{", len(cccMap))
+	for i := 0; i < len(cccMap); i++ {
+		if i%8 == 0 {
+			fmt.Println()
+		}
+		fmt.Printf("%3d, ", cccMap[uint8(i)])
+	}
+	fmt.Println("\n}\n")
+
+	if contains(list, "info") {
+		size += printCharInfoTables()
+	}
+
+	if contains(list, "recomp") {
+		// Note that we use 32 bit keys, instead of 64 bit.
+		// This clips the bits of three entries, but we know
+		// this won't cause a collision. The compiler will catch
+		// any changes made to UnicodeData.txt that introduces
+		// a collision.
+		// Note that the recomposition map for NFC and NFKC
+		// are identical.
+
+		// Recomposition map
+		nrentries := 0
+		for _, c := range chars {
+			f := c.forms[FCanonical]
+			if !f.isOneWay && len(f.decomp) > 0 {
+				nrentries++
+			}
+		}
+		sz := nrentries * 8
+		size += sz
+		fmt.Printf("// recompMap: %d bytes (entries only)\n", sz)
+		fmt.Println("var recompMap = map[uint32]rune{")
+		for i, c := range chars {
+			f := c.forms[FCanonical]
+			d := f.decomp
+			if !f.isOneWay && len(d) > 0 {
+				key := uint32(uint16(d[0]))<<16 + uint32(uint16(d[1]))
+				fmt.Printf("0x%.8X: 0x%.4X,\n", key, i)
+			}
+		}
+		fmt.Printf("}\n\n")
+	}
+
+	fmt.Printf("// Total size of tables: %dKB (%d bytes)\n", (size+512)/1024, size)
+}
+
+func printChars() {
+	if *verbose {
+		for _, c := range chars {
+			if !c.isValid() || c.state == SMissing {
+				continue
+			}
+			fmt.Println(c)
+		}
+	}
+}
+
+// verifyComputed does various consistency tests.
+func verifyComputed() {
+	for i, c := range chars {
+		for _, f := range c.forms {
+			isNo := (f.quickCheck[MDecomposed] == QCNo)
+			if (len(f.decomp) > 0) != isNo && !isHangul(rune(i)) {
+				log.Fatalf("%U: NF*D QC must be No if rune decomposes", i)
+			}
+
+			isMaybe := f.quickCheck[MComposed] == QCMaybe
+			if f.combinesBackward != isMaybe {
+				log.Fatalf("%U: NF*C QC must be Maybe if combinesBackward", i)
+			}
+			if len(f.decomp) > 0 && f.combinesForward && isMaybe {
+				log.Fatalf("%U: NF*C QC must be Yes or No if combinesForward and decomposes", i)
+			}
+
+			if len(f.expandedDecomp) != 0 {
+				continue
+			}
+			if a, b := c.nLeadingNonStarters > 0, (c.ccc > 0 || f.combinesBackward); a != b {
+				// We accept these two runes to be treated differently (it only affects
+				// segment breaking in iteration, most likely on inproper use), but
+				// reconsider if more characters are added.
+				if i != 0xFF9E && i != 0xFF9F {
+					log.Fatalf("%U: nLead was %v; want %v", i, a, b)
+				}
+			}
+		}
+		nfc := c.forms[FCanonical]
+		nfkc := c.forms[FCompatibility]
+		if nfc.combinesBackward != nfkc.combinesBackward {
+			logger.Fatalf("%U: Cannot combine combinesBackward\n", c.codePoint)
+		}
+	}
+}
+
+// Use values in DerivedNormalizationProps.txt to compare against the
+// values we computed.
+// DerivedNormalizationProps.txt has form:
+// 00C0..00C5    ; NFD_QC; N # ...
+// 0374          ; NFD_QC; N # ...
+// See http://unicode.org/reports/tr44/ for full explanation
+func testDerived() {
+	f := openReader("DerivedNormalizationProps.txt")
+	defer f.Close()
+	p := ucd.New(f)
+	for p.Next() {
+		r := p.Rune(0)
+		c := &chars[r]
+
+		var ftype, mode int
+		qt := p.String(1)
+		switch qt {
+		case "NFC_QC":
+			ftype, mode = FCanonical, MComposed
+		case "NFD_QC":
+			ftype, mode = FCanonical, MDecomposed
+		case "NFKC_QC":
+			ftype, mode = FCompatibility, MComposed
+		case "NFKD_QC":
+			ftype, mode = FCompatibility, MDecomposed
+		default:
+			continue
+		}
+		var qr QCResult
+		switch p.String(2) {
+		case "Y":
+			qr = QCYes
+		case "N":
+			qr = QCNo
+		case "M":
+			qr = QCMaybe
+		default:
+			log.Fatalf(`Unexpected quick check value "%s"`, p.String(2))
+		}
+		if got := c.forms[ftype].quickCheck[mode]; got != qr {
+			logger.Printf("%U: FAILED %s (was %v need %v)\n", r, qt, got, qr)
+		}
+		c.forms[ftype].verified[mode] = true
+	}
+	if err := p.Err(); err != nil {
+		logger.Fatal(err)
+	}
+	// Any unspecified value must be QCYes. Verify this.
+	for i, c := range chars {
+		for j, fd := range c.forms {
+			for k, qr := range fd.quickCheck {
+				if !fd.verified[k] && qr != QCYes {
+					m := "%U: FAIL F:%d M:%d (was %v need Yes) %s\n"
+					logger.Printf(m, i, j, k, qr, c.name)
+				}
+			}
+		}
+	}
+}
+
+var testHeader = `// Generated by running
+//   maketables --test --url=%s
+// +build test
+
+package norm
+
+const (
+	Yes = iota
+	No
+	Maybe
+)
+
+type formData struct {
+	qc              uint8
+	combinesForward bool
+	decomposition   string
+}
+
+type runeData struct {
+	r      rune
+	ccc    uint8
+	nLead  uint8
+	nTrail uint8
+	f      [2]formData // 0: canonical; 1: compatibility
+}
+
+func f(qc uint8, cf bool, dec string) [2]formData {
+	return [2]formData{{qc, cf, dec}, {qc, cf, dec}}
+}
+
+func g(qc, qck uint8, cf, cfk bool, d, dk string) [2]formData {
+	return [2]formData{{qc, cf, d}, {qck, cfk, dk}}
+}
+
+var testData = []runeData{
+`
+
+func printTestdata() {
+	type lastInfo struct {
+		ccc    uint8
+		nLead  uint8
+		nTrail uint8
+		f      string
+	}
+	last := lastInfo{}
+	fmt.Printf(testHeader, *url)
+	for r, c := range chars {
+		f := c.forms[FCanonical]
+		qc, cf, d := f.quickCheck[MComposed], f.combinesForward, string(f.expandedDecomp)
+		f = c.forms[FCompatibility]
+		qck, cfk, dk := f.quickCheck[MComposed], f.combinesForward, string(f.expandedDecomp)
+		s := ""
+		if d == dk && qc == qck && cf == cfk {
+			s = fmt.Sprintf("f(%s, %v, %q)", qc, cf, d)
+		} else {
+			s = fmt.Sprintf("g(%s, %s, %v, %v, %q, %q)", qc, qck, cf, cfk, d, dk)
+		}
+		current := lastInfo{c.ccc, c.nLeadingNonStarters, c.nTrailingNonStarters, s}
+		if last != current {
+			fmt.Printf("\t{0x%x, %d, %d, %d, %s},\n", r, c.origCCC, c.nLeadingNonStarters, c.nTrailingNonStarters, s)
+			last = current
+		}
+	}
+	fmt.Println("}")
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/norm_test.go b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/norm_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..12dacfcf3006ceda00dc883a1d14bfd8d4fd0406
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/norm_test.go
@@ -0,0 +1,14 @@
+// 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 norm_test
+
+import (
+	"testing"
+)
+
+func TestPlaceHolder(t *testing.T) {
+	// Does nothing, just allows the Makefile to be canonical
+	// while waiting for the package itself to be written.
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/normalize.go b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/normalize.go
new file mode 100644
index 0000000000000000000000000000000000000000..d8172849401af2afab9957c28549fc8a1bc9422e
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/normalize.go
@@ -0,0 +1,524 @@
+// 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 norm contains types and functions for normalizing Unicode strings.
+package norm
+
+import "unicode/utf8"
+
+// A Form denotes a canonical representation of Unicode code points.
+// The Unicode-defined normalization and equivalence forms are:
+//
+//   NFC   Unicode Normalization Form C
+//   NFD   Unicode Normalization Form D
+//   NFKC  Unicode Normalization Form KC
+//   NFKD  Unicode Normalization Form KD
+//
+// For a Form f, this documentation uses the notation f(x) to mean
+// the bytes or string x converted to the given form.
+// A position n in x is called a boundary if conversion to the form can
+// proceed independently on both sides:
+//   f(x) == append(f(x[0:n]), f(x[n:])...)
+//
+// References: http://unicode.org/reports/tr15/ and
+// http://unicode.org/notes/tn5/.
+type Form int
+
+const (
+	NFC Form = iota
+	NFD
+	NFKC
+	NFKD
+)
+
+// Bytes returns f(b). May return b if f(b) = b.
+func (f Form) Bytes(b []byte) []byte {
+	src := inputBytes(b)
+	ft := formTable[f]
+	n, ok := ft.quickSpan(src, 0, len(b), true)
+	if ok {
+		return b
+	}
+	out := make([]byte, n, len(b))
+	copy(out, b[0:n])
+	rb := reorderBuffer{f: *ft, src: src, nsrc: len(b), out: out, flushF: appendFlush}
+	return doAppendInner(&rb, n)
+}
+
+// String returns f(s).
+func (f Form) String(s string) string {
+	src := inputString(s)
+	ft := formTable[f]
+	n, ok := ft.quickSpan(src, 0, len(s), true)
+	if ok {
+		return s
+	}
+	out := make([]byte, n, len(s))
+	copy(out, s[0:n])
+	rb := reorderBuffer{f: *ft, src: src, nsrc: len(s), out: out, flushF: appendFlush}
+	return string(doAppendInner(&rb, n))
+}
+
+// IsNormal returns true if b == f(b).
+func (f Form) IsNormal(b []byte) bool {
+	src := inputBytes(b)
+	ft := formTable[f]
+	bp, ok := ft.quickSpan(src, 0, len(b), true)
+	if ok {
+		return true
+	}
+	rb := reorderBuffer{f: *ft, src: src, nsrc: len(b)}
+	rb.setFlusher(nil, cmpNormalBytes)
+	for bp < len(b) {
+		rb.out = b[bp:]
+		if bp = decomposeSegment(&rb, bp, true); bp < 0 {
+			return false
+		}
+		bp, _ = rb.f.quickSpan(rb.src, bp, len(b), true)
+	}
+	return true
+}
+
+func cmpNormalBytes(rb *reorderBuffer) bool {
+	b := rb.out
+	for i := 0; i < rb.nrune; i++ {
+		info := rb.rune[i]
+		if int(info.size) > len(b) {
+			return false
+		}
+		p := info.pos
+		pe := p + info.size
+		for ; p < pe; p++ {
+			if b[0] != rb.byte[p] {
+				return false
+			}
+			b = b[1:]
+		}
+	}
+	return true
+}
+
+// IsNormalString returns true if s == f(s).
+func (f Form) IsNormalString(s string) bool {
+	src := inputString(s)
+	ft := formTable[f]
+	bp, ok := ft.quickSpan(src, 0, len(s), true)
+	if ok {
+		return true
+	}
+	rb := reorderBuffer{f: *ft, src: src, nsrc: len(s)}
+	rb.setFlusher(nil, func(rb *reorderBuffer) bool {
+		for i := 0; i < rb.nrune; i++ {
+			info := rb.rune[i]
+			if bp+int(info.size) > len(s) {
+				return false
+			}
+			p := info.pos
+			pe := p + info.size
+			for ; p < pe; p++ {
+				if s[bp] != rb.byte[p] {
+					return false
+				}
+				bp++
+			}
+		}
+		return true
+	})
+	for bp < len(s) {
+		if bp = decomposeSegment(&rb, bp, true); bp < 0 {
+			return false
+		}
+		bp, _ = rb.f.quickSpan(rb.src, bp, len(s), true)
+	}
+	return true
+}
+
+// patchTail fixes a case where a rune may be incorrectly normalized
+// if it is followed by illegal continuation bytes. It returns the
+// patched buffer and whether the decomposition is still in progress.
+func patchTail(rb *reorderBuffer) bool {
+	info, p := lastRuneStart(&rb.f, rb.out)
+	if p == -1 || info.size == 0 {
+		return true
+	}
+	end := p + int(info.size)
+	extra := len(rb.out) - end
+	if extra > 0 {
+		// Potentially allocating memory. However, this only
+		// happens with ill-formed UTF-8.
+		x := make([]byte, 0)
+		x = append(x, rb.out[len(rb.out)-extra:]...)
+		rb.out = rb.out[:end]
+		decomposeToLastBoundary(rb)
+		rb.doFlush()
+		rb.out = append(rb.out, x...)
+		return false
+	}
+	buf := rb.out[p:]
+	rb.out = rb.out[:p]
+	decomposeToLastBoundary(rb)
+	if s := rb.ss.next(info); s == ssStarter {
+		rb.doFlush()
+		rb.ss.first(info)
+	} else if s == ssOverflow {
+		rb.doFlush()
+		rb.insertCGJ()
+		rb.ss = 0
+	}
+	rb.insertUnsafe(inputBytes(buf), 0, info)
+	return true
+}
+
+func appendQuick(rb *reorderBuffer, i int) int {
+	if rb.nsrc == i {
+		return i
+	}
+	end, _ := rb.f.quickSpan(rb.src, i, rb.nsrc, true)
+	rb.out = rb.src.appendSlice(rb.out, i, end)
+	return end
+}
+
+// Append returns f(append(out, b...)).
+// The buffer out must be nil, empty, or equal to f(out).
+func (f Form) Append(out []byte, src ...byte) []byte {
+	return f.doAppend(out, inputBytes(src), len(src))
+}
+
+func (f Form) doAppend(out []byte, src input, n int) []byte {
+	if n == 0 {
+		return out
+	}
+	ft := formTable[f]
+	// Attempt to do a quickSpan first so we can avoid initializing the reorderBuffer.
+	if len(out) == 0 {
+		p, _ := ft.quickSpan(src, 0, n, true)
+		out = src.appendSlice(out, 0, p)
+		if p == n {
+			return out
+		}
+		rb := reorderBuffer{f: *ft, src: src, nsrc: n, out: out, flushF: appendFlush}
+		return doAppendInner(&rb, p)
+	}
+	rb := reorderBuffer{f: *ft, src: src, nsrc: n}
+	return doAppend(&rb, out, 0)
+}
+
+func doAppend(rb *reorderBuffer, out []byte, p int) []byte {
+	rb.setFlusher(out, appendFlush)
+	src, n := rb.src, rb.nsrc
+	doMerge := len(out) > 0
+	if q := src.skipContinuationBytes(p); q > p {
+		// Move leading non-starters to destination.
+		rb.out = src.appendSlice(rb.out, p, q)
+		p = q
+		doMerge = patchTail(rb)
+	}
+	fd := &rb.f
+	if doMerge {
+		var info Properties
+		if p < n {
+			info = fd.info(src, p)
+			if !info.BoundaryBefore() || info.nLeadingNonStarters() > 0 {
+				if p == 0 {
+					decomposeToLastBoundary(rb)
+				}
+				p = decomposeSegment(rb, p, true)
+			}
+		}
+		if info.size == 0 {
+			rb.doFlush()
+			// Append incomplete UTF-8 encoding.
+			return src.appendSlice(rb.out, p, n)
+		}
+		if rb.nrune > 0 {
+			return doAppendInner(rb, p)
+		}
+	}
+	p = appendQuick(rb, p)
+	return doAppendInner(rb, p)
+}
+
+func doAppendInner(rb *reorderBuffer, p int) []byte {
+	for n := rb.nsrc; p < n; {
+		p = decomposeSegment(rb, p, true)
+		p = appendQuick(rb, p)
+	}
+	return rb.out
+}
+
+// AppendString returns f(append(out, []byte(s))).
+// The buffer out must be nil, empty, or equal to f(out).
+func (f Form) AppendString(out []byte, src string) []byte {
+	return f.doAppend(out, inputString(src), len(src))
+}
+
+// QuickSpan returns a boundary n such that b[0:n] == f(b[0:n]).
+// It is not guaranteed to return the largest such n.
+func (f Form) QuickSpan(b []byte) int {
+	n, _ := formTable[f].quickSpan(inputBytes(b), 0, len(b), true)
+	return n
+}
+
+// quickSpan returns a boundary n such that src[0:n] == f(src[0:n]) and
+// whether any non-normalized parts were found. If atEOF is false, n will
+// not point past the last segment if this segment might be become
+// non-normalized by appending other runes.
+func (f *formInfo) quickSpan(src input, i, end int, atEOF bool) (n int, ok bool) {
+	var lastCC uint8
+	ss := streamSafe(0)
+	lastSegStart := i
+	for n = end; i < n; {
+		if j := src.skipASCII(i, n); i != j {
+			i = j
+			lastSegStart = i - 1
+			lastCC = 0
+			ss = 0
+			continue
+		}
+		info := f.info(src, i)
+		if info.size == 0 {
+			if atEOF {
+				// include incomplete runes
+				return n, true
+			}
+			return lastSegStart, true
+		}
+		// This block needs to be before the next, because it is possible to
+		// have an overflow for runes that are starters (e.g. with U+FF9E).
+		switch ss.next(info) {
+		case ssStarter:
+			ss.first(info)
+			lastSegStart = i
+		case ssOverflow:
+			return lastSegStart, false
+		case ssSuccess:
+			if lastCC > info.ccc {
+				return lastSegStart, false
+			}
+		}
+		if f.composing {
+			if !info.isYesC() {
+				break
+			}
+		} else {
+			if !info.isYesD() {
+				break
+			}
+		}
+		lastCC = info.ccc
+		i += int(info.size)
+	}
+	if i == n {
+		if !atEOF {
+			n = lastSegStart
+		}
+		return n, true
+	}
+	return lastSegStart, false
+}
+
+// QuickSpanString returns a boundary n such that b[0:n] == f(s[0:n]).
+// It is not guaranteed to return the largest such n.
+func (f Form) QuickSpanString(s string) int {
+	n, _ := formTable[f].quickSpan(inputString(s), 0, len(s), true)
+	return n
+}
+
+// FirstBoundary returns the position i of the first boundary in b
+// or -1 if b contains no boundary.
+func (f Form) FirstBoundary(b []byte) int {
+	return f.firstBoundary(inputBytes(b), len(b))
+}
+
+func (f Form) firstBoundary(src input, nsrc int) int {
+	i := src.skipContinuationBytes(0)
+	if i >= nsrc {
+		return -1
+	}
+	fd := formTable[f]
+	ss := streamSafe(0)
+	// We should call ss.first here, but we can't as the first rune is
+	// skipped already. This means FirstBoundary can't really determine
+	// CGJ insertion points correctly. Luckily it doesn't have to.
+	// TODO: consider adding NextBoundary
+	for {
+		info := fd.info(src, i)
+		if info.size == 0 {
+			return -1
+		}
+		if s := ss.next(info); s != ssSuccess {
+			return i
+		}
+		i += int(info.size)
+		if i >= nsrc {
+			if !info.BoundaryAfter() && !ss.isMax() {
+				return -1
+			}
+			return nsrc
+		}
+	}
+}
+
+// FirstBoundaryInString returns the position i of the first boundary in s
+// or -1 if s contains no boundary.
+func (f Form) FirstBoundaryInString(s string) int {
+	return f.firstBoundary(inputString(s), len(s))
+}
+
+// LastBoundary returns the position i of the last boundary in b
+// or -1 if b contains no boundary.
+func (f Form) LastBoundary(b []byte) int {
+	return lastBoundary(formTable[f], b)
+}
+
+func lastBoundary(fd *formInfo, b []byte) int {
+	i := len(b)
+	info, p := lastRuneStart(fd, b)
+	if p == -1 {
+		return -1
+	}
+	if info.size == 0 { // ends with incomplete rune
+		if p == 0 { // starts with incomplete rune
+			return -1
+		}
+		i = p
+		info, p = lastRuneStart(fd, b[:i])
+		if p == -1 { // incomplete UTF-8 encoding or non-starter bytes without a starter
+			return i
+		}
+	}
+	if p+int(info.size) != i { // trailing non-starter bytes: illegal UTF-8
+		return i
+	}
+	if info.BoundaryAfter() {
+		return i
+	}
+	ss := streamSafe(0)
+	v := ss.backwards(info)
+	for i = p; i >= 0 && v != ssStarter; i = p {
+		info, p = lastRuneStart(fd, b[:i])
+		if v = ss.backwards(info); v == ssOverflow {
+			break
+		}
+		if p+int(info.size) != i {
+			if p == -1 { // no boundary found
+				return -1
+			}
+			return i // boundary after an illegal UTF-8 encoding
+		}
+	}
+	return i
+}
+
+// decomposeSegment scans the first segment in src into rb. It inserts 0x034f
+// (Grapheme Joiner) when it encounters a sequence of more than 30 non-starters
+// and returns the number of bytes consumed from src or iShortDst or iShortSrc.
+func decomposeSegment(rb *reorderBuffer, sp int, atEOF bool) int {
+	// Force one character to be consumed.
+	info := rb.f.info(rb.src, sp)
+	if info.size == 0 {
+		return 0
+	}
+	if rb.nrune > 0 {
+		if s := rb.ss.next(info); s == ssStarter {
+			goto end
+		} else if s == ssOverflow {
+			rb.insertCGJ()
+			goto end
+		}
+	} else {
+		rb.ss.first(info)
+	}
+	if err := rb.insertFlush(rb.src, sp, info); err != iSuccess {
+		return int(err)
+	}
+	for {
+		sp += int(info.size)
+		if sp >= rb.nsrc {
+			if !atEOF && !info.BoundaryAfter() {
+				return int(iShortSrc)
+			}
+			break
+		}
+		info = rb.f.info(rb.src, sp)
+		if info.size == 0 {
+			if !atEOF {
+				return int(iShortSrc)
+			}
+			break
+		}
+		if s := rb.ss.next(info); s == ssStarter {
+			break
+		} else if s == ssOverflow {
+			rb.insertCGJ()
+			break
+		}
+		if err := rb.insertFlush(rb.src, sp, info); err != iSuccess {
+			return int(err)
+		}
+	}
+end:
+	if !rb.doFlush() {
+		return int(iShortDst)
+	}
+	return sp
+}
+
+// lastRuneStart returns the runeInfo and position of the last
+// rune in buf or the zero runeInfo and -1 if no rune was found.
+func lastRuneStart(fd *formInfo, buf []byte) (Properties, int) {
+	p := len(buf) - 1
+	for ; p >= 0 && !utf8.RuneStart(buf[p]); p-- {
+	}
+	if p < 0 {
+		return Properties{}, -1
+	}
+	return fd.info(inputBytes(buf), p), p
+}
+
+// decomposeToLastBoundary finds an open segment at the end of the buffer
+// and scans it into rb. Returns the buffer minus the last segment.
+func decomposeToLastBoundary(rb *reorderBuffer) {
+	fd := &rb.f
+	info, i := lastRuneStart(fd, rb.out)
+	if int(info.size) != len(rb.out)-i {
+		// illegal trailing continuation bytes
+		return
+	}
+	if info.BoundaryAfter() {
+		return
+	}
+	var add [maxNonStarters + 1]Properties // stores runeInfo in reverse order
+	padd := 0
+	ss := streamSafe(0)
+	p := len(rb.out)
+	for {
+		add[padd] = info
+		v := ss.backwards(info)
+		if v == ssOverflow {
+			// Note that if we have an overflow, it the string we are appending to
+			// is not correctly normalized. In this case the behavior is undefined.
+			break
+		}
+		padd++
+		p -= int(info.size)
+		if v == ssStarter || p < 0 {
+			break
+		}
+		info, i = lastRuneStart(fd, rb.out[:p])
+		if int(info.size) != p-i {
+			break
+		}
+	}
+	rb.ss = ss
+	// Copy bytes for insertion as we may need to overwrite rb.out.
+	var buf [maxBufferSize * utf8.UTFMax]byte
+	cp := buf[:copy(buf[:], rb.out[p:])]
+	rb.out = rb.out[:p]
+	for padd--; padd >= 0; padd-- {
+		info = add[padd]
+		rb.insertUnsafe(inputBytes(cp), 0, info)
+		cp = cp[info.size:]
+	}
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/normalize_test.go b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/normalize_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..643d11edf5f46e29e4582fb167a61b8307727358
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/normalize_test.go
@@ -0,0 +1,1086 @@
+// 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 norm
+
+import (
+	"bytes"
+	"flag"
+	"fmt"
+	"io"
+	"log"
+	"strings"
+	"testing"
+	"unicode/utf8"
+)
+
+var (
+	testn = flag.Int("testn", -1, "specific test number to run or -1 for all")
+)
+
+// pc replaces any rune r that is repeated n times, for n > 1, with r{n}.
+func pc(s string) []byte {
+	b := bytes.NewBuffer(make([]byte, 0, len(s)))
+	for i := 0; i < len(s); {
+		r, sz := utf8.DecodeRuneInString(s[i:])
+		n := 0
+		if sz == 1 {
+			// Special-case one-byte case to handle repetition for invalid UTF-8.
+			for c := s[i]; i+n < len(s) && s[i+n] == c; n++ {
+			}
+		} else {
+			for _, r2 := range s[i:] {
+				if r2 != r {
+					break
+				}
+				n++
+			}
+		}
+		b.WriteString(s[i : i+sz])
+		if n > 1 {
+			fmt.Fprintf(b, "{%d}", n)
+		}
+		i += sz * n
+	}
+	return b.Bytes()
+}
+
+// pidx finds the index from which two strings start to differ, plus context.
+// It returns the index and ellipsis if the index is greater than 0.
+func pidx(a, b string) (i int, prefix string) {
+	for ; i < len(a) && i < len(b) && a[i] == b[i]; i++ {
+	}
+	if i < 8 {
+		return 0, ""
+	}
+	i -= 3 // ensure taking at least one full rune before the difference.
+	for k := i - 7; i > k && !utf8.RuneStart(a[i]); i-- {
+	}
+	return i, "..."
+}
+
+type PositionTest struct {
+	input  string
+	pos    int
+	buffer string // expected contents of reorderBuffer, if applicable
+}
+
+type positionFunc func(rb *reorderBuffer, s string) (int, []byte)
+
+func runPosTests(t *testing.T, name string, f Form, fn positionFunc, tests []PositionTest) {
+	rb := reorderBuffer{}
+	rb.init(f, nil)
+	for i, test := range tests {
+		rb.reset()
+		rb.src = inputString(test.input)
+		rb.nsrc = len(test.input)
+		pos, out := fn(&rb, test.input)
+		if pos != test.pos {
+			t.Errorf("%s:%d: position is %d; want %d", name, i, pos, test.pos)
+		}
+		if outs := string(out); outs != test.buffer {
+			k, pfx := pidx(outs, test.buffer)
+			t.Errorf("%s:%d: buffer \nwas  %s%+q; \nwant %s%+q", name, i, pfx, pc(outs[k:]), pfx, pc(test.buffer[k:]))
+		}
+	}
+}
+
+func grave(n int) string {
+	return rep(0x0300, n)
+}
+
+func rep(r rune, n int) string {
+	return strings.Repeat(string(r), n)
+}
+
+const segSize = maxByteBufferSize
+
+var cgj = GraphemeJoiner
+
+var decomposeSegmentTests = []PositionTest{
+	// illegal runes
+	{"\xC0", 0, ""},
+	{"\u00E0\x80", 2, "\u0061\u0300"},
+	// starter
+	{"a", 1, "a"},
+	{"ab", 1, "a"},
+	// starter + composing
+	{"a\u0300", 3, "a\u0300"},
+	{"a\u0300b", 3, "a\u0300"},
+	// with decomposition
+	{"\u00C0", 2, "A\u0300"},
+	{"\u00C0b", 2, "A\u0300"},
+	// long
+	{grave(31), 60, grave(30) + cgj},
+	{grave(30), 60, grave(30)},
+	{grave(30) + "\uff9e", 60, grave(30) + cgj},
+	// ends with incomplete UTF-8 encoding
+	{"\xCC", 0, ""},
+	{"\u0300\xCC", 2, "\u0300"},
+}
+
+func decomposeSegmentF(rb *reorderBuffer, s string) (int, []byte) {
+	rb.initString(NFD, s)
+	rb.setFlusher(nil, appendFlush)
+	p := decomposeSegment(rb, 0, true)
+	return p, rb.out
+}
+
+func TestDecomposeSegment(t *testing.T) {
+	runPosTests(t, "TestDecomposeSegment", NFC, decomposeSegmentF, decomposeSegmentTests)
+}
+
+var firstBoundaryTests = []PositionTest{
+	// no boundary
+	{"", -1, ""},
+	{"\u0300", -1, ""},
+	{"\x80\x80", -1, ""},
+	// illegal runes
+	{"\xff", 0, ""},
+	{"\u0300\xff", 2, ""},
+	{"\u0300\xc0\x80\x80", 2, ""},
+	// boundaries
+	{"a", 0, ""},
+	{"\u0300a", 2, ""},
+	// Hangul
+	{"\u1103\u1161", 0, ""},
+	{"\u110B\u1173\u11B7", 0, ""},
+	{"\u1161\u110B\u1173\u11B7", 3, ""},
+	{"\u1173\u11B7\u1103\u1161", 6, ""},
+	// too many combining characters.
+	{grave(maxNonStarters - 1), -1, ""},
+	{grave(maxNonStarters), 60, ""},
+	{grave(maxNonStarters + 1), 60, ""},
+}
+
+func firstBoundaryF(rb *reorderBuffer, s string) (int, []byte) {
+	return rb.f.form.FirstBoundary([]byte(s)), nil
+}
+
+func firstBoundaryStringF(rb *reorderBuffer, s string) (int, []byte) {
+	return rb.f.form.FirstBoundaryInString(s), nil
+}
+
+func TestFirstBoundary(t *testing.T) {
+	runPosTests(t, "TestFirstBoundary", NFC, firstBoundaryF, firstBoundaryTests)
+	runPosTests(t, "TestFirstBoundaryInString", NFC, firstBoundaryStringF, firstBoundaryTests)
+}
+
+var decomposeToLastTests = []PositionTest{
+	// ends with inert character
+	{"Hello!", 6, ""},
+	{"\u0632", 2, ""},
+	{"a\u0301\u0635", 5, ""},
+	// ends with non-inert starter
+	{"a", 0, "a"},
+	{"a\u0301a", 3, "a"},
+	{"a\u0301\u03B9", 3, "\u03B9"},
+	{"a\u0327", 0, "a\u0327"},
+	// illegal runes
+	{"\xFF", 1, ""},
+	{"aa\xFF", 3, ""},
+	{"\xC0\x80\x80", 3, ""},
+	{"\xCC\x80\x80", 3, ""},
+	// ends with incomplete UTF-8 encoding
+	{"a\xCC", 2, ""},
+	// ends with combining characters
+	{"\u0300\u0301", 0, "\u0300\u0301"},
+	{"a\u0300\u0301", 0, "a\u0300\u0301"},
+	{"a\u0301\u0308", 0, "a\u0301\u0308"},
+	{"a\u0308\u0301", 0, "a\u0308\u0301"},
+	{"aaaa\u0300\u0301", 3, "a\u0300\u0301"},
+	{"\u0300a\u0300\u0301", 2, "a\u0300\u0301"},
+	{"\u00C0", 0, "A\u0300"},
+	{"a\u00C0", 1, "A\u0300"},
+	// decomposing
+	{"a\u0300\u00E0", 3, "a\u0300"},
+	// multisegment decompositions (flushes leading segments)
+	{"a\u0300\uFDC0", 7, "\u064A"},
+	{"\uFDC0" + grave(29), 4, "\u064A" + grave(29)},
+	{"\uFDC0" + grave(30), 4, "\u064A" + grave(30)},
+	{"\uFDC0" + grave(31), 5, grave(30)},
+	{"\uFDFA" + grave(14), 31, "\u0645" + grave(14)},
+	// Overflow
+	{"\u00E0" + grave(29), 0, "a" + grave(30)},
+	{"\u00E0" + grave(30), 2, grave(30)},
+	// Hangul
+	{"a\u1103", 1, "\u1103"},
+	{"a\u110B", 1, "\u110B"},
+	{"a\u110B\u1173", 1, "\u110B\u1173"},
+	// See comment in composition.go:compBoundaryAfter.
+	{"a\u110B\u1173\u11B7", 1, "\u110B\u1173\u11B7"},
+	{"a\uC73C", 1, "\u110B\u1173"},
+	{"다음", 3, "\u110B\u1173\u11B7"},
+	{"다", 0, "\u1103\u1161"},
+	{"\u1103\u1161\u110B\u1173\u11B7", 6, "\u110B\u1173\u11B7"},
+	{"\u110B\u1173\u11B7\u1103\u1161", 9, "\u1103\u1161"},
+	{"다음음", 6, "\u110B\u1173\u11B7"},
+	{"음다다", 6, "\u1103\u1161"},
+	// maximized buffer
+	{"a" + grave(30), 0, "a" + grave(30)},
+	// Buffer overflow
+	{"a" + grave(31), 3, grave(30)},
+	// weird UTF-8
+	{"a\u0300\u11B7", 0, "a\u0300\u11B7"},
+}
+
+func decomposeToLast(rb *reorderBuffer, s string) (int, []byte) {
+	rb.setFlusher([]byte(s), appendFlush)
+	decomposeToLastBoundary(rb)
+	buf := rb.flush(nil)
+	return len(rb.out), buf
+}
+
+func TestDecomposeToLastBoundary(t *testing.T) {
+	runPosTests(t, "TestDecomposeToLastBoundary", NFKC, decomposeToLast, decomposeToLastTests)
+}
+
+var lastBoundaryTests = []PositionTest{
+	// ends with inert character
+	{"Hello!", 6, ""},
+	{"\u0632", 2, ""},
+	// ends with non-inert starter
+	{"a", 0, ""},
+	// illegal runes
+	{"\xff", 1, ""},
+	{"aa\xff", 3, ""},
+	{"a\xff\u0300", 1, ""},
+	{"\xc0\x80\x80", 3, ""},
+	{"\xc0\x80\x80\u0300", 3, ""},
+	// ends with incomplete UTF-8 encoding
+	{"\xCC", -1, ""},
+	{"\xE0\x80", -1, ""},
+	{"\xF0\x80\x80", -1, ""},
+	{"a\xCC", 0, ""},
+	{"\x80\xCC", 1, ""},
+	{"\xCC\xCC", 1, ""},
+	// ends with combining characters
+	{"a\u0300\u0301", 0, ""},
+	{"aaaa\u0300\u0301", 3, ""},
+	{"\u0300a\u0300\u0301", 2, ""},
+	{"\u00C0", 0, ""},
+	{"a\u00C0", 1, ""},
+	// decomposition may recombine
+	{"\u0226", 0, ""},
+	// no boundary
+	{"", -1, ""},
+	{"\u0300\u0301", -1, ""},
+	{"\u0300", -1, ""},
+	{"\x80\x80", -1, ""},
+	{"\x80\x80\u0301", -1, ""},
+	// Hangul
+	{"다음", 3, ""},
+	{"다", 0, ""},
+	{"\u1103\u1161\u110B\u1173\u11B7", 6, ""},
+	{"\u110B\u1173\u11B7\u1103\u1161", 9, ""},
+	// too many combining characters.
+	{grave(maxNonStarters - 1), -1, ""},
+	// May still be preceded with a non-starter.
+	{grave(maxNonStarters), -1, ""},
+	// May still need to insert a cgj after the last combiner.
+	{grave(maxNonStarters + 1), 2, ""},
+	{grave(maxNonStarters + 2), 4, ""},
+
+	{"a" + grave(maxNonStarters-1), 0, ""},
+	{"a" + grave(maxNonStarters), 0, ""},
+	// May still need to insert a cgj after the last combiner.
+	{"a" + grave(maxNonStarters+1), 3, ""},
+	{"a" + grave(maxNonStarters+2), 5, ""},
+}
+
+func lastBoundaryF(rb *reorderBuffer, s string) (int, []byte) {
+	return rb.f.form.LastBoundary([]byte(s)), nil
+}
+
+func TestLastBoundary(t *testing.T) {
+	runPosTests(t, "TestLastBoundary", NFC, lastBoundaryF, lastBoundaryTests)
+}
+
+var quickSpanTests = []PositionTest{
+	{"", 0, ""},
+	// starters
+	{"a", 1, ""},
+	{"abc", 3, ""},
+	{"\u043Eb", 3, ""},
+	// incomplete last rune.
+	{"\xCC", 1, ""},
+	{"a\xCC", 2, ""},
+	// incorrectly ordered combining characters
+	{"\u0300\u0316", 0, ""},
+	{"\u0300\u0316cd", 0, ""},
+	// have a maximum number of combining characters.
+	{rep(0x035D, 30) + "\u035B", 0, ""},
+	{"a" + rep(0x035D, 30) + "\u035B", 0, ""},
+	{"Ɵ" + rep(0x035D, 30) + "\u035B", 0, ""},
+	{"aa" + rep(0x035D, 30) + "\u035B", 1, ""},
+	{rep(0x035D, 30) + cgj + "\u035B", 64, ""},
+	{"a" + rep(0x035D, 30) + cgj + "\u035B", 65, ""},
+	{"Ɵ" + rep(0x035D, 30) + cgj + "\u035B", 66, ""},
+	{"aa" + rep(0x035D, 30) + cgj + "\u035B", 66, ""},
+}
+
+var quickSpanNFDTests = []PositionTest{
+	// needs decomposing
+	{"\u00C0", 0, ""},
+	{"abc\u00C0", 3, ""},
+	// correctly ordered combining characters
+	{"\u0300", 2, ""},
+	{"ab\u0300", 4, ""},
+	{"ab\u0300cd", 6, ""},
+	{"\u0300cd", 4, ""},
+	{"\u0316\u0300", 4, ""},
+	{"ab\u0316\u0300", 6, ""},
+	{"ab\u0316\u0300cd", 8, ""},
+	{"ab\u0316\u0300\u00C0", 6, ""},
+	{"\u0316\u0300cd", 6, ""},
+	{"\u043E\u0308b", 5, ""},
+	// incorrectly ordered combining characters
+	{"ab\u0300\u0316", 1, ""}, // TODO: we could skip 'b' as well.
+	{"ab\u0300\u0316cd", 1, ""},
+	// Hangul
+	{"같은", 0, ""},
+}
+
+var quickSpanNFCTests = []PositionTest{
+	// okay composed
+	{"\u00C0", 2, ""},
+	{"abc\u00C0", 5, ""},
+	// correctly ordered combining characters
+	{"ab\u0300", 1, ""},
+	{"ab\u0300cd", 1, ""},
+	{"ab\u0316\u0300", 1, ""},
+	{"ab\u0316\u0300cd", 1, ""},
+	{"\u00C0\u035D", 4, ""},
+	// we do not special case leading combining characters
+	{"\u0300cd", 0, ""},
+	{"\u0300", 0, ""},
+	{"\u0316\u0300", 0, ""},
+	{"\u0316\u0300cd", 0, ""},
+	// incorrectly ordered combining characters
+	{"ab\u0300\u0316", 1, ""},
+	{"ab\u0300\u0316cd", 1, ""},
+	// Hangul
+	{"같은", 6, ""},
+	// We return the start of the violating segment in case of overflow.
+	{grave(30) + "\uff9e", 0, ""},
+	{grave(30), 0, ""},
+}
+
+func doQuickSpan(rb *reorderBuffer, s string) (int, []byte) {
+	return rb.f.form.QuickSpan([]byte(s)), nil
+}
+
+func doQuickSpanString(rb *reorderBuffer, s string) (int, []byte) {
+	return rb.f.form.QuickSpanString(s), nil
+}
+
+func TestQuickSpan(t *testing.T) {
+	runPosTests(t, "TestQuickSpanNFD1", NFD, doQuickSpan, quickSpanTests)
+	runPosTests(t, "TestQuickSpanNFD2", NFD, doQuickSpan, quickSpanNFDTests)
+	runPosTests(t, "TestQuickSpanNFC1", NFC, doQuickSpan, quickSpanTests)
+	runPosTests(t, "TestQuickSpanNFC2", NFC, doQuickSpan, quickSpanNFCTests)
+
+	runPosTests(t, "TestQuickSpanStringNFD1", NFD, doQuickSpanString, quickSpanTests)
+	runPosTests(t, "TestQuickSpanStringNFD2", NFD, doQuickSpanString, quickSpanNFDTests)
+	runPosTests(t, "TestQuickSpanStringNFC1", NFC, doQuickSpanString, quickSpanTests)
+	runPosTests(t, "TestQuickSpanStringNFC2", NFC, doQuickSpanString, quickSpanNFCTests)
+}
+
+var isNormalTests = []PositionTest{
+	{"", 1, ""},
+	// illegal runes
+	{"\xff", 1, ""},
+	// starters
+	{"a", 1, ""},
+	{"abc", 1, ""},
+	{"\u043Eb", 1, ""},
+	// incorrectly ordered combining characters
+	{"\u0300\u0316", 0, ""},
+	{"ab\u0300\u0316", 0, ""},
+	{"ab\u0300\u0316cd", 0, ""},
+	{"\u0300\u0316cd", 0, ""},
+}
+var isNormalNFDTests = []PositionTest{
+	// needs decomposing
+	{"\u00C0", 0, ""},
+	{"abc\u00C0", 0, ""},
+	// correctly ordered combining characters
+	{"\u0300", 1, ""},
+	{"ab\u0300", 1, ""},
+	{"ab\u0300cd", 1, ""},
+	{"\u0300cd", 1, ""},
+	{"\u0316\u0300", 1, ""},
+	{"ab\u0316\u0300", 1, ""},
+	{"ab\u0316\u0300cd", 1, ""},
+	{"\u0316\u0300cd", 1, ""},
+	{"\u043E\u0308b", 1, ""},
+	// Hangul
+	{"같은", 0, ""},
+}
+var isNormalNFCTests = []PositionTest{
+	// okay composed
+	{"\u00C0", 1, ""},
+	{"abc\u00C0", 1, ""},
+	// need reordering
+	{"a\u0300", 0, ""},
+	{"a\u0300cd", 0, ""},
+	{"a\u0316\u0300", 0, ""},
+	{"a\u0316\u0300cd", 0, ""},
+	// correctly ordered combining characters
+	{"ab\u0300", 1, ""},
+	{"ab\u0300cd", 1, ""},
+	{"ab\u0316\u0300", 1, ""},
+	{"ab\u0316\u0300cd", 1, ""},
+	{"\u00C0\u035D", 1, ""},
+	{"\u0300", 1, ""},
+	{"\u0316\u0300cd", 1, ""},
+	// Hangul
+	{"같은", 1, ""},
+}
+
+var isNormalNFKXTests = []PositionTest{
+	// Special case.
+	{"\u00BC", 0, ""},
+}
+
+func isNormalF(rb *reorderBuffer, s string) (int, []byte) {
+	if rb.f.form.IsNormal([]byte(s)) {
+		return 1, nil
+	}
+	return 0, nil
+}
+
+func isNormalStringF(rb *reorderBuffer, s string) (int, []byte) {
+	if rb.f.form.IsNormalString(s) {
+		return 1, nil
+	}
+	return 0, nil
+}
+
+func TestIsNormal(t *testing.T) {
+	runPosTests(t, "TestIsNormalNFD1", NFD, isNormalF, isNormalTests)
+	runPosTests(t, "TestIsNormalNFD2", NFD, isNormalF, isNormalNFDTests)
+	runPosTests(t, "TestIsNormalNFC1", NFC, isNormalF, isNormalTests)
+	runPosTests(t, "TestIsNormalNFC2", NFC, isNormalF, isNormalNFCTests)
+	runPosTests(t, "TestIsNormalNFKD1", NFKD, isNormalF, isNormalTests)
+	runPosTests(t, "TestIsNormalNFKD2", NFKD, isNormalF, isNormalNFDTests)
+	runPosTests(t, "TestIsNormalNFKD3", NFKD, isNormalF, isNormalNFKXTests)
+	runPosTests(t, "TestIsNormalNFKC1", NFKC, isNormalF, isNormalTests)
+	runPosTests(t, "TestIsNormalNFKC2", NFKC, isNormalF, isNormalNFCTests)
+	runPosTests(t, "TestIsNormalNFKC3", NFKC, isNormalF, isNormalNFKXTests)
+}
+
+func TestIsNormalString(t *testing.T) {
+	runPosTests(t, "TestIsNormalNFD1", NFD, isNormalStringF, isNormalTests)
+	runPosTests(t, "TestIsNormalNFD2", NFD, isNormalStringF, isNormalNFDTests)
+	runPosTests(t, "TestIsNormalNFC1", NFC, isNormalStringF, isNormalTests)
+	runPosTests(t, "TestIsNormalNFC2", NFC, isNormalStringF, isNormalNFCTests)
+}
+
+type AppendTest struct {
+	left  string
+	right string
+	out   string
+}
+
+type appendFunc func(f Form, out []byte, s string) []byte
+
+var fstr = []string{"NFC", "NFD", "NFKC", "NFKD"}
+
+func runNormTests(t *testing.T, name string, fn appendFunc) {
+	for f := NFC; f <= NFKD; f++ {
+		runAppendTests(t, name, f, fn, normTests[f])
+	}
+}
+
+func runAppendTests(t *testing.T, name string, f Form, fn appendFunc, tests []AppendTest) {
+	for i, test := range tests {
+		if *testn >= 0 && i != *testn {
+			continue
+		}
+		out := []byte(test.left)
+		have := string(fn(f, out, test.right))
+		if len(have) != len(test.out) {
+			t.Errorf("%s.%s:%d: length is %d; want %d (%+q vs %+q)", fstr[f], name, i, len(have), len(test.out), pc(have), pc(test.out))
+		}
+		if have != test.out {
+			k, pf := pidx(have, test.out)
+			t.Errorf("%s.%s:%d: \nwas  %s%+q; \nwant %s%+q", fstr[f], name, i, pf, pc(have[k:]), pf, pc(test.out[k:]))
+		}
+
+		// Bootstrap by normalizing input. Ensures that the various variants
+		// behave the same.
+		for g := NFC; g <= NFKD; g++ {
+			if f == g {
+				continue
+			}
+			want := g.String(test.left + test.right)
+			have := string(fn(g, g.AppendString(nil, test.left), test.right))
+			if len(have) != len(want) {
+				t.Errorf("%s(%s.%s):%d: length is %d; want %d (%+q vs %+q)", fstr[g], fstr[f], name, i, len(have), len(want), pc(have), pc(want))
+			}
+			if have != want {
+				k, pf := pidx(have, want)
+				t.Errorf("%s(%s.%s):%d: \nwas  %s%+q; \nwant %s%+q", fstr[g], fstr[f], name, i, pf, pc(have[k:]), pf, pc(want[k:]))
+			}
+		}
+	}
+}
+
+var normTests = [][]AppendTest{
+	appendTestsNFC,
+	appendTestsNFD,
+	appendTestsNFKC,
+	appendTestsNFKD,
+}
+
+var appendTestsNFC = []AppendTest{
+	{"", ascii, ascii},
+	{"", txt_all, txt_all},
+	{"\uff9e", grave(30), "\uff9e" + grave(29) + cgj + grave(1)},
+	{grave(30), "\uff9e", grave(30) + cgj + "\uff9e"},
+
+	// Tests designed for Iter.
+	{ // ordering of non-composing combining characters
+		"",
+		"\u0305\u0316",
+		"\u0316\u0305",
+	},
+	{ // segment overflow
+		"",
+		"a" + rep(0x0305, maxNonStarters+4) + "\u0316",
+		"a" + rep(0x0305, maxNonStarters) + cgj + "\u0316" + rep(0x305, 4),
+	},
+}
+
+var appendTestsNFD = []AppendTest{
+// TODO: Move some of the tests here.
+}
+
+var appendTestsNFKC = []AppendTest{
+	// empty buffers
+	{"", "", ""},
+	{"a", "", "a"},
+	{"", "a", "a"},
+	{"", "\u0041\u0307\u0304", "\u01E0"},
+	// segment split across buffers
+	{"", "a\u0300b", "\u00E0b"},
+	{"a", "\u0300b", "\u00E0b"},
+	{"a", "\u0300\u0316", "\u00E0\u0316"},
+	{"a", "\u0316\u0300", "\u00E0\u0316"},
+	{"a", "\u0300a\u0300", "\u00E0\u00E0"},
+	{"a", "\u0300a\u0300a\u0300", "\u00E0\u00E0\u00E0"},
+	{"a", "\u0300aaa\u0300aaa\u0300", "\u00E0aa\u00E0aa\u00E0"},
+	{"a\u0300", "\u0327", "\u00E0\u0327"},
+	{"a\u0327", "\u0300", "\u00E0\u0327"},
+	{"a\u0316", "\u0300", "\u00E0\u0316"},
+	{"\u0041\u0307", "\u0304", "\u01E0"},
+	// Hangul
+	{"", "\u110B\u1173", "\uC73C"},
+	{"", "\u1103\u1161", "\uB2E4"},
+	{"", "\u110B\u1173\u11B7", "\uC74C"},
+	{"", "\u320E", "\x28\uAC00\x29"},
+	{"", "\x28\u1100\u1161\x29", "\x28\uAC00\x29"},
+	{"\u1103", "\u1161", "\uB2E4"},
+	{"\u110B", "\u1173\u11B7", "\uC74C"},
+	{"\u110B\u1173", "\u11B7", "\uC74C"},
+	{"\uC73C", "\u11B7", "\uC74C"},
+	// UTF-8 encoding split across buffers
+	{"a\xCC", "\x80", "\u00E0"},
+	{"a\xCC", "\x80b", "\u00E0b"},
+	{"a\xCC", "\x80a\u0300", "\u00E0\u00E0"},
+	{"a\xCC", "\x80\x80", "\u00E0\x80"},
+	{"a\xCC", "\x80\xCC", "\u00E0\xCC"},
+	{"a\u0316\xCC", "\x80a\u0316\u0300", "\u00E0\u0316\u00E0\u0316"},
+	// ending in incomplete UTF-8 encoding
+	{"", "\xCC", "\xCC"},
+	{"a", "\xCC", "a\xCC"},
+	{"a", "b\xCC", "ab\xCC"},
+	{"\u0226", "\xCC", "\u0226\xCC"},
+	// illegal runes
+	{"", "\x80", "\x80"},
+	{"", "\x80\x80\x80", "\x80\x80\x80"},
+	{"", "\xCC\x80\x80\x80", "\xCC\x80\x80\x80"},
+	{"", "a\x80", "a\x80"},
+	{"", "a\x80\x80\x80", "a\x80\x80\x80"},
+	{"", "a\x80\x80\x80\x80\x80\x80", "a\x80\x80\x80\x80\x80\x80"},
+	{"a", "\x80\x80\x80", "a\x80\x80\x80"},
+	// overflow
+	{"", strings.Repeat("\x80", 33), strings.Repeat("\x80", 33)},
+	{strings.Repeat("\x80", 33), "", strings.Repeat("\x80", 33)},
+	{strings.Repeat("\x80", 33), strings.Repeat("\x80", 33), strings.Repeat("\x80", 66)},
+	// overflow of combining characters
+	{"", grave(34), grave(30) + cgj + grave(4)},
+	{"", grave(36), grave(30) + cgj + grave(6)},
+	{grave(29), grave(5), grave(30) + cgj + grave(4)},
+	{grave(30), grave(4), grave(30) + cgj + grave(4)},
+	{grave(30), grave(3), grave(30) + cgj + grave(3)},
+	{grave(30) + "\xCC", "\x80", grave(30) + cgj + grave(1)},
+	{"", "\uFDFA" + grave(14), "\u0635\u0644\u0649 \u0627\u0644\u0644\u0647 \u0639\u0644\u064a\u0647 \u0648\u0633\u0644\u0645" + grave(14)},
+	{"", "\uFDFA" + grave(28) + "\u0316", "\u0635\u0644\u0649 \u0627\u0644\u0644\u0647 \u0639\u0644\u064a\u0647 \u0648\u0633\u0644\u0645\u0316" + grave(28)},
+	// - First rune has a trailing non-starter.
+	{"\u00d5", grave(30), "\u00d5" + grave(29) + cgj + grave(1)},
+	// - U+FF9E decomposes into a non-starter in compatibility mode. A CGJ must be
+	//   inserted even when FF9E starts a new segment.
+	{"\uff9e", grave(30), "\u3099" + grave(29) + cgj + grave(1)},
+	{grave(30), "\uff9e", grave(30) + cgj + "\u3099"},
+	// - Many non-starter decompositions in a row causing overflow.
+	{"", rep(0x340, 31), rep(0x300, 30) + cgj + "\u0300"},
+	{"", rep(0xFF9E, 31), rep(0x3099, 30) + cgj + "\u3099"},
+	// weird UTF-8
+	{"\u00E0\xE1", "\x86", "\u00E0\xE1\x86"},
+	{"a\u0300\u11B7", "\u0300", "\u00E0\u11B7\u0300"},
+	{"a\u0300\u11B7\u0300", "\u0300", "\u00E0\u11B7\u0300\u0300"},
+	{"\u0300", "\xF8\x80\x80\x80\x80\u0300", "\u0300\xF8\x80\x80\x80\x80\u0300"},
+	{"\u0300", "\xFC\x80\x80\x80\x80\x80\u0300", "\u0300\xFC\x80\x80\x80\x80\x80\u0300"},
+	{"\xF8\x80\x80\x80\x80\u0300", "\u0300", "\xF8\x80\x80\x80\x80\u0300\u0300"},
+	{"\xFC\x80\x80\x80\x80\x80\u0300", "\u0300", "\xFC\x80\x80\x80\x80\x80\u0300\u0300"},
+	{"\xF8\x80\x80\x80", "\x80\u0300\u0300", "\xF8\x80\x80\x80\x80\u0300\u0300"},
+
+	{"", strings.Repeat("a\u0316\u0300", 6), strings.Repeat("\u00E0\u0316", 6)},
+	// large input.
+	{"", strings.Repeat("a\u0300\u0316", 4000), strings.Repeat("\u00E0\u0316", 4000)},
+	{"", strings.Repeat("\x80\x80", 4000), strings.Repeat("\x80\x80", 4000)},
+	{"", "\u0041\u0307\u0304", "\u01E0"},
+}
+
+var appendTestsNFKD = []AppendTest{
+	{"", "a" + grave(64), "a" + grave(30) + cgj + grave(30) + cgj + grave(4)},
+
+	{ // segment overflow on unchanged character
+		"",
+		"a" + grave(64) + "\u0316",
+		"a" + grave(30) + cgj + grave(30) + cgj + "\u0316" + grave(4),
+	},
+	{ // segment overflow on unchanged character + start value
+		"",
+		"a" + grave(98) + "\u0316",
+		"a" + grave(30) + cgj + grave(30) + cgj + grave(30) + cgj + "\u0316" + grave(8),
+	},
+	{ // segment overflow on decomposition. (U+0340 decomposes to U+0300.)
+		"",
+		"a" + grave(59) + "\u0340",
+		"a" + grave(30) + cgj + grave(30),
+	},
+	{ // segment overflow on non-starter decomposition
+		"",
+		"a" + grave(33) + "\u0340" + grave(30) + "\u0320",
+		"a" + grave(30) + cgj + grave(30) + cgj + "\u0320" + grave(4),
+	},
+	{ // start value after ASCII overflow
+		"",
+		rep('a', segSize) + grave(32) + "\u0320",
+		rep('a', segSize) + grave(30) + cgj + "\u0320" + grave(2),
+	},
+	{ // Jamo overflow
+		"",
+		"\u1100\u1161" + grave(30) + "\u0320" + grave(2),
+		"\u1100\u1161" + grave(29) + cgj + "\u0320" + grave(3),
+	},
+	{ // Hangul
+		"",
+		"\uac00",
+		"\u1100\u1161",
+	},
+	{ // Hangul overflow
+		"",
+		"\uac00" + grave(32) + "\u0320",
+		"\u1100\u1161" + grave(29) + cgj + "\u0320" + grave(3),
+	},
+	{ // Hangul overflow in Hangul mode.
+		"",
+		"\uac00\uac00" + grave(32) + "\u0320",
+		"\u1100\u1161\u1100\u1161" + grave(29) + cgj + "\u0320" + grave(3),
+	},
+	{ // Hangul overflow in Hangul mode.
+		"",
+		strings.Repeat("\uac00", 3) + grave(32) + "\u0320",
+		strings.Repeat("\u1100\u1161", 3) + grave(29) + cgj + "\u0320" + grave(3),
+	},
+	{ // start value after cc=0
+		"",
+		"您您" + grave(34) + "\u0320",
+		"您您" + grave(30) + cgj + "\u0320" + grave(4),
+	},
+	{ // start value after normalization
+		"",
+		"\u0300\u0320a" + grave(34) + "\u0320",
+		"\u0320\u0300a" + grave(30) + cgj + "\u0320" + grave(4),
+	},
+}
+
+func TestAppend(t *testing.T) {
+	runNormTests(t, "Append", func(f Form, out []byte, s string) []byte {
+		return f.Append(out, []byte(s)...)
+	})
+}
+
+func TestAppendString(t *testing.T) {
+	runNormTests(t, "AppendString", func(f Form, out []byte, s string) []byte {
+		return f.AppendString(out, s)
+	})
+}
+
+func TestBytes(t *testing.T) {
+	runNormTests(t, "Bytes", func(f Form, out []byte, s string) []byte {
+		buf := []byte{}
+		buf = append(buf, out...)
+		buf = append(buf, s...)
+		return f.Bytes(buf)
+	})
+}
+
+func TestString(t *testing.T) {
+	runNormTests(t, "String", func(f Form, out []byte, s string) []byte {
+		outs := string(out) + s
+		return []byte(f.String(outs))
+	})
+}
+
+func appendBench(f Form, in []byte) func() {
+	buf := make([]byte, 0, 4*len(in))
+	return func() {
+		f.Append(buf, in...)
+	}
+}
+
+func bytesBench(f Form, in []byte) func() {
+	return func() {
+		f.Bytes(in)
+	}
+}
+
+func iterBench(f Form, in []byte) func() {
+	iter := Iter{}
+	return func() {
+		iter.Init(f, in)
+		for !iter.Done() {
+			iter.Next()
+		}
+	}
+}
+
+func transformBench(f Form, in []byte) func() {
+	buf := make([]byte, 4*len(in))
+	return func() {
+		if _, n, err := f.Transform(buf, in, true); err != nil || len(in) != n {
+			log.Panic(n, len(in), err)
+		}
+	}
+}
+
+func readerBench(f Form, in []byte) func() {
+	buf := make([]byte, 4*len(in))
+	return func() {
+		r := f.Reader(bytes.NewReader(in))
+		var err error
+		for err == nil {
+			_, err = r.Read(buf)
+		}
+		if err != io.EOF {
+			panic("")
+		}
+	}
+}
+
+func writerBench(f Form, in []byte) func() {
+	buf := make([]byte, 0, 4*len(in))
+	return func() {
+		r := f.Writer(bytes.NewBuffer(buf))
+		if _, err := r.Write(in); err != nil {
+			panic("")
+		}
+	}
+}
+
+func appendBenchmarks(bm []func(), f Form, in []byte) []func() {
+	bm = append(bm, appendBench(f, in))
+	bm = append(bm, iterBench(f, in))
+	bm = append(bm, transformBench(f, in))
+	bm = append(bm, readerBench(f, in))
+	bm = append(bm, writerBench(f, in))
+	return bm
+}
+
+func doFormBenchmark(b *testing.B, inf, f Form, s string) {
+	b.StopTimer()
+	in := inf.Bytes([]byte(s))
+	bm := appendBenchmarks(nil, f, in)
+	b.SetBytes(int64(len(in) * len(bm)))
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		for _, fn := range bm {
+			fn()
+		}
+	}
+}
+
+func doSingle(b *testing.B, f func(Form, []byte) func(), s []byte) {
+	b.StopTimer()
+	fn := f(NFC, s)
+	b.SetBytes(int64(len(s)))
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		fn()
+	}
+}
+
+var (
+	smallNoChange = []byte("nörmalization")
+	smallChange   = []byte("No\u0308rmalization")
+	ascii         = strings.Repeat("There is nothing to change here! ", 500)
+)
+
+func lowerBench(f Form, in []byte) func() {
+	// Use package strings instead of bytes as it doesn't allocate memory
+	// if there aren't any changes.
+	s := string(in)
+	return func() {
+		strings.ToLower(s)
+	}
+}
+
+func BenchmarkLowerCaseNoChange(b *testing.B) {
+	doSingle(b, lowerBench, smallNoChange)
+}
+func BenchmarkLowerCaseChange(b *testing.B) {
+	doSingle(b, lowerBench, smallChange)
+}
+
+func quickSpanBench(f Form, in []byte) func() {
+	return func() {
+		f.QuickSpan(in)
+	}
+}
+
+func BenchmarkQuickSpanChangeNFC(b *testing.B) {
+	doSingle(b, quickSpanBench, smallNoChange)
+}
+
+func BenchmarkBytesNoChangeNFC(b *testing.B) {
+	doSingle(b, bytesBench, smallNoChange)
+}
+func BenchmarkBytesChangeNFC(b *testing.B) {
+	doSingle(b, bytesBench, smallChange)
+}
+
+func BenchmarkAppendNoChangeNFC(b *testing.B) {
+	doSingle(b, appendBench, smallNoChange)
+}
+func BenchmarkAppendChangeNFC(b *testing.B) {
+	doSingle(b, appendBench, smallChange)
+}
+func BenchmarkAppendLargeNFC(b *testing.B) {
+	doSingle(b, appendBench, txt_all_bytes)
+}
+
+func BenchmarkIterNoChangeNFC(b *testing.B) {
+	doSingle(b, iterBench, smallNoChange)
+}
+func BenchmarkIterChangeNFC(b *testing.B) {
+	doSingle(b, iterBench, smallChange)
+}
+func BenchmarkIterLargeNFC(b *testing.B) {
+	doSingle(b, iterBench, txt_all_bytes)
+}
+
+func BenchmarkTransformNoChangeNFC(b *testing.B) {
+	doSingle(b, transformBench, smallNoChange)
+}
+func BenchmarkTransformChangeNFC(b *testing.B) {
+	doSingle(b, transformBench, smallChange)
+}
+func BenchmarkTransformLargeNFC(b *testing.B) {
+	doSingle(b, transformBench, txt_all_bytes)
+}
+
+func BenchmarkNormalizeAsciiNFC(b *testing.B) {
+	doFormBenchmark(b, NFC, NFC, ascii)
+}
+func BenchmarkNormalizeAsciiNFD(b *testing.B) {
+	doFormBenchmark(b, NFC, NFD, ascii)
+}
+func BenchmarkNormalizeAsciiNFKC(b *testing.B) {
+	doFormBenchmark(b, NFC, NFKC, ascii)
+}
+func BenchmarkNormalizeAsciiNFKD(b *testing.B) {
+	doFormBenchmark(b, NFC, NFKD, ascii)
+}
+
+func BenchmarkNormalizeNFC2NFC(b *testing.B) {
+	doFormBenchmark(b, NFC, NFC, txt_all)
+}
+func BenchmarkNormalizeNFC2NFD(b *testing.B) {
+	doFormBenchmark(b, NFC, NFD, txt_all)
+}
+func BenchmarkNormalizeNFD2NFC(b *testing.B) {
+	doFormBenchmark(b, NFD, NFC, txt_all)
+}
+func BenchmarkNormalizeNFD2NFD(b *testing.B) {
+	doFormBenchmark(b, NFD, NFD, txt_all)
+}
+
+// Hangul is often special-cased, so we test it separately.
+func BenchmarkNormalizeHangulNFC2NFC(b *testing.B) {
+	doFormBenchmark(b, NFC, NFC, txt_kr)
+}
+func BenchmarkNormalizeHangulNFC2NFD(b *testing.B) {
+	doFormBenchmark(b, NFC, NFD, txt_kr)
+}
+func BenchmarkNormalizeHangulNFD2NFC(b *testing.B) {
+	doFormBenchmark(b, NFD, NFC, txt_kr)
+}
+func BenchmarkNormalizeHangulNFD2NFD(b *testing.B) {
+	doFormBenchmark(b, NFD, NFD, txt_kr)
+}
+
+var forms = []Form{NFC, NFD, NFKC, NFKD}
+
+func doTextBenchmark(b *testing.B, s string) {
+	b.StopTimer()
+	in := []byte(s)
+	bm := []func(){}
+	for _, f := range forms {
+		bm = appendBenchmarks(bm, f, in)
+	}
+	b.SetBytes(int64(len(s) * len(bm)))
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		for _, f := range bm {
+			f()
+		}
+	}
+}
+
+func BenchmarkCanonicalOrdering(b *testing.B) {
+	doTextBenchmark(b, txt_canon)
+}
+func BenchmarkExtendedLatin(b *testing.B) {
+	doTextBenchmark(b, txt_vn)
+}
+func BenchmarkMiscTwoByteUtf8(b *testing.B) {
+	doTextBenchmark(b, twoByteUtf8)
+}
+func BenchmarkMiscThreeByteUtf8(b *testing.B) {
+	doTextBenchmark(b, threeByteUtf8)
+}
+func BenchmarkHangul(b *testing.B) {
+	doTextBenchmark(b, txt_kr)
+}
+func BenchmarkJapanese(b *testing.B) {
+	doTextBenchmark(b, txt_jp)
+}
+func BenchmarkChinese(b *testing.B) {
+	doTextBenchmark(b, txt_cn)
+}
+func BenchmarkOverflow(b *testing.B) {
+	doTextBenchmark(b, overflow)
+}
+
+var overflow = string(bytes.Repeat([]byte("\u035D"), 4096)) + "\u035B"
+
+// Tests sampled from the Canonical ordering tests (Part 2) of
+// http://unicode.org/Public/UNIDATA/NormalizationTest.txt
+const txt_canon = `\u0061\u0315\u0300\u05AE\u0300\u0062 \u0061\u0300\u0315\u0300\u05AE\u0062
+\u0061\u0302\u0315\u0300\u05AE\u0062 \u0061\u0307\u0315\u0300\u05AE\u0062
+\u0061\u0315\u0300\u05AE\u030A\u0062 \u0061\u059A\u0316\u302A\u031C\u0062
+\u0061\u032E\u059A\u0316\u302A\u0062 \u0061\u0338\u093C\u0334\u0062 
+\u0061\u059A\u0316\u302A\u0339       \u0061\u0341\u0315\u0300\u05AE\u0062
+\u0061\u0348\u059A\u0316\u302A\u0062 \u0061\u0361\u0345\u035D\u035C\u0062
+\u0061\u0366\u0315\u0300\u05AE\u0062 \u0061\u0315\u0300\u05AE\u0486\u0062
+\u0061\u05A4\u059A\u0316\u302A\u0062 \u0061\u0315\u0300\u05AE\u0613\u0062
+\u0061\u0315\u0300\u05AE\u0615\u0062 \u0061\u0617\u0315\u0300\u05AE\u0062
+\u0061\u0619\u0618\u064D\u064E\u0062 \u0061\u0315\u0300\u05AE\u0654\u0062
+\u0061\u0315\u0300\u05AE\u06DC\u0062 \u0061\u0733\u0315\u0300\u05AE\u0062
+\u0061\u0744\u059A\u0316\u302A\u0062 \u0061\u0315\u0300\u05AE\u0745\u0062
+\u0061\u09CD\u05B0\u094D\u3099\u0062 \u0061\u0E38\u0E48\u0E38\u0C56\u0062
+\u0061\u0EB8\u0E48\u0E38\u0E49\u0062 \u0061\u0F72\u0F71\u0EC8\u0F71\u0062
+\u0061\u1039\u05B0\u094D\u3099\u0062 \u0061\u05B0\u094D\u3099\u1A60\u0062
+\u0061\u3099\u093C\u0334\u1BE6\u0062 \u0061\u3099\u093C\u0334\u1C37\u0062
+\u0061\u1CD9\u059A\u0316\u302A\u0062 \u0061\u2DED\u0315\u0300\u05AE\u0062
+\u0061\u2DEF\u0315\u0300\u05AE\u0062 \u0061\u302D\u302E\u059A\u0316\u0062`
+
+// Taken from http://creativecommons.org/licenses/by-sa/3.0/vn/
+const txt_vn = `Với các điều kiện sau: Ghi nhận công của tác giả. 
+Nếu bạn sử dụng, chuyển đổi, hoặc xây dựng dự án từ 
+nội dung được chia sẻ này, bạn phải áp dụng giấy phép này hoặc 
+một giấy phép khác có các điều khoản tương tự như giấy phép này
+cho dự án của bạn. Hiểu rằng: Miễn — Bất kỳ các điều kiện nào
+trên đây cũng có thể được miễn bỏ nếu bạn được sự cho phép của
+người sở hữu bản quyền. Phạm vi công chúng — Khi tác phẩm hoặc
+bất kỳ chương nào của tác phẩm đã trong vùng dành cho công
+chúng theo quy định của pháp luật thì tình trạng của nó không 
+bị ảnh hưởng bởi giấy phép trong bất kỳ trường hợp nào.`
+
+// Taken from http://creativecommons.org/licenses/by-sa/1.0/deed.ru
+const txt_ru = `При обязательном соблюдении следующих условий:
+Attribution — Вы должны атрибутировать произведение (указывать
+автора и источник) в порядке, предусмотренном автором или
+лицензиаром (но только так, чтобы никоим образом не подразумевалось,
+что они поддерживают вас или использование вами данного произведения).
+Υπό τις ακόλουθες προϋποθέσεις:`
+
+// Taken from http://creativecommons.org/licenses/by-sa/3.0/gr/
+const txt_gr = `Αναφορά Δημιουργού — Θα πρέπει να κάνετε την αναφορά στο έργο με τον
+τρόπο που έχει οριστεί από το δημιουργό ή το χορηγούντο την άδεια
+(χωρίς όμως να εννοείται με οποιονδήποτε τρόπο ότι εγκρίνουν εσάς ή
+τη χρήση του έργου από εσάς). Παρόμοια Διανομή — Εάν αλλοιώσετε,
+τροποποιήσετε ή δημιουργήσετε περαιτέρω βασισμένοι στο έργο θα
+μπορείτε να διανέμετε το έργο που θα προκύψει μόνο με την ίδια ή
+παρόμοια άδεια.`
+
+// Taken from http://creativecommons.org/licenses/by-sa/3.0/deed.ar
+const txt_ar = `بموجب الشروط التالية نسب المصنف — يجب عليك أن
+تنسب العمل بالطريقة التي تحددها المؤلف أو المرخص (ولكن ليس بأي حال من
+الأحوال أن توحي وتقترح بتحول أو استخدامك للعمل).
+المشاركة على قدم المساواة — إذا كنت يعدل ، والتغيير ، أو الاستفادة
+من هذا العمل ، قد ينتج عن توزيع العمل إلا في ظل تشابه او تطابق فى واحد
+لهذا الترخيص.`
+
+// Taken from http://creativecommons.org/licenses/by-sa/1.0/il/
+const txt_il = `בכפוף לתנאים הבאים: ייחוס — עליך לייחס את היצירה (לתת קרדיט) באופן
+המצויין על-ידי היוצר או מעניק הרישיון (אך לא בשום אופן המרמז על כך
+שהם תומכים בך או בשימוש שלך ביצירה). שיתוף זהה — אם תחליט/י לשנות,
+לעבד או ליצור יצירה נגזרת בהסתמך על יצירה זו, תוכל/י להפיץ את יצירתך
+החדשה רק תחת אותו הרישיון או רישיון דומה לרישיון זה.`
+
+const twoByteUtf8 = txt_ru + txt_gr + txt_ar + txt_il
+
+// Taken from http://creativecommons.org/licenses/by-sa/2.0/kr/
+const txt_kr = `다음과 같은 조건을 따라야 합니다: 저작자표시
+(Attribution) — 저작자나 이용허락자가 정한 방법으로 저작물의
+원저작자를 표시하여야 합니다(그러나 원저작자가 이용자나 이용자의
+이용을 보증하거나 추천한다는 의미로 표시해서는 안됩니다). 
+동일조건변경허락 — 이 저작물을 이용하여 만든 이차적 저작물에는 본
+라이선스와 동일한 라이선스를 적용해야 합니다.`
+
+// Taken from http://creativecommons.org/licenses/by-sa/3.0/th/
+const txt_th = `ภายใต้เงื่อนไข ดังต่อไปนี้ : แสดงที่มา — คุณต้องแสดงที่
+มาของงานดังกล่าว ตามรูปแบบที่ผู้สร้างสรรค์หรือผู้อนุญาตกำหนด (แต่
+ไม่ใช่ในลักษณะที่ว่า พวกเขาสนับสนุนคุณหรือสนับสนุนการที่
+คุณนำงานไปใช้) อนุญาตแบบเดียวกัน — หากคุณดัดแปลง เปลี่ยนรูป หรื
+อต่อเติมงานนี้ คุณต้องใช้สัญญาอนุญาตแบบเดียวกันหรือแบบที่เหมื
+อนกับสัญญาอนุญาตที่ใช้กับงานนี้เท่านั้น`
+
+const threeByteUtf8 = txt_th
+
+// Taken from http://creativecommons.org/licenses/by-sa/2.0/jp/
+const txt_jp = `あなたの従うべき条件は以下の通りです。
+表示 — あなたは原著作者のクレジットを表示しなければなりません。
+継承 — もしあなたがこの作品を改変、変形または加工した場合、
+あなたはその結果生じた作品をこの作品と同一の許諾条件の下でのみ
+頒布することができます。`
+
+// http://creativecommons.org/licenses/by-sa/2.5/cn/
+const txt_cn = `您可以自由: 复制、发行、展览、表演、放映、
+广播或通过信息网络传播本作品 创作演绎作品
+对本作品进行商业性使用 惟须遵守下列条件:
+署名 — 您必须按照作者或者许可人指定的方式对作品进行署名。
+相同方式共享 — 如果您改变、转换本作品或者以本作品为基础进行创作,
+您只能采用与本协议相同的许可协议发布基于本作品的演绎作品。`
+
+const txt_cjk = txt_cn + txt_jp + txt_kr
+const txt_all = txt_vn + twoByteUtf8 + threeByteUtf8 + txt_cjk
+
+var txt_all_bytes = []byte(txt_all)
diff --git a/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/normregtest.go b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/normregtest.go
new file mode 100644
index 0000000000000000000000000000000000000000..654b25b16d2c737b9a5c1b7e7608432a5b8751ec
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/normregtest.go
@@ -0,0 +1,318 @@
+// 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 ignore
+
+package main
+
+import (
+	"bufio"
+	"bytes"
+	"flag"
+	"fmt"
+	"log"
+	"net/http"
+	"os"
+	"path"
+	"regexp"
+	"runtime"
+	"strconv"
+	"strings"
+	"time"
+	"unicode"
+	"unicode/utf8"
+
+	"golang.org/x/text/unicode/norm"
+)
+
+func main() {
+	flag.Parse()
+	loadTestData()
+	CharacterByCharacterTests()
+	StandardTests()
+	PerformanceTest()
+	if errorCount == 0 {
+		fmt.Println("PASS")
+	}
+}
+
+const file = "NormalizationTest.txt"
+
+var url = flag.String("url",
+	"http://www.unicode.org/Public/"+unicode.Version+"/ucd/"+file,
+	"URL of Unicode database directory")
+var localFiles = flag.Bool("local",
+	false,
+	"data files have been copied to the current directory; for debugging only")
+
+var logger = log.New(os.Stderr, "", log.Lshortfile)
+
+// This regression test runs the test set in NormalizationTest.txt
+// (taken from http://www.unicode.org/Public/<unicode.Version>/ucd/).
+//
+// NormalizationTest.txt has form:
+// @Part0 # Specific cases
+// #
+// 1E0A;1E0A;0044 0307;1E0A;0044 0307; # (Ḋ; Ḋ; D◌̇; Ḋ; D◌̇; ) LATIN CAPITAL LETTER D WITH DOT ABOVE
+// 1E0C;1E0C;0044 0323;1E0C;0044 0323; # (Ḍ; Ḍ; D◌̣; Ḍ; D◌̣; ) LATIN CAPITAL LETTER D WITH DOT BELOW
+//
+// Each test has 5 columns (c1, c2, c3, c4, c5), where
+// (c1, c2, c3, c4, c5) == (c1, NFC(c1), NFD(c1), NFKC(c1), NFKD(c1))
+//
+// CONFORMANCE:
+// 1. The following invariants must be true for all conformant implementations
+//
+//    NFC
+//      c2 ==  NFC(c1) ==  NFC(c2) ==  NFC(c3)
+//      c4 ==  NFC(c4) ==  NFC(c5)
+//
+//    NFD
+//      c3 ==  NFD(c1) ==  NFD(c2) ==  NFD(c3)
+//      c5 ==  NFD(c4) ==  NFD(c5)
+//
+//    NFKC
+//      c4 == NFKC(c1) == NFKC(c2) == NFKC(c3) == NFKC(c4) == NFKC(c5)
+//
+//    NFKD
+//      c5 == NFKD(c1) == NFKD(c2) == NFKD(c3) == NFKD(c4) == NFKD(c5)
+//
+// 2. For every code point X assigned in this version of Unicode that is not
+//    specifically listed in Part 1, the following invariants must be true
+//    for all conformant implementations:
+//
+//      X == NFC(X) == NFD(X) == NFKC(X) == NFKD(X)
+//
+
+// Column types.
+const (
+	cRaw = iota
+	cNFC
+	cNFD
+	cNFKC
+	cNFKD
+	cMaxColumns
+)
+
+// Holds data from NormalizationTest.txt
+var part []Part
+
+type Part struct {
+	name   string
+	number int
+	tests  []Test
+}
+
+type Test struct {
+	name   string
+	partnr int
+	number int
+	r      rune                // used for character by character test
+	cols   [cMaxColumns]string // Each has 5 entries, see below.
+}
+
+func (t Test) Name() string {
+	if t.number < 0 {
+		return part[t.partnr].name
+	}
+	return fmt.Sprintf("%s:%d", part[t.partnr].name, t.number)
+}
+
+var partRe = regexp.MustCompile(`@Part(\d) # (.*)$`)
+var testRe = regexp.MustCompile(`^` + strings.Repeat(`([\dA-F ]+);`, 5) + ` # (.*)$`)
+
+var counter int
+
+// Load the data form NormalizationTest.txt
+func loadTestData() {
+	if *localFiles {
+		pwd, _ := os.Getwd()
+		*url = "file://" + path.Join(pwd, file)
+	}
+	t := &http.Transport{}
+	t.RegisterProtocol("file", http.NewFileTransport(http.Dir("/")))
+	c := &http.Client{Transport: t}
+	resp, err := c.Get(*url)
+	if err != nil {
+		logger.Fatal(err)
+	}
+	if resp.StatusCode != 200 {
+		logger.Fatal("bad GET status for "+file, resp.Status)
+	}
+	f := resp.Body
+	defer f.Close()
+	scanner := bufio.NewScanner(f)
+	for scanner.Scan() {
+		line := scanner.Text()
+		if len(line) == 0 || line[0] == '#' {
+			continue
+		}
+		m := partRe.FindStringSubmatch(line)
+		if m != nil {
+			if len(m) < 3 {
+				logger.Fatal("Failed to parse Part: ", line)
+			}
+			i, err := strconv.Atoi(m[1])
+			if err != nil {
+				logger.Fatal(err)
+			}
+			name := m[2]
+			part = append(part, Part{name: name[:len(name)-1], number: i})
+			continue
+		}
+		m = testRe.FindStringSubmatch(line)
+		if m == nil || len(m) < 7 {
+			logger.Fatalf(`Failed to parse: "%s" result: %#v`, line, m)
+		}
+		test := Test{name: m[6], partnr: len(part) - 1, number: counter}
+		counter++
+		for j := 1; j < len(m)-1; j++ {
+			for _, split := range strings.Split(m[j], " ") {
+				r, err := strconv.ParseUint(split, 16, 64)
+				if err != nil {
+					logger.Fatal(err)
+				}
+				if test.r == 0 {
+					// save for CharacterByCharacterTests
+					test.r = rune(r)
+				}
+				var buf [utf8.UTFMax]byte
+				sz := utf8.EncodeRune(buf[:], rune(r))
+				test.cols[j-1] += string(buf[:sz])
+			}
+		}
+		part := &part[len(part)-1]
+		part.tests = append(part.tests, test)
+	}
+	if scanner.Err() != nil {
+		logger.Fatal(scanner.Err())
+	}
+}
+
+var fstr = []string{"NFC", "NFD", "NFKC", "NFKD"}
+
+var errorCount int
+
+func cmpResult(t *Test, name string, f norm.Form, gold, test, result string) {
+	if gold != result {
+		errorCount++
+		if errorCount > 20 {
+			return
+		}
+		logger.Printf("%s:%s: %s(%+q)=%+q; want %+q: %s",
+			t.Name(), name, fstr[f], test, result, gold, t.name)
+	}
+}
+
+func cmpIsNormal(t *Test, name string, f norm.Form, test string, result, want bool) {
+	if result != want {
+		errorCount++
+		if errorCount > 20 {
+			return
+		}
+		logger.Printf("%s:%s: %s(%+q)=%v; want %v", t.Name(), name, fstr[f], test, result, want)
+	}
+}
+
+func doTest(t *Test, f norm.Form, gold, test string) {
+	testb := []byte(test)
+	result := f.Bytes(testb)
+	cmpResult(t, "Bytes", f, gold, test, string(result))
+
+	sresult := f.String(test)
+	cmpResult(t, "String", f, gold, test, sresult)
+
+	acc := []byte{}
+	i := norm.Iter{}
+	i.InitString(f, test)
+	for !i.Done() {
+		acc = append(acc, i.Next()...)
+	}
+	cmpResult(t, "Iter.Next", f, gold, test, string(acc))
+
+	buf := make([]byte, 128)
+	acc = nil
+	for p := 0; p < len(testb); {
+		nDst, nSrc, _ := f.Transform(buf, testb[p:], true)
+		acc = append(acc, buf[:nDst]...)
+		p += nSrc
+	}
+	cmpResult(t, "Transform", f, gold, test, string(acc))
+
+	for i := range test {
+		out := f.Append(f.Bytes([]byte(test[:i])), []byte(test[i:])...)
+		cmpResult(t, fmt.Sprintf(":Append:%d", i), f, gold, test, string(out))
+	}
+	cmpIsNormal(t, "IsNormal", f, test, f.IsNormal([]byte(test)), test == gold)
+	cmpIsNormal(t, "IsNormalString", f, test, f.IsNormalString(test), test == gold)
+}
+
+func doConformanceTests(t *Test, partn int) {
+	for i := 0; i <= 2; i++ {
+		doTest(t, norm.NFC, t.cols[1], t.cols[i])
+		doTest(t, norm.NFD, t.cols[2], t.cols[i])
+		doTest(t, norm.NFKC, t.cols[3], t.cols[i])
+		doTest(t, norm.NFKD, t.cols[4], t.cols[i])
+	}
+	for i := 3; i <= 4; i++ {
+		doTest(t, norm.NFC, t.cols[3], t.cols[i])
+		doTest(t, norm.NFD, t.cols[4], t.cols[i])
+		doTest(t, norm.NFKC, t.cols[3], t.cols[i])
+		doTest(t, norm.NFKD, t.cols[4], t.cols[i])
+	}
+}
+
+func CharacterByCharacterTests() {
+	tests := part[1].tests
+	var last rune = 0
+	for i := 0; i <= len(tests); i++ { // last one is special case
+		var r rune
+		if i == len(tests) {
+			r = 0x2FA1E // Don't have to go to 0x10FFFF
+		} else {
+			r = tests[i].r
+		}
+		for last++; last < r; last++ {
+			// Check all characters that were not explicitly listed in the test.
+			t := &Test{partnr: 1, number: -1}
+			char := string(last)
+			doTest(t, norm.NFC, char, char)
+			doTest(t, norm.NFD, char, char)
+			doTest(t, norm.NFKC, char, char)
+			doTest(t, norm.NFKD, char, char)
+		}
+		if i < len(tests) {
+			doConformanceTests(&tests[i], 1)
+		}
+	}
+}
+
+func StandardTests() {
+	for _, j := range []int{0, 2, 3} {
+		for _, test := range part[j].tests {
+			doConformanceTests(&test, j)
+		}
+	}
+}
+
+// PerformanceTest verifies that normalization is O(n). If any of the
+// code does not properly check for maxCombiningChars, normalization
+// may exhibit O(n**2) behavior.
+func PerformanceTest() {
+	runtime.GOMAXPROCS(2)
+	success := make(chan bool, 1)
+	go func() {
+		buf := bytes.Repeat([]byte("\u035D"), 1024*1024)
+		buf = append(buf, "\u035B"...)
+		norm.NFC.Append(nil, buf...)
+		success <- true
+	}()
+	timeout := time.After(1 * time.Second)
+	select {
+	case <-success:
+		// test completed before the timeout
+	case <-timeout:
+		errorCount++
+		logger.Printf(`unexpectedly long time to complete PerformanceTest`)
+	}
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/readwriter.go b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/readwriter.go
new file mode 100644
index 0000000000000000000000000000000000000000..4fa0e04b21f4a3f7400d94fb808ffeffd3cff957
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/readwriter.go
@@ -0,0 +1,126 @@
+// 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 norm
+
+import "io"
+
+type normWriter struct {
+	rb  reorderBuffer
+	w   io.Writer
+	buf []byte
+}
+
+// Write implements the standard write interface.  If the last characters are
+// not at a normalization boundary, the bytes will be buffered for the next
+// write. The remaining bytes will be written on close.
+func (w *normWriter) Write(data []byte) (n int, err error) {
+	// Process data in pieces to keep w.buf size bounded.
+	const chunk = 4000
+
+	for len(data) > 0 {
+		// Normalize into w.buf.
+		m := len(data)
+		if m > chunk {
+			m = chunk
+		}
+		w.rb.src = inputBytes(data[:m])
+		w.rb.nsrc = m
+		w.buf = doAppend(&w.rb, w.buf, 0)
+		data = data[m:]
+		n += m
+
+		// Write out complete prefix, save remainder.
+		// Note that lastBoundary looks back at most 31 runes.
+		i := lastBoundary(&w.rb.f, w.buf)
+		if i == -1 {
+			i = 0
+		}
+		if i > 0 {
+			if _, err = w.w.Write(w.buf[:i]); err != nil {
+				break
+			}
+			bn := copy(w.buf, w.buf[i:])
+			w.buf = w.buf[:bn]
+		}
+	}
+	return n, err
+}
+
+// Close forces data that remains in the buffer to be written.
+func (w *normWriter) Close() error {
+	if len(w.buf) > 0 {
+		_, err := w.w.Write(w.buf)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// Writer returns a new writer that implements Write(b)
+// by writing f(b) to w.  The returned writer may use an
+// an internal buffer to maintain state across Write calls.
+// Calling its Close method writes any buffered data to w.
+func (f Form) Writer(w io.Writer) io.WriteCloser {
+	wr := &normWriter{rb: reorderBuffer{}, w: w}
+	wr.rb.init(f, nil)
+	return wr
+}
+
+type normReader struct {
+	rb           reorderBuffer
+	r            io.Reader
+	inbuf        []byte
+	outbuf       []byte
+	bufStart     int
+	lastBoundary int
+	err          error
+}
+
+// Read implements the standard read interface.
+func (r *normReader) Read(p []byte) (int, error) {
+	for {
+		if r.lastBoundary-r.bufStart > 0 {
+			n := copy(p, r.outbuf[r.bufStart:r.lastBoundary])
+			r.bufStart += n
+			if r.lastBoundary-r.bufStart > 0 {
+				return n, nil
+			}
+			return n, r.err
+		}
+		if r.err != nil {
+			return 0, r.err
+		}
+		outn := copy(r.outbuf, r.outbuf[r.lastBoundary:])
+		r.outbuf = r.outbuf[0:outn]
+		r.bufStart = 0
+
+		n, err := r.r.Read(r.inbuf)
+		r.rb.src = inputBytes(r.inbuf[0:n])
+		r.rb.nsrc, r.err = n, err
+		if n > 0 {
+			r.outbuf = doAppend(&r.rb, r.outbuf, 0)
+		}
+		if err == io.EOF {
+			r.lastBoundary = len(r.outbuf)
+		} else {
+			r.lastBoundary = lastBoundary(&r.rb.f, r.outbuf)
+			if r.lastBoundary == -1 {
+				r.lastBoundary = 0
+			}
+		}
+	}
+	panic("should not reach here")
+}
+
+// Reader returns a new reader that implements Read
+// by reading data from r and returning f(data).
+func (f Form) Reader(r io.Reader) io.Reader {
+	const chunk = 4000
+	buf := make([]byte, chunk)
+	rr := &normReader{rb: reorderBuffer{}, r: r, inbuf: buf}
+	rr.rb.init(f, buf)
+	return rr
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/readwriter_test.go b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/readwriter_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..b7756ba24e272613cdbda009bee95f91e399e8c7
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/readwriter_test.go
@@ -0,0 +1,56 @@
+// 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 norm
+
+import (
+	"bytes"
+	"fmt"
+	"testing"
+)
+
+var bufSizes = []int{1, 2, 3, 4, 5, 6, 7, 8, 100, 101, 102, 103, 4000, 4001, 4002, 4003}
+
+func readFunc(size int) appendFunc {
+	return func(f Form, out []byte, s string) []byte {
+		out = append(out, s...)
+		r := f.Reader(bytes.NewBuffer(out))
+		buf := make([]byte, size)
+		result := []byte{}
+		for n, err := 0, error(nil); err == nil; {
+			n, err = r.Read(buf)
+			result = append(result, buf[:n]...)
+		}
+		return result
+	}
+}
+
+func TestReader(t *testing.T) {
+	for _, s := range bufSizes {
+		name := fmt.Sprintf("TestReader%d", s)
+		runNormTests(t, name, readFunc(s))
+	}
+}
+
+func writeFunc(size int) appendFunc {
+	return func(f Form, out []byte, s string) []byte {
+		in := append(out, s...)
+		result := new(bytes.Buffer)
+		w := f.Writer(result)
+		buf := make([]byte, size)
+		for n := 0; len(in) > 0; in = in[n:] {
+			n = copy(buf, in)
+			_, _ = w.Write(buf[:n])
+		}
+		w.Close()
+		return result.Bytes()
+	}
+}
+
+func TestWriter(t *testing.T) {
+	for _, s := range bufSizes {
+		name := fmt.Sprintf("TestWriter%d", s)
+		runNormTests(t, name, writeFunc(s))
+	}
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/tables.go b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/tables.go
new file mode 100644
index 0000000000000000000000000000000000000000..932c4ec528517475526eeadad1aa27c93e4bb09d
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/tables.go
@@ -0,0 +1,7549 @@
+// Generated by running
+//	maketables --tables=all --url=http://www.unicode.org/Public/7.0.0/ucd/
+// DO NOT EDIT
+
+package norm
+
+const (
+	// Version is the Unicode edition from which the tables are derived.
+	Version = "7.0.0"
+
+	// MaxTransformChunkSize indicates the maximum number of bytes that Transform
+	// may need to write atomically for any Form. Making a destination buffer at
+	// least this size ensures that Transform can always make progress and that
+	// the user does not need to grow the buffer on an ErrShortDst.
+	MaxTransformChunkSize = 35 + maxNonStarters*4
+)
+
+var ccc = [55]uint8{
+	0, 1, 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,
+	84, 91, 103, 107, 118, 122, 129, 130,
+	132, 202, 214, 216, 218, 220, 222, 224,
+	226, 228, 230, 232, 233, 234, 240,
+}
+
+const (
+	firstMulti            = 0x18E1
+	firstCCC              = 0x2EC5
+	endMulti              = 0x2F9B
+	firstLeadingCCC       = 0x49E9
+	firstCCCZeroExcept    = 0x49FF
+	firstStarterWithNLead = 0x4A26
+	lastDecomp            = 0x4A28
+	maxDecomp             = 0x8000
+)
+
+// decomps: 18984 bytes
+var decomps = [...]byte{
+	// Bytes 0 - 3f
+	0x00, 0x41, 0x20, 0x41, 0x21, 0x41, 0x22, 0x41,
+	0x23, 0x41, 0x24, 0x41, 0x25, 0x41, 0x26, 0x41,
+	0x27, 0x41, 0x28, 0x41, 0x29, 0x41, 0x2A, 0x41,
+	0x2B, 0x41, 0x2C, 0x41, 0x2D, 0x41, 0x2E, 0x41,
+	0x2F, 0x41, 0x30, 0x41, 0x31, 0x41, 0x32, 0x41,
+	0x33, 0x41, 0x34, 0x41, 0x35, 0x41, 0x36, 0x41,
+	0x37, 0x41, 0x38, 0x41, 0x39, 0x41, 0x3A, 0x41,
+	0x3B, 0x41, 0x3C, 0x41, 0x3D, 0x41, 0x3E, 0x41,
+	// Bytes 40 - 7f
+	0x3F, 0x41, 0x40, 0x41, 0x41, 0x41, 0x42, 0x41,
+	0x43, 0x41, 0x44, 0x41, 0x45, 0x41, 0x46, 0x41,
+	0x47, 0x41, 0x48, 0x41, 0x49, 0x41, 0x4A, 0x41,
+	0x4B, 0x41, 0x4C, 0x41, 0x4D, 0x41, 0x4E, 0x41,
+	0x4F, 0x41, 0x50, 0x41, 0x51, 0x41, 0x52, 0x41,
+	0x53, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41,
+	0x57, 0x41, 0x58, 0x41, 0x59, 0x41, 0x5A, 0x41,
+	0x5B, 0x41, 0x5C, 0x41, 0x5D, 0x41, 0x5E, 0x41,
+	// Bytes 80 - bf
+	0x5F, 0x41, 0x60, 0x41, 0x61, 0x41, 0x62, 0x41,
+	0x63, 0x41, 0x64, 0x41, 0x65, 0x41, 0x66, 0x41,
+	0x67, 0x41, 0x68, 0x41, 0x69, 0x41, 0x6A, 0x41,
+	0x6B, 0x41, 0x6C, 0x41, 0x6D, 0x41, 0x6E, 0x41,
+	0x6F, 0x41, 0x70, 0x41, 0x71, 0x41, 0x72, 0x41,
+	0x73, 0x41, 0x74, 0x41, 0x75, 0x41, 0x76, 0x41,
+	0x77, 0x41, 0x78, 0x41, 0x79, 0x41, 0x7A, 0x41,
+	0x7B, 0x41, 0x7C, 0x41, 0x7D, 0x41, 0x7E, 0x42,
+	// Bytes c0 - ff
+	0xC2, 0xA2, 0x42, 0xC2, 0xA3, 0x42, 0xC2, 0xA5,
+	0x42, 0xC2, 0xA6, 0x42, 0xC2, 0xAC, 0x42, 0xC2,
+	0xB7, 0x42, 0xC3, 0x86, 0x42, 0xC3, 0xB0, 0x42,
+	0xC4, 0xA6, 0x42, 0xC4, 0xA7, 0x42, 0xC4, 0xB1,
+	0x42, 0xC5, 0x8B, 0x42, 0xC5, 0x93, 0x42, 0xC6,
+	0x8E, 0x42, 0xC6, 0x90, 0x42, 0xC6, 0xAB, 0x42,
+	0xC8, 0xA2, 0x42, 0xC8, 0xB7, 0x42, 0xC9, 0x90,
+	0x42, 0xC9, 0x91, 0x42, 0xC9, 0x92, 0x42, 0xC9,
+	// Bytes 100 - 13f
+	0x94, 0x42, 0xC9, 0x95, 0x42, 0xC9, 0x99, 0x42,
+	0xC9, 0x9B, 0x42, 0xC9, 0x9C, 0x42, 0xC9, 0x9F,
+	0x42, 0xC9, 0xA1, 0x42, 0xC9, 0xA3, 0x42, 0xC9,
+	0xA5, 0x42, 0xC9, 0xA6, 0x42, 0xC9, 0xA8, 0x42,
+	0xC9, 0xA9, 0x42, 0xC9, 0xAA, 0x42, 0xC9, 0xAB,
+	0x42, 0xC9, 0xAD, 0x42, 0xC9, 0xAF, 0x42, 0xC9,
+	0xB0, 0x42, 0xC9, 0xB1, 0x42, 0xC9, 0xB2, 0x42,
+	0xC9, 0xB3, 0x42, 0xC9, 0xB4, 0x42, 0xC9, 0xB5,
+	// Bytes 140 - 17f
+	0x42, 0xC9, 0xB8, 0x42, 0xC9, 0xB9, 0x42, 0xC9,
+	0xBB, 0x42, 0xCA, 0x81, 0x42, 0xCA, 0x82, 0x42,
+	0xCA, 0x83, 0x42, 0xCA, 0x89, 0x42, 0xCA, 0x8A,
+	0x42, 0xCA, 0x8B, 0x42, 0xCA, 0x8C, 0x42, 0xCA,
+	0x90, 0x42, 0xCA, 0x91, 0x42, 0xCA, 0x92, 0x42,
+	0xCA, 0x95, 0x42, 0xCA, 0x9D, 0x42, 0xCA, 0x9F,
+	0x42, 0xCA, 0xB9, 0x42, 0xCE, 0x91, 0x42, 0xCE,
+	0x92, 0x42, 0xCE, 0x93, 0x42, 0xCE, 0x94, 0x42,
+	// Bytes 180 - 1bf
+	0xCE, 0x95, 0x42, 0xCE, 0x96, 0x42, 0xCE, 0x97,
+	0x42, 0xCE, 0x98, 0x42, 0xCE, 0x99, 0x42, 0xCE,
+	0x9A, 0x42, 0xCE, 0x9B, 0x42, 0xCE, 0x9C, 0x42,
+	0xCE, 0x9D, 0x42, 0xCE, 0x9E, 0x42, 0xCE, 0x9F,
+	0x42, 0xCE, 0xA0, 0x42, 0xCE, 0xA1, 0x42, 0xCE,
+	0xA3, 0x42, 0xCE, 0xA4, 0x42, 0xCE, 0xA5, 0x42,
+	0xCE, 0xA6, 0x42, 0xCE, 0xA7, 0x42, 0xCE, 0xA8,
+	0x42, 0xCE, 0xA9, 0x42, 0xCE, 0xB1, 0x42, 0xCE,
+	// Bytes 1c0 - 1ff
+	0xB2, 0x42, 0xCE, 0xB3, 0x42, 0xCE, 0xB4, 0x42,
+	0xCE, 0xB5, 0x42, 0xCE, 0xB6, 0x42, 0xCE, 0xB7,
+	0x42, 0xCE, 0xB8, 0x42, 0xCE, 0xB9, 0x42, 0xCE,
+	0xBA, 0x42, 0xCE, 0xBB, 0x42, 0xCE, 0xBC, 0x42,
+	0xCE, 0xBD, 0x42, 0xCE, 0xBE, 0x42, 0xCE, 0xBF,
+	0x42, 0xCF, 0x80, 0x42, 0xCF, 0x81, 0x42, 0xCF,
+	0x82, 0x42, 0xCF, 0x83, 0x42, 0xCF, 0x84, 0x42,
+	0xCF, 0x85, 0x42, 0xCF, 0x86, 0x42, 0xCF, 0x87,
+	// Bytes 200 - 23f
+	0x42, 0xCF, 0x88, 0x42, 0xCF, 0x89, 0x42, 0xCF,
+	0x9C, 0x42, 0xCF, 0x9D, 0x42, 0xD0, 0xBD, 0x42,
+	0xD1, 0x8A, 0x42, 0xD1, 0x8C, 0x42, 0xD7, 0x90,
+	0x42, 0xD7, 0x91, 0x42, 0xD7, 0x92, 0x42, 0xD7,
+	0x93, 0x42, 0xD7, 0x94, 0x42, 0xD7, 0x9B, 0x42,
+	0xD7, 0x9C, 0x42, 0xD7, 0x9D, 0x42, 0xD7, 0xA2,
+	0x42, 0xD7, 0xA8, 0x42, 0xD7, 0xAA, 0x42, 0xD8,
+	0xA1, 0x42, 0xD8, 0xA7, 0x42, 0xD8, 0xA8, 0x42,
+	// Bytes 240 - 27f
+	0xD8, 0xA9, 0x42, 0xD8, 0xAA, 0x42, 0xD8, 0xAB,
+	0x42, 0xD8, 0xAC, 0x42, 0xD8, 0xAD, 0x42, 0xD8,
+	0xAE, 0x42, 0xD8, 0xAF, 0x42, 0xD8, 0xB0, 0x42,
+	0xD8, 0xB1, 0x42, 0xD8, 0xB2, 0x42, 0xD8, 0xB3,
+	0x42, 0xD8, 0xB4, 0x42, 0xD8, 0xB5, 0x42, 0xD8,
+	0xB6, 0x42, 0xD8, 0xB7, 0x42, 0xD8, 0xB8, 0x42,
+	0xD8, 0xB9, 0x42, 0xD8, 0xBA, 0x42, 0xD9, 0x81,
+	0x42, 0xD9, 0x82, 0x42, 0xD9, 0x83, 0x42, 0xD9,
+	// Bytes 280 - 2bf
+	0x84, 0x42, 0xD9, 0x85, 0x42, 0xD9, 0x86, 0x42,
+	0xD9, 0x87, 0x42, 0xD9, 0x88, 0x42, 0xD9, 0x89,
+	0x42, 0xD9, 0x8A, 0x42, 0xD9, 0xAE, 0x42, 0xD9,
+	0xAF, 0x42, 0xD9, 0xB1, 0x42, 0xD9, 0xB9, 0x42,
+	0xD9, 0xBA, 0x42, 0xD9, 0xBB, 0x42, 0xD9, 0xBE,
+	0x42, 0xD9, 0xBF, 0x42, 0xDA, 0x80, 0x42, 0xDA,
+	0x83, 0x42, 0xDA, 0x84, 0x42, 0xDA, 0x86, 0x42,
+	0xDA, 0x87, 0x42, 0xDA, 0x88, 0x42, 0xDA, 0x8C,
+	// Bytes 2c0 - 2ff
+	0x42, 0xDA, 0x8D, 0x42, 0xDA, 0x8E, 0x42, 0xDA,
+	0x91, 0x42, 0xDA, 0x98, 0x42, 0xDA, 0xA1, 0x42,
+	0xDA, 0xA4, 0x42, 0xDA, 0xA6, 0x42, 0xDA, 0xA9,
+	0x42, 0xDA, 0xAD, 0x42, 0xDA, 0xAF, 0x42, 0xDA,
+	0xB1, 0x42, 0xDA, 0xB3, 0x42, 0xDA, 0xBA, 0x42,
+	0xDA, 0xBB, 0x42, 0xDA, 0xBE, 0x42, 0xDB, 0x81,
+	0x42, 0xDB, 0x85, 0x42, 0xDB, 0x86, 0x42, 0xDB,
+	0x87, 0x42, 0xDB, 0x88, 0x42, 0xDB, 0x89, 0x42,
+	// Bytes 300 - 33f
+	0xDB, 0x8B, 0x42, 0xDB, 0x8C, 0x42, 0xDB, 0x90,
+	0x42, 0xDB, 0x92, 0x43, 0xE0, 0xBC, 0x8B, 0x43,
+	0xE1, 0x83, 0x9C, 0x43, 0xE1, 0x84, 0x80, 0x43,
+	0xE1, 0x84, 0x81, 0x43, 0xE1, 0x84, 0x82, 0x43,
+	0xE1, 0x84, 0x83, 0x43, 0xE1, 0x84, 0x84, 0x43,
+	0xE1, 0x84, 0x85, 0x43, 0xE1, 0x84, 0x86, 0x43,
+	0xE1, 0x84, 0x87, 0x43, 0xE1, 0x84, 0x88, 0x43,
+	0xE1, 0x84, 0x89, 0x43, 0xE1, 0x84, 0x8A, 0x43,
+	// Bytes 340 - 37f
+	0xE1, 0x84, 0x8B, 0x43, 0xE1, 0x84, 0x8C, 0x43,
+	0xE1, 0x84, 0x8D, 0x43, 0xE1, 0x84, 0x8E, 0x43,
+	0xE1, 0x84, 0x8F, 0x43, 0xE1, 0x84, 0x90, 0x43,
+	0xE1, 0x84, 0x91, 0x43, 0xE1, 0x84, 0x92, 0x43,
+	0xE1, 0x84, 0x94, 0x43, 0xE1, 0x84, 0x95, 0x43,
+	0xE1, 0x84, 0x9A, 0x43, 0xE1, 0x84, 0x9C, 0x43,
+	0xE1, 0x84, 0x9D, 0x43, 0xE1, 0x84, 0x9E, 0x43,
+	0xE1, 0x84, 0xA0, 0x43, 0xE1, 0x84, 0xA1, 0x43,
+	// Bytes 380 - 3bf
+	0xE1, 0x84, 0xA2, 0x43, 0xE1, 0x84, 0xA3, 0x43,
+	0xE1, 0x84, 0xA7, 0x43, 0xE1, 0x84, 0xA9, 0x43,
+	0xE1, 0x84, 0xAB, 0x43, 0xE1, 0x84, 0xAC, 0x43,
+	0xE1, 0x84, 0xAD, 0x43, 0xE1, 0x84, 0xAE, 0x43,
+	0xE1, 0x84, 0xAF, 0x43, 0xE1, 0x84, 0xB2, 0x43,
+	0xE1, 0x84, 0xB6, 0x43, 0xE1, 0x85, 0x80, 0x43,
+	0xE1, 0x85, 0x87, 0x43, 0xE1, 0x85, 0x8C, 0x43,
+	0xE1, 0x85, 0x97, 0x43, 0xE1, 0x85, 0x98, 0x43,
+	// Bytes 3c0 - 3ff
+	0xE1, 0x85, 0x99, 0x43, 0xE1, 0x85, 0xA0, 0x43,
+	0xE1, 0x85, 0xA1, 0x43, 0xE1, 0x85, 0xA2, 0x43,
+	0xE1, 0x85, 0xA3, 0x43, 0xE1, 0x85, 0xA4, 0x43,
+	0xE1, 0x85, 0xA5, 0x43, 0xE1, 0x85, 0xA6, 0x43,
+	0xE1, 0x85, 0xA7, 0x43, 0xE1, 0x85, 0xA8, 0x43,
+	0xE1, 0x85, 0xA9, 0x43, 0xE1, 0x85, 0xAA, 0x43,
+	0xE1, 0x85, 0xAB, 0x43, 0xE1, 0x85, 0xAC, 0x43,
+	0xE1, 0x85, 0xAD, 0x43, 0xE1, 0x85, 0xAE, 0x43,
+	// Bytes 400 - 43f
+	0xE1, 0x85, 0xAF, 0x43, 0xE1, 0x85, 0xB0, 0x43,
+	0xE1, 0x85, 0xB1, 0x43, 0xE1, 0x85, 0xB2, 0x43,
+	0xE1, 0x85, 0xB3, 0x43, 0xE1, 0x85, 0xB4, 0x43,
+	0xE1, 0x85, 0xB5, 0x43, 0xE1, 0x86, 0x84, 0x43,
+	0xE1, 0x86, 0x85, 0x43, 0xE1, 0x86, 0x88, 0x43,
+	0xE1, 0x86, 0x91, 0x43, 0xE1, 0x86, 0x92, 0x43,
+	0xE1, 0x86, 0x94, 0x43, 0xE1, 0x86, 0x9E, 0x43,
+	0xE1, 0x86, 0xA1, 0x43, 0xE1, 0x86, 0xAA, 0x43,
+	// Bytes 440 - 47f
+	0xE1, 0x86, 0xAC, 0x43, 0xE1, 0x86, 0xAD, 0x43,
+	0xE1, 0x86, 0xB0, 0x43, 0xE1, 0x86, 0xB1, 0x43,
+	0xE1, 0x86, 0xB2, 0x43, 0xE1, 0x86, 0xB3, 0x43,
+	0xE1, 0x86, 0xB4, 0x43, 0xE1, 0x86, 0xB5, 0x43,
+	0xE1, 0x87, 0x87, 0x43, 0xE1, 0x87, 0x88, 0x43,
+	0xE1, 0x87, 0x8C, 0x43, 0xE1, 0x87, 0x8E, 0x43,
+	0xE1, 0x87, 0x93, 0x43, 0xE1, 0x87, 0x97, 0x43,
+	0xE1, 0x87, 0x99, 0x43, 0xE1, 0x87, 0x9D, 0x43,
+	// Bytes 480 - 4bf
+	0xE1, 0x87, 0x9F, 0x43, 0xE1, 0x87, 0xB1, 0x43,
+	0xE1, 0x87, 0xB2, 0x43, 0xE1, 0xB4, 0x82, 0x43,
+	0xE1, 0xB4, 0x96, 0x43, 0xE1, 0xB4, 0x97, 0x43,
+	0xE1, 0xB4, 0x9C, 0x43, 0xE1, 0xB4, 0x9D, 0x43,
+	0xE1, 0xB4, 0xA5, 0x43, 0xE1, 0xB5, 0xBB, 0x43,
+	0xE1, 0xB6, 0x85, 0x43, 0xE2, 0x80, 0x82, 0x43,
+	0xE2, 0x80, 0x83, 0x43, 0xE2, 0x80, 0x90, 0x43,
+	0xE2, 0x80, 0x93, 0x43, 0xE2, 0x80, 0x94, 0x43,
+	// Bytes 4c0 - 4ff
+	0xE2, 0x82, 0xA9, 0x43, 0xE2, 0x86, 0x90, 0x43,
+	0xE2, 0x86, 0x91, 0x43, 0xE2, 0x86, 0x92, 0x43,
+	0xE2, 0x86, 0x93, 0x43, 0xE2, 0x88, 0x82, 0x43,
+	0xE2, 0x88, 0x87, 0x43, 0xE2, 0x88, 0x91, 0x43,
+	0xE2, 0x88, 0x92, 0x43, 0xE2, 0x94, 0x82, 0x43,
+	0xE2, 0x96, 0xA0, 0x43, 0xE2, 0x97, 0x8B, 0x43,
+	0xE2, 0xA6, 0x85, 0x43, 0xE2, 0xA6, 0x86, 0x43,
+	0xE2, 0xB5, 0xA1, 0x43, 0xE3, 0x80, 0x81, 0x43,
+	// Bytes 500 - 53f
+	0xE3, 0x80, 0x82, 0x43, 0xE3, 0x80, 0x88, 0x43,
+	0xE3, 0x80, 0x89, 0x43, 0xE3, 0x80, 0x8A, 0x43,
+	0xE3, 0x80, 0x8B, 0x43, 0xE3, 0x80, 0x8C, 0x43,
+	0xE3, 0x80, 0x8D, 0x43, 0xE3, 0x80, 0x8E, 0x43,
+	0xE3, 0x80, 0x8F, 0x43, 0xE3, 0x80, 0x90, 0x43,
+	0xE3, 0x80, 0x91, 0x43, 0xE3, 0x80, 0x92, 0x43,
+	0xE3, 0x80, 0x94, 0x43, 0xE3, 0x80, 0x95, 0x43,
+	0xE3, 0x80, 0x96, 0x43, 0xE3, 0x80, 0x97, 0x43,
+	// Bytes 540 - 57f
+	0xE3, 0x82, 0xA1, 0x43, 0xE3, 0x82, 0xA2, 0x43,
+	0xE3, 0x82, 0xA3, 0x43, 0xE3, 0x82, 0xA4, 0x43,
+	0xE3, 0x82, 0xA5, 0x43, 0xE3, 0x82, 0xA6, 0x43,
+	0xE3, 0x82, 0xA7, 0x43, 0xE3, 0x82, 0xA8, 0x43,
+	0xE3, 0x82, 0xA9, 0x43, 0xE3, 0x82, 0xAA, 0x43,
+	0xE3, 0x82, 0xAB, 0x43, 0xE3, 0x82, 0xAD, 0x43,
+	0xE3, 0x82, 0xAF, 0x43, 0xE3, 0x82, 0xB1, 0x43,
+	0xE3, 0x82, 0xB3, 0x43, 0xE3, 0x82, 0xB5, 0x43,
+	// Bytes 580 - 5bf
+	0xE3, 0x82, 0xB7, 0x43, 0xE3, 0x82, 0xB9, 0x43,
+	0xE3, 0x82, 0xBB, 0x43, 0xE3, 0x82, 0xBD, 0x43,
+	0xE3, 0x82, 0xBF, 0x43, 0xE3, 0x83, 0x81, 0x43,
+	0xE3, 0x83, 0x83, 0x43, 0xE3, 0x83, 0x84, 0x43,
+	0xE3, 0x83, 0x86, 0x43, 0xE3, 0x83, 0x88, 0x43,
+	0xE3, 0x83, 0x8A, 0x43, 0xE3, 0x83, 0x8B, 0x43,
+	0xE3, 0x83, 0x8C, 0x43, 0xE3, 0x83, 0x8D, 0x43,
+	0xE3, 0x83, 0x8E, 0x43, 0xE3, 0x83, 0x8F, 0x43,
+	// Bytes 5c0 - 5ff
+	0xE3, 0x83, 0x92, 0x43, 0xE3, 0x83, 0x95, 0x43,
+	0xE3, 0x83, 0x98, 0x43, 0xE3, 0x83, 0x9B, 0x43,
+	0xE3, 0x83, 0x9E, 0x43, 0xE3, 0x83, 0x9F, 0x43,
+	0xE3, 0x83, 0xA0, 0x43, 0xE3, 0x83, 0xA1, 0x43,
+	0xE3, 0x83, 0xA2, 0x43, 0xE3, 0x83, 0xA3, 0x43,
+	0xE3, 0x83, 0xA4, 0x43, 0xE3, 0x83, 0xA5, 0x43,
+	0xE3, 0x83, 0xA6, 0x43, 0xE3, 0x83, 0xA7, 0x43,
+	0xE3, 0x83, 0xA8, 0x43, 0xE3, 0x83, 0xA9, 0x43,
+	// Bytes 600 - 63f
+	0xE3, 0x83, 0xAA, 0x43, 0xE3, 0x83, 0xAB, 0x43,
+	0xE3, 0x83, 0xAC, 0x43, 0xE3, 0x83, 0xAD, 0x43,
+	0xE3, 0x83, 0xAF, 0x43, 0xE3, 0x83, 0xB0, 0x43,
+	0xE3, 0x83, 0xB1, 0x43, 0xE3, 0x83, 0xB2, 0x43,
+	0xE3, 0x83, 0xB3, 0x43, 0xE3, 0x83, 0xBB, 0x43,
+	0xE3, 0x83, 0xBC, 0x43, 0xE3, 0x92, 0x9E, 0x43,
+	0xE3, 0x92, 0xB9, 0x43, 0xE3, 0x92, 0xBB, 0x43,
+	0xE3, 0x93, 0x9F, 0x43, 0xE3, 0x94, 0x95, 0x43,
+	// Bytes 640 - 67f
+	0xE3, 0x9B, 0xAE, 0x43, 0xE3, 0x9B, 0xBC, 0x43,
+	0xE3, 0x9E, 0x81, 0x43, 0xE3, 0xA0, 0xAF, 0x43,
+	0xE3, 0xA1, 0xA2, 0x43, 0xE3, 0xA1, 0xBC, 0x43,
+	0xE3, 0xA3, 0x87, 0x43, 0xE3, 0xA3, 0xA3, 0x43,
+	0xE3, 0xA4, 0x9C, 0x43, 0xE3, 0xA4, 0xBA, 0x43,
+	0xE3, 0xA8, 0xAE, 0x43, 0xE3, 0xA9, 0xAC, 0x43,
+	0xE3, 0xAB, 0xA4, 0x43, 0xE3, 0xAC, 0x88, 0x43,
+	0xE3, 0xAC, 0x99, 0x43, 0xE3, 0xAD, 0x89, 0x43,
+	// Bytes 680 - 6bf
+	0xE3, 0xAE, 0x9D, 0x43, 0xE3, 0xB0, 0x98, 0x43,
+	0xE3, 0xB1, 0x8E, 0x43, 0xE3, 0xB4, 0xB3, 0x43,
+	0xE3, 0xB6, 0x96, 0x43, 0xE3, 0xBA, 0xAC, 0x43,
+	0xE3, 0xBA, 0xB8, 0x43, 0xE3, 0xBC, 0x9B, 0x43,
+	0xE3, 0xBF, 0xBC, 0x43, 0xE4, 0x80, 0x88, 0x43,
+	0xE4, 0x80, 0x98, 0x43, 0xE4, 0x80, 0xB9, 0x43,
+	0xE4, 0x81, 0x86, 0x43, 0xE4, 0x82, 0x96, 0x43,
+	0xE4, 0x83, 0xA3, 0x43, 0xE4, 0x84, 0xAF, 0x43,
+	// Bytes 6c0 - 6ff
+	0xE4, 0x88, 0x82, 0x43, 0xE4, 0x88, 0xA7, 0x43,
+	0xE4, 0x8A, 0xA0, 0x43, 0xE4, 0x8C, 0x81, 0x43,
+	0xE4, 0x8C, 0xB4, 0x43, 0xE4, 0x8D, 0x99, 0x43,
+	0xE4, 0x8F, 0x95, 0x43, 0xE4, 0x8F, 0x99, 0x43,
+	0xE4, 0x90, 0x8B, 0x43, 0xE4, 0x91, 0xAB, 0x43,
+	0xE4, 0x94, 0xAB, 0x43, 0xE4, 0x95, 0x9D, 0x43,
+	0xE4, 0x95, 0xA1, 0x43, 0xE4, 0x95, 0xAB, 0x43,
+	0xE4, 0x97, 0x97, 0x43, 0xE4, 0x97, 0xB9, 0x43,
+	// Bytes 700 - 73f
+	0xE4, 0x98, 0xB5, 0x43, 0xE4, 0x9A, 0xBE, 0x43,
+	0xE4, 0x9B, 0x87, 0x43, 0xE4, 0xA6, 0x95, 0x43,
+	0xE4, 0xA7, 0xA6, 0x43, 0xE4, 0xA9, 0xAE, 0x43,
+	0xE4, 0xA9, 0xB6, 0x43, 0xE4, 0xAA, 0xB2, 0x43,
+	0xE4, 0xAC, 0xB3, 0x43, 0xE4, 0xAF, 0x8E, 0x43,
+	0xE4, 0xB3, 0x8E, 0x43, 0xE4, 0xB3, 0xAD, 0x43,
+	0xE4, 0xB3, 0xB8, 0x43, 0xE4, 0xB5, 0x96, 0x43,
+	0xE4, 0xB8, 0x80, 0x43, 0xE4, 0xB8, 0x81, 0x43,
+	// Bytes 740 - 77f
+	0xE4, 0xB8, 0x83, 0x43, 0xE4, 0xB8, 0x89, 0x43,
+	0xE4, 0xB8, 0x8A, 0x43, 0xE4, 0xB8, 0x8B, 0x43,
+	0xE4, 0xB8, 0x8D, 0x43, 0xE4, 0xB8, 0x99, 0x43,
+	0xE4, 0xB8, 0xA6, 0x43, 0xE4, 0xB8, 0xA8, 0x43,
+	0xE4, 0xB8, 0xAD, 0x43, 0xE4, 0xB8, 0xB2, 0x43,
+	0xE4, 0xB8, 0xB6, 0x43, 0xE4, 0xB8, 0xB8, 0x43,
+	0xE4, 0xB8, 0xB9, 0x43, 0xE4, 0xB8, 0xBD, 0x43,
+	0xE4, 0xB8, 0xBF, 0x43, 0xE4, 0xB9, 0x81, 0x43,
+	// Bytes 780 - 7bf
+	0xE4, 0xB9, 0x99, 0x43, 0xE4, 0xB9, 0x9D, 0x43,
+	0xE4, 0xBA, 0x82, 0x43, 0xE4, 0xBA, 0x85, 0x43,
+	0xE4, 0xBA, 0x86, 0x43, 0xE4, 0xBA, 0x8C, 0x43,
+	0xE4, 0xBA, 0x94, 0x43, 0xE4, 0xBA, 0xA0, 0x43,
+	0xE4, 0xBA, 0xA4, 0x43, 0xE4, 0xBA, 0xAE, 0x43,
+	0xE4, 0xBA, 0xBA, 0x43, 0xE4, 0xBB, 0x80, 0x43,
+	0xE4, 0xBB, 0x8C, 0x43, 0xE4, 0xBB, 0xA4, 0x43,
+	0xE4, 0xBC, 0x81, 0x43, 0xE4, 0xBC, 0x91, 0x43,
+	// Bytes 7c0 - 7ff
+	0xE4, 0xBD, 0xA0, 0x43, 0xE4, 0xBE, 0x80, 0x43,
+	0xE4, 0xBE, 0x86, 0x43, 0xE4, 0xBE, 0x8B, 0x43,
+	0xE4, 0xBE, 0xAE, 0x43, 0xE4, 0xBE, 0xBB, 0x43,
+	0xE4, 0xBE, 0xBF, 0x43, 0xE5, 0x80, 0x82, 0x43,
+	0xE5, 0x80, 0xAB, 0x43, 0xE5, 0x81, 0xBA, 0x43,
+	0xE5, 0x82, 0x99, 0x43, 0xE5, 0x83, 0x8F, 0x43,
+	0xE5, 0x83, 0x9A, 0x43, 0xE5, 0x83, 0xA7, 0x43,
+	0xE5, 0x84, 0xAA, 0x43, 0xE5, 0x84, 0xBF, 0x43,
+	// Bytes 800 - 83f
+	0xE5, 0x85, 0x80, 0x43, 0xE5, 0x85, 0x85, 0x43,
+	0xE5, 0x85, 0x8D, 0x43, 0xE5, 0x85, 0x94, 0x43,
+	0xE5, 0x85, 0xA4, 0x43, 0xE5, 0x85, 0xA5, 0x43,
+	0xE5, 0x85, 0xA7, 0x43, 0xE5, 0x85, 0xA8, 0x43,
+	0xE5, 0x85, 0xA9, 0x43, 0xE5, 0x85, 0xAB, 0x43,
+	0xE5, 0x85, 0xAD, 0x43, 0xE5, 0x85, 0xB7, 0x43,
+	0xE5, 0x86, 0x80, 0x43, 0xE5, 0x86, 0x82, 0x43,
+	0xE5, 0x86, 0x8D, 0x43, 0xE5, 0x86, 0x92, 0x43,
+	// Bytes 840 - 87f
+	0xE5, 0x86, 0x95, 0x43, 0xE5, 0x86, 0x96, 0x43,
+	0xE5, 0x86, 0x97, 0x43, 0xE5, 0x86, 0x99, 0x43,
+	0xE5, 0x86, 0xA4, 0x43, 0xE5, 0x86, 0xAB, 0x43,
+	0xE5, 0x86, 0xAC, 0x43, 0xE5, 0x86, 0xB5, 0x43,
+	0xE5, 0x86, 0xB7, 0x43, 0xE5, 0x87, 0x89, 0x43,
+	0xE5, 0x87, 0x8C, 0x43, 0xE5, 0x87, 0x9C, 0x43,
+	0xE5, 0x87, 0x9E, 0x43, 0xE5, 0x87, 0xA0, 0x43,
+	0xE5, 0x87, 0xB5, 0x43, 0xE5, 0x88, 0x80, 0x43,
+	// Bytes 880 - 8bf
+	0xE5, 0x88, 0x83, 0x43, 0xE5, 0x88, 0x87, 0x43,
+	0xE5, 0x88, 0x97, 0x43, 0xE5, 0x88, 0x9D, 0x43,
+	0xE5, 0x88, 0xA9, 0x43, 0xE5, 0x88, 0xBA, 0x43,
+	0xE5, 0x88, 0xBB, 0x43, 0xE5, 0x89, 0x86, 0x43,
+	0xE5, 0x89, 0x8D, 0x43, 0xE5, 0x89, 0xB2, 0x43,
+	0xE5, 0x89, 0xB7, 0x43, 0xE5, 0x8A, 0x89, 0x43,
+	0xE5, 0x8A, 0x9B, 0x43, 0xE5, 0x8A, 0xA3, 0x43,
+	0xE5, 0x8A, 0xB3, 0x43, 0xE5, 0x8A, 0xB4, 0x43,
+	// Bytes 8c0 - 8ff
+	0xE5, 0x8B, 0x87, 0x43, 0xE5, 0x8B, 0x89, 0x43,
+	0xE5, 0x8B, 0x92, 0x43, 0xE5, 0x8B, 0x9E, 0x43,
+	0xE5, 0x8B, 0xA4, 0x43, 0xE5, 0x8B, 0xB5, 0x43,
+	0xE5, 0x8B, 0xB9, 0x43, 0xE5, 0x8B, 0xBA, 0x43,
+	0xE5, 0x8C, 0x85, 0x43, 0xE5, 0x8C, 0x86, 0x43,
+	0xE5, 0x8C, 0x95, 0x43, 0xE5, 0x8C, 0x97, 0x43,
+	0xE5, 0x8C, 0x9A, 0x43, 0xE5, 0x8C, 0xB8, 0x43,
+	0xE5, 0x8C, 0xBB, 0x43, 0xE5, 0x8C, 0xBF, 0x43,
+	// Bytes 900 - 93f
+	0xE5, 0x8D, 0x81, 0x43, 0xE5, 0x8D, 0x84, 0x43,
+	0xE5, 0x8D, 0x85, 0x43, 0xE5, 0x8D, 0x89, 0x43,
+	0xE5, 0x8D, 0x91, 0x43, 0xE5, 0x8D, 0x94, 0x43,
+	0xE5, 0x8D, 0x9A, 0x43, 0xE5, 0x8D, 0x9C, 0x43,
+	0xE5, 0x8D, 0xA9, 0x43, 0xE5, 0x8D, 0xB0, 0x43,
+	0xE5, 0x8D, 0xB3, 0x43, 0xE5, 0x8D, 0xB5, 0x43,
+	0xE5, 0x8D, 0xBD, 0x43, 0xE5, 0x8D, 0xBF, 0x43,
+	0xE5, 0x8E, 0x82, 0x43, 0xE5, 0x8E, 0xB6, 0x43,
+	// Bytes 940 - 97f
+	0xE5, 0x8F, 0x83, 0x43, 0xE5, 0x8F, 0x88, 0x43,
+	0xE5, 0x8F, 0x8A, 0x43, 0xE5, 0x8F, 0x8C, 0x43,
+	0xE5, 0x8F, 0x9F, 0x43, 0xE5, 0x8F, 0xA3, 0x43,
+	0xE5, 0x8F, 0xA5, 0x43, 0xE5, 0x8F, 0xAB, 0x43,
+	0xE5, 0x8F, 0xAF, 0x43, 0xE5, 0x8F, 0xB1, 0x43,
+	0xE5, 0x8F, 0xB3, 0x43, 0xE5, 0x90, 0x86, 0x43,
+	0xE5, 0x90, 0x88, 0x43, 0xE5, 0x90, 0x8D, 0x43,
+	0xE5, 0x90, 0x8F, 0x43, 0xE5, 0x90, 0x9D, 0x43,
+	// Bytes 980 - 9bf
+	0xE5, 0x90, 0xB8, 0x43, 0xE5, 0x90, 0xB9, 0x43,
+	0xE5, 0x91, 0x82, 0x43, 0xE5, 0x91, 0x88, 0x43,
+	0xE5, 0x91, 0xA8, 0x43, 0xE5, 0x92, 0x9E, 0x43,
+	0xE5, 0x92, 0xA2, 0x43, 0xE5, 0x92, 0xBD, 0x43,
+	0xE5, 0x93, 0xB6, 0x43, 0xE5, 0x94, 0x90, 0x43,
+	0xE5, 0x95, 0x8F, 0x43, 0xE5, 0x95, 0x93, 0x43,
+	0xE5, 0x95, 0x95, 0x43, 0xE5, 0x95, 0xA3, 0x43,
+	0xE5, 0x96, 0x84, 0x43, 0xE5, 0x96, 0x87, 0x43,
+	// Bytes 9c0 - 9ff
+	0xE5, 0x96, 0x99, 0x43, 0xE5, 0x96, 0x9D, 0x43,
+	0xE5, 0x96, 0xAB, 0x43, 0xE5, 0x96, 0xB3, 0x43,
+	0xE5, 0x96, 0xB6, 0x43, 0xE5, 0x97, 0x80, 0x43,
+	0xE5, 0x97, 0x82, 0x43, 0xE5, 0x97, 0xA2, 0x43,
+	0xE5, 0x98, 0x86, 0x43, 0xE5, 0x99, 0x91, 0x43,
+	0xE5, 0x99, 0xA8, 0x43, 0xE5, 0x99, 0xB4, 0x43,
+	0xE5, 0x9B, 0x97, 0x43, 0xE5, 0x9B, 0x9B, 0x43,
+	0xE5, 0x9B, 0xB9, 0x43, 0xE5, 0x9C, 0x96, 0x43,
+	// Bytes a00 - a3f
+	0xE5, 0x9C, 0x97, 0x43, 0xE5, 0x9C, 0x9F, 0x43,
+	0xE5, 0x9C, 0xB0, 0x43, 0xE5, 0x9E, 0x8B, 0x43,
+	0xE5, 0x9F, 0x8E, 0x43, 0xE5, 0x9F, 0xB4, 0x43,
+	0xE5, 0xA0, 0x8D, 0x43, 0xE5, 0xA0, 0xB1, 0x43,
+	0xE5, 0xA0, 0xB2, 0x43, 0xE5, 0xA1, 0x80, 0x43,
+	0xE5, 0xA1, 0x9A, 0x43, 0xE5, 0xA1, 0x9E, 0x43,
+	0xE5, 0xA2, 0xA8, 0x43, 0xE5, 0xA2, 0xAC, 0x43,
+	0xE5, 0xA2, 0xB3, 0x43, 0xE5, 0xA3, 0x98, 0x43,
+	// Bytes a40 - a7f
+	0xE5, 0xA3, 0x9F, 0x43, 0xE5, 0xA3, 0xAB, 0x43,
+	0xE5, 0xA3, 0xAE, 0x43, 0xE5, 0xA3, 0xB0, 0x43,
+	0xE5, 0xA3, 0xB2, 0x43, 0xE5, 0xA3, 0xB7, 0x43,
+	0xE5, 0xA4, 0x82, 0x43, 0xE5, 0xA4, 0x86, 0x43,
+	0xE5, 0xA4, 0x8A, 0x43, 0xE5, 0xA4, 0x95, 0x43,
+	0xE5, 0xA4, 0x9A, 0x43, 0xE5, 0xA4, 0x9C, 0x43,
+	0xE5, 0xA4, 0xA2, 0x43, 0xE5, 0xA4, 0xA7, 0x43,
+	0xE5, 0xA4, 0xA9, 0x43, 0xE5, 0xA5, 0x84, 0x43,
+	// Bytes a80 - abf
+	0xE5, 0xA5, 0x88, 0x43, 0xE5, 0xA5, 0x91, 0x43,
+	0xE5, 0xA5, 0x94, 0x43, 0xE5, 0xA5, 0xA2, 0x43,
+	0xE5, 0xA5, 0xB3, 0x43, 0xE5, 0xA7, 0x98, 0x43,
+	0xE5, 0xA7, 0xAC, 0x43, 0xE5, 0xA8, 0x9B, 0x43,
+	0xE5, 0xA8, 0xA7, 0x43, 0xE5, 0xA9, 0xA2, 0x43,
+	0xE5, 0xA9, 0xA6, 0x43, 0xE5, 0xAA, 0xB5, 0x43,
+	0xE5, 0xAC, 0x88, 0x43, 0xE5, 0xAC, 0xA8, 0x43,
+	0xE5, 0xAC, 0xBE, 0x43, 0xE5, 0xAD, 0x90, 0x43,
+	// Bytes ac0 - aff
+	0xE5, 0xAD, 0x97, 0x43, 0xE5, 0xAD, 0xA6, 0x43,
+	0xE5, 0xAE, 0x80, 0x43, 0xE5, 0xAE, 0x85, 0x43,
+	0xE5, 0xAE, 0x97, 0x43, 0xE5, 0xAF, 0x83, 0x43,
+	0xE5, 0xAF, 0x98, 0x43, 0xE5, 0xAF, 0xA7, 0x43,
+	0xE5, 0xAF, 0xAE, 0x43, 0xE5, 0xAF, 0xB3, 0x43,
+	0xE5, 0xAF, 0xB8, 0x43, 0xE5, 0xAF, 0xBF, 0x43,
+	0xE5, 0xB0, 0x86, 0x43, 0xE5, 0xB0, 0x8F, 0x43,
+	0xE5, 0xB0, 0xA2, 0x43, 0xE5, 0xB0, 0xB8, 0x43,
+	// Bytes b00 - b3f
+	0xE5, 0xB0, 0xBF, 0x43, 0xE5, 0xB1, 0xA0, 0x43,
+	0xE5, 0xB1, 0xA2, 0x43, 0xE5, 0xB1, 0xA4, 0x43,
+	0xE5, 0xB1, 0xA5, 0x43, 0xE5, 0xB1, 0xAE, 0x43,
+	0xE5, 0xB1, 0xB1, 0x43, 0xE5, 0xB2, 0x8D, 0x43,
+	0xE5, 0xB3, 0x80, 0x43, 0xE5, 0xB4, 0x99, 0x43,
+	0xE5, 0xB5, 0x83, 0x43, 0xE5, 0xB5, 0x90, 0x43,
+	0xE5, 0xB5, 0xAB, 0x43, 0xE5, 0xB5, 0xAE, 0x43,
+	0xE5, 0xB5, 0xBC, 0x43, 0xE5, 0xB6, 0xB2, 0x43,
+	// Bytes b40 - b7f
+	0xE5, 0xB6, 0xBA, 0x43, 0xE5, 0xB7, 0x9B, 0x43,
+	0xE5, 0xB7, 0xA1, 0x43, 0xE5, 0xB7, 0xA2, 0x43,
+	0xE5, 0xB7, 0xA5, 0x43, 0xE5, 0xB7, 0xA6, 0x43,
+	0xE5, 0xB7, 0xB1, 0x43, 0xE5, 0xB7, 0xBD, 0x43,
+	0xE5, 0xB7, 0xBE, 0x43, 0xE5, 0xB8, 0xA8, 0x43,
+	0xE5, 0xB8, 0xBD, 0x43, 0xE5, 0xB9, 0xA9, 0x43,
+	0xE5, 0xB9, 0xB2, 0x43, 0xE5, 0xB9, 0xB4, 0x43,
+	0xE5, 0xB9, 0xBA, 0x43, 0xE5, 0xB9, 0xBC, 0x43,
+	// Bytes b80 - bbf
+	0xE5, 0xB9, 0xBF, 0x43, 0xE5, 0xBA, 0xA6, 0x43,
+	0xE5, 0xBA, 0xB0, 0x43, 0xE5, 0xBA, 0xB3, 0x43,
+	0xE5, 0xBA, 0xB6, 0x43, 0xE5, 0xBB, 0x89, 0x43,
+	0xE5, 0xBB, 0x8A, 0x43, 0xE5, 0xBB, 0x92, 0x43,
+	0xE5, 0xBB, 0x93, 0x43, 0xE5, 0xBB, 0x99, 0x43,
+	0xE5, 0xBB, 0xAC, 0x43, 0xE5, 0xBB, 0xB4, 0x43,
+	0xE5, 0xBB, 0xBE, 0x43, 0xE5, 0xBC, 0x84, 0x43,
+	0xE5, 0xBC, 0x8B, 0x43, 0xE5, 0xBC, 0x93, 0x43,
+	// Bytes bc0 - bff
+	0xE5, 0xBC, 0xA2, 0x43, 0xE5, 0xBD, 0x90, 0x43,
+	0xE5, 0xBD, 0x93, 0x43, 0xE5, 0xBD, 0xA1, 0x43,
+	0xE5, 0xBD, 0xA2, 0x43, 0xE5, 0xBD, 0xA9, 0x43,
+	0xE5, 0xBD, 0xAB, 0x43, 0xE5, 0xBD, 0xB3, 0x43,
+	0xE5, 0xBE, 0x8B, 0x43, 0xE5, 0xBE, 0x8C, 0x43,
+	0xE5, 0xBE, 0x97, 0x43, 0xE5, 0xBE, 0x9A, 0x43,
+	0xE5, 0xBE, 0xA9, 0x43, 0xE5, 0xBE, 0xAD, 0x43,
+	0xE5, 0xBF, 0x83, 0x43, 0xE5, 0xBF, 0x8D, 0x43,
+	// Bytes c00 - c3f
+	0xE5, 0xBF, 0x97, 0x43, 0xE5, 0xBF, 0xB5, 0x43,
+	0xE5, 0xBF, 0xB9, 0x43, 0xE6, 0x80, 0x92, 0x43,
+	0xE6, 0x80, 0x9C, 0x43, 0xE6, 0x81, 0xB5, 0x43,
+	0xE6, 0x82, 0x81, 0x43, 0xE6, 0x82, 0x94, 0x43,
+	0xE6, 0x83, 0x87, 0x43, 0xE6, 0x83, 0x98, 0x43,
+	0xE6, 0x83, 0xA1, 0x43, 0xE6, 0x84, 0x88, 0x43,
+	0xE6, 0x85, 0x84, 0x43, 0xE6, 0x85, 0x88, 0x43,
+	0xE6, 0x85, 0x8C, 0x43, 0xE6, 0x85, 0x8E, 0x43,
+	// Bytes c40 - c7f
+	0xE6, 0x85, 0xA0, 0x43, 0xE6, 0x85, 0xA8, 0x43,
+	0xE6, 0x85, 0xBA, 0x43, 0xE6, 0x86, 0x8E, 0x43,
+	0xE6, 0x86, 0x90, 0x43, 0xE6, 0x86, 0xA4, 0x43,
+	0xE6, 0x86, 0xAF, 0x43, 0xE6, 0x86, 0xB2, 0x43,
+	0xE6, 0x87, 0x9E, 0x43, 0xE6, 0x87, 0xB2, 0x43,
+	0xE6, 0x87, 0xB6, 0x43, 0xE6, 0x88, 0x80, 0x43,
+	0xE6, 0x88, 0x88, 0x43, 0xE6, 0x88, 0x90, 0x43,
+	0xE6, 0x88, 0x9B, 0x43, 0xE6, 0x88, 0xAE, 0x43,
+	// Bytes c80 - cbf
+	0xE6, 0x88, 0xB4, 0x43, 0xE6, 0x88, 0xB6, 0x43,
+	0xE6, 0x89, 0x8B, 0x43, 0xE6, 0x89, 0x93, 0x43,
+	0xE6, 0x89, 0x9D, 0x43, 0xE6, 0x8A, 0x95, 0x43,
+	0xE6, 0x8A, 0xB1, 0x43, 0xE6, 0x8B, 0x89, 0x43,
+	0xE6, 0x8B, 0x8F, 0x43, 0xE6, 0x8B, 0x93, 0x43,
+	0xE6, 0x8B, 0x94, 0x43, 0xE6, 0x8B, 0xBC, 0x43,
+	0xE6, 0x8B, 0xBE, 0x43, 0xE6, 0x8C, 0x87, 0x43,
+	0xE6, 0x8C, 0xBD, 0x43, 0xE6, 0x8D, 0x90, 0x43,
+	// Bytes cc0 - cff
+	0xE6, 0x8D, 0x95, 0x43, 0xE6, 0x8D, 0xA8, 0x43,
+	0xE6, 0x8D, 0xBB, 0x43, 0xE6, 0x8E, 0x83, 0x43,
+	0xE6, 0x8E, 0xA0, 0x43, 0xE6, 0x8E, 0xA9, 0x43,
+	0xE6, 0x8F, 0x84, 0x43, 0xE6, 0x8F, 0x85, 0x43,
+	0xE6, 0x8F, 0xA4, 0x43, 0xE6, 0x90, 0x9C, 0x43,
+	0xE6, 0x90, 0xA2, 0x43, 0xE6, 0x91, 0x92, 0x43,
+	0xE6, 0x91, 0xA9, 0x43, 0xE6, 0x91, 0xB7, 0x43,
+	0xE6, 0x91, 0xBE, 0x43, 0xE6, 0x92, 0x9A, 0x43,
+	// Bytes d00 - d3f
+	0xE6, 0x92, 0x9D, 0x43, 0xE6, 0x93, 0x84, 0x43,
+	0xE6, 0x94, 0xAF, 0x43, 0xE6, 0x94, 0xB4, 0x43,
+	0xE6, 0x95, 0x8F, 0x43, 0xE6, 0x95, 0x96, 0x43,
+	0xE6, 0x95, 0xAC, 0x43, 0xE6, 0x95, 0xB8, 0x43,
+	0xE6, 0x96, 0x87, 0x43, 0xE6, 0x96, 0x97, 0x43,
+	0xE6, 0x96, 0x99, 0x43, 0xE6, 0x96, 0xA4, 0x43,
+	0xE6, 0x96, 0xB0, 0x43, 0xE6, 0x96, 0xB9, 0x43,
+	0xE6, 0x97, 0x85, 0x43, 0xE6, 0x97, 0xA0, 0x43,
+	// Bytes d40 - d7f
+	0xE6, 0x97, 0xA2, 0x43, 0xE6, 0x97, 0xA3, 0x43,
+	0xE6, 0x97, 0xA5, 0x43, 0xE6, 0x98, 0x93, 0x43,
+	0xE6, 0x98, 0xA0, 0x43, 0xE6, 0x99, 0x89, 0x43,
+	0xE6, 0x99, 0xB4, 0x43, 0xE6, 0x9A, 0x88, 0x43,
+	0xE6, 0x9A, 0x91, 0x43, 0xE6, 0x9A, 0x9C, 0x43,
+	0xE6, 0x9A, 0xB4, 0x43, 0xE6, 0x9B, 0x86, 0x43,
+	0xE6, 0x9B, 0xB0, 0x43, 0xE6, 0x9B, 0xB4, 0x43,
+	0xE6, 0x9B, 0xB8, 0x43, 0xE6, 0x9C, 0x80, 0x43,
+	// Bytes d80 - dbf
+	0xE6, 0x9C, 0x88, 0x43, 0xE6, 0x9C, 0x89, 0x43,
+	0xE6, 0x9C, 0x97, 0x43, 0xE6, 0x9C, 0x9B, 0x43,
+	0xE6, 0x9C, 0xA1, 0x43, 0xE6, 0x9C, 0xA8, 0x43,
+	0xE6, 0x9D, 0x8E, 0x43, 0xE6, 0x9D, 0x93, 0x43,
+	0xE6, 0x9D, 0x96, 0x43, 0xE6, 0x9D, 0x9E, 0x43,
+	0xE6, 0x9D, 0xBB, 0x43, 0xE6, 0x9E, 0x85, 0x43,
+	0xE6, 0x9E, 0x97, 0x43, 0xE6, 0x9F, 0xB3, 0x43,
+	0xE6, 0x9F, 0xBA, 0x43, 0xE6, 0xA0, 0x97, 0x43,
+	// Bytes dc0 - dff
+	0xE6, 0xA0, 0x9F, 0x43, 0xE6, 0xA0, 0xAA, 0x43,
+	0xE6, 0xA1, 0x92, 0x43, 0xE6, 0xA2, 0x81, 0x43,
+	0xE6, 0xA2, 0x85, 0x43, 0xE6, 0xA2, 0x8E, 0x43,
+	0xE6, 0xA2, 0xA8, 0x43, 0xE6, 0xA4, 0x94, 0x43,
+	0xE6, 0xA5, 0x82, 0x43, 0xE6, 0xA6, 0xA3, 0x43,
+	0xE6, 0xA7, 0xAA, 0x43, 0xE6, 0xA8, 0x82, 0x43,
+	0xE6, 0xA8, 0x93, 0x43, 0xE6, 0xAA, 0xA8, 0x43,
+	0xE6, 0xAB, 0x93, 0x43, 0xE6, 0xAB, 0x9B, 0x43,
+	// Bytes e00 - e3f
+	0xE6, 0xAC, 0x84, 0x43, 0xE6, 0xAC, 0xA0, 0x43,
+	0xE6, 0xAC, 0xA1, 0x43, 0xE6, 0xAD, 0x94, 0x43,
+	0xE6, 0xAD, 0xA2, 0x43, 0xE6, 0xAD, 0xA3, 0x43,
+	0xE6, 0xAD, 0xB2, 0x43, 0xE6, 0xAD, 0xB7, 0x43,
+	0xE6, 0xAD, 0xB9, 0x43, 0xE6, 0xAE, 0x9F, 0x43,
+	0xE6, 0xAE, 0xAE, 0x43, 0xE6, 0xAE, 0xB3, 0x43,
+	0xE6, 0xAE, 0xBA, 0x43, 0xE6, 0xAE, 0xBB, 0x43,
+	0xE6, 0xAF, 0x8B, 0x43, 0xE6, 0xAF, 0x8D, 0x43,
+	// Bytes e40 - e7f
+	0xE6, 0xAF, 0x94, 0x43, 0xE6, 0xAF, 0x9B, 0x43,
+	0xE6, 0xB0, 0x8F, 0x43, 0xE6, 0xB0, 0x94, 0x43,
+	0xE6, 0xB0, 0xB4, 0x43, 0xE6, 0xB1, 0x8E, 0x43,
+	0xE6, 0xB1, 0xA7, 0x43, 0xE6, 0xB2, 0x88, 0x43,
+	0xE6, 0xB2, 0xBF, 0x43, 0xE6, 0xB3, 0x8C, 0x43,
+	0xE6, 0xB3, 0x8D, 0x43, 0xE6, 0xB3, 0xA5, 0x43,
+	0xE6, 0xB3, 0xA8, 0x43, 0xE6, 0xB4, 0x96, 0x43,
+	0xE6, 0xB4, 0x9B, 0x43, 0xE6, 0xB4, 0x9E, 0x43,
+	// Bytes e80 - ebf
+	0xE6, 0xB4, 0xB4, 0x43, 0xE6, 0xB4, 0xBE, 0x43,
+	0xE6, 0xB5, 0x81, 0x43, 0xE6, 0xB5, 0xA9, 0x43,
+	0xE6, 0xB5, 0xAA, 0x43, 0xE6, 0xB5, 0xB7, 0x43,
+	0xE6, 0xB5, 0xB8, 0x43, 0xE6, 0xB6, 0x85, 0x43,
+	0xE6, 0xB7, 0x8B, 0x43, 0xE6, 0xB7, 0x9A, 0x43,
+	0xE6, 0xB7, 0xAA, 0x43, 0xE6, 0xB7, 0xB9, 0x43,
+	0xE6, 0xB8, 0x9A, 0x43, 0xE6, 0xB8, 0xAF, 0x43,
+	0xE6, 0xB9, 0xAE, 0x43, 0xE6, 0xBA, 0x80, 0x43,
+	// Bytes ec0 - eff
+	0xE6, 0xBA, 0x9C, 0x43, 0xE6, 0xBA, 0xBA, 0x43,
+	0xE6, 0xBB, 0x87, 0x43, 0xE6, 0xBB, 0x8B, 0x43,
+	0xE6, 0xBB, 0x91, 0x43, 0xE6, 0xBB, 0x9B, 0x43,
+	0xE6, 0xBC, 0x8F, 0x43, 0xE6, 0xBC, 0x94, 0x43,
+	0xE6, 0xBC, 0xA2, 0x43, 0xE6, 0xBC, 0xA3, 0x43,
+	0xE6, 0xBD, 0xAE, 0x43, 0xE6, 0xBF, 0x86, 0x43,
+	0xE6, 0xBF, 0xAB, 0x43, 0xE6, 0xBF, 0xBE, 0x43,
+	0xE7, 0x80, 0x9B, 0x43, 0xE7, 0x80, 0x9E, 0x43,
+	// Bytes f00 - f3f
+	0xE7, 0x80, 0xB9, 0x43, 0xE7, 0x81, 0x8A, 0x43,
+	0xE7, 0x81, 0xAB, 0x43, 0xE7, 0x81, 0xB0, 0x43,
+	0xE7, 0x81, 0xB7, 0x43, 0xE7, 0x81, 0xBD, 0x43,
+	0xE7, 0x82, 0x99, 0x43, 0xE7, 0x82, 0xAD, 0x43,
+	0xE7, 0x83, 0x88, 0x43, 0xE7, 0x83, 0x99, 0x43,
+	0xE7, 0x84, 0xA1, 0x43, 0xE7, 0x85, 0x85, 0x43,
+	0xE7, 0x85, 0x89, 0x43, 0xE7, 0x85, 0xAE, 0x43,
+	0xE7, 0x86, 0x9C, 0x43, 0xE7, 0x87, 0x8E, 0x43,
+	// Bytes f40 - f7f
+	0xE7, 0x87, 0x90, 0x43, 0xE7, 0x88, 0x90, 0x43,
+	0xE7, 0x88, 0x9B, 0x43, 0xE7, 0x88, 0xA8, 0x43,
+	0xE7, 0x88, 0xAA, 0x43, 0xE7, 0x88, 0xAB, 0x43,
+	0xE7, 0x88, 0xB5, 0x43, 0xE7, 0x88, 0xB6, 0x43,
+	0xE7, 0x88, 0xBB, 0x43, 0xE7, 0x88, 0xBF, 0x43,
+	0xE7, 0x89, 0x87, 0x43, 0xE7, 0x89, 0x90, 0x43,
+	0xE7, 0x89, 0x99, 0x43, 0xE7, 0x89, 0x9B, 0x43,
+	0xE7, 0x89, 0xA2, 0x43, 0xE7, 0x89, 0xB9, 0x43,
+	// Bytes f80 - fbf
+	0xE7, 0x8A, 0x80, 0x43, 0xE7, 0x8A, 0x95, 0x43,
+	0xE7, 0x8A, 0xAC, 0x43, 0xE7, 0x8A, 0xAF, 0x43,
+	0xE7, 0x8B, 0x80, 0x43, 0xE7, 0x8B, 0xBC, 0x43,
+	0xE7, 0x8C, 0xAA, 0x43, 0xE7, 0x8D, 0xB5, 0x43,
+	0xE7, 0x8D, 0xBA, 0x43, 0xE7, 0x8E, 0x84, 0x43,
+	0xE7, 0x8E, 0x87, 0x43, 0xE7, 0x8E, 0x89, 0x43,
+	0xE7, 0x8E, 0x8B, 0x43, 0xE7, 0x8E, 0xA5, 0x43,
+	0xE7, 0x8E, 0xB2, 0x43, 0xE7, 0x8F, 0x9E, 0x43,
+	// Bytes fc0 - fff
+	0xE7, 0x90, 0x86, 0x43, 0xE7, 0x90, 0x89, 0x43,
+	0xE7, 0x90, 0xA2, 0x43, 0xE7, 0x91, 0x87, 0x43,
+	0xE7, 0x91, 0x9C, 0x43, 0xE7, 0x91, 0xA9, 0x43,
+	0xE7, 0x91, 0xB1, 0x43, 0xE7, 0x92, 0x85, 0x43,
+	0xE7, 0x92, 0x89, 0x43, 0xE7, 0x92, 0x98, 0x43,
+	0xE7, 0x93, 0x8A, 0x43, 0xE7, 0x93, 0x9C, 0x43,
+	0xE7, 0x93, 0xA6, 0x43, 0xE7, 0x94, 0x86, 0x43,
+	0xE7, 0x94, 0x98, 0x43, 0xE7, 0x94, 0x9F, 0x43,
+	// Bytes 1000 - 103f
+	0xE7, 0x94, 0xA4, 0x43, 0xE7, 0x94, 0xA8, 0x43,
+	0xE7, 0x94, 0xB0, 0x43, 0xE7, 0x94, 0xB2, 0x43,
+	0xE7, 0x94, 0xB3, 0x43, 0xE7, 0x94, 0xB7, 0x43,
+	0xE7, 0x94, 0xBB, 0x43, 0xE7, 0x94, 0xBE, 0x43,
+	0xE7, 0x95, 0x99, 0x43, 0xE7, 0x95, 0xA5, 0x43,
+	0xE7, 0x95, 0xB0, 0x43, 0xE7, 0x96, 0x8B, 0x43,
+	0xE7, 0x96, 0x92, 0x43, 0xE7, 0x97, 0xA2, 0x43,
+	0xE7, 0x98, 0x90, 0x43, 0xE7, 0x98, 0x9D, 0x43,
+	// Bytes 1040 - 107f
+	0xE7, 0x98, 0x9F, 0x43, 0xE7, 0x99, 0x82, 0x43,
+	0xE7, 0x99, 0xA9, 0x43, 0xE7, 0x99, 0xB6, 0x43,
+	0xE7, 0x99, 0xBD, 0x43, 0xE7, 0x9A, 0xAE, 0x43,
+	0xE7, 0x9A, 0xBF, 0x43, 0xE7, 0x9B, 0x8A, 0x43,
+	0xE7, 0x9B, 0x9B, 0x43, 0xE7, 0x9B, 0xA3, 0x43,
+	0xE7, 0x9B, 0xA7, 0x43, 0xE7, 0x9B, 0xAE, 0x43,
+	0xE7, 0x9B, 0xB4, 0x43, 0xE7, 0x9C, 0x81, 0x43,
+	0xE7, 0x9C, 0x9E, 0x43, 0xE7, 0x9C, 0x9F, 0x43,
+	// Bytes 1080 - 10bf
+	0xE7, 0x9D, 0x80, 0x43, 0xE7, 0x9D, 0x8A, 0x43,
+	0xE7, 0x9E, 0x8B, 0x43, 0xE7, 0x9E, 0xA7, 0x43,
+	0xE7, 0x9F, 0x9B, 0x43, 0xE7, 0x9F, 0xA2, 0x43,
+	0xE7, 0x9F, 0xB3, 0x43, 0xE7, 0xA1, 0x8E, 0x43,
+	0xE7, 0xA1, 0xAB, 0x43, 0xE7, 0xA2, 0x8C, 0x43,
+	0xE7, 0xA2, 0x91, 0x43, 0xE7, 0xA3, 0x8A, 0x43,
+	0xE7, 0xA3, 0x8C, 0x43, 0xE7, 0xA3, 0xBB, 0x43,
+	0xE7, 0xA4, 0xAA, 0x43, 0xE7, 0xA4, 0xBA, 0x43,
+	// Bytes 10c0 - 10ff
+	0xE7, 0xA4, 0xBC, 0x43, 0xE7, 0xA4, 0xBE, 0x43,
+	0xE7, 0xA5, 0x88, 0x43, 0xE7, 0xA5, 0x89, 0x43,
+	0xE7, 0xA5, 0x90, 0x43, 0xE7, 0xA5, 0x96, 0x43,
+	0xE7, 0xA5, 0x9D, 0x43, 0xE7, 0xA5, 0x9E, 0x43,
+	0xE7, 0xA5, 0xA5, 0x43, 0xE7, 0xA5, 0xBF, 0x43,
+	0xE7, 0xA6, 0x81, 0x43, 0xE7, 0xA6, 0x8D, 0x43,
+	0xE7, 0xA6, 0x8E, 0x43, 0xE7, 0xA6, 0x8F, 0x43,
+	0xE7, 0xA6, 0xAE, 0x43, 0xE7, 0xA6, 0xB8, 0x43,
+	// Bytes 1100 - 113f
+	0xE7, 0xA6, 0xBE, 0x43, 0xE7, 0xA7, 0x8A, 0x43,
+	0xE7, 0xA7, 0x98, 0x43, 0xE7, 0xA7, 0xAB, 0x43,
+	0xE7, 0xA8, 0x9C, 0x43, 0xE7, 0xA9, 0x80, 0x43,
+	0xE7, 0xA9, 0x8A, 0x43, 0xE7, 0xA9, 0x8F, 0x43,
+	0xE7, 0xA9, 0xB4, 0x43, 0xE7, 0xA9, 0xBA, 0x43,
+	0xE7, 0xAA, 0x81, 0x43, 0xE7, 0xAA, 0xB1, 0x43,
+	0xE7, 0xAB, 0x8B, 0x43, 0xE7, 0xAB, 0xAE, 0x43,
+	0xE7, 0xAB, 0xB9, 0x43, 0xE7, 0xAC, 0xA0, 0x43,
+	// Bytes 1140 - 117f
+	0xE7, 0xAE, 0x8F, 0x43, 0xE7, 0xAF, 0x80, 0x43,
+	0xE7, 0xAF, 0x86, 0x43, 0xE7, 0xAF, 0x89, 0x43,
+	0xE7, 0xB0, 0xBE, 0x43, 0xE7, 0xB1, 0xA0, 0x43,
+	0xE7, 0xB1, 0xB3, 0x43, 0xE7, 0xB1, 0xBB, 0x43,
+	0xE7, 0xB2, 0x92, 0x43, 0xE7, 0xB2, 0xBE, 0x43,
+	0xE7, 0xB3, 0x92, 0x43, 0xE7, 0xB3, 0x96, 0x43,
+	0xE7, 0xB3, 0xA3, 0x43, 0xE7, 0xB3, 0xA7, 0x43,
+	0xE7, 0xB3, 0xA8, 0x43, 0xE7, 0xB3, 0xB8, 0x43,
+	// Bytes 1180 - 11bf
+	0xE7, 0xB4, 0x80, 0x43, 0xE7, 0xB4, 0x90, 0x43,
+	0xE7, 0xB4, 0xA2, 0x43, 0xE7, 0xB4, 0xAF, 0x43,
+	0xE7, 0xB5, 0x82, 0x43, 0xE7, 0xB5, 0x9B, 0x43,
+	0xE7, 0xB5, 0xA3, 0x43, 0xE7, 0xB6, 0xA0, 0x43,
+	0xE7, 0xB6, 0xBE, 0x43, 0xE7, 0xB7, 0x87, 0x43,
+	0xE7, 0xB7, 0xB4, 0x43, 0xE7, 0xB8, 0x82, 0x43,
+	0xE7, 0xB8, 0x89, 0x43, 0xE7, 0xB8, 0xB7, 0x43,
+	0xE7, 0xB9, 0x81, 0x43, 0xE7, 0xB9, 0x85, 0x43,
+	// Bytes 11c0 - 11ff
+	0xE7, 0xBC, 0xB6, 0x43, 0xE7, 0xBC, 0xBE, 0x43,
+	0xE7, 0xBD, 0x91, 0x43, 0xE7, 0xBD, 0xB2, 0x43,
+	0xE7, 0xBD, 0xB9, 0x43, 0xE7, 0xBD, 0xBA, 0x43,
+	0xE7, 0xBE, 0x85, 0x43, 0xE7, 0xBE, 0x8A, 0x43,
+	0xE7, 0xBE, 0x95, 0x43, 0xE7, 0xBE, 0x9A, 0x43,
+	0xE7, 0xBE, 0xBD, 0x43, 0xE7, 0xBF, 0xBA, 0x43,
+	0xE8, 0x80, 0x81, 0x43, 0xE8, 0x80, 0x85, 0x43,
+	0xE8, 0x80, 0x8C, 0x43, 0xE8, 0x80, 0x92, 0x43,
+	// Bytes 1200 - 123f
+	0xE8, 0x80, 0xB3, 0x43, 0xE8, 0x81, 0x86, 0x43,
+	0xE8, 0x81, 0xA0, 0x43, 0xE8, 0x81, 0xAF, 0x43,
+	0xE8, 0x81, 0xB0, 0x43, 0xE8, 0x81, 0xBE, 0x43,
+	0xE8, 0x81, 0xBF, 0x43, 0xE8, 0x82, 0x89, 0x43,
+	0xE8, 0x82, 0x8B, 0x43, 0xE8, 0x82, 0xAD, 0x43,
+	0xE8, 0x82, 0xB2, 0x43, 0xE8, 0x84, 0x83, 0x43,
+	0xE8, 0x84, 0xBE, 0x43, 0xE8, 0x87, 0x98, 0x43,
+	0xE8, 0x87, 0xA3, 0x43, 0xE8, 0x87, 0xA8, 0x43,
+	// Bytes 1240 - 127f
+	0xE8, 0x87, 0xAA, 0x43, 0xE8, 0x87, 0xAD, 0x43,
+	0xE8, 0x87, 0xB3, 0x43, 0xE8, 0x87, 0xBC, 0x43,
+	0xE8, 0x88, 0x81, 0x43, 0xE8, 0x88, 0x84, 0x43,
+	0xE8, 0x88, 0x8C, 0x43, 0xE8, 0x88, 0x98, 0x43,
+	0xE8, 0x88, 0x9B, 0x43, 0xE8, 0x88, 0x9F, 0x43,
+	0xE8, 0x89, 0xAE, 0x43, 0xE8, 0x89, 0xAF, 0x43,
+	0xE8, 0x89, 0xB2, 0x43, 0xE8, 0x89, 0xB8, 0x43,
+	0xE8, 0x89, 0xB9, 0x43, 0xE8, 0x8A, 0x8B, 0x43,
+	// Bytes 1280 - 12bf
+	0xE8, 0x8A, 0x91, 0x43, 0xE8, 0x8A, 0x9D, 0x43,
+	0xE8, 0x8A, 0xB1, 0x43, 0xE8, 0x8A, 0xB3, 0x43,
+	0xE8, 0x8A, 0xBD, 0x43, 0xE8, 0x8B, 0xA5, 0x43,
+	0xE8, 0x8B, 0xA6, 0x43, 0xE8, 0x8C, 0x9D, 0x43,
+	0xE8, 0x8C, 0xA3, 0x43, 0xE8, 0x8C, 0xB6, 0x43,
+	0xE8, 0x8D, 0x92, 0x43, 0xE8, 0x8D, 0x93, 0x43,
+	0xE8, 0x8D, 0xA3, 0x43, 0xE8, 0x8E, 0xAD, 0x43,
+	0xE8, 0x8E, 0xBD, 0x43, 0xE8, 0x8F, 0x89, 0x43,
+	// Bytes 12c0 - 12ff
+	0xE8, 0x8F, 0x8A, 0x43, 0xE8, 0x8F, 0x8C, 0x43,
+	0xE8, 0x8F, 0x9C, 0x43, 0xE8, 0x8F, 0xA7, 0x43,
+	0xE8, 0x8F, 0xAF, 0x43, 0xE8, 0x8F, 0xB1, 0x43,
+	0xE8, 0x90, 0xBD, 0x43, 0xE8, 0x91, 0x89, 0x43,
+	0xE8, 0x91, 0x97, 0x43, 0xE8, 0x93, 0xAE, 0x43,
+	0xE8, 0x93, 0xB1, 0x43, 0xE8, 0x93, 0xB3, 0x43,
+	0xE8, 0x93, 0xBC, 0x43, 0xE8, 0x94, 0x96, 0x43,
+	0xE8, 0x95, 0xA4, 0x43, 0xE8, 0x97, 0x8D, 0x43,
+	// Bytes 1300 - 133f
+	0xE8, 0x97, 0xBA, 0x43, 0xE8, 0x98, 0x86, 0x43,
+	0xE8, 0x98, 0x92, 0x43, 0xE8, 0x98, 0xAD, 0x43,
+	0xE8, 0x98, 0xBF, 0x43, 0xE8, 0x99, 0x8D, 0x43,
+	0xE8, 0x99, 0x90, 0x43, 0xE8, 0x99, 0x9C, 0x43,
+	0xE8, 0x99, 0xA7, 0x43, 0xE8, 0x99, 0xA9, 0x43,
+	0xE8, 0x99, 0xAB, 0x43, 0xE8, 0x9A, 0x88, 0x43,
+	0xE8, 0x9A, 0xA9, 0x43, 0xE8, 0x9B, 0xA2, 0x43,
+	0xE8, 0x9C, 0x8E, 0x43, 0xE8, 0x9C, 0xA8, 0x43,
+	// Bytes 1340 - 137f
+	0xE8, 0x9D, 0xAB, 0x43, 0xE8, 0x9D, 0xB9, 0x43,
+	0xE8, 0x9E, 0x86, 0x43, 0xE8, 0x9E, 0xBA, 0x43,
+	0xE8, 0x9F, 0xA1, 0x43, 0xE8, 0xA0, 0x81, 0x43,
+	0xE8, 0xA0, 0x9F, 0x43, 0xE8, 0xA1, 0x80, 0x43,
+	0xE8, 0xA1, 0x8C, 0x43, 0xE8, 0xA1, 0xA0, 0x43,
+	0xE8, 0xA1, 0xA3, 0x43, 0xE8, 0xA3, 0x82, 0x43,
+	0xE8, 0xA3, 0x8F, 0x43, 0xE8, 0xA3, 0x97, 0x43,
+	0xE8, 0xA3, 0x9E, 0x43, 0xE8, 0xA3, 0xA1, 0x43,
+	// Bytes 1380 - 13bf
+	0xE8, 0xA3, 0xB8, 0x43, 0xE8, 0xA3, 0xBA, 0x43,
+	0xE8, 0xA4, 0x90, 0x43, 0xE8, 0xA5, 0x81, 0x43,
+	0xE8, 0xA5, 0xA4, 0x43, 0xE8, 0xA5, 0xBE, 0x43,
+	0xE8, 0xA6, 0x86, 0x43, 0xE8, 0xA6, 0x8B, 0x43,
+	0xE8, 0xA6, 0x96, 0x43, 0xE8, 0xA7, 0x92, 0x43,
+	0xE8, 0xA7, 0xA3, 0x43, 0xE8, 0xA8, 0x80, 0x43,
+	0xE8, 0xAA, 0xA0, 0x43, 0xE8, 0xAA, 0xAA, 0x43,
+	0xE8, 0xAA, 0xBF, 0x43, 0xE8, 0xAB, 0x8B, 0x43,
+	// Bytes 13c0 - 13ff
+	0xE8, 0xAB, 0x92, 0x43, 0xE8, 0xAB, 0x96, 0x43,
+	0xE8, 0xAB, 0xAD, 0x43, 0xE8, 0xAB, 0xB8, 0x43,
+	0xE8, 0xAB, 0xBE, 0x43, 0xE8, 0xAC, 0x81, 0x43,
+	0xE8, 0xAC, 0xB9, 0x43, 0xE8, 0xAD, 0x98, 0x43,
+	0xE8, 0xAE, 0x80, 0x43, 0xE8, 0xAE, 0x8A, 0x43,
+	0xE8, 0xB0, 0xB7, 0x43, 0xE8, 0xB1, 0x86, 0x43,
+	0xE8, 0xB1, 0x88, 0x43, 0xE8, 0xB1, 0x95, 0x43,
+	0xE8, 0xB1, 0xB8, 0x43, 0xE8, 0xB2, 0x9D, 0x43,
+	// Bytes 1400 - 143f
+	0xE8, 0xB2, 0xA1, 0x43, 0xE8, 0xB2, 0xA9, 0x43,
+	0xE8, 0xB2, 0xAB, 0x43, 0xE8, 0xB3, 0x81, 0x43,
+	0xE8, 0xB3, 0x82, 0x43, 0xE8, 0xB3, 0x87, 0x43,
+	0xE8, 0xB3, 0x88, 0x43, 0xE8, 0xB3, 0x93, 0x43,
+	0xE8, 0xB4, 0x88, 0x43, 0xE8, 0xB4, 0x9B, 0x43,
+	0xE8, 0xB5, 0xA4, 0x43, 0xE8, 0xB5, 0xB0, 0x43,
+	0xE8, 0xB5, 0xB7, 0x43, 0xE8, 0xB6, 0xB3, 0x43,
+	0xE8, 0xB6, 0xBC, 0x43, 0xE8, 0xB7, 0x8B, 0x43,
+	// Bytes 1440 - 147f
+	0xE8, 0xB7, 0xAF, 0x43, 0xE8, 0xB7, 0xB0, 0x43,
+	0xE8, 0xBA, 0xAB, 0x43, 0xE8, 0xBB, 0x8A, 0x43,
+	0xE8, 0xBB, 0x94, 0x43, 0xE8, 0xBC, 0xA6, 0x43,
+	0xE8, 0xBC, 0xAA, 0x43, 0xE8, 0xBC, 0xB8, 0x43,
+	0xE8, 0xBC, 0xBB, 0x43, 0xE8, 0xBD, 0xA2, 0x43,
+	0xE8, 0xBE, 0x9B, 0x43, 0xE8, 0xBE, 0x9E, 0x43,
+	0xE8, 0xBE, 0xB0, 0x43, 0xE8, 0xBE, 0xB5, 0x43,
+	0xE8, 0xBE, 0xB6, 0x43, 0xE9, 0x80, 0xA3, 0x43,
+	// Bytes 1480 - 14bf
+	0xE9, 0x80, 0xB8, 0x43, 0xE9, 0x81, 0x8A, 0x43,
+	0xE9, 0x81, 0xA9, 0x43, 0xE9, 0x81, 0xB2, 0x43,
+	0xE9, 0x81, 0xBC, 0x43, 0xE9, 0x82, 0x8F, 0x43,
+	0xE9, 0x82, 0x91, 0x43, 0xE9, 0x82, 0x94, 0x43,
+	0xE9, 0x83, 0x8E, 0x43, 0xE9, 0x83, 0x9E, 0x43,
+	0xE9, 0x83, 0xB1, 0x43, 0xE9, 0x83, 0xBD, 0x43,
+	0xE9, 0x84, 0x91, 0x43, 0xE9, 0x84, 0x9B, 0x43,
+	0xE9, 0x85, 0x89, 0x43, 0xE9, 0x85, 0xAA, 0x43,
+	// Bytes 14c0 - 14ff
+	0xE9, 0x86, 0x99, 0x43, 0xE9, 0x86, 0xB4, 0x43,
+	0xE9, 0x87, 0x86, 0x43, 0xE9, 0x87, 0x8C, 0x43,
+	0xE9, 0x87, 0x8F, 0x43, 0xE9, 0x87, 0x91, 0x43,
+	0xE9, 0x88, 0xB4, 0x43, 0xE9, 0x88, 0xB8, 0x43,
+	0xE9, 0x89, 0xB6, 0x43, 0xE9, 0x89, 0xBC, 0x43,
+	0xE9, 0x8B, 0x97, 0x43, 0xE9, 0x8B, 0x98, 0x43,
+	0xE9, 0x8C, 0x84, 0x43, 0xE9, 0x8D, 0x8A, 0x43,
+	0xE9, 0x8F, 0xB9, 0x43, 0xE9, 0x90, 0x95, 0x43,
+	// Bytes 1500 - 153f
+	0xE9, 0x95, 0xB7, 0x43, 0xE9, 0x96, 0x80, 0x43,
+	0xE9, 0x96, 0x8B, 0x43, 0xE9, 0x96, 0xAD, 0x43,
+	0xE9, 0x96, 0xB7, 0x43, 0xE9, 0x98, 0x9C, 0x43,
+	0xE9, 0x98, 0xAE, 0x43, 0xE9, 0x99, 0x8B, 0x43,
+	0xE9, 0x99, 0x8D, 0x43, 0xE9, 0x99, 0xB5, 0x43,
+	0xE9, 0x99, 0xB8, 0x43, 0xE9, 0x99, 0xBC, 0x43,
+	0xE9, 0x9A, 0x86, 0x43, 0xE9, 0x9A, 0xA3, 0x43,
+	0xE9, 0x9A, 0xB6, 0x43, 0xE9, 0x9A, 0xB7, 0x43,
+	// Bytes 1540 - 157f
+	0xE9, 0x9A, 0xB8, 0x43, 0xE9, 0x9A, 0xB9, 0x43,
+	0xE9, 0x9B, 0x83, 0x43, 0xE9, 0x9B, 0xA2, 0x43,
+	0xE9, 0x9B, 0xA3, 0x43, 0xE9, 0x9B, 0xA8, 0x43,
+	0xE9, 0x9B, 0xB6, 0x43, 0xE9, 0x9B, 0xB7, 0x43,
+	0xE9, 0x9C, 0xA3, 0x43, 0xE9, 0x9C, 0xB2, 0x43,
+	0xE9, 0x9D, 0x88, 0x43, 0xE9, 0x9D, 0x91, 0x43,
+	0xE9, 0x9D, 0x96, 0x43, 0xE9, 0x9D, 0x9E, 0x43,
+	0xE9, 0x9D, 0xA2, 0x43, 0xE9, 0x9D, 0xA9, 0x43,
+	// Bytes 1580 - 15bf
+	0xE9, 0x9F, 0x8B, 0x43, 0xE9, 0x9F, 0x9B, 0x43,
+	0xE9, 0x9F, 0xA0, 0x43, 0xE9, 0x9F, 0xAD, 0x43,
+	0xE9, 0x9F, 0xB3, 0x43, 0xE9, 0x9F, 0xBF, 0x43,
+	0xE9, 0xA0, 0x81, 0x43, 0xE9, 0xA0, 0x85, 0x43,
+	0xE9, 0xA0, 0x8B, 0x43, 0xE9, 0xA0, 0x98, 0x43,
+	0xE9, 0xA0, 0xA9, 0x43, 0xE9, 0xA0, 0xBB, 0x43,
+	0xE9, 0xA1, 0x9E, 0x43, 0xE9, 0xA2, 0xA8, 0x43,
+	0xE9, 0xA3, 0x9B, 0x43, 0xE9, 0xA3, 0x9F, 0x43,
+	// Bytes 15c0 - 15ff
+	0xE9, 0xA3, 0xA2, 0x43, 0xE9, 0xA3, 0xAF, 0x43,
+	0xE9, 0xA3, 0xBC, 0x43, 0xE9, 0xA4, 0xA8, 0x43,
+	0xE9, 0xA4, 0xA9, 0x43, 0xE9, 0xA6, 0x96, 0x43,
+	0xE9, 0xA6, 0x99, 0x43, 0xE9, 0xA6, 0xA7, 0x43,
+	0xE9, 0xA6, 0xAC, 0x43, 0xE9, 0xA7, 0x82, 0x43,
+	0xE9, 0xA7, 0xB1, 0x43, 0xE9, 0xA7, 0xBE, 0x43,
+	0xE9, 0xA9, 0xAA, 0x43, 0xE9, 0xAA, 0xA8, 0x43,
+	0xE9, 0xAB, 0x98, 0x43, 0xE9, 0xAB, 0x9F, 0x43,
+	// Bytes 1600 - 163f
+	0xE9, 0xAC, 0x92, 0x43, 0xE9, 0xAC, 0xA5, 0x43,
+	0xE9, 0xAC, 0xAF, 0x43, 0xE9, 0xAC, 0xB2, 0x43,
+	0xE9, 0xAC, 0xBC, 0x43, 0xE9, 0xAD, 0x9A, 0x43,
+	0xE9, 0xAD, 0xAF, 0x43, 0xE9, 0xB1, 0x80, 0x43,
+	0xE9, 0xB1, 0x97, 0x43, 0xE9, 0xB3, 0xA5, 0x43,
+	0xE9, 0xB3, 0xBD, 0x43, 0xE9, 0xB5, 0xA7, 0x43,
+	0xE9, 0xB6, 0xB4, 0x43, 0xE9, 0xB7, 0xBA, 0x43,
+	0xE9, 0xB8, 0x9E, 0x43, 0xE9, 0xB9, 0xB5, 0x43,
+	// Bytes 1640 - 167f
+	0xE9, 0xB9, 0xBF, 0x43, 0xE9, 0xBA, 0x97, 0x43,
+	0xE9, 0xBA, 0x9F, 0x43, 0xE9, 0xBA, 0xA5, 0x43,
+	0xE9, 0xBA, 0xBB, 0x43, 0xE9, 0xBB, 0x83, 0x43,
+	0xE9, 0xBB, 0x8D, 0x43, 0xE9, 0xBB, 0x8E, 0x43,
+	0xE9, 0xBB, 0x91, 0x43, 0xE9, 0xBB, 0xB9, 0x43,
+	0xE9, 0xBB, 0xBD, 0x43, 0xE9, 0xBB, 0xBE, 0x43,
+	0xE9, 0xBC, 0x85, 0x43, 0xE9, 0xBC, 0x8E, 0x43,
+	0xE9, 0xBC, 0x8F, 0x43, 0xE9, 0xBC, 0x93, 0x43,
+	// Bytes 1680 - 16bf
+	0xE9, 0xBC, 0x96, 0x43, 0xE9, 0xBC, 0xA0, 0x43,
+	0xE9, 0xBC, 0xBB, 0x43, 0xE9, 0xBD, 0x83, 0x43,
+	0xE9, 0xBD, 0x8A, 0x43, 0xE9, 0xBD, 0x92, 0x43,
+	0xE9, 0xBE, 0x8D, 0x43, 0xE9, 0xBE, 0x8E, 0x43,
+	0xE9, 0xBE, 0x9C, 0x43, 0xE9, 0xBE, 0x9F, 0x43,
+	0xE9, 0xBE, 0xA0, 0x43, 0xEA, 0x9C, 0xA7, 0x43,
+	0xEA, 0x9D, 0xAF, 0x43, 0xEA, 0xAC, 0xB7, 0x43,
+	0xEA, 0xAD, 0x92, 0x44, 0xF0, 0xA0, 0x84, 0xA2,
+	// Bytes 16c0 - 16ff
+	0x44, 0xF0, 0xA0, 0x94, 0x9C, 0x44, 0xF0, 0xA0,
+	0x94, 0xA5, 0x44, 0xF0, 0xA0, 0x95, 0x8B, 0x44,
+	0xF0, 0xA0, 0x98, 0xBA, 0x44, 0xF0, 0xA0, 0xA0,
+	0x84, 0x44, 0xF0, 0xA0, 0xA3, 0x9E, 0x44, 0xF0,
+	0xA0, 0xA8, 0xAC, 0x44, 0xF0, 0xA0, 0xAD, 0xA3,
+	0x44, 0xF0, 0xA1, 0x93, 0xA4, 0x44, 0xF0, 0xA1,
+	0x9A, 0xA8, 0x44, 0xF0, 0xA1, 0x9B, 0xAA, 0x44,
+	0xF0, 0xA1, 0xA7, 0x88, 0x44, 0xF0, 0xA1, 0xAC,
+	// Bytes 1700 - 173f
+	0x98, 0x44, 0xF0, 0xA1, 0xB4, 0x8B, 0x44, 0xF0,
+	0xA1, 0xB7, 0xA4, 0x44, 0xF0, 0xA1, 0xB7, 0xA6,
+	0x44, 0xF0, 0xA2, 0x86, 0x83, 0x44, 0xF0, 0xA2,
+	0x86, 0x9F, 0x44, 0xF0, 0xA2, 0x8C, 0xB1, 0x44,
+	0xF0, 0xA2, 0x9B, 0x94, 0x44, 0xF0, 0xA2, 0xA1,
+	0x84, 0x44, 0xF0, 0xA2, 0xA1, 0x8A, 0x44, 0xF0,
+	0xA2, 0xAC, 0x8C, 0x44, 0xF0, 0xA2, 0xAF, 0xB1,
+	0x44, 0xF0, 0xA3, 0x80, 0x8A, 0x44, 0xF0, 0xA3,
+	// Bytes 1740 - 177f
+	0x8A, 0xB8, 0x44, 0xF0, 0xA3, 0x8D, 0x9F, 0x44,
+	0xF0, 0xA3, 0x8E, 0x93, 0x44, 0xF0, 0xA3, 0x8E,
+	0x9C, 0x44, 0xF0, 0xA3, 0x8F, 0x83, 0x44, 0xF0,
+	0xA3, 0x8F, 0x95, 0x44, 0xF0, 0xA3, 0x91, 0xAD,
+	0x44, 0xF0, 0xA3, 0x9A, 0xA3, 0x44, 0xF0, 0xA3,
+	0xA2, 0xA7, 0x44, 0xF0, 0xA3, 0xAA, 0x8D, 0x44,
+	0xF0, 0xA3, 0xAB, 0xBA, 0x44, 0xF0, 0xA3, 0xB2,
+	0xBC, 0x44, 0xF0, 0xA3, 0xB4, 0x9E, 0x44, 0xF0,
+	// Bytes 1780 - 17bf
+	0xA3, 0xBB, 0x91, 0x44, 0xF0, 0xA3, 0xBD, 0x9E,
+	0x44, 0xF0, 0xA3, 0xBE, 0x8E, 0x44, 0xF0, 0xA4,
+	0x89, 0xA3, 0x44, 0xF0, 0xA4, 0x8B, 0xAE, 0x44,
+	0xF0, 0xA4, 0x8E, 0xAB, 0x44, 0xF0, 0xA4, 0x98,
+	0x88, 0x44, 0xF0, 0xA4, 0x9C, 0xB5, 0x44, 0xF0,
+	0xA4, 0xA0, 0x94, 0x44, 0xF0, 0xA4, 0xB0, 0xB6,
+	0x44, 0xF0, 0xA4, 0xB2, 0x92, 0x44, 0xF0, 0xA4,
+	0xBE, 0xA1, 0x44, 0xF0, 0xA4, 0xBE, 0xB8, 0x44,
+	// Bytes 17c0 - 17ff
+	0xF0, 0xA5, 0x81, 0x84, 0x44, 0xF0, 0xA5, 0x83,
+	0xB2, 0x44, 0xF0, 0xA5, 0x83, 0xB3, 0x44, 0xF0,
+	0xA5, 0x84, 0x99, 0x44, 0xF0, 0xA5, 0x84, 0xB3,
+	0x44, 0xF0, 0xA5, 0x89, 0x89, 0x44, 0xF0, 0xA5,
+	0x90, 0x9D, 0x44, 0xF0, 0xA5, 0x98, 0xA6, 0x44,
+	0xF0, 0xA5, 0x9A, 0x9A, 0x44, 0xF0, 0xA5, 0x9B,
+	0x85, 0x44, 0xF0, 0xA5, 0xA5, 0xBC, 0x44, 0xF0,
+	0xA5, 0xAA, 0xA7, 0x44, 0xF0, 0xA5, 0xAE, 0xAB,
+	// Bytes 1800 - 183f
+	0x44, 0xF0, 0xA5, 0xB2, 0x80, 0x44, 0xF0, 0xA5,
+	0xB3, 0x90, 0x44, 0xF0, 0xA5, 0xBE, 0x86, 0x44,
+	0xF0, 0xA6, 0x87, 0x9A, 0x44, 0xF0, 0xA6, 0x88,
+	0xA8, 0x44, 0xF0, 0xA6, 0x89, 0x87, 0x44, 0xF0,
+	0xA6, 0x8B, 0x99, 0x44, 0xF0, 0xA6, 0x8C, 0xBE,
+	0x44, 0xF0, 0xA6, 0x93, 0x9A, 0x44, 0xF0, 0xA6,
+	0x94, 0xA3, 0x44, 0xF0, 0xA6, 0x96, 0xA8, 0x44,
+	0xF0, 0xA6, 0x9E, 0xA7, 0x44, 0xF0, 0xA6, 0x9E,
+	// Bytes 1840 - 187f
+	0xB5, 0x44, 0xF0, 0xA6, 0xAC, 0xBC, 0x44, 0xF0,
+	0xA6, 0xB0, 0xB6, 0x44, 0xF0, 0xA6, 0xB3, 0x95,
+	0x44, 0xF0, 0xA6, 0xB5, 0xAB, 0x44, 0xF0, 0xA6,
+	0xBC, 0xAC, 0x44, 0xF0, 0xA6, 0xBE, 0xB1, 0x44,
+	0xF0, 0xA7, 0x83, 0x92, 0x44, 0xF0, 0xA7, 0x8F,
+	0x8A, 0x44, 0xF0, 0xA7, 0x99, 0xA7, 0x44, 0xF0,
+	0xA7, 0xA2, 0xAE, 0x44, 0xF0, 0xA7, 0xA5, 0xA6,
+	0x44, 0xF0, 0xA7, 0xB2, 0xA8, 0x44, 0xF0, 0xA7,
+	// Bytes 1880 - 18bf
+	0xBB, 0x93, 0x44, 0xF0, 0xA7, 0xBC, 0xAF, 0x44,
+	0xF0, 0xA8, 0x97, 0x92, 0x44, 0xF0, 0xA8, 0x97,
+	0xAD, 0x44, 0xF0, 0xA8, 0x9C, 0xAE, 0x44, 0xF0,
+	0xA8, 0xAF, 0xBA, 0x44, 0xF0, 0xA8, 0xB5, 0xB7,
+	0x44, 0xF0, 0xA9, 0x85, 0x85, 0x44, 0xF0, 0xA9,
+	0x87, 0x9F, 0x44, 0xF0, 0xA9, 0x88, 0x9A, 0x44,
+	0xF0, 0xA9, 0x90, 0x8A, 0x44, 0xF0, 0xA9, 0x92,
+	0x96, 0x44, 0xF0, 0xA9, 0x96, 0xB6, 0x44, 0xF0,
+	// Bytes 18c0 - 18ff
+	0xA9, 0xAC, 0xB0, 0x44, 0xF0, 0xAA, 0x83, 0x8E,
+	0x44, 0xF0, 0xAA, 0x84, 0x85, 0x44, 0xF0, 0xAA,
+	0x88, 0x8E, 0x44, 0xF0, 0xAA, 0x8A, 0x91, 0x44,
+	0xF0, 0xAA, 0x8E, 0x92, 0x44, 0xF0, 0xAA, 0x98,
+	0x80, 0x06, 0xE0, 0xA7, 0x87, 0xE0, 0xA6, 0xBE,
+	0x06, 0xE0, 0xA7, 0x87, 0xE0, 0xA7, 0x97, 0x06,
+	0xE0, 0xAD, 0x87, 0xE0, 0xAC, 0xBE, 0x06, 0xE0,
+	0xAD, 0x87, 0xE0, 0xAD, 0x96, 0x06, 0xE0, 0xAD,
+	// Bytes 1900 - 193f
+	0x87, 0xE0, 0xAD, 0x97, 0x06, 0xE0, 0xAE, 0x92,
+	0xE0, 0xAF, 0x97, 0x06, 0xE0, 0xAF, 0x86, 0xE0,
+	0xAE, 0xBE, 0x06, 0xE0, 0xAF, 0x86, 0xE0, 0xAF,
+	0x97, 0x06, 0xE0, 0xAF, 0x87, 0xE0, 0xAE, 0xBE,
+	0x06, 0xE0, 0xB2, 0xBF, 0xE0, 0xB3, 0x95, 0x06,
+	0xE0, 0xB3, 0x86, 0xE0, 0xB3, 0x95, 0x06, 0xE0,
+	0xB3, 0x86, 0xE0, 0xB3, 0x96, 0x06, 0xE0, 0xB5,
+	0x86, 0xE0, 0xB4, 0xBE, 0x06, 0xE0, 0xB5, 0x86,
+	// Bytes 1940 - 197f
+	0xE0, 0xB5, 0x97, 0x06, 0xE0, 0xB5, 0x87, 0xE0,
+	0xB4, 0xBE, 0x06, 0xE0, 0xB7, 0x99, 0xE0, 0xB7,
+	0x9F, 0x06, 0xE1, 0x80, 0xA5, 0xE1, 0x80, 0xAE,
+	0x06, 0xE1, 0xAC, 0x85, 0xE1, 0xAC, 0xB5, 0x06,
+	0xE1, 0xAC, 0x87, 0xE1, 0xAC, 0xB5, 0x06, 0xE1,
+	0xAC, 0x89, 0xE1, 0xAC, 0xB5, 0x06, 0xE1, 0xAC,
+	0x8B, 0xE1, 0xAC, 0xB5, 0x06, 0xE1, 0xAC, 0x8D,
+	0xE1, 0xAC, 0xB5, 0x06, 0xE1, 0xAC, 0x91, 0xE1,
+	// Bytes 1980 - 19bf
+	0xAC, 0xB5, 0x06, 0xE1, 0xAC, 0xBA, 0xE1, 0xAC,
+	0xB5, 0x06, 0xE1, 0xAC, 0xBC, 0xE1, 0xAC, 0xB5,
+	0x06, 0xE1, 0xAC, 0xBE, 0xE1, 0xAC, 0xB5, 0x06,
+	0xE1, 0xAC, 0xBF, 0xE1, 0xAC, 0xB5, 0x06, 0xE1,
+	0xAD, 0x82, 0xE1, 0xAC, 0xB5, 0x08, 0xF0, 0x91,
+	0x84, 0xB1, 0xF0, 0x91, 0x84, 0xA7, 0x08, 0xF0,
+	0x91, 0x84, 0xB2, 0xF0, 0x91, 0x84, 0xA7, 0x08,
+	0xF0, 0x91, 0x8D, 0x87, 0xF0, 0x91, 0x8C, 0xBE,
+	// Bytes 19c0 - 19ff
+	0x08, 0xF0, 0x91, 0x8D, 0x87, 0xF0, 0x91, 0x8D,
+	0x97, 0x08, 0xF0, 0x91, 0x92, 0xB9, 0xF0, 0x91,
+	0x92, 0xB0, 0x08, 0xF0, 0x91, 0x92, 0xB9, 0xF0,
+	0x91, 0x92, 0xBA, 0x08, 0xF0, 0x91, 0x92, 0xB9,
+	0xF0, 0x91, 0x92, 0xBD, 0x08, 0xF0, 0x91, 0x96,
+	0xB8, 0xF0, 0x91, 0x96, 0xAF, 0x08, 0xF0, 0x91,
+	0x96, 0xB9, 0xF0, 0x91, 0x96, 0xAF, 0x09, 0xE0,
+	0xB3, 0x86, 0xE0, 0xB3, 0x82, 0xE0, 0xB3, 0x95,
+	// Bytes 1a00 - 1a3f
+	0x42, 0x21, 0x21, 0x42, 0x21, 0x3F, 0x42, 0x2E,
+	0x2E, 0x42, 0x30, 0x2C, 0x42, 0x30, 0x2E, 0x42,
+	0x31, 0x2C, 0x42, 0x31, 0x2E, 0x42, 0x31, 0x30,
+	0x42, 0x31, 0x31, 0x42, 0x31, 0x32, 0x42, 0x31,
+	0x33, 0x42, 0x31, 0x34, 0x42, 0x31, 0x35, 0x42,
+	0x31, 0x36, 0x42, 0x31, 0x37, 0x42, 0x31, 0x38,
+	0x42, 0x31, 0x39, 0x42, 0x32, 0x2C, 0x42, 0x32,
+	0x2E, 0x42, 0x32, 0x30, 0x42, 0x32, 0x31, 0x42,
+	// Bytes 1a40 - 1a7f
+	0x32, 0x32, 0x42, 0x32, 0x33, 0x42, 0x32, 0x34,
+	0x42, 0x32, 0x35, 0x42, 0x32, 0x36, 0x42, 0x32,
+	0x37, 0x42, 0x32, 0x38, 0x42, 0x32, 0x39, 0x42,
+	0x33, 0x2C, 0x42, 0x33, 0x2E, 0x42, 0x33, 0x30,
+	0x42, 0x33, 0x31, 0x42, 0x33, 0x32, 0x42, 0x33,
+	0x33, 0x42, 0x33, 0x34, 0x42, 0x33, 0x35, 0x42,
+	0x33, 0x36, 0x42, 0x33, 0x37, 0x42, 0x33, 0x38,
+	0x42, 0x33, 0x39, 0x42, 0x34, 0x2C, 0x42, 0x34,
+	// Bytes 1a80 - 1abf
+	0x2E, 0x42, 0x34, 0x30, 0x42, 0x34, 0x31, 0x42,
+	0x34, 0x32, 0x42, 0x34, 0x33, 0x42, 0x34, 0x34,
+	0x42, 0x34, 0x35, 0x42, 0x34, 0x36, 0x42, 0x34,
+	0x37, 0x42, 0x34, 0x38, 0x42, 0x34, 0x39, 0x42,
+	0x35, 0x2C, 0x42, 0x35, 0x2E, 0x42, 0x35, 0x30,
+	0x42, 0x36, 0x2C, 0x42, 0x36, 0x2E, 0x42, 0x37,
+	0x2C, 0x42, 0x37, 0x2E, 0x42, 0x38, 0x2C, 0x42,
+	0x38, 0x2E, 0x42, 0x39, 0x2C, 0x42, 0x39, 0x2E,
+	// Bytes 1ac0 - 1aff
+	0x42, 0x3D, 0x3D, 0x42, 0x3F, 0x21, 0x42, 0x3F,
+	0x3F, 0x42, 0x41, 0x55, 0x42, 0x42, 0x71, 0x42,
+	0x43, 0x44, 0x42, 0x44, 0x4A, 0x42, 0x44, 0x5A,
+	0x42, 0x44, 0x7A, 0x42, 0x47, 0x42, 0x42, 0x47,
+	0x79, 0x42, 0x48, 0x50, 0x42, 0x48, 0x56, 0x42,
+	0x48, 0x67, 0x42, 0x48, 0x7A, 0x42, 0x49, 0x49,
+	0x42, 0x49, 0x4A, 0x42, 0x49, 0x55, 0x42, 0x49,
+	0x56, 0x42, 0x49, 0x58, 0x42, 0x4B, 0x42, 0x42,
+	// Bytes 1b00 - 1b3f
+	0x4B, 0x4B, 0x42, 0x4B, 0x4D, 0x42, 0x4C, 0x4A,
+	0x42, 0x4C, 0x6A, 0x42, 0x4D, 0x42, 0x42, 0x4D,
+	0x43, 0x42, 0x4D, 0x44, 0x42, 0x4D, 0x56, 0x42,
+	0x4D, 0x57, 0x42, 0x4E, 0x4A, 0x42, 0x4E, 0x6A,
+	0x42, 0x4E, 0x6F, 0x42, 0x50, 0x48, 0x42, 0x50,
+	0x52, 0x42, 0x50, 0x61, 0x42, 0x52, 0x73, 0x42,
+	0x53, 0x44, 0x42, 0x53, 0x4D, 0x42, 0x53, 0x53,
+	0x42, 0x53, 0x76, 0x42, 0x54, 0x4D, 0x42, 0x56,
+	// Bytes 1b40 - 1b7f
+	0x49, 0x42, 0x57, 0x43, 0x42, 0x57, 0x5A, 0x42,
+	0x57, 0x62, 0x42, 0x58, 0x49, 0x42, 0x63, 0x63,
+	0x42, 0x63, 0x64, 0x42, 0x63, 0x6D, 0x42, 0x64,
+	0x42, 0x42, 0x64, 0x61, 0x42, 0x64, 0x6C, 0x42,
+	0x64, 0x6D, 0x42, 0x64, 0x7A, 0x42, 0x65, 0x56,
+	0x42, 0x66, 0x66, 0x42, 0x66, 0x69, 0x42, 0x66,
+	0x6C, 0x42, 0x66, 0x6D, 0x42, 0x68, 0x61, 0x42,
+	0x69, 0x69, 0x42, 0x69, 0x6A, 0x42, 0x69, 0x6E,
+	// Bytes 1b80 - 1bbf
+	0x42, 0x69, 0x76, 0x42, 0x69, 0x78, 0x42, 0x6B,
+	0x41, 0x42, 0x6B, 0x56, 0x42, 0x6B, 0x57, 0x42,
+	0x6B, 0x67, 0x42, 0x6B, 0x6C, 0x42, 0x6B, 0x6D,
+	0x42, 0x6B, 0x74, 0x42, 0x6C, 0x6A, 0x42, 0x6C,
+	0x6D, 0x42, 0x6C, 0x6E, 0x42, 0x6C, 0x78, 0x42,
+	0x6D, 0x32, 0x42, 0x6D, 0x33, 0x42, 0x6D, 0x41,
+	0x42, 0x6D, 0x56, 0x42, 0x6D, 0x57, 0x42, 0x6D,
+	0x62, 0x42, 0x6D, 0x67, 0x42, 0x6D, 0x6C, 0x42,
+	// Bytes 1bc0 - 1bff
+	0x6D, 0x6D, 0x42, 0x6D, 0x73, 0x42, 0x6E, 0x41,
+	0x42, 0x6E, 0x46, 0x42, 0x6E, 0x56, 0x42, 0x6E,
+	0x57, 0x42, 0x6E, 0x6A, 0x42, 0x6E, 0x6D, 0x42,
+	0x6E, 0x73, 0x42, 0x6F, 0x56, 0x42, 0x70, 0x41,
+	0x42, 0x70, 0x46, 0x42, 0x70, 0x56, 0x42, 0x70,
+	0x57, 0x42, 0x70, 0x63, 0x42, 0x70, 0x73, 0x42,
+	0x73, 0x72, 0x42, 0x73, 0x74, 0x42, 0x76, 0x69,
+	0x42, 0x78, 0x69, 0x43, 0x28, 0x31, 0x29, 0x43,
+	// Bytes 1c00 - 1c3f
+	0x28, 0x32, 0x29, 0x43, 0x28, 0x33, 0x29, 0x43,
+	0x28, 0x34, 0x29, 0x43, 0x28, 0x35, 0x29, 0x43,
+	0x28, 0x36, 0x29, 0x43, 0x28, 0x37, 0x29, 0x43,
+	0x28, 0x38, 0x29, 0x43, 0x28, 0x39, 0x29, 0x43,
+	0x28, 0x41, 0x29, 0x43, 0x28, 0x42, 0x29, 0x43,
+	0x28, 0x43, 0x29, 0x43, 0x28, 0x44, 0x29, 0x43,
+	0x28, 0x45, 0x29, 0x43, 0x28, 0x46, 0x29, 0x43,
+	0x28, 0x47, 0x29, 0x43, 0x28, 0x48, 0x29, 0x43,
+	// Bytes 1c40 - 1c7f
+	0x28, 0x49, 0x29, 0x43, 0x28, 0x4A, 0x29, 0x43,
+	0x28, 0x4B, 0x29, 0x43, 0x28, 0x4C, 0x29, 0x43,
+	0x28, 0x4D, 0x29, 0x43, 0x28, 0x4E, 0x29, 0x43,
+	0x28, 0x4F, 0x29, 0x43, 0x28, 0x50, 0x29, 0x43,
+	0x28, 0x51, 0x29, 0x43, 0x28, 0x52, 0x29, 0x43,
+	0x28, 0x53, 0x29, 0x43, 0x28, 0x54, 0x29, 0x43,
+	0x28, 0x55, 0x29, 0x43, 0x28, 0x56, 0x29, 0x43,
+	0x28, 0x57, 0x29, 0x43, 0x28, 0x58, 0x29, 0x43,
+	// Bytes 1c80 - 1cbf
+	0x28, 0x59, 0x29, 0x43, 0x28, 0x5A, 0x29, 0x43,
+	0x28, 0x61, 0x29, 0x43, 0x28, 0x62, 0x29, 0x43,
+	0x28, 0x63, 0x29, 0x43, 0x28, 0x64, 0x29, 0x43,
+	0x28, 0x65, 0x29, 0x43, 0x28, 0x66, 0x29, 0x43,
+	0x28, 0x67, 0x29, 0x43, 0x28, 0x68, 0x29, 0x43,
+	0x28, 0x69, 0x29, 0x43, 0x28, 0x6A, 0x29, 0x43,
+	0x28, 0x6B, 0x29, 0x43, 0x28, 0x6C, 0x29, 0x43,
+	0x28, 0x6D, 0x29, 0x43, 0x28, 0x6E, 0x29, 0x43,
+	// Bytes 1cc0 - 1cff
+	0x28, 0x6F, 0x29, 0x43, 0x28, 0x70, 0x29, 0x43,
+	0x28, 0x71, 0x29, 0x43, 0x28, 0x72, 0x29, 0x43,
+	0x28, 0x73, 0x29, 0x43, 0x28, 0x74, 0x29, 0x43,
+	0x28, 0x75, 0x29, 0x43, 0x28, 0x76, 0x29, 0x43,
+	0x28, 0x77, 0x29, 0x43, 0x28, 0x78, 0x29, 0x43,
+	0x28, 0x79, 0x29, 0x43, 0x28, 0x7A, 0x29, 0x43,
+	0x2E, 0x2E, 0x2E, 0x43, 0x31, 0x30, 0x2E, 0x43,
+	0x31, 0x31, 0x2E, 0x43, 0x31, 0x32, 0x2E, 0x43,
+	// Bytes 1d00 - 1d3f
+	0x31, 0x33, 0x2E, 0x43, 0x31, 0x34, 0x2E, 0x43,
+	0x31, 0x35, 0x2E, 0x43, 0x31, 0x36, 0x2E, 0x43,
+	0x31, 0x37, 0x2E, 0x43, 0x31, 0x38, 0x2E, 0x43,
+	0x31, 0x39, 0x2E, 0x43, 0x32, 0x30, 0x2E, 0x43,
+	0x3A, 0x3A, 0x3D, 0x43, 0x3D, 0x3D, 0x3D, 0x43,
+	0x43, 0x6F, 0x2E, 0x43, 0x46, 0x41, 0x58, 0x43,
+	0x47, 0x48, 0x7A, 0x43, 0x47, 0x50, 0x61, 0x43,
+	0x49, 0x49, 0x49, 0x43, 0x4C, 0x54, 0x44, 0x43,
+	// Bytes 1d40 - 1d7f
+	0x4C, 0xC2, 0xB7, 0x43, 0x4D, 0x48, 0x7A, 0x43,
+	0x4D, 0x50, 0x61, 0x43, 0x4D, 0xCE, 0xA9, 0x43,
+	0x50, 0x50, 0x4D, 0x43, 0x50, 0x50, 0x56, 0x43,
+	0x50, 0x54, 0x45, 0x43, 0x54, 0x45, 0x4C, 0x43,
+	0x54, 0x48, 0x7A, 0x43, 0x56, 0x49, 0x49, 0x43,
+	0x58, 0x49, 0x49, 0x43, 0x61, 0x2F, 0x63, 0x43,
+	0x61, 0x2F, 0x73, 0x43, 0x61, 0xCA, 0xBE, 0x43,
+	0x62, 0x61, 0x72, 0x43, 0x63, 0x2F, 0x6F, 0x43,
+	// Bytes 1d80 - 1dbf
+	0x63, 0x2F, 0x75, 0x43, 0x63, 0x61, 0x6C, 0x43,
+	0x63, 0x6D, 0x32, 0x43, 0x63, 0x6D, 0x33, 0x43,
+	0x64, 0x6D, 0x32, 0x43, 0x64, 0x6D, 0x33, 0x43,
+	0x65, 0x72, 0x67, 0x43, 0x66, 0x66, 0x69, 0x43,
+	0x66, 0x66, 0x6C, 0x43, 0x67, 0x61, 0x6C, 0x43,
+	0x68, 0x50, 0x61, 0x43, 0x69, 0x69, 0x69, 0x43,
+	0x6B, 0x48, 0x7A, 0x43, 0x6B, 0x50, 0x61, 0x43,
+	0x6B, 0x6D, 0x32, 0x43, 0x6B, 0x6D, 0x33, 0x43,
+	// Bytes 1dc0 - 1dff
+	0x6B, 0xCE, 0xA9, 0x43, 0x6C, 0x6F, 0x67, 0x43,
+	0x6C, 0xC2, 0xB7, 0x43, 0x6D, 0x69, 0x6C, 0x43,
+	0x6D, 0x6D, 0x32, 0x43, 0x6D, 0x6D, 0x33, 0x43,
+	0x6D, 0x6F, 0x6C, 0x43, 0x72, 0x61, 0x64, 0x43,
+	0x76, 0x69, 0x69, 0x43, 0x78, 0x69, 0x69, 0x43,
+	0xC2, 0xB0, 0x43, 0x43, 0xC2, 0xB0, 0x46, 0x43,
+	0xCA, 0xBC, 0x6E, 0x43, 0xCE, 0xBC, 0x41, 0x43,
+	0xCE, 0xBC, 0x46, 0x43, 0xCE, 0xBC, 0x56, 0x43,
+	// Bytes 1e00 - 1e3f
+	0xCE, 0xBC, 0x57, 0x43, 0xCE, 0xBC, 0x67, 0x43,
+	0xCE, 0xBC, 0x6C, 0x43, 0xCE, 0xBC, 0x6D, 0x43,
+	0xCE, 0xBC, 0x73, 0x44, 0x28, 0x31, 0x30, 0x29,
+	0x44, 0x28, 0x31, 0x31, 0x29, 0x44, 0x28, 0x31,
+	0x32, 0x29, 0x44, 0x28, 0x31, 0x33, 0x29, 0x44,
+	0x28, 0x31, 0x34, 0x29, 0x44, 0x28, 0x31, 0x35,
+	0x29, 0x44, 0x28, 0x31, 0x36, 0x29, 0x44, 0x28,
+	0x31, 0x37, 0x29, 0x44, 0x28, 0x31, 0x38, 0x29,
+	// Bytes 1e40 - 1e7f
+	0x44, 0x28, 0x31, 0x39, 0x29, 0x44, 0x28, 0x32,
+	0x30, 0x29, 0x44, 0x30, 0xE7, 0x82, 0xB9, 0x44,
+	0x31, 0xE2, 0x81, 0x84, 0x44, 0x31, 0xE6, 0x97,
+	0xA5, 0x44, 0x31, 0xE6, 0x9C, 0x88, 0x44, 0x31,
+	0xE7, 0x82, 0xB9, 0x44, 0x32, 0xE6, 0x97, 0xA5,
+	0x44, 0x32, 0xE6, 0x9C, 0x88, 0x44, 0x32, 0xE7,
+	0x82, 0xB9, 0x44, 0x33, 0xE6, 0x97, 0xA5, 0x44,
+	0x33, 0xE6, 0x9C, 0x88, 0x44, 0x33, 0xE7, 0x82,
+	// Bytes 1e80 - 1ebf
+	0xB9, 0x44, 0x34, 0xE6, 0x97, 0xA5, 0x44, 0x34,
+	0xE6, 0x9C, 0x88, 0x44, 0x34, 0xE7, 0x82, 0xB9,
+	0x44, 0x35, 0xE6, 0x97, 0xA5, 0x44, 0x35, 0xE6,
+	0x9C, 0x88, 0x44, 0x35, 0xE7, 0x82, 0xB9, 0x44,
+	0x36, 0xE6, 0x97, 0xA5, 0x44, 0x36, 0xE6, 0x9C,
+	0x88, 0x44, 0x36, 0xE7, 0x82, 0xB9, 0x44, 0x37,
+	0xE6, 0x97, 0xA5, 0x44, 0x37, 0xE6, 0x9C, 0x88,
+	0x44, 0x37, 0xE7, 0x82, 0xB9, 0x44, 0x38, 0xE6,
+	// Bytes 1ec0 - 1eff
+	0x97, 0xA5, 0x44, 0x38, 0xE6, 0x9C, 0x88, 0x44,
+	0x38, 0xE7, 0x82, 0xB9, 0x44, 0x39, 0xE6, 0x97,
+	0xA5, 0x44, 0x39, 0xE6, 0x9C, 0x88, 0x44, 0x39,
+	0xE7, 0x82, 0xB9, 0x44, 0x56, 0x49, 0x49, 0x49,
+	0x44, 0x61, 0x2E, 0x6D, 0x2E, 0x44, 0x6B, 0x63,
+	0x61, 0x6C, 0x44, 0x70, 0x2E, 0x6D, 0x2E, 0x44,
+	0x76, 0x69, 0x69, 0x69, 0x44, 0xD5, 0xA5, 0xD6,
+	0x82, 0x44, 0xD5, 0xB4, 0xD5, 0xA5, 0x44, 0xD5,
+	// Bytes 1f00 - 1f3f
+	0xB4, 0xD5, 0xAB, 0x44, 0xD5, 0xB4, 0xD5, 0xAD,
+	0x44, 0xD5, 0xB4, 0xD5, 0xB6, 0x44, 0xD5, 0xBE,
+	0xD5, 0xB6, 0x44, 0xD7, 0x90, 0xD7, 0x9C, 0x44,
+	0xD8, 0xA7, 0xD9, 0xB4, 0x44, 0xD8, 0xA8, 0xD8,
+	0xAC, 0x44, 0xD8, 0xA8, 0xD8, 0xAD, 0x44, 0xD8,
+	0xA8, 0xD8, 0xAE, 0x44, 0xD8, 0xA8, 0xD8, 0xB1,
+	0x44, 0xD8, 0xA8, 0xD8, 0xB2, 0x44, 0xD8, 0xA8,
+	0xD9, 0x85, 0x44, 0xD8, 0xA8, 0xD9, 0x86, 0x44,
+	// Bytes 1f40 - 1f7f
+	0xD8, 0xA8, 0xD9, 0x87, 0x44, 0xD8, 0xA8, 0xD9,
+	0x89, 0x44, 0xD8, 0xA8, 0xD9, 0x8A, 0x44, 0xD8,
+	0xAA, 0xD8, 0xAC, 0x44, 0xD8, 0xAA, 0xD8, 0xAD,
+	0x44, 0xD8, 0xAA, 0xD8, 0xAE, 0x44, 0xD8, 0xAA,
+	0xD8, 0xB1, 0x44, 0xD8, 0xAA, 0xD8, 0xB2, 0x44,
+	0xD8, 0xAA, 0xD9, 0x85, 0x44, 0xD8, 0xAA, 0xD9,
+	0x86, 0x44, 0xD8, 0xAA, 0xD9, 0x87, 0x44, 0xD8,
+	0xAA, 0xD9, 0x89, 0x44, 0xD8, 0xAA, 0xD9, 0x8A,
+	// Bytes 1f80 - 1fbf
+	0x44, 0xD8, 0xAB, 0xD8, 0xAC, 0x44, 0xD8, 0xAB,
+	0xD8, 0xB1, 0x44, 0xD8, 0xAB, 0xD8, 0xB2, 0x44,
+	0xD8, 0xAB, 0xD9, 0x85, 0x44, 0xD8, 0xAB, 0xD9,
+	0x86, 0x44, 0xD8, 0xAB, 0xD9, 0x87, 0x44, 0xD8,
+	0xAB, 0xD9, 0x89, 0x44, 0xD8, 0xAB, 0xD9, 0x8A,
+	0x44, 0xD8, 0xAC, 0xD8, 0xAD, 0x44, 0xD8, 0xAC,
+	0xD9, 0x85, 0x44, 0xD8, 0xAC, 0xD9, 0x89, 0x44,
+	0xD8, 0xAC, 0xD9, 0x8A, 0x44, 0xD8, 0xAD, 0xD8,
+	// Bytes 1fc0 - 1fff
+	0xAC, 0x44, 0xD8, 0xAD, 0xD9, 0x85, 0x44, 0xD8,
+	0xAD, 0xD9, 0x89, 0x44, 0xD8, 0xAD, 0xD9, 0x8A,
+	0x44, 0xD8, 0xAE, 0xD8, 0xAC, 0x44, 0xD8, 0xAE,
+	0xD8, 0xAD, 0x44, 0xD8, 0xAE, 0xD9, 0x85, 0x44,
+	0xD8, 0xAE, 0xD9, 0x89, 0x44, 0xD8, 0xAE, 0xD9,
+	0x8A, 0x44, 0xD8, 0xB3, 0xD8, 0xAC, 0x44, 0xD8,
+	0xB3, 0xD8, 0xAD, 0x44, 0xD8, 0xB3, 0xD8, 0xAE,
+	0x44, 0xD8, 0xB3, 0xD8, 0xB1, 0x44, 0xD8, 0xB3,
+	// Bytes 2000 - 203f
+	0xD9, 0x85, 0x44, 0xD8, 0xB3, 0xD9, 0x87, 0x44,
+	0xD8, 0xB3, 0xD9, 0x89, 0x44, 0xD8, 0xB3, 0xD9,
+	0x8A, 0x44, 0xD8, 0xB4, 0xD8, 0xAC, 0x44, 0xD8,
+	0xB4, 0xD8, 0xAD, 0x44, 0xD8, 0xB4, 0xD8, 0xAE,
+	0x44, 0xD8, 0xB4, 0xD8, 0xB1, 0x44, 0xD8, 0xB4,
+	0xD9, 0x85, 0x44, 0xD8, 0xB4, 0xD9, 0x87, 0x44,
+	0xD8, 0xB4, 0xD9, 0x89, 0x44, 0xD8, 0xB4, 0xD9,
+	0x8A, 0x44, 0xD8, 0xB5, 0xD8, 0xAD, 0x44, 0xD8,
+	// Bytes 2040 - 207f
+	0xB5, 0xD8, 0xAE, 0x44, 0xD8, 0xB5, 0xD8, 0xB1,
+	0x44, 0xD8, 0xB5, 0xD9, 0x85, 0x44, 0xD8, 0xB5,
+	0xD9, 0x89, 0x44, 0xD8, 0xB5, 0xD9, 0x8A, 0x44,
+	0xD8, 0xB6, 0xD8, 0xAC, 0x44, 0xD8, 0xB6, 0xD8,
+	0xAD, 0x44, 0xD8, 0xB6, 0xD8, 0xAE, 0x44, 0xD8,
+	0xB6, 0xD8, 0xB1, 0x44, 0xD8, 0xB6, 0xD9, 0x85,
+	0x44, 0xD8, 0xB6, 0xD9, 0x89, 0x44, 0xD8, 0xB6,
+	0xD9, 0x8A, 0x44, 0xD8, 0xB7, 0xD8, 0xAD, 0x44,
+	// Bytes 2080 - 20bf
+	0xD8, 0xB7, 0xD9, 0x85, 0x44, 0xD8, 0xB7, 0xD9,
+	0x89, 0x44, 0xD8, 0xB7, 0xD9, 0x8A, 0x44, 0xD8,
+	0xB8, 0xD9, 0x85, 0x44, 0xD8, 0xB9, 0xD8, 0xAC,
+	0x44, 0xD8, 0xB9, 0xD9, 0x85, 0x44, 0xD8, 0xB9,
+	0xD9, 0x89, 0x44, 0xD8, 0xB9, 0xD9, 0x8A, 0x44,
+	0xD8, 0xBA, 0xD8, 0xAC, 0x44, 0xD8, 0xBA, 0xD9,
+	0x85, 0x44, 0xD8, 0xBA, 0xD9, 0x89, 0x44, 0xD8,
+	0xBA, 0xD9, 0x8A, 0x44, 0xD9, 0x81, 0xD8, 0xAC,
+	// Bytes 20c0 - 20ff
+	0x44, 0xD9, 0x81, 0xD8, 0xAD, 0x44, 0xD9, 0x81,
+	0xD8, 0xAE, 0x44, 0xD9, 0x81, 0xD9, 0x85, 0x44,
+	0xD9, 0x81, 0xD9, 0x89, 0x44, 0xD9, 0x81, 0xD9,
+	0x8A, 0x44, 0xD9, 0x82, 0xD8, 0xAD, 0x44, 0xD9,
+	0x82, 0xD9, 0x85, 0x44, 0xD9, 0x82, 0xD9, 0x89,
+	0x44, 0xD9, 0x82, 0xD9, 0x8A, 0x44, 0xD9, 0x83,
+	0xD8, 0xA7, 0x44, 0xD9, 0x83, 0xD8, 0xAC, 0x44,
+	0xD9, 0x83, 0xD8, 0xAD, 0x44, 0xD9, 0x83, 0xD8,
+	// Bytes 2100 - 213f
+	0xAE, 0x44, 0xD9, 0x83, 0xD9, 0x84, 0x44, 0xD9,
+	0x83, 0xD9, 0x85, 0x44, 0xD9, 0x83, 0xD9, 0x89,
+	0x44, 0xD9, 0x83, 0xD9, 0x8A, 0x44, 0xD9, 0x84,
+	0xD8, 0xA7, 0x44, 0xD9, 0x84, 0xD8, 0xAC, 0x44,
+	0xD9, 0x84, 0xD8, 0xAD, 0x44, 0xD9, 0x84, 0xD8,
+	0xAE, 0x44, 0xD9, 0x84, 0xD9, 0x85, 0x44, 0xD9,
+	0x84, 0xD9, 0x87, 0x44, 0xD9, 0x84, 0xD9, 0x89,
+	0x44, 0xD9, 0x84, 0xD9, 0x8A, 0x44, 0xD9, 0x85,
+	// Bytes 2140 - 217f
+	0xD8, 0xA7, 0x44, 0xD9, 0x85, 0xD8, 0xAC, 0x44,
+	0xD9, 0x85, 0xD8, 0xAD, 0x44, 0xD9, 0x85, 0xD8,
+	0xAE, 0x44, 0xD9, 0x85, 0xD9, 0x85, 0x44, 0xD9,
+	0x85, 0xD9, 0x89, 0x44, 0xD9, 0x85, 0xD9, 0x8A,
+	0x44, 0xD9, 0x86, 0xD8, 0xAC, 0x44, 0xD9, 0x86,
+	0xD8, 0xAD, 0x44, 0xD9, 0x86, 0xD8, 0xAE, 0x44,
+	0xD9, 0x86, 0xD8, 0xB1, 0x44, 0xD9, 0x86, 0xD8,
+	0xB2, 0x44, 0xD9, 0x86, 0xD9, 0x85, 0x44, 0xD9,
+	// Bytes 2180 - 21bf
+	0x86, 0xD9, 0x86, 0x44, 0xD9, 0x86, 0xD9, 0x87,
+	0x44, 0xD9, 0x86, 0xD9, 0x89, 0x44, 0xD9, 0x86,
+	0xD9, 0x8A, 0x44, 0xD9, 0x87, 0xD8, 0xAC, 0x44,
+	0xD9, 0x87, 0xD9, 0x85, 0x44, 0xD9, 0x87, 0xD9,
+	0x89, 0x44, 0xD9, 0x87, 0xD9, 0x8A, 0x44, 0xD9,
+	0x88, 0xD9, 0xB4, 0x44, 0xD9, 0x8A, 0xD8, 0xAC,
+	0x44, 0xD9, 0x8A, 0xD8, 0xAD, 0x44, 0xD9, 0x8A,
+	0xD8, 0xAE, 0x44, 0xD9, 0x8A, 0xD8, 0xB1, 0x44,
+	// Bytes 21c0 - 21ff
+	0xD9, 0x8A, 0xD8, 0xB2, 0x44, 0xD9, 0x8A, 0xD9,
+	0x85, 0x44, 0xD9, 0x8A, 0xD9, 0x86, 0x44, 0xD9,
+	0x8A, 0xD9, 0x87, 0x44, 0xD9, 0x8A, 0xD9, 0x89,
+	0x44, 0xD9, 0x8A, 0xD9, 0x8A, 0x44, 0xD9, 0x8A,
+	0xD9, 0xB4, 0x44, 0xDB, 0x87, 0xD9, 0xB4, 0x45,
+	0x28, 0xE1, 0x84, 0x80, 0x29, 0x45, 0x28, 0xE1,
+	0x84, 0x82, 0x29, 0x45, 0x28, 0xE1, 0x84, 0x83,
+	0x29, 0x45, 0x28, 0xE1, 0x84, 0x85, 0x29, 0x45,
+	// Bytes 2200 - 223f
+	0x28, 0xE1, 0x84, 0x86, 0x29, 0x45, 0x28, 0xE1,
+	0x84, 0x87, 0x29, 0x45, 0x28, 0xE1, 0x84, 0x89,
+	0x29, 0x45, 0x28, 0xE1, 0x84, 0x8B, 0x29, 0x45,
+	0x28, 0xE1, 0x84, 0x8C, 0x29, 0x45, 0x28, 0xE1,
+	0x84, 0x8E, 0x29, 0x45, 0x28, 0xE1, 0x84, 0x8F,
+	0x29, 0x45, 0x28, 0xE1, 0x84, 0x90, 0x29, 0x45,
+	0x28, 0xE1, 0x84, 0x91, 0x29, 0x45, 0x28, 0xE1,
+	0x84, 0x92, 0x29, 0x45, 0x28, 0xE4, 0xB8, 0x80,
+	// Bytes 2240 - 227f
+	0x29, 0x45, 0x28, 0xE4, 0xB8, 0x83, 0x29, 0x45,
+	0x28, 0xE4, 0xB8, 0x89, 0x29, 0x45, 0x28, 0xE4,
+	0xB9, 0x9D, 0x29, 0x45, 0x28, 0xE4, 0xBA, 0x8C,
+	0x29, 0x45, 0x28, 0xE4, 0xBA, 0x94, 0x29, 0x45,
+	0x28, 0xE4, 0xBB, 0xA3, 0x29, 0x45, 0x28, 0xE4,
+	0xBC, 0x81, 0x29, 0x45, 0x28, 0xE4, 0xBC, 0x91,
+	0x29, 0x45, 0x28, 0xE5, 0x85, 0xAB, 0x29, 0x45,
+	0x28, 0xE5, 0x85, 0xAD, 0x29, 0x45, 0x28, 0xE5,
+	// Bytes 2280 - 22bf
+	0x8A, 0xB4, 0x29, 0x45, 0x28, 0xE5, 0x8D, 0x81,
+	0x29, 0x45, 0x28, 0xE5, 0x8D, 0x94, 0x29, 0x45,
+	0x28, 0xE5, 0x90, 0x8D, 0x29, 0x45, 0x28, 0xE5,
+	0x91, 0xBC, 0x29, 0x45, 0x28, 0xE5, 0x9B, 0x9B,
+	0x29, 0x45, 0x28, 0xE5, 0x9C, 0x9F, 0x29, 0x45,
+	0x28, 0xE5, 0xAD, 0xA6, 0x29, 0x45, 0x28, 0xE6,
+	0x97, 0xA5, 0x29, 0x45, 0x28, 0xE6, 0x9C, 0x88,
+	0x29, 0x45, 0x28, 0xE6, 0x9C, 0x89, 0x29, 0x45,
+	// Bytes 22c0 - 22ff
+	0x28, 0xE6, 0x9C, 0xA8, 0x29, 0x45, 0x28, 0xE6,
+	0xA0, 0xAA, 0x29, 0x45, 0x28, 0xE6, 0xB0, 0xB4,
+	0x29, 0x45, 0x28, 0xE7, 0x81, 0xAB, 0x29, 0x45,
+	0x28, 0xE7, 0x89, 0xB9, 0x29, 0x45, 0x28, 0xE7,
+	0x9B, 0xA3, 0x29, 0x45, 0x28, 0xE7, 0xA4, 0xBE,
+	0x29, 0x45, 0x28, 0xE7, 0xA5, 0x9D, 0x29, 0x45,
+	0x28, 0xE7, 0xA5, 0xAD, 0x29, 0x45, 0x28, 0xE8,
+	0x87, 0xAA, 0x29, 0x45, 0x28, 0xE8, 0x87, 0xB3,
+	// Bytes 2300 - 233f
+	0x29, 0x45, 0x28, 0xE8, 0xB2, 0xA1, 0x29, 0x45,
+	0x28, 0xE8, 0xB3, 0x87, 0x29, 0x45, 0x28, 0xE9,
+	0x87, 0x91, 0x29, 0x45, 0x30, 0xE2, 0x81, 0x84,
+	0x33, 0x45, 0x31, 0x30, 0xE6, 0x97, 0xA5, 0x45,
+	0x31, 0x30, 0xE6, 0x9C, 0x88, 0x45, 0x31, 0x30,
+	0xE7, 0x82, 0xB9, 0x45, 0x31, 0x31, 0xE6, 0x97,
+	0xA5, 0x45, 0x31, 0x31, 0xE6, 0x9C, 0x88, 0x45,
+	0x31, 0x31, 0xE7, 0x82, 0xB9, 0x45, 0x31, 0x32,
+	// Bytes 2340 - 237f
+	0xE6, 0x97, 0xA5, 0x45, 0x31, 0x32, 0xE6, 0x9C,
+	0x88, 0x45, 0x31, 0x32, 0xE7, 0x82, 0xB9, 0x45,
+	0x31, 0x33, 0xE6, 0x97, 0xA5, 0x45, 0x31, 0x33,
+	0xE7, 0x82, 0xB9, 0x45, 0x31, 0x34, 0xE6, 0x97,
+	0xA5, 0x45, 0x31, 0x34, 0xE7, 0x82, 0xB9, 0x45,
+	0x31, 0x35, 0xE6, 0x97, 0xA5, 0x45, 0x31, 0x35,
+	0xE7, 0x82, 0xB9, 0x45, 0x31, 0x36, 0xE6, 0x97,
+	0xA5, 0x45, 0x31, 0x36, 0xE7, 0x82, 0xB9, 0x45,
+	// Bytes 2380 - 23bf
+	0x31, 0x37, 0xE6, 0x97, 0xA5, 0x45, 0x31, 0x37,
+	0xE7, 0x82, 0xB9, 0x45, 0x31, 0x38, 0xE6, 0x97,
+	0xA5, 0x45, 0x31, 0x38, 0xE7, 0x82, 0xB9, 0x45,
+	0x31, 0x39, 0xE6, 0x97, 0xA5, 0x45, 0x31, 0x39,
+	0xE7, 0x82, 0xB9, 0x45, 0x31, 0xE2, 0x81, 0x84,
+	0x32, 0x45, 0x31, 0xE2, 0x81, 0x84, 0x33, 0x45,
+	0x31, 0xE2, 0x81, 0x84, 0x34, 0x45, 0x31, 0xE2,
+	0x81, 0x84, 0x35, 0x45, 0x31, 0xE2, 0x81, 0x84,
+	// Bytes 23c0 - 23ff
+	0x36, 0x45, 0x31, 0xE2, 0x81, 0x84, 0x37, 0x45,
+	0x31, 0xE2, 0x81, 0x84, 0x38, 0x45, 0x31, 0xE2,
+	0x81, 0x84, 0x39, 0x45, 0x32, 0x30, 0xE6, 0x97,
+	0xA5, 0x45, 0x32, 0x30, 0xE7, 0x82, 0xB9, 0x45,
+	0x32, 0x31, 0xE6, 0x97, 0xA5, 0x45, 0x32, 0x31,
+	0xE7, 0x82, 0xB9, 0x45, 0x32, 0x32, 0xE6, 0x97,
+	0xA5, 0x45, 0x32, 0x32, 0xE7, 0x82, 0xB9, 0x45,
+	0x32, 0x33, 0xE6, 0x97, 0xA5, 0x45, 0x32, 0x33,
+	// Bytes 2400 - 243f
+	0xE7, 0x82, 0xB9, 0x45, 0x32, 0x34, 0xE6, 0x97,
+	0xA5, 0x45, 0x32, 0x34, 0xE7, 0x82, 0xB9, 0x45,
+	0x32, 0x35, 0xE6, 0x97, 0xA5, 0x45, 0x32, 0x36,
+	0xE6, 0x97, 0xA5, 0x45, 0x32, 0x37, 0xE6, 0x97,
+	0xA5, 0x45, 0x32, 0x38, 0xE6, 0x97, 0xA5, 0x45,
+	0x32, 0x39, 0xE6, 0x97, 0xA5, 0x45, 0x32, 0xE2,
+	0x81, 0x84, 0x33, 0x45, 0x32, 0xE2, 0x81, 0x84,
+	0x35, 0x45, 0x33, 0x30, 0xE6, 0x97, 0xA5, 0x45,
+	// Bytes 2440 - 247f
+	0x33, 0x31, 0xE6, 0x97, 0xA5, 0x45, 0x33, 0xE2,
+	0x81, 0x84, 0x34, 0x45, 0x33, 0xE2, 0x81, 0x84,
+	0x35, 0x45, 0x33, 0xE2, 0x81, 0x84, 0x38, 0x45,
+	0x34, 0xE2, 0x81, 0x84, 0x35, 0x45, 0x35, 0xE2,
+	0x81, 0x84, 0x36, 0x45, 0x35, 0xE2, 0x81, 0x84,
+	0x38, 0x45, 0x37, 0xE2, 0x81, 0x84, 0x38, 0x45,
+	0x41, 0xE2, 0x88, 0x95, 0x6D, 0x45, 0x56, 0xE2,
+	0x88, 0x95, 0x6D, 0x45, 0x6D, 0xE2, 0x88, 0x95,
+	// Bytes 2480 - 24bf
+	0x73, 0x46, 0x31, 0xE2, 0x81, 0x84, 0x31, 0x30,
+	0x46, 0x43, 0xE2, 0x88, 0x95, 0x6B, 0x67, 0x46,
+	0x6D, 0xE2, 0x88, 0x95, 0x73, 0x32, 0x46, 0xD8,
+	0xA8, 0xD8, 0xAD, 0xD9, 0x8A, 0x46, 0xD8, 0xA8,
+	0xD8, 0xAE, 0xD9, 0x8A, 0x46, 0xD8, 0xAA, 0xD8,
+	0xAC, 0xD9, 0x85, 0x46, 0xD8, 0xAA, 0xD8, 0xAC,
+	0xD9, 0x89, 0x46, 0xD8, 0xAA, 0xD8, 0xAC, 0xD9,
+	0x8A, 0x46, 0xD8, 0xAA, 0xD8, 0xAD, 0xD8, 0xAC,
+	// Bytes 24c0 - 24ff
+	0x46, 0xD8, 0xAA, 0xD8, 0xAD, 0xD9, 0x85, 0x46,
+	0xD8, 0xAA, 0xD8, 0xAE, 0xD9, 0x85, 0x46, 0xD8,
+	0xAA, 0xD8, 0xAE, 0xD9, 0x89, 0x46, 0xD8, 0xAA,
+	0xD8, 0xAE, 0xD9, 0x8A, 0x46, 0xD8, 0xAA, 0xD9,
+	0x85, 0xD8, 0xAC, 0x46, 0xD8, 0xAA, 0xD9, 0x85,
+	0xD8, 0xAD, 0x46, 0xD8, 0xAA, 0xD9, 0x85, 0xD8,
+	0xAE, 0x46, 0xD8, 0xAA, 0xD9, 0x85, 0xD9, 0x89,
+	0x46, 0xD8, 0xAA, 0xD9, 0x85, 0xD9, 0x8A, 0x46,
+	// Bytes 2500 - 253f
+	0xD8, 0xAC, 0xD8, 0xAD, 0xD9, 0x89, 0x46, 0xD8,
+	0xAC, 0xD8, 0xAD, 0xD9, 0x8A, 0x46, 0xD8, 0xAC,
+	0xD9, 0x85, 0xD8, 0xAD, 0x46, 0xD8, 0xAC, 0xD9,
+	0x85, 0xD9, 0x89, 0x46, 0xD8, 0xAC, 0xD9, 0x85,
+	0xD9, 0x8A, 0x46, 0xD8, 0xAD, 0xD8, 0xAC, 0xD9,
+	0x8A, 0x46, 0xD8, 0xAD, 0xD9, 0x85, 0xD9, 0x89,
+	0x46, 0xD8, 0xAD, 0xD9, 0x85, 0xD9, 0x8A, 0x46,
+	0xD8, 0xB3, 0xD8, 0xAC, 0xD8, 0xAD, 0x46, 0xD8,
+	// Bytes 2540 - 257f
+	0xB3, 0xD8, 0xAC, 0xD9, 0x89, 0x46, 0xD8, 0xB3,
+	0xD8, 0xAD, 0xD8, 0xAC, 0x46, 0xD8, 0xB3, 0xD8,
+	0xAE, 0xD9, 0x89, 0x46, 0xD8, 0xB3, 0xD8, 0xAE,
+	0xD9, 0x8A, 0x46, 0xD8, 0xB3, 0xD9, 0x85, 0xD8,
+	0xAC, 0x46, 0xD8, 0xB3, 0xD9, 0x85, 0xD8, 0xAD,
+	0x46, 0xD8, 0xB3, 0xD9, 0x85, 0xD9, 0x85, 0x46,
+	0xD8, 0xB4, 0xD8, 0xAC, 0xD9, 0x8A, 0x46, 0xD8,
+	0xB4, 0xD8, 0xAD, 0xD9, 0x85, 0x46, 0xD8, 0xB4,
+	// Bytes 2580 - 25bf
+	0xD8, 0xAD, 0xD9, 0x8A, 0x46, 0xD8, 0xB4, 0xD9,
+	0x85, 0xD8, 0xAE, 0x46, 0xD8, 0xB4, 0xD9, 0x85,
+	0xD9, 0x85, 0x46, 0xD8, 0xB5, 0xD8, 0xAD, 0xD8,
+	0xAD, 0x46, 0xD8, 0xB5, 0xD8, 0xAD, 0xD9, 0x8A,
+	0x46, 0xD8, 0xB5, 0xD9, 0x84, 0xD9, 0x89, 0x46,
+	0xD8, 0xB5, 0xD9, 0x84, 0xDB, 0x92, 0x46, 0xD8,
+	0xB5, 0xD9, 0x85, 0xD9, 0x85, 0x46, 0xD8, 0xB6,
+	0xD8, 0xAD, 0xD9, 0x89, 0x46, 0xD8, 0xB6, 0xD8,
+	// Bytes 25c0 - 25ff
+	0xAD, 0xD9, 0x8A, 0x46, 0xD8, 0xB6, 0xD8, 0xAE,
+	0xD9, 0x85, 0x46, 0xD8, 0xB7, 0xD9, 0x85, 0xD8,
+	0xAD, 0x46, 0xD8, 0xB7, 0xD9, 0x85, 0xD9, 0x85,
+	0x46, 0xD8, 0xB7, 0xD9, 0x85, 0xD9, 0x8A, 0x46,
+	0xD8, 0xB9, 0xD8, 0xAC, 0xD9, 0x85, 0x46, 0xD8,
+	0xB9, 0xD9, 0x85, 0xD9, 0x85, 0x46, 0xD8, 0xB9,
+	0xD9, 0x85, 0xD9, 0x89, 0x46, 0xD8, 0xB9, 0xD9,
+	0x85, 0xD9, 0x8A, 0x46, 0xD8, 0xBA, 0xD9, 0x85,
+	// Bytes 2600 - 263f
+	0xD9, 0x85, 0x46, 0xD8, 0xBA, 0xD9, 0x85, 0xD9,
+	0x89, 0x46, 0xD8, 0xBA, 0xD9, 0x85, 0xD9, 0x8A,
+	0x46, 0xD9, 0x81, 0xD8, 0xAE, 0xD9, 0x85, 0x46,
+	0xD9, 0x81, 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD9,
+	0x82, 0xD9, 0x84, 0xDB, 0x92, 0x46, 0xD9, 0x82,
+	0xD9, 0x85, 0xD8, 0xAD, 0x46, 0xD9, 0x82, 0xD9,
+	0x85, 0xD9, 0x85, 0x46, 0xD9, 0x82, 0xD9, 0x85,
+	0xD9, 0x8A, 0x46, 0xD9, 0x83, 0xD9, 0x85, 0xD9,
+	// Bytes 2640 - 267f
+	0x85, 0x46, 0xD9, 0x83, 0xD9, 0x85, 0xD9, 0x8A,
+	0x46, 0xD9, 0x84, 0xD8, 0xAC, 0xD8, 0xAC, 0x46,
+	0xD9, 0x84, 0xD8, 0xAC, 0xD9, 0x85, 0x46, 0xD9,
+	0x84, 0xD8, 0xAC, 0xD9, 0x8A, 0x46, 0xD9, 0x84,
+	0xD8, 0xAD, 0xD9, 0x85, 0x46, 0xD9, 0x84, 0xD8,
+	0xAD, 0xD9, 0x89, 0x46, 0xD9, 0x84, 0xD8, 0xAD,
+	0xD9, 0x8A, 0x46, 0xD9, 0x84, 0xD8, 0xAE, 0xD9,
+	0x85, 0x46, 0xD9, 0x84, 0xD9, 0x85, 0xD8, 0xAD,
+	// Bytes 2680 - 26bf
+	0x46, 0xD9, 0x84, 0xD9, 0x85, 0xD9, 0x8A, 0x46,
+	0xD9, 0x85, 0xD8, 0xAC, 0xD8, 0xAD, 0x46, 0xD9,
+	0x85, 0xD8, 0xAC, 0xD8, 0xAE, 0x46, 0xD9, 0x85,
+	0xD8, 0xAC, 0xD9, 0x85, 0x46, 0xD9, 0x85, 0xD8,
+	0xAC, 0xD9, 0x8A, 0x46, 0xD9, 0x85, 0xD8, 0xAD,
+	0xD8, 0xAC, 0x46, 0xD9, 0x85, 0xD8, 0xAD, 0xD9,
+	0x85, 0x46, 0xD9, 0x85, 0xD8, 0xAD, 0xD9, 0x8A,
+	0x46, 0xD9, 0x85, 0xD8, 0xAE, 0xD8, 0xAC, 0x46,
+	// Bytes 26c0 - 26ff
+	0xD9, 0x85, 0xD8, 0xAE, 0xD9, 0x85, 0x46, 0xD9,
+	0x85, 0xD8, 0xAE, 0xD9, 0x8A, 0x46, 0xD9, 0x85,
+	0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD9, 0x86, 0xD8,
+	0xAC, 0xD8, 0xAD, 0x46, 0xD9, 0x86, 0xD8, 0xAC,
+	0xD9, 0x85, 0x46, 0xD9, 0x86, 0xD8, 0xAC, 0xD9,
+	0x89, 0x46, 0xD9, 0x86, 0xD8, 0xAC, 0xD9, 0x8A,
+	0x46, 0xD9, 0x86, 0xD8, 0xAD, 0xD9, 0x85, 0x46,
+	0xD9, 0x86, 0xD8, 0xAD, 0xD9, 0x89, 0x46, 0xD9,
+	// Bytes 2700 - 273f
+	0x86, 0xD8, 0xAD, 0xD9, 0x8A, 0x46, 0xD9, 0x86,
+	0xD9, 0x85, 0xD9, 0x89, 0x46, 0xD9, 0x86, 0xD9,
+	0x85, 0xD9, 0x8A, 0x46, 0xD9, 0x87, 0xD9, 0x85,
+	0xD8, 0xAC, 0x46, 0xD9, 0x87, 0xD9, 0x85, 0xD9,
+	0x85, 0x46, 0xD9, 0x8A, 0xD8, 0xAC, 0xD9, 0x8A,
+	0x46, 0xD9, 0x8A, 0xD8, 0xAD, 0xD9, 0x8A, 0x46,
+	0xD9, 0x8A, 0xD9, 0x85, 0xD9, 0x85, 0x46, 0xD9,
+	0x8A, 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD9, 0x8A,
+	// Bytes 2740 - 277f
+	0xD9, 0x94, 0xD8, 0xA7, 0x46, 0xD9, 0x8A, 0xD9,
+	0x94, 0xD8, 0xAC, 0x46, 0xD9, 0x8A, 0xD9, 0x94,
+	0xD8, 0xAD, 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD8,
+	0xAE, 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD8, 0xB1,
+	0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD8, 0xB2, 0x46,
+	0xD9, 0x8A, 0xD9, 0x94, 0xD9, 0x85, 0x46, 0xD9,
+	0x8A, 0xD9, 0x94, 0xD9, 0x86, 0x46, 0xD9, 0x8A,
+	0xD9, 0x94, 0xD9, 0x87, 0x46, 0xD9, 0x8A, 0xD9,
+	// Bytes 2780 - 27bf
+	0x94, 0xD9, 0x88, 0x46, 0xD9, 0x8A, 0xD9, 0x94,
+	0xD9, 0x89, 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD9,
+	0x8A, 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xDB, 0x86,
+	0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xDB, 0x87, 0x46,
+	0xD9, 0x8A, 0xD9, 0x94, 0xDB, 0x88, 0x46, 0xD9,
+	0x8A, 0xD9, 0x94, 0xDB, 0x90, 0x46, 0xD9, 0x8A,
+	0xD9, 0x94, 0xDB, 0x95, 0x46, 0xE0, 0xB9, 0x8D,
+	0xE0, 0xB8, 0xB2, 0x46, 0xE0, 0xBA, 0xAB, 0xE0,
+	// Bytes 27c0 - 27ff
+	0xBA, 0x99, 0x46, 0xE0, 0xBA, 0xAB, 0xE0, 0xBA,
+	0xA1, 0x46, 0xE0, 0xBB, 0x8D, 0xE0, 0xBA, 0xB2,
+	0x46, 0xE0, 0xBD, 0x80, 0xE0, 0xBE, 0xB5, 0x46,
+	0xE0, 0xBD, 0x82, 0xE0, 0xBE, 0xB7, 0x46, 0xE0,
+	0xBD, 0x8C, 0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBD,
+	0x91, 0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBD, 0x96,
+	0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBD, 0x9B, 0xE0,
+	0xBE, 0xB7, 0x46, 0xE0, 0xBE, 0x90, 0xE0, 0xBE,
+	// Bytes 2800 - 283f
+	0xB5, 0x46, 0xE0, 0xBE, 0x92, 0xE0, 0xBE, 0xB7,
+	0x46, 0xE0, 0xBE, 0x9C, 0xE0, 0xBE, 0xB7, 0x46,
+	0xE0, 0xBE, 0xA1, 0xE0, 0xBE, 0xB7, 0x46, 0xE0,
+	0xBE, 0xA6, 0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBE,
+	0xAB, 0xE0, 0xBE, 0xB7, 0x46, 0xE1, 0x84, 0x80,
+	0xE1, 0x85, 0xA1, 0x46, 0xE1, 0x84, 0x82, 0xE1,
+	0x85, 0xA1, 0x46, 0xE1, 0x84, 0x83, 0xE1, 0x85,
+	0xA1, 0x46, 0xE1, 0x84, 0x85, 0xE1, 0x85, 0xA1,
+	// Bytes 2840 - 287f
+	0x46, 0xE1, 0x84, 0x86, 0xE1, 0x85, 0xA1, 0x46,
+	0xE1, 0x84, 0x87, 0xE1, 0x85, 0xA1, 0x46, 0xE1,
+	0x84, 0x89, 0xE1, 0x85, 0xA1, 0x46, 0xE1, 0x84,
+	0x8B, 0xE1, 0x85, 0xA1, 0x46, 0xE1, 0x84, 0x8B,
+	0xE1, 0x85, 0xAE, 0x46, 0xE1, 0x84, 0x8C, 0xE1,
+	0x85, 0xA1, 0x46, 0xE1, 0x84, 0x8E, 0xE1, 0x85,
+	0xA1, 0x46, 0xE1, 0x84, 0x8F, 0xE1, 0x85, 0xA1,
+	0x46, 0xE1, 0x84, 0x90, 0xE1, 0x85, 0xA1, 0x46,
+	// Bytes 2880 - 28bf
+	0xE1, 0x84, 0x91, 0xE1, 0x85, 0xA1, 0x46, 0xE1,
+	0x84, 0x92, 0xE1, 0x85, 0xA1, 0x46, 0xE2, 0x80,
+	0xB2, 0xE2, 0x80, 0xB2, 0x46, 0xE2, 0x80, 0xB5,
+	0xE2, 0x80, 0xB5, 0x46, 0xE2, 0x88, 0xAB, 0xE2,
+	0x88, 0xAB, 0x46, 0xE2, 0x88, 0xAE, 0xE2, 0x88,
+	0xAE, 0x46, 0xE3, 0x81, 0xBB, 0xE3, 0x81, 0x8B,
+	0x46, 0xE3, 0x82, 0x88, 0xE3, 0x82, 0x8A, 0x46,
+	0xE3, 0x82, 0xAD, 0xE3, 0x83, 0xAD, 0x46, 0xE3,
+	// Bytes 28c0 - 28ff
+	0x82, 0xB3, 0xE3, 0x82, 0xB3, 0x46, 0xE3, 0x82,
+	0xB3, 0xE3, 0x83, 0x88, 0x46, 0xE3, 0x83, 0x88,
+	0xE3, 0x83, 0xB3, 0x46, 0xE3, 0x83, 0x8A, 0xE3,
+	0x83, 0x8E, 0x46, 0xE3, 0x83, 0x9B, 0xE3, 0x83,
+	0xB3, 0x46, 0xE3, 0x83, 0x9F, 0xE3, 0x83, 0xAA,
+	0x46, 0xE3, 0x83, 0xAA, 0xE3, 0x83, 0xA9, 0x46,
+	0xE3, 0x83, 0xAC, 0xE3, 0x83, 0xA0, 0x46, 0xE5,
+	0xA4, 0xA7, 0xE6, 0xAD, 0xA3, 0x46, 0xE5, 0xB9,
+	// Bytes 2900 - 293f
+	0xB3, 0xE6, 0x88, 0x90, 0x46, 0xE6, 0x98, 0x8E,
+	0xE6, 0xB2, 0xBB, 0x46, 0xE6, 0x98, 0xAD, 0xE5,
+	0x92, 0x8C, 0x47, 0x72, 0x61, 0x64, 0xE2, 0x88,
+	0x95, 0x73, 0x47, 0xE3, 0x80, 0x94, 0x53, 0xE3,
+	0x80, 0x95, 0x48, 0x28, 0xE1, 0x84, 0x80, 0xE1,
+	0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84, 0x82,
+	0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84,
+	0x83, 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1,
+	// Bytes 2940 - 297f
+	0x84, 0x85, 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28,
+	0xE1, 0x84, 0x86, 0xE1, 0x85, 0xA1, 0x29, 0x48,
+	0x28, 0xE1, 0x84, 0x87, 0xE1, 0x85, 0xA1, 0x29,
+	0x48, 0x28, 0xE1, 0x84, 0x89, 0xE1, 0x85, 0xA1,
+	0x29, 0x48, 0x28, 0xE1, 0x84, 0x8B, 0xE1, 0x85,
+	0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84, 0x8C, 0xE1,
+	0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84, 0x8C,
+	0xE1, 0x85, 0xAE, 0x29, 0x48, 0x28, 0xE1, 0x84,
+	// Bytes 2980 - 29bf
+	0x8E, 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1,
+	0x84, 0x8F, 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28,
+	0xE1, 0x84, 0x90, 0xE1, 0x85, 0xA1, 0x29, 0x48,
+	0x28, 0xE1, 0x84, 0x91, 0xE1, 0x85, 0xA1, 0x29,
+	0x48, 0x28, 0xE1, 0x84, 0x92, 0xE1, 0x85, 0xA1,
+	0x29, 0x48, 0x72, 0x61, 0x64, 0xE2, 0x88, 0x95,
+	0x73, 0x32, 0x48, 0xD8, 0xA7, 0xD9, 0x83, 0xD8,
+	0xA8, 0xD8, 0xB1, 0x48, 0xD8, 0xA7, 0xD9, 0x84,
+	// Bytes 29c0 - 29ff
+	0xD9, 0x84, 0xD9, 0x87, 0x48, 0xD8, 0xB1, 0xD8,
+	0xB3, 0xD9, 0x88, 0xD9, 0x84, 0x48, 0xD8, 0xB1,
+	0xDB, 0x8C, 0xD8, 0xA7, 0xD9, 0x84, 0x48, 0xD8,
+	0xB5, 0xD9, 0x84, 0xD8, 0xB9, 0xD9, 0x85, 0x48,
+	0xD8, 0xB9, 0xD9, 0x84, 0xD9, 0x8A, 0xD9, 0x87,
+	0x48, 0xD9, 0x85, 0xD8, 0xAD, 0xD9, 0x85, 0xD8,
+	0xAF, 0x48, 0xD9, 0x88, 0xD8, 0xB3, 0xD9, 0x84,
+	0xD9, 0x85, 0x49, 0xE2, 0x80, 0xB2, 0xE2, 0x80,
+	// Bytes 2a00 - 2a3f
+	0xB2, 0xE2, 0x80, 0xB2, 0x49, 0xE2, 0x80, 0xB5,
+	0xE2, 0x80, 0xB5, 0xE2, 0x80, 0xB5, 0x49, 0xE2,
+	0x88, 0xAB, 0xE2, 0x88, 0xAB, 0xE2, 0x88, 0xAB,
+	0x49, 0xE2, 0x88, 0xAE, 0xE2, 0x88, 0xAE, 0xE2,
+	0x88, 0xAE, 0x49, 0xE3, 0x80, 0x94, 0xE4, 0xB8,
+	0x89, 0xE3, 0x80, 0x95, 0x49, 0xE3, 0x80, 0x94,
+	0xE4, 0xBA, 0x8C, 0xE3, 0x80, 0x95, 0x49, 0xE3,
+	0x80, 0x94, 0xE5, 0x8B, 0x9D, 0xE3, 0x80, 0x95,
+	// Bytes 2a40 - 2a7f
+	0x49, 0xE3, 0x80, 0x94, 0xE5, 0xAE, 0x89, 0xE3,
+	0x80, 0x95, 0x49, 0xE3, 0x80, 0x94, 0xE6, 0x89,
+	0x93, 0xE3, 0x80, 0x95, 0x49, 0xE3, 0x80, 0x94,
+	0xE6, 0x95, 0x97, 0xE3, 0x80, 0x95, 0x49, 0xE3,
+	0x80, 0x94, 0xE6, 0x9C, 0xAC, 0xE3, 0x80, 0x95,
+	0x49, 0xE3, 0x80, 0x94, 0xE7, 0x82, 0xB9, 0xE3,
+	0x80, 0x95, 0x49, 0xE3, 0x80, 0x94, 0xE7, 0x9B,
+	0x97, 0xE3, 0x80, 0x95, 0x49, 0xE3, 0x82, 0xA2,
+	// Bytes 2a80 - 2abf
+	0xE3, 0x83, 0xBC, 0xE3, 0x83, 0xAB, 0x49, 0xE3,
+	0x82, 0xA4, 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x81,
+	0x49, 0xE3, 0x82, 0xA6, 0xE3, 0x82, 0xA9, 0xE3,
+	0x83, 0xB3, 0x49, 0xE3, 0x82, 0xAA, 0xE3, 0x83,
+	0xB3, 0xE3, 0x82, 0xB9, 0x49, 0xE3, 0x82, 0xAA,
+	0xE3, 0x83, 0xBC, 0xE3, 0x83, 0xA0, 0x49, 0xE3,
+	0x82, 0xAB, 0xE3, 0x82, 0xA4, 0xE3, 0x83, 0xAA,
+	0x49, 0xE3, 0x82, 0xB1, 0xE3, 0x83, 0xBC, 0xE3,
+	// Bytes 2ac0 - 2aff
+	0x82, 0xB9, 0x49, 0xE3, 0x82, 0xB3, 0xE3, 0x83,
+	0xAB, 0xE3, 0x83, 0x8A, 0x49, 0xE3, 0x82, 0xBB,
+	0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x81, 0x49, 0xE3,
+	0x82, 0xBB, 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x88,
+	0x49, 0xE3, 0x83, 0x86, 0xE3, 0x82, 0x99, 0xE3,
+	0x82, 0xB7, 0x49, 0xE3, 0x83, 0x88, 0xE3, 0x82,
+	0x99, 0xE3, 0x83, 0xAB, 0x49, 0xE3, 0x83, 0x8E,
+	0xE3, 0x83, 0x83, 0xE3, 0x83, 0x88, 0x49, 0xE3,
+	// Bytes 2b00 - 2b3f
+	0x83, 0x8F, 0xE3, 0x82, 0xA4, 0xE3, 0x83, 0x84,
+	0x49, 0xE3, 0x83, 0x92, 0xE3, 0x82, 0x99, 0xE3,
+	0x83, 0xAB, 0x49, 0xE3, 0x83, 0x92, 0xE3, 0x82,
+	0x9A, 0xE3, 0x82, 0xB3, 0x49, 0xE3, 0x83, 0x95,
+	0xE3, 0x83, 0xA9, 0xE3, 0x83, 0xB3, 0x49, 0xE3,
+	0x83, 0x98, 0xE3, 0x82, 0x9A, 0xE3, 0x82, 0xBD,
+	0x49, 0xE3, 0x83, 0x98, 0xE3, 0x83, 0xAB, 0xE3,
+	0x83, 0x84, 0x49, 0xE3, 0x83, 0x9B, 0xE3, 0x83,
+	// Bytes 2b40 - 2b7f
+	0xBC, 0xE3, 0x83, 0xAB, 0x49, 0xE3, 0x83, 0x9B,
+	0xE3, 0x83, 0xBC, 0xE3, 0x83, 0xB3, 0x49, 0xE3,
+	0x83, 0x9E, 0xE3, 0x82, 0xA4, 0xE3, 0x83, 0xAB,
+	0x49, 0xE3, 0x83, 0x9E, 0xE3, 0x83, 0x83, 0xE3,
+	0x83, 0x8F, 0x49, 0xE3, 0x83, 0x9E, 0xE3, 0x83,
+	0xAB, 0xE3, 0x82, 0xAF, 0x49, 0xE3, 0x83, 0xA4,
+	0xE3, 0x83, 0xBC, 0xE3, 0x83, 0xAB, 0x49, 0xE3,
+	0x83, 0xA6, 0xE3, 0x82, 0xA2, 0xE3, 0x83, 0xB3,
+	// Bytes 2b80 - 2bbf
+	0x49, 0xE3, 0x83, 0xAF, 0xE3, 0x83, 0x83, 0xE3,
+	0x83, 0x88, 0x4C, 0xE1, 0x84, 0x8C, 0xE1, 0x85,
+	0xAE, 0xE1, 0x84, 0x8B, 0xE1, 0x85, 0xB4, 0x4C,
+	0xE2, 0x80, 0xB2, 0xE2, 0x80, 0xB2, 0xE2, 0x80,
+	0xB2, 0xE2, 0x80, 0xB2, 0x4C, 0xE2, 0x88, 0xAB,
+	0xE2, 0x88, 0xAB, 0xE2, 0x88, 0xAB, 0xE2, 0x88,
+	0xAB, 0x4C, 0xE3, 0x82, 0xA2, 0xE3, 0x83, 0xAB,
+	0xE3, 0x83, 0x95, 0xE3, 0x82, 0xA1, 0x4C, 0xE3,
+	// Bytes 2bc0 - 2bff
+	0x82, 0xA8, 0xE3, 0x83, 0xBC, 0xE3, 0x82, 0xAB,
+	0xE3, 0x83, 0xBC, 0x4C, 0xE3, 0x82, 0xAB, 0xE3,
+	0x82, 0x99, 0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xB3,
+	0x4C, 0xE3, 0x82, 0xAB, 0xE3, 0x82, 0x99, 0xE3,
+	0x83, 0xB3, 0xE3, 0x83, 0x9E, 0x4C, 0xE3, 0x82,
+	0xAB, 0xE3, 0x83, 0xA9, 0xE3, 0x83, 0x83, 0xE3,
+	0x83, 0x88, 0x4C, 0xE3, 0x82, 0xAB, 0xE3, 0x83,
+	0xAD, 0xE3, 0x83, 0xAA, 0xE3, 0x83, 0xBC, 0x4C,
+	// Bytes 2c00 - 2c3f
+	0xE3, 0x82, 0xAD, 0xE3, 0x82, 0x99, 0xE3, 0x83,
+	0x8B, 0xE3, 0x83, 0xBC, 0x4C, 0xE3, 0x82, 0xAD,
+	0xE3, 0x83, 0xA5, 0xE3, 0x83, 0xAA, 0xE3, 0x83,
+	0xBC, 0x4C, 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0x99,
+	0xE3, 0x83, 0xA9, 0xE3, 0x83, 0xA0, 0x4C, 0xE3,
+	0x82, 0xAF, 0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xBC,
+	0xE3, 0x83, 0x8D, 0x4C, 0xE3, 0x82, 0xB5, 0xE3,
+	0x82, 0xA4, 0xE3, 0x82, 0xAF, 0xE3, 0x83, 0xAB,
+	// Bytes 2c40 - 2c7f
+	0x4C, 0xE3, 0x82, 0xBF, 0xE3, 0x82, 0x99, 0xE3,
+	0x83, 0xBC, 0xE3, 0x82, 0xB9, 0x4C, 0xE3, 0x83,
+	0x8F, 0xE3, 0x82, 0x9A, 0xE3, 0x83, 0xBC, 0xE3,
+	0x83, 0x84, 0x4C, 0xE3, 0x83, 0x92, 0xE3, 0x82,
+	0x9A, 0xE3, 0x82, 0xAF, 0xE3, 0x83, 0xAB, 0x4C,
+	0xE3, 0x83, 0x95, 0xE3, 0x82, 0xA3, 0xE3, 0x83,
+	0xBC, 0xE3, 0x83, 0x88, 0x4C, 0xE3, 0x83, 0x98,
+	0xE3, 0x82, 0x99, 0xE3, 0x83, 0xBC, 0xE3, 0x82,
+	// Bytes 2c80 - 2cbf
+	0xBF, 0x4C, 0xE3, 0x83, 0x98, 0xE3, 0x82, 0x9A,
+	0xE3, 0x83, 0x8B, 0xE3, 0x83, 0x92, 0x4C, 0xE3,
+	0x83, 0x98, 0xE3, 0x82, 0x9A, 0xE3, 0x83, 0xB3,
+	0xE3, 0x82, 0xB9, 0x4C, 0xE3, 0x83, 0x9B, 0xE3,
+	0x82, 0x99, 0xE3, 0x83, 0xAB, 0xE3, 0x83, 0x88,
+	0x4C, 0xE3, 0x83, 0x9E, 0xE3, 0x82, 0xA4, 0xE3,
+	0x82, 0xAF, 0xE3, 0x83, 0xAD, 0x4C, 0xE3, 0x83,
+	0x9F, 0xE3, 0x82, 0xAF, 0xE3, 0x83, 0xAD, 0xE3,
+	// Bytes 2cc0 - 2cff
+	0x83, 0xB3, 0x4C, 0xE3, 0x83, 0xA1, 0xE3, 0x83,
+	0xBC, 0xE3, 0x83, 0x88, 0xE3, 0x83, 0xAB, 0x4C,
+	0xE3, 0x83, 0xAA, 0xE3, 0x83, 0x83, 0xE3, 0x83,
+	0x88, 0xE3, 0x83, 0xAB, 0x4C, 0xE3, 0x83, 0xAB,
+	0xE3, 0x83, 0x92, 0xE3, 0x82, 0x9A, 0xE3, 0x83,
+	0xBC, 0x4C, 0xE6, 0xA0, 0xAA, 0xE5, 0xBC, 0x8F,
+	0xE4, 0xBC, 0x9A, 0xE7, 0xA4, 0xBE, 0x4E, 0x28,
+	0xE1, 0x84, 0x8B, 0xE1, 0x85, 0xA9, 0xE1, 0x84,
+	// Bytes 2d00 - 2d3f
+	0x92, 0xE1, 0x85, 0xAE, 0x29, 0x4F, 0xD8, 0xAC,
+	0xD9, 0x84, 0x20, 0xD8, 0xAC, 0xD9, 0x84, 0xD8,
+	0xA7, 0xD9, 0x84, 0xD9, 0x87, 0x4F, 0xE1, 0x84,
+	0x8E, 0xE1, 0x85, 0xA1, 0xE1, 0x86, 0xB7, 0xE1,
+	0x84, 0x80, 0xE1, 0x85, 0xA9, 0x4F, 0xE3, 0x82,
+	0xA2, 0xE3, 0x83, 0x8F, 0xE3, 0x82, 0x9A, 0xE3,
+	0x83, 0xBC, 0xE3, 0x83, 0x88, 0x4F, 0xE3, 0x82,
+	0xA2, 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x98, 0xE3,
+	// Bytes 2d40 - 2d7f
+	0x82, 0x9A, 0xE3, 0x82, 0xA2, 0x4F, 0xE3, 0x82,
+	0xAD, 0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xAF, 0xE3,
+	0x83, 0x83, 0xE3, 0x83, 0x88, 0x4F, 0xE3, 0x82,
+	0xB5, 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x81, 0xE3,
+	0x83, 0xBC, 0xE3, 0x83, 0xA0, 0x4F, 0xE3, 0x83,
+	0x8F, 0xE3, 0x82, 0x99, 0xE3, 0x83, 0xBC, 0xE3,
+	0x83, 0xAC, 0xE3, 0x83, 0xAB, 0x4F, 0xE3, 0x83,
+	0x98, 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0xBF, 0xE3,
+	// Bytes 2d80 - 2dbf
+	0x83, 0xBC, 0xE3, 0x83, 0xAB, 0x4F, 0xE3, 0x83,
+	0x9B, 0xE3, 0x82, 0x9A, 0xE3, 0x82, 0xA4, 0xE3,
+	0x83, 0xB3, 0xE3, 0x83, 0x88, 0x4F, 0xE3, 0x83,
+	0x9E, 0xE3, 0x83, 0xB3, 0xE3, 0x82, 0xB7, 0xE3,
+	0x83, 0xA7, 0xE3, 0x83, 0xB3, 0x4F, 0xE3, 0x83,
+	0xA1, 0xE3, 0x82, 0xAB, 0xE3, 0x82, 0x99, 0xE3,
+	0x83, 0x88, 0xE3, 0x83, 0xB3, 0x4F, 0xE3, 0x83,
+	0xAB, 0xE3, 0x83, 0xBC, 0xE3, 0x83, 0x95, 0xE3,
+	// Bytes 2dc0 - 2dff
+	0x82, 0x99, 0xE3, 0x83, 0xAB, 0x51, 0x28, 0xE1,
+	0x84, 0x8B, 0xE1, 0x85, 0xA9, 0xE1, 0x84, 0x8C,
+	0xE1, 0x85, 0xA5, 0xE1, 0x86, 0xAB, 0x29, 0x52,
+	0xE3, 0x82, 0xAD, 0xE3, 0x82, 0x99, 0xE3, 0x83,
+	0xAB, 0xE3, 0x82, 0xBF, 0xE3, 0x82, 0x99, 0xE3,
+	0x83, 0xBC, 0x52, 0xE3, 0x82, 0xAD, 0xE3, 0x83,
+	0xAD, 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0x99, 0xE3,
+	0x83, 0xA9, 0xE3, 0x83, 0xA0, 0x52, 0xE3, 0x82,
+	// Bytes 2e00 - 2e3f
+	0xAD, 0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xA1, 0xE3,
+	0x83, 0xBC, 0xE3, 0x83, 0x88, 0xE3, 0x83, 0xAB,
+	0x52, 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0x99, 0xE3,
+	0x83, 0xA9, 0xE3, 0x83, 0xA0, 0xE3, 0x83, 0x88,
+	0xE3, 0x83, 0xB3, 0x52, 0xE3, 0x82, 0xAF, 0xE3,
+	0x83, 0xAB, 0xE3, 0x82, 0xBB, 0xE3, 0x82, 0x99,
+	0xE3, 0x82, 0xA4, 0xE3, 0x83, 0xAD, 0x52, 0xE3,
+	0x83, 0x8F, 0xE3, 0x82, 0x9A, 0xE3, 0x83, 0xBC,
+	// Bytes 2e40 - 2e7f
+	0xE3, 0x82, 0xBB, 0xE3, 0x83, 0xB3, 0xE3, 0x83,
+	0x88, 0x52, 0xE3, 0x83, 0x92, 0xE3, 0x82, 0x9A,
+	0xE3, 0x82, 0xA2, 0xE3, 0x82, 0xB9, 0xE3, 0x83,
+	0x88, 0xE3, 0x83, 0xAB, 0x52, 0xE3, 0x83, 0x95,
+	0xE3, 0x82, 0x99, 0xE3, 0x83, 0x83, 0xE3, 0x82,
+	0xB7, 0xE3, 0x82, 0xA7, 0xE3, 0x83, 0xAB, 0x52,
+	0xE3, 0x83, 0x9F, 0xE3, 0x83, 0xAA, 0xE3, 0x83,
+	0x8F, 0xE3, 0x82, 0x99, 0xE3, 0x83, 0xBC, 0xE3,
+	// Bytes 2e80 - 2ebf
+	0x83, 0xAB, 0x52, 0xE3, 0x83, 0xAC, 0xE3, 0x83,
+	0xB3, 0xE3, 0x83, 0x88, 0xE3, 0x82, 0xB1, 0xE3,
+	0x82, 0x99, 0xE3, 0x83, 0xB3, 0x61, 0xD8, 0xB5,
+	0xD9, 0x84, 0xD9, 0x89, 0x20, 0xD8, 0xA7, 0xD9,
+	0x84, 0xD9, 0x84, 0xD9, 0x87, 0x20, 0xD8, 0xB9,
+	0xD9, 0x84, 0xD9, 0x8A, 0xD9, 0x87, 0x20, 0xD9,
+	0x88, 0xD8, 0xB3, 0xD9, 0x84, 0xD9, 0x85, 0x86,
+	0xE0, 0xB3, 0x86, 0xE0, 0xB3, 0x82, 0x86, 0xE0,
+	// Bytes 2ec0 - 2eff
+	0xB7, 0x99, 0xE0, 0xB7, 0x8F, 0x09, 0xE0, 0xB7,
+	0x99, 0xE0, 0xB7, 0x8F, 0xE0, 0xB7, 0x8A, 0x11,
+	0x44, 0x44, 0x5A, 0xCC, 0x8C, 0xC9, 0x44, 0x44,
+	0x7A, 0xCC, 0x8C, 0xC9, 0x44, 0x64, 0x7A, 0xCC,
+	0x8C, 0xC9, 0x46, 0xD9, 0x84, 0xD8, 0xA7, 0xD9,
+	0x93, 0xC9, 0x46, 0xD9, 0x84, 0xD8, 0xA7, 0xD9,
+	0x94, 0xC9, 0x46, 0xD9, 0x84, 0xD8, 0xA7, 0xD9,
+	0x95, 0xB5, 0x49, 0xE3, 0x83, 0xA1, 0xE3, 0x82,
+	// Bytes 2f00 - 2f3f
+	0xAB, 0xE3, 0x82, 0x99, 0x0D, 0x4C, 0xE3, 0x82,
+	0xAD, 0xE3, 0x82, 0x99, 0xE3, 0x82, 0xAB, 0xE3,
+	0x82, 0x99, 0x0D, 0x4C, 0xE3, 0x82, 0xB3, 0xE3,
+	0x83, 0xBC, 0xE3, 0x83, 0x9B, 0xE3, 0x82, 0x9A,
+	0x0D, 0x4C, 0xE3, 0x83, 0xA4, 0xE3, 0x83, 0xBC,
+	0xE3, 0x83, 0x88, 0xE3, 0x82, 0x99, 0x0D, 0x4F,
+	0xE3, 0x82, 0xA4, 0xE3, 0x83, 0x8B, 0xE3, 0x83,
+	0xB3, 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0x99, 0x0D,
+	// Bytes 2f40 - 2f7f
+	0x4F, 0xE3, 0x82, 0xB7, 0xE3, 0x83, 0xAA, 0xE3,
+	0x83, 0xB3, 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0x99,
+	0x0D, 0x4F, 0xE3, 0x83, 0x98, 0xE3, 0x82, 0x9A,
+	0xE3, 0x83, 0xBC, 0xE3, 0x82, 0xB7, 0xE3, 0x82,
+	0x99, 0x0D, 0x4F, 0xE3, 0x83, 0x9B, 0xE3, 0x82,
+	0x9A, 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x88, 0xE3,
+	0x82, 0x99, 0x0D, 0x52, 0xE3, 0x82, 0xA8, 0xE3,
+	0x82, 0xB9, 0xE3, 0x82, 0xAF, 0xE3, 0x83, 0xBC,
+	// Bytes 2f80 - 2fbf
+	0xE3, 0x83, 0x88, 0xE3, 0x82, 0x99, 0x0D, 0x52,
+	0xE3, 0x83, 0x95, 0xE3, 0x82, 0xA1, 0xE3, 0x83,
+	0xA9, 0xE3, 0x83, 0x83, 0xE3, 0x83, 0x88, 0xE3,
+	0x82, 0x99, 0x0D, 0x03, 0x3C, 0xCC, 0xB8, 0x05,
+	0x03, 0x3D, 0xCC, 0xB8, 0x05, 0x03, 0x3E, 0xCC,
+	0xB8, 0x05, 0x03, 0x41, 0xCC, 0x80, 0xC9, 0x03,
+	0x41, 0xCC, 0x81, 0xC9, 0x03, 0x41, 0xCC, 0x83,
+	0xC9, 0x03, 0x41, 0xCC, 0x84, 0xC9, 0x03, 0x41,
+	// Bytes 2fc0 - 2fff
+	0xCC, 0x89, 0xC9, 0x03, 0x41, 0xCC, 0x8C, 0xC9,
+	0x03, 0x41, 0xCC, 0x8F, 0xC9, 0x03, 0x41, 0xCC,
+	0x91, 0xC9, 0x03, 0x41, 0xCC, 0xA5, 0xB5, 0x03,
+	0x41, 0xCC, 0xA8, 0xA5, 0x03, 0x42, 0xCC, 0x87,
+	0xC9, 0x03, 0x42, 0xCC, 0xA3, 0xB5, 0x03, 0x42,
+	0xCC, 0xB1, 0xB5, 0x03, 0x43, 0xCC, 0x81, 0xC9,
+	0x03, 0x43, 0xCC, 0x82, 0xC9, 0x03, 0x43, 0xCC,
+	0x87, 0xC9, 0x03, 0x43, 0xCC, 0x8C, 0xC9, 0x03,
+	// Bytes 3000 - 303f
+	0x44, 0xCC, 0x87, 0xC9, 0x03, 0x44, 0xCC, 0x8C,
+	0xC9, 0x03, 0x44, 0xCC, 0xA3, 0xB5, 0x03, 0x44,
+	0xCC, 0xA7, 0xA5, 0x03, 0x44, 0xCC, 0xAD, 0xB5,
+	0x03, 0x44, 0xCC, 0xB1, 0xB5, 0x03, 0x45, 0xCC,
+	0x80, 0xC9, 0x03, 0x45, 0xCC, 0x81, 0xC9, 0x03,
+	0x45, 0xCC, 0x83, 0xC9, 0x03, 0x45, 0xCC, 0x86,
+	0xC9, 0x03, 0x45, 0xCC, 0x87, 0xC9, 0x03, 0x45,
+	0xCC, 0x88, 0xC9, 0x03, 0x45, 0xCC, 0x89, 0xC9,
+	// Bytes 3040 - 307f
+	0x03, 0x45, 0xCC, 0x8C, 0xC9, 0x03, 0x45, 0xCC,
+	0x8F, 0xC9, 0x03, 0x45, 0xCC, 0x91, 0xC9, 0x03,
+	0x45, 0xCC, 0xA8, 0xA5, 0x03, 0x45, 0xCC, 0xAD,
+	0xB5, 0x03, 0x45, 0xCC, 0xB0, 0xB5, 0x03, 0x46,
+	0xCC, 0x87, 0xC9, 0x03, 0x47, 0xCC, 0x81, 0xC9,
+	0x03, 0x47, 0xCC, 0x82, 0xC9, 0x03, 0x47, 0xCC,
+	0x84, 0xC9, 0x03, 0x47, 0xCC, 0x86, 0xC9, 0x03,
+	0x47, 0xCC, 0x87, 0xC9, 0x03, 0x47, 0xCC, 0x8C,
+	// Bytes 3080 - 30bf
+	0xC9, 0x03, 0x47, 0xCC, 0xA7, 0xA5, 0x03, 0x48,
+	0xCC, 0x82, 0xC9, 0x03, 0x48, 0xCC, 0x87, 0xC9,
+	0x03, 0x48, 0xCC, 0x88, 0xC9, 0x03, 0x48, 0xCC,
+	0x8C, 0xC9, 0x03, 0x48, 0xCC, 0xA3, 0xB5, 0x03,
+	0x48, 0xCC, 0xA7, 0xA5, 0x03, 0x48, 0xCC, 0xAE,
+	0xB5, 0x03, 0x49, 0xCC, 0x80, 0xC9, 0x03, 0x49,
+	0xCC, 0x81, 0xC9, 0x03, 0x49, 0xCC, 0x82, 0xC9,
+	0x03, 0x49, 0xCC, 0x83, 0xC9, 0x03, 0x49, 0xCC,
+	// Bytes 30c0 - 30ff
+	0x84, 0xC9, 0x03, 0x49, 0xCC, 0x86, 0xC9, 0x03,
+	0x49, 0xCC, 0x87, 0xC9, 0x03, 0x49, 0xCC, 0x89,
+	0xC9, 0x03, 0x49, 0xCC, 0x8C, 0xC9, 0x03, 0x49,
+	0xCC, 0x8F, 0xC9, 0x03, 0x49, 0xCC, 0x91, 0xC9,
+	0x03, 0x49, 0xCC, 0xA3, 0xB5, 0x03, 0x49, 0xCC,
+	0xA8, 0xA5, 0x03, 0x49, 0xCC, 0xB0, 0xB5, 0x03,
+	0x4A, 0xCC, 0x82, 0xC9, 0x03, 0x4B, 0xCC, 0x81,
+	0xC9, 0x03, 0x4B, 0xCC, 0x8C, 0xC9, 0x03, 0x4B,
+	// Bytes 3100 - 313f
+	0xCC, 0xA3, 0xB5, 0x03, 0x4B, 0xCC, 0xA7, 0xA5,
+	0x03, 0x4B, 0xCC, 0xB1, 0xB5, 0x03, 0x4C, 0xCC,
+	0x81, 0xC9, 0x03, 0x4C, 0xCC, 0x8C, 0xC9, 0x03,
+	0x4C, 0xCC, 0xA7, 0xA5, 0x03, 0x4C, 0xCC, 0xAD,
+	0xB5, 0x03, 0x4C, 0xCC, 0xB1, 0xB5, 0x03, 0x4D,
+	0xCC, 0x81, 0xC9, 0x03, 0x4D, 0xCC, 0x87, 0xC9,
+	0x03, 0x4D, 0xCC, 0xA3, 0xB5, 0x03, 0x4E, 0xCC,
+	0x80, 0xC9, 0x03, 0x4E, 0xCC, 0x81, 0xC9, 0x03,
+	// Bytes 3140 - 317f
+	0x4E, 0xCC, 0x83, 0xC9, 0x03, 0x4E, 0xCC, 0x87,
+	0xC9, 0x03, 0x4E, 0xCC, 0x8C, 0xC9, 0x03, 0x4E,
+	0xCC, 0xA3, 0xB5, 0x03, 0x4E, 0xCC, 0xA7, 0xA5,
+	0x03, 0x4E, 0xCC, 0xAD, 0xB5, 0x03, 0x4E, 0xCC,
+	0xB1, 0xB5, 0x03, 0x4F, 0xCC, 0x80, 0xC9, 0x03,
+	0x4F, 0xCC, 0x81, 0xC9, 0x03, 0x4F, 0xCC, 0x86,
+	0xC9, 0x03, 0x4F, 0xCC, 0x89, 0xC9, 0x03, 0x4F,
+	0xCC, 0x8B, 0xC9, 0x03, 0x4F, 0xCC, 0x8C, 0xC9,
+	// Bytes 3180 - 31bf
+	0x03, 0x4F, 0xCC, 0x8F, 0xC9, 0x03, 0x4F, 0xCC,
+	0x91, 0xC9, 0x03, 0x50, 0xCC, 0x81, 0xC9, 0x03,
+	0x50, 0xCC, 0x87, 0xC9, 0x03, 0x52, 0xCC, 0x81,
+	0xC9, 0x03, 0x52, 0xCC, 0x87, 0xC9, 0x03, 0x52,
+	0xCC, 0x8C, 0xC9, 0x03, 0x52, 0xCC, 0x8F, 0xC9,
+	0x03, 0x52, 0xCC, 0x91, 0xC9, 0x03, 0x52, 0xCC,
+	0xA7, 0xA5, 0x03, 0x52, 0xCC, 0xB1, 0xB5, 0x03,
+	0x53, 0xCC, 0x82, 0xC9, 0x03, 0x53, 0xCC, 0x87,
+	// Bytes 31c0 - 31ff
+	0xC9, 0x03, 0x53, 0xCC, 0xA6, 0xB5, 0x03, 0x53,
+	0xCC, 0xA7, 0xA5, 0x03, 0x54, 0xCC, 0x87, 0xC9,
+	0x03, 0x54, 0xCC, 0x8C, 0xC9, 0x03, 0x54, 0xCC,
+	0xA3, 0xB5, 0x03, 0x54, 0xCC, 0xA6, 0xB5, 0x03,
+	0x54, 0xCC, 0xA7, 0xA5, 0x03, 0x54, 0xCC, 0xAD,
+	0xB5, 0x03, 0x54, 0xCC, 0xB1, 0xB5, 0x03, 0x55,
+	0xCC, 0x80, 0xC9, 0x03, 0x55, 0xCC, 0x81, 0xC9,
+	0x03, 0x55, 0xCC, 0x82, 0xC9, 0x03, 0x55, 0xCC,
+	// Bytes 3200 - 323f
+	0x86, 0xC9, 0x03, 0x55, 0xCC, 0x89, 0xC9, 0x03,
+	0x55, 0xCC, 0x8A, 0xC9, 0x03, 0x55, 0xCC, 0x8B,
+	0xC9, 0x03, 0x55, 0xCC, 0x8C, 0xC9, 0x03, 0x55,
+	0xCC, 0x8F, 0xC9, 0x03, 0x55, 0xCC, 0x91, 0xC9,
+	0x03, 0x55, 0xCC, 0xA3, 0xB5, 0x03, 0x55, 0xCC,
+	0xA4, 0xB5, 0x03, 0x55, 0xCC, 0xA8, 0xA5, 0x03,
+	0x55, 0xCC, 0xAD, 0xB5, 0x03, 0x55, 0xCC, 0xB0,
+	0xB5, 0x03, 0x56, 0xCC, 0x83, 0xC9, 0x03, 0x56,
+	// Bytes 3240 - 327f
+	0xCC, 0xA3, 0xB5, 0x03, 0x57, 0xCC, 0x80, 0xC9,
+	0x03, 0x57, 0xCC, 0x81, 0xC9, 0x03, 0x57, 0xCC,
+	0x82, 0xC9, 0x03, 0x57, 0xCC, 0x87, 0xC9, 0x03,
+	0x57, 0xCC, 0x88, 0xC9, 0x03, 0x57, 0xCC, 0xA3,
+	0xB5, 0x03, 0x58, 0xCC, 0x87, 0xC9, 0x03, 0x58,
+	0xCC, 0x88, 0xC9, 0x03, 0x59, 0xCC, 0x80, 0xC9,
+	0x03, 0x59, 0xCC, 0x81, 0xC9, 0x03, 0x59, 0xCC,
+	0x82, 0xC9, 0x03, 0x59, 0xCC, 0x83, 0xC9, 0x03,
+	// Bytes 3280 - 32bf
+	0x59, 0xCC, 0x84, 0xC9, 0x03, 0x59, 0xCC, 0x87,
+	0xC9, 0x03, 0x59, 0xCC, 0x88, 0xC9, 0x03, 0x59,
+	0xCC, 0x89, 0xC9, 0x03, 0x59, 0xCC, 0xA3, 0xB5,
+	0x03, 0x5A, 0xCC, 0x81, 0xC9, 0x03, 0x5A, 0xCC,
+	0x82, 0xC9, 0x03, 0x5A, 0xCC, 0x87, 0xC9, 0x03,
+	0x5A, 0xCC, 0x8C, 0xC9, 0x03, 0x5A, 0xCC, 0xA3,
+	0xB5, 0x03, 0x5A, 0xCC, 0xB1, 0xB5, 0x03, 0x61,
+	0xCC, 0x80, 0xC9, 0x03, 0x61, 0xCC, 0x81, 0xC9,
+	// Bytes 32c0 - 32ff
+	0x03, 0x61, 0xCC, 0x83, 0xC9, 0x03, 0x61, 0xCC,
+	0x84, 0xC9, 0x03, 0x61, 0xCC, 0x89, 0xC9, 0x03,
+	0x61, 0xCC, 0x8C, 0xC9, 0x03, 0x61, 0xCC, 0x8F,
+	0xC9, 0x03, 0x61, 0xCC, 0x91, 0xC9, 0x03, 0x61,
+	0xCC, 0xA5, 0xB5, 0x03, 0x61, 0xCC, 0xA8, 0xA5,
+	0x03, 0x62, 0xCC, 0x87, 0xC9, 0x03, 0x62, 0xCC,
+	0xA3, 0xB5, 0x03, 0x62, 0xCC, 0xB1, 0xB5, 0x03,
+	0x63, 0xCC, 0x81, 0xC9, 0x03, 0x63, 0xCC, 0x82,
+	// Bytes 3300 - 333f
+	0xC9, 0x03, 0x63, 0xCC, 0x87, 0xC9, 0x03, 0x63,
+	0xCC, 0x8C, 0xC9, 0x03, 0x64, 0xCC, 0x87, 0xC9,
+	0x03, 0x64, 0xCC, 0x8C, 0xC9, 0x03, 0x64, 0xCC,
+	0xA3, 0xB5, 0x03, 0x64, 0xCC, 0xA7, 0xA5, 0x03,
+	0x64, 0xCC, 0xAD, 0xB5, 0x03, 0x64, 0xCC, 0xB1,
+	0xB5, 0x03, 0x65, 0xCC, 0x80, 0xC9, 0x03, 0x65,
+	0xCC, 0x81, 0xC9, 0x03, 0x65, 0xCC, 0x83, 0xC9,
+	0x03, 0x65, 0xCC, 0x86, 0xC9, 0x03, 0x65, 0xCC,
+	// Bytes 3340 - 337f
+	0x87, 0xC9, 0x03, 0x65, 0xCC, 0x88, 0xC9, 0x03,
+	0x65, 0xCC, 0x89, 0xC9, 0x03, 0x65, 0xCC, 0x8C,
+	0xC9, 0x03, 0x65, 0xCC, 0x8F, 0xC9, 0x03, 0x65,
+	0xCC, 0x91, 0xC9, 0x03, 0x65, 0xCC, 0xA8, 0xA5,
+	0x03, 0x65, 0xCC, 0xAD, 0xB5, 0x03, 0x65, 0xCC,
+	0xB0, 0xB5, 0x03, 0x66, 0xCC, 0x87, 0xC9, 0x03,
+	0x67, 0xCC, 0x81, 0xC9, 0x03, 0x67, 0xCC, 0x82,
+	0xC9, 0x03, 0x67, 0xCC, 0x84, 0xC9, 0x03, 0x67,
+	// Bytes 3380 - 33bf
+	0xCC, 0x86, 0xC9, 0x03, 0x67, 0xCC, 0x87, 0xC9,
+	0x03, 0x67, 0xCC, 0x8C, 0xC9, 0x03, 0x67, 0xCC,
+	0xA7, 0xA5, 0x03, 0x68, 0xCC, 0x82, 0xC9, 0x03,
+	0x68, 0xCC, 0x87, 0xC9, 0x03, 0x68, 0xCC, 0x88,
+	0xC9, 0x03, 0x68, 0xCC, 0x8C, 0xC9, 0x03, 0x68,
+	0xCC, 0xA3, 0xB5, 0x03, 0x68, 0xCC, 0xA7, 0xA5,
+	0x03, 0x68, 0xCC, 0xAE, 0xB5, 0x03, 0x68, 0xCC,
+	0xB1, 0xB5, 0x03, 0x69, 0xCC, 0x80, 0xC9, 0x03,
+	// Bytes 33c0 - 33ff
+	0x69, 0xCC, 0x81, 0xC9, 0x03, 0x69, 0xCC, 0x82,
+	0xC9, 0x03, 0x69, 0xCC, 0x83, 0xC9, 0x03, 0x69,
+	0xCC, 0x84, 0xC9, 0x03, 0x69, 0xCC, 0x86, 0xC9,
+	0x03, 0x69, 0xCC, 0x89, 0xC9, 0x03, 0x69, 0xCC,
+	0x8C, 0xC9, 0x03, 0x69, 0xCC, 0x8F, 0xC9, 0x03,
+	0x69, 0xCC, 0x91, 0xC9, 0x03, 0x69, 0xCC, 0xA3,
+	0xB5, 0x03, 0x69, 0xCC, 0xA8, 0xA5, 0x03, 0x69,
+	0xCC, 0xB0, 0xB5, 0x03, 0x6A, 0xCC, 0x82, 0xC9,
+	// Bytes 3400 - 343f
+	0x03, 0x6A, 0xCC, 0x8C, 0xC9, 0x03, 0x6B, 0xCC,
+	0x81, 0xC9, 0x03, 0x6B, 0xCC, 0x8C, 0xC9, 0x03,
+	0x6B, 0xCC, 0xA3, 0xB5, 0x03, 0x6B, 0xCC, 0xA7,
+	0xA5, 0x03, 0x6B, 0xCC, 0xB1, 0xB5, 0x03, 0x6C,
+	0xCC, 0x81, 0xC9, 0x03, 0x6C, 0xCC, 0x8C, 0xC9,
+	0x03, 0x6C, 0xCC, 0xA7, 0xA5, 0x03, 0x6C, 0xCC,
+	0xAD, 0xB5, 0x03, 0x6C, 0xCC, 0xB1, 0xB5, 0x03,
+	0x6D, 0xCC, 0x81, 0xC9, 0x03, 0x6D, 0xCC, 0x87,
+	// Bytes 3440 - 347f
+	0xC9, 0x03, 0x6D, 0xCC, 0xA3, 0xB5, 0x03, 0x6E,
+	0xCC, 0x80, 0xC9, 0x03, 0x6E, 0xCC, 0x81, 0xC9,
+	0x03, 0x6E, 0xCC, 0x83, 0xC9, 0x03, 0x6E, 0xCC,
+	0x87, 0xC9, 0x03, 0x6E, 0xCC, 0x8C, 0xC9, 0x03,
+	0x6E, 0xCC, 0xA3, 0xB5, 0x03, 0x6E, 0xCC, 0xA7,
+	0xA5, 0x03, 0x6E, 0xCC, 0xAD, 0xB5, 0x03, 0x6E,
+	0xCC, 0xB1, 0xB5, 0x03, 0x6F, 0xCC, 0x80, 0xC9,
+	0x03, 0x6F, 0xCC, 0x81, 0xC9, 0x03, 0x6F, 0xCC,
+	// Bytes 3480 - 34bf
+	0x86, 0xC9, 0x03, 0x6F, 0xCC, 0x89, 0xC9, 0x03,
+	0x6F, 0xCC, 0x8B, 0xC9, 0x03, 0x6F, 0xCC, 0x8C,
+	0xC9, 0x03, 0x6F, 0xCC, 0x8F, 0xC9, 0x03, 0x6F,
+	0xCC, 0x91, 0xC9, 0x03, 0x70, 0xCC, 0x81, 0xC9,
+	0x03, 0x70, 0xCC, 0x87, 0xC9, 0x03, 0x72, 0xCC,
+	0x81, 0xC9, 0x03, 0x72, 0xCC, 0x87, 0xC9, 0x03,
+	0x72, 0xCC, 0x8C, 0xC9, 0x03, 0x72, 0xCC, 0x8F,
+	0xC9, 0x03, 0x72, 0xCC, 0x91, 0xC9, 0x03, 0x72,
+	// Bytes 34c0 - 34ff
+	0xCC, 0xA7, 0xA5, 0x03, 0x72, 0xCC, 0xB1, 0xB5,
+	0x03, 0x73, 0xCC, 0x82, 0xC9, 0x03, 0x73, 0xCC,
+	0x87, 0xC9, 0x03, 0x73, 0xCC, 0xA6, 0xB5, 0x03,
+	0x73, 0xCC, 0xA7, 0xA5, 0x03, 0x74, 0xCC, 0x87,
+	0xC9, 0x03, 0x74, 0xCC, 0x88, 0xC9, 0x03, 0x74,
+	0xCC, 0x8C, 0xC9, 0x03, 0x74, 0xCC, 0xA3, 0xB5,
+	0x03, 0x74, 0xCC, 0xA6, 0xB5, 0x03, 0x74, 0xCC,
+	0xA7, 0xA5, 0x03, 0x74, 0xCC, 0xAD, 0xB5, 0x03,
+	// Bytes 3500 - 353f
+	0x74, 0xCC, 0xB1, 0xB5, 0x03, 0x75, 0xCC, 0x80,
+	0xC9, 0x03, 0x75, 0xCC, 0x81, 0xC9, 0x03, 0x75,
+	0xCC, 0x82, 0xC9, 0x03, 0x75, 0xCC, 0x86, 0xC9,
+	0x03, 0x75, 0xCC, 0x89, 0xC9, 0x03, 0x75, 0xCC,
+	0x8A, 0xC9, 0x03, 0x75, 0xCC, 0x8B, 0xC9, 0x03,
+	0x75, 0xCC, 0x8C, 0xC9, 0x03, 0x75, 0xCC, 0x8F,
+	0xC9, 0x03, 0x75, 0xCC, 0x91, 0xC9, 0x03, 0x75,
+	0xCC, 0xA3, 0xB5, 0x03, 0x75, 0xCC, 0xA4, 0xB5,
+	// Bytes 3540 - 357f
+	0x03, 0x75, 0xCC, 0xA8, 0xA5, 0x03, 0x75, 0xCC,
+	0xAD, 0xB5, 0x03, 0x75, 0xCC, 0xB0, 0xB5, 0x03,
+	0x76, 0xCC, 0x83, 0xC9, 0x03, 0x76, 0xCC, 0xA3,
+	0xB5, 0x03, 0x77, 0xCC, 0x80, 0xC9, 0x03, 0x77,
+	0xCC, 0x81, 0xC9, 0x03, 0x77, 0xCC, 0x82, 0xC9,
+	0x03, 0x77, 0xCC, 0x87, 0xC9, 0x03, 0x77, 0xCC,
+	0x88, 0xC9, 0x03, 0x77, 0xCC, 0x8A, 0xC9, 0x03,
+	0x77, 0xCC, 0xA3, 0xB5, 0x03, 0x78, 0xCC, 0x87,
+	// Bytes 3580 - 35bf
+	0xC9, 0x03, 0x78, 0xCC, 0x88, 0xC9, 0x03, 0x79,
+	0xCC, 0x80, 0xC9, 0x03, 0x79, 0xCC, 0x81, 0xC9,
+	0x03, 0x79, 0xCC, 0x82, 0xC9, 0x03, 0x79, 0xCC,
+	0x83, 0xC9, 0x03, 0x79, 0xCC, 0x84, 0xC9, 0x03,
+	0x79, 0xCC, 0x87, 0xC9, 0x03, 0x79, 0xCC, 0x88,
+	0xC9, 0x03, 0x79, 0xCC, 0x89, 0xC9, 0x03, 0x79,
+	0xCC, 0x8A, 0xC9, 0x03, 0x79, 0xCC, 0xA3, 0xB5,
+	0x03, 0x7A, 0xCC, 0x81, 0xC9, 0x03, 0x7A, 0xCC,
+	// Bytes 35c0 - 35ff
+	0x82, 0xC9, 0x03, 0x7A, 0xCC, 0x87, 0xC9, 0x03,
+	0x7A, 0xCC, 0x8C, 0xC9, 0x03, 0x7A, 0xCC, 0xA3,
+	0xB5, 0x03, 0x7A, 0xCC, 0xB1, 0xB5, 0x04, 0xC2,
+	0xA8, 0xCC, 0x80, 0xCA, 0x04, 0xC2, 0xA8, 0xCC,
+	0x81, 0xCA, 0x04, 0xC2, 0xA8, 0xCD, 0x82, 0xCA,
+	0x04, 0xC3, 0x86, 0xCC, 0x81, 0xC9, 0x04, 0xC3,
+	0x86, 0xCC, 0x84, 0xC9, 0x04, 0xC3, 0x98, 0xCC,
+	0x81, 0xC9, 0x04, 0xC3, 0xA6, 0xCC, 0x81, 0xC9,
+	// Bytes 3600 - 363f
+	0x04, 0xC3, 0xA6, 0xCC, 0x84, 0xC9, 0x04, 0xC3,
+	0xB8, 0xCC, 0x81, 0xC9, 0x04, 0xC5, 0xBF, 0xCC,
+	0x87, 0xC9, 0x04, 0xC6, 0xB7, 0xCC, 0x8C, 0xC9,
+	0x04, 0xCA, 0x92, 0xCC, 0x8C, 0xC9, 0x04, 0xCE,
+	0x91, 0xCC, 0x80, 0xC9, 0x04, 0xCE, 0x91, 0xCC,
+	0x81, 0xC9, 0x04, 0xCE, 0x91, 0xCC, 0x84, 0xC9,
+	0x04, 0xCE, 0x91, 0xCC, 0x86, 0xC9, 0x04, 0xCE,
+	0x91, 0xCD, 0x85, 0xD9, 0x04, 0xCE, 0x95, 0xCC,
+	// Bytes 3640 - 367f
+	0x80, 0xC9, 0x04, 0xCE, 0x95, 0xCC, 0x81, 0xC9,
+	0x04, 0xCE, 0x97, 0xCC, 0x80, 0xC9, 0x04, 0xCE,
+	0x97, 0xCC, 0x81, 0xC9, 0x04, 0xCE, 0x97, 0xCD,
+	0x85, 0xD9, 0x04, 0xCE, 0x99, 0xCC, 0x80, 0xC9,
+	0x04, 0xCE, 0x99, 0xCC, 0x81, 0xC9, 0x04, 0xCE,
+	0x99, 0xCC, 0x84, 0xC9, 0x04, 0xCE, 0x99, 0xCC,
+	0x86, 0xC9, 0x04, 0xCE, 0x99, 0xCC, 0x88, 0xC9,
+	0x04, 0xCE, 0x9F, 0xCC, 0x80, 0xC9, 0x04, 0xCE,
+	// Bytes 3680 - 36bf
+	0x9F, 0xCC, 0x81, 0xC9, 0x04, 0xCE, 0xA1, 0xCC,
+	0x94, 0xC9, 0x04, 0xCE, 0xA5, 0xCC, 0x80, 0xC9,
+	0x04, 0xCE, 0xA5, 0xCC, 0x81, 0xC9, 0x04, 0xCE,
+	0xA5, 0xCC, 0x84, 0xC9, 0x04, 0xCE, 0xA5, 0xCC,
+	0x86, 0xC9, 0x04, 0xCE, 0xA5, 0xCC, 0x88, 0xC9,
+	0x04, 0xCE, 0xA9, 0xCC, 0x80, 0xC9, 0x04, 0xCE,
+	0xA9, 0xCC, 0x81, 0xC9, 0x04, 0xCE, 0xA9, 0xCD,
+	0x85, 0xD9, 0x04, 0xCE, 0xB1, 0xCC, 0x84, 0xC9,
+	// Bytes 36c0 - 36ff
+	0x04, 0xCE, 0xB1, 0xCC, 0x86, 0xC9, 0x04, 0xCE,
+	0xB1, 0xCD, 0x85, 0xD9, 0x04, 0xCE, 0xB5, 0xCC,
+	0x80, 0xC9, 0x04, 0xCE, 0xB5, 0xCC, 0x81, 0xC9,
+	0x04, 0xCE, 0xB7, 0xCD, 0x85, 0xD9, 0x04, 0xCE,
+	0xB9, 0xCC, 0x80, 0xC9, 0x04, 0xCE, 0xB9, 0xCC,
+	0x81, 0xC9, 0x04, 0xCE, 0xB9, 0xCC, 0x84, 0xC9,
+	0x04, 0xCE, 0xB9, 0xCC, 0x86, 0xC9, 0x04, 0xCE,
+	0xB9, 0xCD, 0x82, 0xC9, 0x04, 0xCE, 0xBF, 0xCC,
+	// Bytes 3700 - 373f
+	0x80, 0xC9, 0x04, 0xCE, 0xBF, 0xCC, 0x81, 0xC9,
+	0x04, 0xCF, 0x81, 0xCC, 0x93, 0xC9, 0x04, 0xCF,
+	0x81, 0xCC, 0x94, 0xC9, 0x04, 0xCF, 0x85, 0xCC,
+	0x80, 0xC9, 0x04, 0xCF, 0x85, 0xCC, 0x81, 0xC9,
+	0x04, 0xCF, 0x85, 0xCC, 0x84, 0xC9, 0x04, 0xCF,
+	0x85, 0xCC, 0x86, 0xC9, 0x04, 0xCF, 0x85, 0xCD,
+	0x82, 0xC9, 0x04, 0xCF, 0x89, 0xCD, 0x85, 0xD9,
+	0x04, 0xCF, 0x92, 0xCC, 0x81, 0xC9, 0x04, 0xCF,
+	// Bytes 3740 - 377f
+	0x92, 0xCC, 0x88, 0xC9, 0x04, 0xD0, 0x86, 0xCC,
+	0x88, 0xC9, 0x04, 0xD0, 0x90, 0xCC, 0x86, 0xC9,
+	0x04, 0xD0, 0x90, 0xCC, 0x88, 0xC9, 0x04, 0xD0,
+	0x93, 0xCC, 0x81, 0xC9, 0x04, 0xD0, 0x95, 0xCC,
+	0x80, 0xC9, 0x04, 0xD0, 0x95, 0xCC, 0x86, 0xC9,
+	0x04, 0xD0, 0x95, 0xCC, 0x88, 0xC9, 0x04, 0xD0,
+	0x96, 0xCC, 0x86, 0xC9, 0x04, 0xD0, 0x96, 0xCC,
+	0x88, 0xC9, 0x04, 0xD0, 0x97, 0xCC, 0x88, 0xC9,
+	// Bytes 3780 - 37bf
+	0x04, 0xD0, 0x98, 0xCC, 0x80, 0xC9, 0x04, 0xD0,
+	0x98, 0xCC, 0x84, 0xC9, 0x04, 0xD0, 0x98, 0xCC,
+	0x86, 0xC9, 0x04, 0xD0, 0x98, 0xCC, 0x88, 0xC9,
+	0x04, 0xD0, 0x9A, 0xCC, 0x81, 0xC9, 0x04, 0xD0,
+	0x9E, 0xCC, 0x88, 0xC9, 0x04, 0xD0, 0xA3, 0xCC,
+	0x84, 0xC9, 0x04, 0xD0, 0xA3, 0xCC, 0x86, 0xC9,
+	0x04, 0xD0, 0xA3, 0xCC, 0x88, 0xC9, 0x04, 0xD0,
+	0xA3, 0xCC, 0x8B, 0xC9, 0x04, 0xD0, 0xA7, 0xCC,
+	// Bytes 37c0 - 37ff
+	0x88, 0xC9, 0x04, 0xD0, 0xAB, 0xCC, 0x88, 0xC9,
+	0x04, 0xD0, 0xAD, 0xCC, 0x88, 0xC9, 0x04, 0xD0,
+	0xB0, 0xCC, 0x86, 0xC9, 0x04, 0xD0, 0xB0, 0xCC,
+	0x88, 0xC9, 0x04, 0xD0, 0xB3, 0xCC, 0x81, 0xC9,
+	0x04, 0xD0, 0xB5, 0xCC, 0x80, 0xC9, 0x04, 0xD0,
+	0xB5, 0xCC, 0x86, 0xC9, 0x04, 0xD0, 0xB5, 0xCC,
+	0x88, 0xC9, 0x04, 0xD0, 0xB6, 0xCC, 0x86, 0xC9,
+	0x04, 0xD0, 0xB6, 0xCC, 0x88, 0xC9, 0x04, 0xD0,
+	// Bytes 3800 - 383f
+	0xB7, 0xCC, 0x88, 0xC9, 0x04, 0xD0, 0xB8, 0xCC,
+	0x80, 0xC9, 0x04, 0xD0, 0xB8, 0xCC, 0x84, 0xC9,
+	0x04, 0xD0, 0xB8, 0xCC, 0x86, 0xC9, 0x04, 0xD0,
+	0xB8, 0xCC, 0x88, 0xC9, 0x04, 0xD0, 0xBA, 0xCC,
+	0x81, 0xC9, 0x04, 0xD0, 0xBE, 0xCC, 0x88, 0xC9,
+	0x04, 0xD1, 0x83, 0xCC, 0x84, 0xC9, 0x04, 0xD1,
+	0x83, 0xCC, 0x86, 0xC9, 0x04, 0xD1, 0x83, 0xCC,
+	0x88, 0xC9, 0x04, 0xD1, 0x83, 0xCC, 0x8B, 0xC9,
+	// Bytes 3840 - 387f
+	0x04, 0xD1, 0x87, 0xCC, 0x88, 0xC9, 0x04, 0xD1,
+	0x8B, 0xCC, 0x88, 0xC9, 0x04, 0xD1, 0x8D, 0xCC,
+	0x88, 0xC9, 0x04, 0xD1, 0x96, 0xCC, 0x88, 0xC9,
+	0x04, 0xD1, 0xB4, 0xCC, 0x8F, 0xC9, 0x04, 0xD1,
+	0xB5, 0xCC, 0x8F, 0xC9, 0x04, 0xD3, 0x98, 0xCC,
+	0x88, 0xC9, 0x04, 0xD3, 0x99, 0xCC, 0x88, 0xC9,
+	0x04, 0xD3, 0xA8, 0xCC, 0x88, 0xC9, 0x04, 0xD3,
+	0xA9, 0xCC, 0x88, 0xC9, 0x04, 0xD8, 0xA7, 0xD9,
+	// Bytes 3880 - 38bf
+	0x93, 0xC9, 0x04, 0xD8, 0xA7, 0xD9, 0x94, 0xC9,
+	0x04, 0xD8, 0xA7, 0xD9, 0x95, 0xB5, 0x04, 0xD9,
+	0x88, 0xD9, 0x94, 0xC9, 0x04, 0xD9, 0x8A, 0xD9,
+	0x94, 0xC9, 0x04, 0xDB, 0x81, 0xD9, 0x94, 0xC9,
+	0x04, 0xDB, 0x92, 0xD9, 0x94, 0xC9, 0x04, 0xDB,
+	0x95, 0xD9, 0x94, 0xC9, 0x05, 0x41, 0xCC, 0x82,
+	0xCC, 0x80, 0xCA, 0x05, 0x41, 0xCC, 0x82, 0xCC,
+	0x81, 0xCA, 0x05, 0x41, 0xCC, 0x82, 0xCC, 0x83,
+	// Bytes 38c0 - 38ff
+	0xCA, 0x05, 0x41, 0xCC, 0x82, 0xCC, 0x89, 0xCA,
+	0x05, 0x41, 0xCC, 0x86, 0xCC, 0x80, 0xCA, 0x05,
+	0x41, 0xCC, 0x86, 0xCC, 0x81, 0xCA, 0x05, 0x41,
+	0xCC, 0x86, 0xCC, 0x83, 0xCA, 0x05, 0x41, 0xCC,
+	0x86, 0xCC, 0x89, 0xCA, 0x05, 0x41, 0xCC, 0x87,
+	0xCC, 0x84, 0xCA, 0x05, 0x41, 0xCC, 0x88, 0xCC,
+	0x84, 0xCA, 0x05, 0x41, 0xCC, 0x8A, 0xCC, 0x81,
+	0xCA, 0x05, 0x41, 0xCC, 0xA3, 0xCC, 0x82, 0xCA,
+	// Bytes 3900 - 393f
+	0x05, 0x41, 0xCC, 0xA3, 0xCC, 0x86, 0xCA, 0x05,
+	0x43, 0xCC, 0xA7, 0xCC, 0x81, 0xCA, 0x05, 0x45,
+	0xCC, 0x82, 0xCC, 0x80, 0xCA, 0x05, 0x45, 0xCC,
+	0x82, 0xCC, 0x81, 0xCA, 0x05, 0x45, 0xCC, 0x82,
+	0xCC, 0x83, 0xCA, 0x05, 0x45, 0xCC, 0x82, 0xCC,
+	0x89, 0xCA, 0x05, 0x45, 0xCC, 0x84, 0xCC, 0x80,
+	0xCA, 0x05, 0x45, 0xCC, 0x84, 0xCC, 0x81, 0xCA,
+	0x05, 0x45, 0xCC, 0xA3, 0xCC, 0x82, 0xCA, 0x05,
+	// Bytes 3940 - 397f
+	0x45, 0xCC, 0xA7, 0xCC, 0x86, 0xCA, 0x05, 0x49,
+	0xCC, 0x88, 0xCC, 0x81, 0xCA, 0x05, 0x4C, 0xCC,
+	0xA3, 0xCC, 0x84, 0xCA, 0x05, 0x4F, 0xCC, 0x82,
+	0xCC, 0x80, 0xCA, 0x05, 0x4F, 0xCC, 0x82, 0xCC,
+	0x81, 0xCA, 0x05, 0x4F, 0xCC, 0x82, 0xCC, 0x83,
+	0xCA, 0x05, 0x4F, 0xCC, 0x82, 0xCC, 0x89, 0xCA,
+	0x05, 0x4F, 0xCC, 0x83, 0xCC, 0x81, 0xCA, 0x05,
+	0x4F, 0xCC, 0x83, 0xCC, 0x84, 0xCA, 0x05, 0x4F,
+	// Bytes 3980 - 39bf
+	0xCC, 0x83, 0xCC, 0x88, 0xCA, 0x05, 0x4F, 0xCC,
+	0x84, 0xCC, 0x80, 0xCA, 0x05, 0x4F, 0xCC, 0x84,
+	0xCC, 0x81, 0xCA, 0x05, 0x4F, 0xCC, 0x87, 0xCC,
+	0x84, 0xCA, 0x05, 0x4F, 0xCC, 0x88, 0xCC, 0x84,
+	0xCA, 0x05, 0x4F, 0xCC, 0x9B, 0xCC, 0x80, 0xCA,
+	0x05, 0x4F, 0xCC, 0x9B, 0xCC, 0x81, 0xCA, 0x05,
+	0x4F, 0xCC, 0x9B, 0xCC, 0x83, 0xCA, 0x05, 0x4F,
+	0xCC, 0x9B, 0xCC, 0x89, 0xCA, 0x05, 0x4F, 0xCC,
+	// Bytes 39c0 - 39ff
+	0x9B, 0xCC, 0xA3, 0xB6, 0x05, 0x4F, 0xCC, 0xA3,
+	0xCC, 0x82, 0xCA, 0x05, 0x4F, 0xCC, 0xA8, 0xCC,
+	0x84, 0xCA, 0x05, 0x52, 0xCC, 0xA3, 0xCC, 0x84,
+	0xCA, 0x05, 0x53, 0xCC, 0x81, 0xCC, 0x87, 0xCA,
+	0x05, 0x53, 0xCC, 0x8C, 0xCC, 0x87, 0xCA, 0x05,
+	0x53, 0xCC, 0xA3, 0xCC, 0x87, 0xCA, 0x05, 0x55,
+	0xCC, 0x83, 0xCC, 0x81, 0xCA, 0x05, 0x55, 0xCC,
+	0x84, 0xCC, 0x88, 0xCA, 0x05, 0x55, 0xCC, 0x88,
+	// Bytes 3a00 - 3a3f
+	0xCC, 0x80, 0xCA, 0x05, 0x55, 0xCC, 0x88, 0xCC,
+	0x81, 0xCA, 0x05, 0x55, 0xCC, 0x88, 0xCC, 0x84,
+	0xCA, 0x05, 0x55, 0xCC, 0x88, 0xCC, 0x8C, 0xCA,
+	0x05, 0x55, 0xCC, 0x9B, 0xCC, 0x80, 0xCA, 0x05,
+	0x55, 0xCC, 0x9B, 0xCC, 0x81, 0xCA, 0x05, 0x55,
+	0xCC, 0x9B, 0xCC, 0x83, 0xCA, 0x05, 0x55, 0xCC,
+	0x9B, 0xCC, 0x89, 0xCA, 0x05, 0x55, 0xCC, 0x9B,
+	0xCC, 0xA3, 0xB6, 0x05, 0x61, 0xCC, 0x82, 0xCC,
+	// Bytes 3a40 - 3a7f
+	0x80, 0xCA, 0x05, 0x61, 0xCC, 0x82, 0xCC, 0x81,
+	0xCA, 0x05, 0x61, 0xCC, 0x82, 0xCC, 0x83, 0xCA,
+	0x05, 0x61, 0xCC, 0x82, 0xCC, 0x89, 0xCA, 0x05,
+	0x61, 0xCC, 0x86, 0xCC, 0x80, 0xCA, 0x05, 0x61,
+	0xCC, 0x86, 0xCC, 0x81, 0xCA, 0x05, 0x61, 0xCC,
+	0x86, 0xCC, 0x83, 0xCA, 0x05, 0x61, 0xCC, 0x86,
+	0xCC, 0x89, 0xCA, 0x05, 0x61, 0xCC, 0x87, 0xCC,
+	0x84, 0xCA, 0x05, 0x61, 0xCC, 0x88, 0xCC, 0x84,
+	// Bytes 3a80 - 3abf
+	0xCA, 0x05, 0x61, 0xCC, 0x8A, 0xCC, 0x81, 0xCA,
+	0x05, 0x61, 0xCC, 0xA3, 0xCC, 0x82, 0xCA, 0x05,
+	0x61, 0xCC, 0xA3, 0xCC, 0x86, 0xCA, 0x05, 0x63,
+	0xCC, 0xA7, 0xCC, 0x81, 0xCA, 0x05, 0x65, 0xCC,
+	0x82, 0xCC, 0x80, 0xCA, 0x05, 0x65, 0xCC, 0x82,
+	0xCC, 0x81, 0xCA, 0x05, 0x65, 0xCC, 0x82, 0xCC,
+	0x83, 0xCA, 0x05, 0x65, 0xCC, 0x82, 0xCC, 0x89,
+	0xCA, 0x05, 0x65, 0xCC, 0x84, 0xCC, 0x80, 0xCA,
+	// Bytes 3ac0 - 3aff
+	0x05, 0x65, 0xCC, 0x84, 0xCC, 0x81, 0xCA, 0x05,
+	0x65, 0xCC, 0xA3, 0xCC, 0x82, 0xCA, 0x05, 0x65,
+	0xCC, 0xA7, 0xCC, 0x86, 0xCA, 0x05, 0x69, 0xCC,
+	0x88, 0xCC, 0x81, 0xCA, 0x05, 0x6C, 0xCC, 0xA3,
+	0xCC, 0x84, 0xCA, 0x05, 0x6F, 0xCC, 0x82, 0xCC,
+	0x80, 0xCA, 0x05, 0x6F, 0xCC, 0x82, 0xCC, 0x81,
+	0xCA, 0x05, 0x6F, 0xCC, 0x82, 0xCC, 0x83, 0xCA,
+	0x05, 0x6F, 0xCC, 0x82, 0xCC, 0x89, 0xCA, 0x05,
+	// Bytes 3b00 - 3b3f
+	0x6F, 0xCC, 0x83, 0xCC, 0x81, 0xCA, 0x05, 0x6F,
+	0xCC, 0x83, 0xCC, 0x84, 0xCA, 0x05, 0x6F, 0xCC,
+	0x83, 0xCC, 0x88, 0xCA, 0x05, 0x6F, 0xCC, 0x84,
+	0xCC, 0x80, 0xCA, 0x05, 0x6F, 0xCC, 0x84, 0xCC,
+	0x81, 0xCA, 0x05, 0x6F, 0xCC, 0x87, 0xCC, 0x84,
+	0xCA, 0x05, 0x6F, 0xCC, 0x88, 0xCC, 0x84, 0xCA,
+	0x05, 0x6F, 0xCC, 0x9B, 0xCC, 0x80, 0xCA, 0x05,
+	0x6F, 0xCC, 0x9B, 0xCC, 0x81, 0xCA, 0x05, 0x6F,
+	// Bytes 3b40 - 3b7f
+	0xCC, 0x9B, 0xCC, 0x83, 0xCA, 0x05, 0x6F, 0xCC,
+	0x9B, 0xCC, 0x89, 0xCA, 0x05, 0x6F, 0xCC, 0x9B,
+	0xCC, 0xA3, 0xB6, 0x05, 0x6F, 0xCC, 0xA3, 0xCC,
+	0x82, 0xCA, 0x05, 0x6F, 0xCC, 0xA8, 0xCC, 0x84,
+	0xCA, 0x05, 0x72, 0xCC, 0xA3, 0xCC, 0x84, 0xCA,
+	0x05, 0x73, 0xCC, 0x81, 0xCC, 0x87, 0xCA, 0x05,
+	0x73, 0xCC, 0x8C, 0xCC, 0x87, 0xCA, 0x05, 0x73,
+	0xCC, 0xA3, 0xCC, 0x87, 0xCA, 0x05, 0x75, 0xCC,
+	// Bytes 3b80 - 3bbf
+	0x83, 0xCC, 0x81, 0xCA, 0x05, 0x75, 0xCC, 0x84,
+	0xCC, 0x88, 0xCA, 0x05, 0x75, 0xCC, 0x88, 0xCC,
+	0x80, 0xCA, 0x05, 0x75, 0xCC, 0x88, 0xCC, 0x81,
+	0xCA, 0x05, 0x75, 0xCC, 0x88, 0xCC, 0x84, 0xCA,
+	0x05, 0x75, 0xCC, 0x88, 0xCC, 0x8C, 0xCA, 0x05,
+	0x75, 0xCC, 0x9B, 0xCC, 0x80, 0xCA, 0x05, 0x75,
+	0xCC, 0x9B, 0xCC, 0x81, 0xCA, 0x05, 0x75, 0xCC,
+	0x9B, 0xCC, 0x83, 0xCA, 0x05, 0x75, 0xCC, 0x9B,
+	// Bytes 3bc0 - 3bff
+	0xCC, 0x89, 0xCA, 0x05, 0x75, 0xCC, 0x9B, 0xCC,
+	0xA3, 0xB6, 0x05, 0xE1, 0xBE, 0xBF, 0xCC, 0x80,
+	0xCA, 0x05, 0xE1, 0xBE, 0xBF, 0xCC, 0x81, 0xCA,
+	0x05, 0xE1, 0xBE, 0xBF, 0xCD, 0x82, 0xCA, 0x05,
+	0xE1, 0xBF, 0xBE, 0xCC, 0x80, 0xCA, 0x05, 0xE1,
+	0xBF, 0xBE, 0xCC, 0x81, 0xCA, 0x05, 0xE1, 0xBF,
+	0xBE, 0xCD, 0x82, 0xCA, 0x05, 0xE2, 0x86, 0x90,
+	0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x86, 0x92, 0xCC,
+	// Bytes 3c00 - 3c3f
+	0xB8, 0x05, 0x05, 0xE2, 0x86, 0x94, 0xCC, 0xB8,
+	0x05, 0x05, 0xE2, 0x87, 0x90, 0xCC, 0xB8, 0x05,
+	0x05, 0xE2, 0x87, 0x92, 0xCC, 0xB8, 0x05, 0x05,
+	0xE2, 0x87, 0x94, 0xCC, 0xB8, 0x05, 0x05, 0xE2,
+	0x88, 0x83, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x88,
+	0x88, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x88, 0x8B,
+	0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x88, 0xA3, 0xCC,
+	0xB8, 0x05, 0x05, 0xE2, 0x88, 0xA5, 0xCC, 0xB8,
+	// Bytes 3c40 - 3c7f
+	0x05, 0x05, 0xE2, 0x88, 0xBC, 0xCC, 0xB8, 0x05,
+	0x05, 0xE2, 0x89, 0x83, 0xCC, 0xB8, 0x05, 0x05,
+	0xE2, 0x89, 0x85, 0xCC, 0xB8, 0x05, 0x05, 0xE2,
+	0x89, 0x88, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x89,
+	0x8D, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x89, 0xA1,
+	0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x89, 0xA4, 0xCC,
+	0xB8, 0x05, 0x05, 0xE2, 0x89, 0xA5, 0xCC, 0xB8,
+	0x05, 0x05, 0xE2, 0x89, 0xB2, 0xCC, 0xB8, 0x05,
+	// Bytes 3c80 - 3cbf
+	0x05, 0xE2, 0x89, 0xB3, 0xCC, 0xB8, 0x05, 0x05,
+	0xE2, 0x89, 0xB6, 0xCC, 0xB8, 0x05, 0x05, 0xE2,
+	0x89, 0xB7, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x89,
+	0xBA, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x89, 0xBB,
+	0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x89, 0xBC, 0xCC,
+	0xB8, 0x05, 0x05, 0xE2, 0x89, 0xBD, 0xCC, 0xB8,
+	0x05, 0x05, 0xE2, 0x8A, 0x82, 0xCC, 0xB8, 0x05,
+	0x05, 0xE2, 0x8A, 0x83, 0xCC, 0xB8, 0x05, 0x05,
+	// Bytes 3cc0 - 3cff
+	0xE2, 0x8A, 0x86, 0xCC, 0xB8, 0x05, 0x05, 0xE2,
+	0x8A, 0x87, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x8A,
+	0x91, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x8A, 0x92,
+	0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x8A, 0xA2, 0xCC,
+	0xB8, 0x05, 0x05, 0xE2, 0x8A, 0xA8, 0xCC, 0xB8,
+	0x05, 0x05, 0xE2, 0x8A, 0xA9, 0xCC, 0xB8, 0x05,
+	0x05, 0xE2, 0x8A, 0xAB, 0xCC, 0xB8, 0x05, 0x05,
+	0xE2, 0x8A, 0xB2, 0xCC, 0xB8, 0x05, 0x05, 0xE2,
+	// Bytes 3d00 - 3d3f
+	0x8A, 0xB3, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x8A,
+	0xB4, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x8A, 0xB5,
+	0xCC, 0xB8, 0x05, 0x06, 0xCE, 0x91, 0xCC, 0x93,
+	0xCD, 0x85, 0xDA, 0x06, 0xCE, 0x91, 0xCC, 0x94,
+	0xCD, 0x85, 0xDA, 0x06, 0xCE, 0x95, 0xCC, 0x93,
+	0xCC, 0x80, 0xCA, 0x06, 0xCE, 0x95, 0xCC, 0x93,
+	0xCC, 0x81, 0xCA, 0x06, 0xCE, 0x95, 0xCC, 0x94,
+	0xCC, 0x80, 0xCA, 0x06, 0xCE, 0x95, 0xCC, 0x94,
+	// Bytes 3d40 - 3d7f
+	0xCC, 0x81, 0xCA, 0x06, 0xCE, 0x97, 0xCC, 0x93,
+	0xCD, 0x85, 0xDA, 0x06, 0xCE, 0x97, 0xCC, 0x94,
+	0xCD, 0x85, 0xDA, 0x06, 0xCE, 0x99, 0xCC, 0x93,
+	0xCC, 0x80, 0xCA, 0x06, 0xCE, 0x99, 0xCC, 0x93,
+	0xCC, 0x81, 0xCA, 0x06, 0xCE, 0x99, 0xCC, 0x93,
+	0xCD, 0x82, 0xCA, 0x06, 0xCE, 0x99, 0xCC, 0x94,
+	0xCC, 0x80, 0xCA, 0x06, 0xCE, 0x99, 0xCC, 0x94,
+	0xCC, 0x81, 0xCA, 0x06, 0xCE, 0x99, 0xCC, 0x94,
+	// Bytes 3d80 - 3dbf
+	0xCD, 0x82, 0xCA, 0x06, 0xCE, 0x9F, 0xCC, 0x93,
+	0xCC, 0x80, 0xCA, 0x06, 0xCE, 0x9F, 0xCC, 0x93,
+	0xCC, 0x81, 0xCA, 0x06, 0xCE, 0x9F, 0xCC, 0x94,
+	0xCC, 0x80, 0xCA, 0x06, 0xCE, 0x9F, 0xCC, 0x94,
+	0xCC, 0x81, 0xCA, 0x06, 0xCE, 0xA5, 0xCC, 0x94,
+	0xCC, 0x80, 0xCA, 0x06, 0xCE, 0xA5, 0xCC, 0x94,
+	0xCC, 0x81, 0xCA, 0x06, 0xCE, 0xA5, 0xCC, 0x94,
+	0xCD, 0x82, 0xCA, 0x06, 0xCE, 0xA9, 0xCC, 0x93,
+	// Bytes 3dc0 - 3dff
+	0xCD, 0x85, 0xDA, 0x06, 0xCE, 0xA9, 0xCC, 0x94,
+	0xCD, 0x85, 0xDA, 0x06, 0xCE, 0xB1, 0xCC, 0x80,
+	0xCD, 0x85, 0xDA, 0x06, 0xCE, 0xB1, 0xCC, 0x81,
+	0xCD, 0x85, 0xDA, 0x06, 0xCE, 0xB1, 0xCC, 0x93,
+	0xCD, 0x85, 0xDA, 0x06, 0xCE, 0xB1, 0xCC, 0x94,
+	0xCD, 0x85, 0xDA, 0x06, 0xCE, 0xB1, 0xCD, 0x82,
+	0xCD, 0x85, 0xDA, 0x06, 0xCE, 0xB5, 0xCC, 0x93,
+	0xCC, 0x80, 0xCA, 0x06, 0xCE, 0xB5, 0xCC, 0x93,
+	// Bytes 3e00 - 3e3f
+	0xCC, 0x81, 0xCA, 0x06, 0xCE, 0xB5, 0xCC, 0x94,
+	0xCC, 0x80, 0xCA, 0x06, 0xCE, 0xB5, 0xCC, 0x94,
+	0xCC, 0x81, 0xCA, 0x06, 0xCE, 0xB7, 0xCC, 0x80,
+	0xCD, 0x85, 0xDA, 0x06, 0xCE, 0xB7, 0xCC, 0x81,
+	0xCD, 0x85, 0xDA, 0x06, 0xCE, 0xB7, 0xCC, 0x93,
+	0xCD, 0x85, 0xDA, 0x06, 0xCE, 0xB7, 0xCC, 0x94,
+	0xCD, 0x85, 0xDA, 0x06, 0xCE, 0xB7, 0xCD, 0x82,
+	0xCD, 0x85, 0xDA, 0x06, 0xCE, 0xB9, 0xCC, 0x88,
+	// Bytes 3e40 - 3e7f
+	0xCC, 0x80, 0xCA, 0x06, 0xCE, 0xB9, 0xCC, 0x88,
+	0xCC, 0x81, 0xCA, 0x06, 0xCE, 0xB9, 0xCC, 0x88,
+	0xCD, 0x82, 0xCA, 0x06, 0xCE, 0xB9, 0xCC, 0x93,
+	0xCC, 0x80, 0xCA, 0x06, 0xCE, 0xB9, 0xCC, 0x93,
+	0xCC, 0x81, 0xCA, 0x06, 0xCE, 0xB9, 0xCC, 0x93,
+	0xCD, 0x82, 0xCA, 0x06, 0xCE, 0xB9, 0xCC, 0x94,
+	0xCC, 0x80, 0xCA, 0x06, 0xCE, 0xB9, 0xCC, 0x94,
+	0xCC, 0x81, 0xCA, 0x06, 0xCE, 0xB9, 0xCC, 0x94,
+	// Bytes 3e80 - 3ebf
+	0xCD, 0x82, 0xCA, 0x06, 0xCE, 0xBF, 0xCC, 0x93,
+	0xCC, 0x80, 0xCA, 0x06, 0xCE, 0xBF, 0xCC, 0x93,
+	0xCC, 0x81, 0xCA, 0x06, 0xCE, 0xBF, 0xCC, 0x94,
+	0xCC, 0x80, 0xCA, 0x06, 0xCE, 0xBF, 0xCC, 0x94,
+	0xCC, 0x81, 0xCA, 0x06, 0xCF, 0x85, 0xCC, 0x88,
+	0xCC, 0x80, 0xCA, 0x06, 0xCF, 0x85, 0xCC, 0x88,
+	0xCC, 0x81, 0xCA, 0x06, 0xCF, 0x85, 0xCC, 0x88,
+	0xCD, 0x82, 0xCA, 0x06, 0xCF, 0x85, 0xCC, 0x93,
+	// Bytes 3ec0 - 3eff
+	0xCC, 0x80, 0xCA, 0x06, 0xCF, 0x85, 0xCC, 0x93,
+	0xCC, 0x81, 0xCA, 0x06, 0xCF, 0x85, 0xCC, 0x93,
+	0xCD, 0x82, 0xCA, 0x06, 0xCF, 0x85, 0xCC, 0x94,
+	0xCC, 0x80, 0xCA, 0x06, 0xCF, 0x85, 0xCC, 0x94,
+	0xCC, 0x81, 0xCA, 0x06, 0xCF, 0x85, 0xCC, 0x94,
+	0xCD, 0x82, 0xCA, 0x06, 0xCF, 0x89, 0xCC, 0x80,
+	0xCD, 0x85, 0xDA, 0x06, 0xCF, 0x89, 0xCC, 0x81,
+	0xCD, 0x85, 0xDA, 0x06, 0xCF, 0x89, 0xCC, 0x93,
+	// Bytes 3f00 - 3f3f
+	0xCD, 0x85, 0xDA, 0x06, 0xCF, 0x89, 0xCC, 0x94,
+	0xCD, 0x85, 0xDA, 0x06, 0xCF, 0x89, 0xCD, 0x82,
+	0xCD, 0x85, 0xDA, 0x06, 0xE0, 0xA4, 0xA8, 0xE0,
+	0xA4, 0xBC, 0x09, 0x06, 0xE0, 0xA4, 0xB0, 0xE0,
+	0xA4, 0xBC, 0x09, 0x06, 0xE0, 0xA4, 0xB3, 0xE0,
+	0xA4, 0xBC, 0x09, 0x06, 0xE0, 0xB1, 0x86, 0xE0,
+	0xB1, 0x96, 0x85, 0x06, 0xE0, 0xB7, 0x99, 0xE0,
+	0xB7, 0x8A, 0x11, 0x06, 0xE3, 0x81, 0x86, 0xE3,
+	// Bytes 3f40 - 3f7f
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x81, 0x8B, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x81, 0x8D, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x81, 0x8F, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x81, 0x91, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x81, 0x93, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x81, 0x95, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x81, 0x97, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x81, 0x99, 0xE3,
+	// Bytes 3f80 - 3fbf
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x81, 0x9B, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x81, 0x9D, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x81, 0x9F, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x81, 0xA1, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x81, 0xA4, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x81, 0xA6, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x81, 0xA8, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x81, 0xAF, 0xE3,
+	// Bytes 3fc0 - 3fff
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x81, 0xAF, 0xE3,
+	0x82, 0x9A, 0x0D, 0x06, 0xE3, 0x81, 0xB2, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x81, 0xB2, 0xE3,
+	0x82, 0x9A, 0x0D, 0x06, 0xE3, 0x81, 0xB5, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x81, 0xB5, 0xE3,
+	0x82, 0x9A, 0x0D, 0x06, 0xE3, 0x81, 0xB8, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x81, 0xB8, 0xE3,
+	0x82, 0x9A, 0x0D, 0x06, 0xE3, 0x81, 0xBB, 0xE3,
+	// Bytes 4000 - 403f
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x81, 0xBB, 0xE3,
+	0x82, 0x9A, 0x0D, 0x06, 0xE3, 0x82, 0x9D, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x82, 0xA6, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x82, 0xAB, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x82, 0xAD, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x82, 0xAF, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x82, 0xB1, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x82, 0xB3, 0xE3,
+	// Bytes 4040 - 407f
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x82, 0xB5, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x82, 0xB7, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x82, 0xB9, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x82, 0xBB, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x82, 0xBD, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x82, 0xBF, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x83, 0x81, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x83, 0x84, 0xE3,
+	// Bytes 4080 - 40bf
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x83, 0x86, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x83, 0x88, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x83, 0x8F, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x83, 0x8F, 0xE3,
+	0x82, 0x9A, 0x0D, 0x06, 0xE3, 0x83, 0x92, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x83, 0x92, 0xE3,
+	0x82, 0x9A, 0x0D, 0x06, 0xE3, 0x83, 0x95, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x83, 0x95, 0xE3,
+	// Bytes 40c0 - 40ff
+	0x82, 0x9A, 0x0D, 0x06, 0xE3, 0x83, 0x98, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x83, 0x98, 0xE3,
+	0x82, 0x9A, 0x0D, 0x06, 0xE3, 0x83, 0x9B, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x83, 0x9B, 0xE3,
+	0x82, 0x9A, 0x0D, 0x06, 0xE3, 0x83, 0xAF, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x83, 0xB0, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x83, 0xB1, 0xE3,
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x83, 0xB2, 0xE3,
+	// Bytes 4100 - 413f
+	0x82, 0x99, 0x0D, 0x06, 0xE3, 0x83, 0xBD, 0xE3,
+	0x82, 0x99, 0x0D, 0x08, 0xCE, 0x91, 0xCC, 0x93,
+	0xCC, 0x80, 0xCD, 0x85, 0xDB, 0x08, 0xCE, 0x91,
+	0xCC, 0x93, 0xCC, 0x81, 0xCD, 0x85, 0xDB, 0x08,
+	0xCE, 0x91, 0xCC, 0x93, 0xCD, 0x82, 0xCD, 0x85,
+	0xDB, 0x08, 0xCE, 0x91, 0xCC, 0x94, 0xCC, 0x80,
+	0xCD, 0x85, 0xDB, 0x08, 0xCE, 0x91, 0xCC, 0x94,
+	0xCC, 0x81, 0xCD, 0x85, 0xDB, 0x08, 0xCE, 0x91,
+	// Bytes 4140 - 417f
+	0xCC, 0x94, 0xCD, 0x82, 0xCD, 0x85, 0xDB, 0x08,
+	0xCE, 0x97, 0xCC, 0x93, 0xCC, 0x80, 0xCD, 0x85,
+	0xDB, 0x08, 0xCE, 0x97, 0xCC, 0x93, 0xCC, 0x81,
+	0xCD, 0x85, 0xDB, 0x08, 0xCE, 0x97, 0xCC, 0x93,
+	0xCD, 0x82, 0xCD, 0x85, 0xDB, 0x08, 0xCE, 0x97,
+	0xCC, 0x94, 0xCC, 0x80, 0xCD, 0x85, 0xDB, 0x08,
+	0xCE, 0x97, 0xCC, 0x94, 0xCC, 0x81, 0xCD, 0x85,
+	0xDB, 0x08, 0xCE, 0x97, 0xCC, 0x94, 0xCD, 0x82,
+	// Bytes 4180 - 41bf
+	0xCD, 0x85, 0xDB, 0x08, 0xCE, 0xA9, 0xCC, 0x93,
+	0xCC, 0x80, 0xCD, 0x85, 0xDB, 0x08, 0xCE, 0xA9,
+	0xCC, 0x93, 0xCC, 0x81, 0xCD, 0x85, 0xDB, 0x08,
+	0xCE, 0xA9, 0xCC, 0x93, 0xCD, 0x82, 0xCD, 0x85,
+	0xDB, 0x08, 0xCE, 0xA9, 0xCC, 0x94, 0xCC, 0x80,
+	0xCD, 0x85, 0xDB, 0x08, 0xCE, 0xA9, 0xCC, 0x94,
+	0xCC, 0x81, 0xCD, 0x85, 0xDB, 0x08, 0xCE, 0xA9,
+	0xCC, 0x94, 0xCD, 0x82, 0xCD, 0x85, 0xDB, 0x08,
+	// Bytes 41c0 - 41ff
+	0xCE, 0xB1, 0xCC, 0x93, 0xCC, 0x80, 0xCD, 0x85,
+	0xDB, 0x08, 0xCE, 0xB1, 0xCC, 0x93, 0xCC, 0x81,
+	0xCD, 0x85, 0xDB, 0x08, 0xCE, 0xB1, 0xCC, 0x93,
+	0xCD, 0x82, 0xCD, 0x85, 0xDB, 0x08, 0xCE, 0xB1,
+	0xCC, 0x94, 0xCC, 0x80, 0xCD, 0x85, 0xDB, 0x08,
+	0xCE, 0xB1, 0xCC, 0x94, 0xCC, 0x81, 0xCD, 0x85,
+	0xDB, 0x08, 0xCE, 0xB1, 0xCC, 0x94, 0xCD, 0x82,
+	0xCD, 0x85, 0xDB, 0x08, 0xCE, 0xB7, 0xCC, 0x93,
+	// Bytes 4200 - 423f
+	0xCC, 0x80, 0xCD, 0x85, 0xDB, 0x08, 0xCE, 0xB7,
+	0xCC, 0x93, 0xCC, 0x81, 0xCD, 0x85, 0xDB, 0x08,
+	0xCE, 0xB7, 0xCC, 0x93, 0xCD, 0x82, 0xCD, 0x85,
+	0xDB, 0x08, 0xCE, 0xB7, 0xCC, 0x94, 0xCC, 0x80,
+	0xCD, 0x85, 0xDB, 0x08, 0xCE, 0xB7, 0xCC, 0x94,
+	0xCC, 0x81, 0xCD, 0x85, 0xDB, 0x08, 0xCE, 0xB7,
+	0xCC, 0x94, 0xCD, 0x82, 0xCD, 0x85, 0xDB, 0x08,
+	0xCF, 0x89, 0xCC, 0x93, 0xCC, 0x80, 0xCD, 0x85,
+	// Bytes 4240 - 427f
+	0xDB, 0x08, 0xCF, 0x89, 0xCC, 0x93, 0xCC, 0x81,
+	0xCD, 0x85, 0xDB, 0x08, 0xCF, 0x89, 0xCC, 0x93,
+	0xCD, 0x82, 0xCD, 0x85, 0xDB, 0x08, 0xCF, 0x89,
+	0xCC, 0x94, 0xCC, 0x80, 0xCD, 0x85, 0xDB, 0x08,
+	0xCF, 0x89, 0xCC, 0x94, 0xCC, 0x81, 0xCD, 0x85,
+	0xDB, 0x08, 0xCF, 0x89, 0xCC, 0x94, 0xCD, 0x82,
+	0xCD, 0x85, 0xDB, 0x08, 0xF0, 0x91, 0x82, 0x99,
+	0xF0, 0x91, 0x82, 0xBA, 0x09, 0x08, 0xF0, 0x91,
+	// Bytes 4280 - 42bf
+	0x82, 0x9B, 0xF0, 0x91, 0x82, 0xBA, 0x09, 0x08,
+	0xF0, 0x91, 0x82, 0xA5, 0xF0, 0x91, 0x82, 0xBA,
+	0x09, 0x42, 0xC2, 0xB4, 0x01, 0x43, 0x20, 0xCC,
+	0x81, 0xC9, 0x43, 0x20, 0xCC, 0x83, 0xC9, 0x43,
+	0x20, 0xCC, 0x84, 0xC9, 0x43, 0x20, 0xCC, 0x85,
+	0xC9, 0x43, 0x20, 0xCC, 0x86, 0xC9, 0x43, 0x20,
+	0xCC, 0x87, 0xC9, 0x43, 0x20, 0xCC, 0x88, 0xC9,
+	0x43, 0x20, 0xCC, 0x8A, 0xC9, 0x43, 0x20, 0xCC,
+	// Bytes 42c0 - 42ff
+	0x8B, 0xC9, 0x43, 0x20, 0xCC, 0x93, 0xC9, 0x43,
+	0x20, 0xCC, 0x94, 0xC9, 0x43, 0x20, 0xCC, 0xA7,
+	0xA5, 0x43, 0x20, 0xCC, 0xA8, 0xA5, 0x43, 0x20,
+	0xCC, 0xB3, 0xB5, 0x43, 0x20, 0xCD, 0x82, 0xC9,
+	0x43, 0x20, 0xCD, 0x85, 0xD9, 0x43, 0x20, 0xD9,
+	0x8B, 0x59, 0x43, 0x20, 0xD9, 0x8C, 0x5D, 0x43,
+	0x20, 0xD9, 0x8D, 0x61, 0x43, 0x20, 0xD9, 0x8E,
+	0x65, 0x43, 0x20, 0xD9, 0x8F, 0x69, 0x43, 0x20,
+	// Bytes 4300 - 433f
+	0xD9, 0x90, 0x6D, 0x43, 0x20, 0xD9, 0x91, 0x71,
+	0x43, 0x20, 0xD9, 0x92, 0x75, 0x43, 0x41, 0xCC,
+	0x8A, 0xC9, 0x43, 0x73, 0xCC, 0x87, 0xC9, 0x44,
+	0x20, 0xE3, 0x82, 0x99, 0x0D, 0x44, 0x20, 0xE3,
+	0x82, 0x9A, 0x0D, 0x44, 0xC2, 0xA8, 0xCC, 0x81,
+	0xCA, 0x44, 0xCE, 0x91, 0xCC, 0x81, 0xC9, 0x44,
+	0xCE, 0x95, 0xCC, 0x81, 0xC9, 0x44, 0xCE, 0x97,
+	0xCC, 0x81, 0xC9, 0x44, 0xCE, 0x99, 0xCC, 0x81,
+	// Bytes 4340 - 437f
+	0xC9, 0x44, 0xCE, 0x9F, 0xCC, 0x81, 0xC9, 0x44,
+	0xCE, 0xA5, 0xCC, 0x81, 0xC9, 0x44, 0xCE, 0xA5,
+	0xCC, 0x88, 0xC9, 0x44, 0xCE, 0xA9, 0xCC, 0x81,
+	0xC9, 0x44, 0xCE, 0xB1, 0xCC, 0x81, 0xC9, 0x44,
+	0xCE, 0xB5, 0xCC, 0x81, 0xC9, 0x44, 0xCE, 0xB7,
+	0xCC, 0x81, 0xC9, 0x44, 0xCE, 0xB9, 0xCC, 0x81,
+	0xC9, 0x44, 0xCE, 0xBF, 0xCC, 0x81, 0xC9, 0x44,
+	0xCF, 0x85, 0xCC, 0x81, 0xC9, 0x44, 0xCF, 0x89,
+	// Bytes 4380 - 43bf
+	0xCC, 0x81, 0xC9, 0x44, 0xD7, 0x90, 0xD6, 0xB7,
+	0x31, 0x44, 0xD7, 0x90, 0xD6, 0xB8, 0x35, 0x44,
+	0xD7, 0x90, 0xD6, 0xBC, 0x41, 0x44, 0xD7, 0x91,
+	0xD6, 0xBC, 0x41, 0x44, 0xD7, 0x91, 0xD6, 0xBF,
+	0x49, 0x44, 0xD7, 0x92, 0xD6, 0xBC, 0x41, 0x44,
+	0xD7, 0x93, 0xD6, 0xBC, 0x41, 0x44, 0xD7, 0x94,
+	0xD6, 0xBC, 0x41, 0x44, 0xD7, 0x95, 0xD6, 0xB9,
+	0x39, 0x44, 0xD7, 0x95, 0xD6, 0xBC, 0x41, 0x44,
+	// Bytes 43c0 - 43ff
+	0xD7, 0x96, 0xD6, 0xBC, 0x41, 0x44, 0xD7, 0x98,
+	0xD6, 0xBC, 0x41, 0x44, 0xD7, 0x99, 0xD6, 0xB4,
+	0x25, 0x44, 0xD7, 0x99, 0xD6, 0xBC, 0x41, 0x44,
+	0xD7, 0x9A, 0xD6, 0xBC, 0x41, 0x44, 0xD7, 0x9B,
+	0xD6, 0xBC, 0x41, 0x44, 0xD7, 0x9B, 0xD6, 0xBF,
+	0x49, 0x44, 0xD7, 0x9C, 0xD6, 0xBC, 0x41, 0x44,
+	0xD7, 0x9E, 0xD6, 0xBC, 0x41, 0x44, 0xD7, 0xA0,
+	0xD6, 0xBC, 0x41, 0x44, 0xD7, 0xA1, 0xD6, 0xBC,
+	// Bytes 4400 - 443f
+	0x41, 0x44, 0xD7, 0xA3, 0xD6, 0xBC, 0x41, 0x44,
+	0xD7, 0xA4, 0xD6, 0xBC, 0x41, 0x44, 0xD7, 0xA4,
+	0xD6, 0xBF, 0x49, 0x44, 0xD7, 0xA6, 0xD6, 0xBC,
+	0x41, 0x44, 0xD7, 0xA7, 0xD6, 0xBC, 0x41, 0x44,
+	0xD7, 0xA8, 0xD6, 0xBC, 0x41, 0x44, 0xD7, 0xA9,
+	0xD6, 0xBC, 0x41, 0x44, 0xD7, 0xA9, 0xD7, 0x81,
+	0x4D, 0x44, 0xD7, 0xA9, 0xD7, 0x82, 0x51, 0x44,
+	0xD7, 0xAA, 0xD6, 0xBC, 0x41, 0x44, 0xD7, 0xB2,
+	// Bytes 4440 - 447f
+	0xD6, 0xB7, 0x31, 0x44, 0xD8, 0xA7, 0xD9, 0x8B,
+	0x59, 0x44, 0xD8, 0xA7, 0xD9, 0x93, 0xC9, 0x44,
+	0xD8, 0xA7, 0xD9, 0x94, 0xC9, 0x44, 0xD8, 0xA7,
+	0xD9, 0x95, 0xB5, 0x44, 0xD8, 0xB0, 0xD9, 0xB0,
+	0x79, 0x44, 0xD8, 0xB1, 0xD9, 0xB0, 0x79, 0x44,
+	0xD9, 0x80, 0xD9, 0x8B, 0x59, 0x44, 0xD9, 0x80,
+	0xD9, 0x8E, 0x65, 0x44, 0xD9, 0x80, 0xD9, 0x8F,
+	0x69, 0x44, 0xD9, 0x80, 0xD9, 0x90, 0x6D, 0x44,
+	// Bytes 4480 - 44bf
+	0xD9, 0x80, 0xD9, 0x91, 0x71, 0x44, 0xD9, 0x80,
+	0xD9, 0x92, 0x75, 0x44, 0xD9, 0x87, 0xD9, 0xB0,
+	0x79, 0x44, 0xD9, 0x88, 0xD9, 0x94, 0xC9, 0x44,
+	0xD9, 0x89, 0xD9, 0xB0, 0x79, 0x44, 0xD9, 0x8A,
+	0xD9, 0x94, 0xC9, 0x44, 0xDB, 0x92, 0xD9, 0x94,
+	0xC9, 0x44, 0xDB, 0x95, 0xD9, 0x94, 0xC9, 0x45,
+	0x20, 0xCC, 0x88, 0xCC, 0x80, 0xCA, 0x45, 0x20,
+	0xCC, 0x88, 0xCC, 0x81, 0xCA, 0x45, 0x20, 0xCC,
+	// Bytes 44c0 - 44ff
+	0x88, 0xCD, 0x82, 0xCA, 0x45, 0x20, 0xCC, 0x93,
+	0xCC, 0x80, 0xCA, 0x45, 0x20, 0xCC, 0x93, 0xCC,
+	0x81, 0xCA, 0x45, 0x20, 0xCC, 0x93, 0xCD, 0x82,
+	0xCA, 0x45, 0x20, 0xCC, 0x94, 0xCC, 0x80, 0xCA,
+	0x45, 0x20, 0xCC, 0x94, 0xCC, 0x81, 0xCA, 0x45,
+	0x20, 0xCC, 0x94, 0xCD, 0x82, 0xCA, 0x45, 0x20,
+	0xD9, 0x8C, 0xD9, 0x91, 0x72, 0x45, 0x20, 0xD9,
+	0x8D, 0xD9, 0x91, 0x72, 0x45, 0x20, 0xD9, 0x8E,
+	// Bytes 4500 - 453f
+	0xD9, 0x91, 0x72, 0x45, 0x20, 0xD9, 0x8F, 0xD9,
+	0x91, 0x72, 0x45, 0x20, 0xD9, 0x90, 0xD9, 0x91,
+	0x72, 0x45, 0x20, 0xD9, 0x91, 0xD9, 0xB0, 0x7A,
+	0x45, 0xE2, 0xAB, 0x9D, 0xCC, 0xB8, 0x05, 0x46,
+	0xCE, 0xB9, 0xCC, 0x88, 0xCC, 0x81, 0xCA, 0x46,
+	0xCF, 0x85, 0xCC, 0x88, 0xCC, 0x81, 0xCA, 0x46,
+	0xD7, 0xA9, 0xD6, 0xBC, 0xD7, 0x81, 0x4E, 0x46,
+	0xD7, 0xA9, 0xD6, 0xBC, 0xD7, 0x82, 0x52, 0x46,
+	// Bytes 4540 - 457f
+	0xD9, 0x80, 0xD9, 0x8E, 0xD9, 0x91, 0x72, 0x46,
+	0xD9, 0x80, 0xD9, 0x8F, 0xD9, 0x91, 0x72, 0x46,
+	0xD9, 0x80, 0xD9, 0x90, 0xD9, 0x91, 0x72, 0x46,
+	0xE0, 0xA4, 0x95, 0xE0, 0xA4, 0xBC, 0x09, 0x46,
+	0xE0, 0xA4, 0x96, 0xE0, 0xA4, 0xBC, 0x09, 0x46,
+	0xE0, 0xA4, 0x97, 0xE0, 0xA4, 0xBC, 0x09, 0x46,
+	0xE0, 0xA4, 0x9C, 0xE0, 0xA4, 0xBC, 0x09, 0x46,
+	0xE0, 0xA4, 0xA1, 0xE0, 0xA4, 0xBC, 0x09, 0x46,
+	// Bytes 4580 - 45bf
+	0xE0, 0xA4, 0xA2, 0xE0, 0xA4, 0xBC, 0x09, 0x46,
+	0xE0, 0xA4, 0xAB, 0xE0, 0xA4, 0xBC, 0x09, 0x46,
+	0xE0, 0xA4, 0xAF, 0xE0, 0xA4, 0xBC, 0x09, 0x46,
+	0xE0, 0xA6, 0xA1, 0xE0, 0xA6, 0xBC, 0x09, 0x46,
+	0xE0, 0xA6, 0xA2, 0xE0, 0xA6, 0xBC, 0x09, 0x46,
+	0xE0, 0xA6, 0xAF, 0xE0, 0xA6, 0xBC, 0x09, 0x46,
+	0xE0, 0xA8, 0x96, 0xE0, 0xA8, 0xBC, 0x09, 0x46,
+	0xE0, 0xA8, 0x97, 0xE0, 0xA8, 0xBC, 0x09, 0x46,
+	// Bytes 45c0 - 45ff
+	0xE0, 0xA8, 0x9C, 0xE0, 0xA8, 0xBC, 0x09, 0x46,
+	0xE0, 0xA8, 0xAB, 0xE0, 0xA8, 0xBC, 0x09, 0x46,
+	0xE0, 0xA8, 0xB2, 0xE0, 0xA8, 0xBC, 0x09, 0x46,
+	0xE0, 0xA8, 0xB8, 0xE0, 0xA8, 0xBC, 0x09, 0x46,
+	0xE0, 0xAC, 0xA1, 0xE0, 0xAC, 0xBC, 0x09, 0x46,
+	0xE0, 0xAC, 0xA2, 0xE0, 0xAC, 0xBC, 0x09, 0x46,
+	0xE0, 0xBE, 0xB2, 0xE0, 0xBE, 0x80, 0x9D, 0x46,
+	0xE0, 0xBE, 0xB3, 0xE0, 0xBE, 0x80, 0x9D, 0x46,
+	// Bytes 4600 - 463f
+	0xE3, 0x83, 0x86, 0xE3, 0x82, 0x99, 0x0D, 0x48,
+	0xF0, 0x9D, 0x85, 0x97, 0xF0, 0x9D, 0x85, 0xA5,
+	0xAD, 0x48, 0xF0, 0x9D, 0x85, 0x98, 0xF0, 0x9D,
+	0x85, 0xA5, 0xAD, 0x48, 0xF0, 0x9D, 0x86, 0xB9,
+	0xF0, 0x9D, 0x85, 0xA5, 0xAD, 0x48, 0xF0, 0x9D,
+	0x86, 0xBA, 0xF0, 0x9D, 0x85, 0xA5, 0xAD, 0x49,
+	0xE0, 0xBE, 0xB2, 0xE0, 0xBD, 0xB1, 0xE0, 0xBE,
+	0x80, 0x9E, 0x49, 0xE0, 0xBE, 0xB3, 0xE0, 0xBD,
+	// Bytes 4640 - 467f
+	0xB1, 0xE0, 0xBE, 0x80, 0x9E, 0x4C, 0xF0, 0x9D,
+	0x85, 0x98, 0xF0, 0x9D, 0x85, 0xA5, 0xF0, 0x9D,
+	0x85, 0xAE, 0xAE, 0x4C, 0xF0, 0x9D, 0x85, 0x98,
+	0xF0, 0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85, 0xAF,
+	0xAE, 0x4C, 0xF0, 0x9D, 0x85, 0x98, 0xF0, 0x9D,
+	0x85, 0xA5, 0xF0, 0x9D, 0x85, 0xB0, 0xAE, 0x4C,
+	0xF0, 0x9D, 0x85, 0x98, 0xF0, 0x9D, 0x85, 0xA5,
+	0xF0, 0x9D, 0x85, 0xB1, 0xAE, 0x4C, 0xF0, 0x9D,
+	// Bytes 4680 - 46bf
+	0x85, 0x98, 0xF0, 0x9D, 0x85, 0xA5, 0xF0, 0x9D,
+	0x85, 0xB2, 0xAE, 0x4C, 0xF0, 0x9D, 0x86, 0xB9,
+	0xF0, 0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85, 0xAE,
+	0xAE, 0x4C, 0xF0, 0x9D, 0x86, 0xB9, 0xF0, 0x9D,
+	0x85, 0xA5, 0xF0, 0x9D, 0x85, 0xAF, 0xAE, 0x4C,
+	0xF0, 0x9D, 0x86, 0xBA, 0xF0, 0x9D, 0x85, 0xA5,
+	0xF0, 0x9D, 0x85, 0xAE, 0xAE, 0x4C, 0xF0, 0x9D,
+	0x86, 0xBA, 0xF0, 0x9D, 0x85, 0xA5, 0xF0, 0x9D,
+	// Bytes 46c0 - 46ff
+	0x85, 0xAF, 0xAE, 0x83, 0x41, 0xCC, 0x82, 0xC9,
+	0x83, 0x41, 0xCC, 0x86, 0xC9, 0x83, 0x41, 0xCC,
+	0x87, 0xC9, 0x83, 0x41, 0xCC, 0x88, 0xC9, 0x83,
+	0x41, 0xCC, 0x8A, 0xC9, 0x83, 0x41, 0xCC, 0xA3,
+	0xB5, 0x83, 0x43, 0xCC, 0xA7, 0xA5, 0x83, 0x45,
+	0xCC, 0x82, 0xC9, 0x83, 0x45, 0xCC, 0x84, 0xC9,
+	0x83, 0x45, 0xCC, 0xA3, 0xB5, 0x83, 0x45, 0xCC,
+	0xA7, 0xA5, 0x83, 0x49, 0xCC, 0x88, 0xC9, 0x83,
+	// Bytes 4700 - 473f
+	0x4C, 0xCC, 0xA3, 0xB5, 0x83, 0x4F, 0xCC, 0x82,
+	0xC9, 0x83, 0x4F, 0xCC, 0x83, 0xC9, 0x83, 0x4F,
+	0xCC, 0x84, 0xC9, 0x83, 0x4F, 0xCC, 0x87, 0xC9,
+	0x83, 0x4F, 0xCC, 0x88, 0xC9, 0x83, 0x4F, 0xCC,
+	0x9B, 0xAD, 0x83, 0x4F, 0xCC, 0xA3, 0xB5, 0x83,
+	0x4F, 0xCC, 0xA8, 0xA5, 0x83, 0x52, 0xCC, 0xA3,
+	0xB5, 0x83, 0x53, 0xCC, 0x81, 0xC9, 0x83, 0x53,
+	0xCC, 0x8C, 0xC9, 0x83, 0x53, 0xCC, 0xA3, 0xB5,
+	// Bytes 4740 - 477f
+	0x83, 0x55, 0xCC, 0x83, 0xC9, 0x83, 0x55, 0xCC,
+	0x84, 0xC9, 0x83, 0x55, 0xCC, 0x88, 0xC9, 0x83,
+	0x55, 0xCC, 0x9B, 0xAD, 0x83, 0x61, 0xCC, 0x82,
+	0xC9, 0x83, 0x61, 0xCC, 0x86, 0xC9, 0x83, 0x61,
+	0xCC, 0x87, 0xC9, 0x83, 0x61, 0xCC, 0x88, 0xC9,
+	0x83, 0x61, 0xCC, 0x8A, 0xC9, 0x83, 0x61, 0xCC,
+	0xA3, 0xB5, 0x83, 0x63, 0xCC, 0xA7, 0xA5, 0x83,
+	0x65, 0xCC, 0x82, 0xC9, 0x83, 0x65, 0xCC, 0x84,
+	// Bytes 4780 - 47bf
+	0xC9, 0x83, 0x65, 0xCC, 0xA3, 0xB5, 0x83, 0x65,
+	0xCC, 0xA7, 0xA5, 0x83, 0x69, 0xCC, 0x88, 0xC9,
+	0x83, 0x6C, 0xCC, 0xA3, 0xB5, 0x83, 0x6F, 0xCC,
+	0x82, 0xC9, 0x83, 0x6F, 0xCC, 0x83, 0xC9, 0x83,
+	0x6F, 0xCC, 0x84, 0xC9, 0x83, 0x6F, 0xCC, 0x87,
+	0xC9, 0x83, 0x6F, 0xCC, 0x88, 0xC9, 0x83, 0x6F,
+	0xCC, 0x9B, 0xAD, 0x83, 0x6F, 0xCC, 0xA3, 0xB5,
+	0x83, 0x6F, 0xCC, 0xA8, 0xA5, 0x83, 0x72, 0xCC,
+	// Bytes 47c0 - 47ff
+	0xA3, 0xB5, 0x83, 0x73, 0xCC, 0x81, 0xC9, 0x83,
+	0x73, 0xCC, 0x8C, 0xC9, 0x83, 0x73, 0xCC, 0xA3,
+	0xB5, 0x83, 0x75, 0xCC, 0x83, 0xC9, 0x83, 0x75,
+	0xCC, 0x84, 0xC9, 0x83, 0x75, 0xCC, 0x88, 0xC9,
+	0x83, 0x75, 0xCC, 0x9B, 0xAD, 0x84, 0xCE, 0x91,
+	0xCC, 0x93, 0xC9, 0x84, 0xCE, 0x91, 0xCC, 0x94,
+	0xC9, 0x84, 0xCE, 0x95, 0xCC, 0x93, 0xC9, 0x84,
+	0xCE, 0x95, 0xCC, 0x94, 0xC9, 0x84, 0xCE, 0x97,
+	// Bytes 4800 - 483f
+	0xCC, 0x93, 0xC9, 0x84, 0xCE, 0x97, 0xCC, 0x94,
+	0xC9, 0x84, 0xCE, 0x99, 0xCC, 0x93, 0xC9, 0x84,
+	0xCE, 0x99, 0xCC, 0x94, 0xC9, 0x84, 0xCE, 0x9F,
+	0xCC, 0x93, 0xC9, 0x84, 0xCE, 0x9F, 0xCC, 0x94,
+	0xC9, 0x84, 0xCE, 0xA5, 0xCC, 0x94, 0xC9, 0x84,
+	0xCE, 0xA9, 0xCC, 0x93, 0xC9, 0x84, 0xCE, 0xA9,
+	0xCC, 0x94, 0xC9, 0x84, 0xCE, 0xB1, 0xCC, 0x80,
+	0xC9, 0x84, 0xCE, 0xB1, 0xCC, 0x81, 0xC9, 0x84,
+	// Bytes 4840 - 487f
+	0xCE, 0xB1, 0xCC, 0x93, 0xC9, 0x84, 0xCE, 0xB1,
+	0xCC, 0x94, 0xC9, 0x84, 0xCE, 0xB1, 0xCD, 0x82,
+	0xC9, 0x84, 0xCE, 0xB5, 0xCC, 0x93, 0xC9, 0x84,
+	0xCE, 0xB5, 0xCC, 0x94, 0xC9, 0x84, 0xCE, 0xB7,
+	0xCC, 0x80, 0xC9, 0x84, 0xCE, 0xB7, 0xCC, 0x81,
+	0xC9, 0x84, 0xCE, 0xB7, 0xCC, 0x93, 0xC9, 0x84,
+	0xCE, 0xB7, 0xCC, 0x94, 0xC9, 0x84, 0xCE, 0xB7,
+	0xCD, 0x82, 0xC9, 0x84, 0xCE, 0xB9, 0xCC, 0x88,
+	// Bytes 4880 - 48bf
+	0xC9, 0x84, 0xCE, 0xB9, 0xCC, 0x93, 0xC9, 0x84,
+	0xCE, 0xB9, 0xCC, 0x94, 0xC9, 0x84, 0xCE, 0xBF,
+	0xCC, 0x93, 0xC9, 0x84, 0xCE, 0xBF, 0xCC, 0x94,
+	0xC9, 0x84, 0xCF, 0x85, 0xCC, 0x88, 0xC9, 0x84,
+	0xCF, 0x85, 0xCC, 0x93, 0xC9, 0x84, 0xCF, 0x85,
+	0xCC, 0x94, 0xC9, 0x84, 0xCF, 0x89, 0xCC, 0x80,
+	0xC9, 0x84, 0xCF, 0x89, 0xCC, 0x81, 0xC9, 0x84,
+	0xCF, 0x89, 0xCC, 0x93, 0xC9, 0x84, 0xCF, 0x89,
+	// Bytes 48c0 - 48ff
+	0xCC, 0x94, 0xC9, 0x84, 0xCF, 0x89, 0xCD, 0x82,
+	0xC9, 0x86, 0xCE, 0x91, 0xCC, 0x93, 0xCC, 0x80,
+	0xCA, 0x86, 0xCE, 0x91, 0xCC, 0x93, 0xCC, 0x81,
+	0xCA, 0x86, 0xCE, 0x91, 0xCC, 0x93, 0xCD, 0x82,
+	0xCA, 0x86, 0xCE, 0x91, 0xCC, 0x94, 0xCC, 0x80,
+	0xCA, 0x86, 0xCE, 0x91, 0xCC, 0x94, 0xCC, 0x81,
+	0xCA, 0x86, 0xCE, 0x91, 0xCC, 0x94, 0xCD, 0x82,
+	0xCA, 0x86, 0xCE, 0x97, 0xCC, 0x93, 0xCC, 0x80,
+	// Bytes 4900 - 493f
+	0xCA, 0x86, 0xCE, 0x97, 0xCC, 0x93, 0xCC, 0x81,
+	0xCA, 0x86, 0xCE, 0x97, 0xCC, 0x93, 0xCD, 0x82,
+	0xCA, 0x86, 0xCE, 0x97, 0xCC, 0x94, 0xCC, 0x80,
+	0xCA, 0x86, 0xCE, 0x97, 0xCC, 0x94, 0xCC, 0x81,
+	0xCA, 0x86, 0xCE, 0x97, 0xCC, 0x94, 0xCD, 0x82,
+	0xCA, 0x86, 0xCE, 0xA9, 0xCC, 0x93, 0xCC, 0x80,
+	0xCA, 0x86, 0xCE, 0xA9, 0xCC, 0x93, 0xCC, 0x81,
+	0xCA, 0x86, 0xCE, 0xA9, 0xCC, 0x93, 0xCD, 0x82,
+	// Bytes 4940 - 497f
+	0xCA, 0x86, 0xCE, 0xA9, 0xCC, 0x94, 0xCC, 0x80,
+	0xCA, 0x86, 0xCE, 0xA9, 0xCC, 0x94, 0xCC, 0x81,
+	0xCA, 0x86, 0xCE, 0xA9, 0xCC, 0x94, 0xCD, 0x82,
+	0xCA, 0x86, 0xCE, 0xB1, 0xCC, 0x93, 0xCC, 0x80,
+	0xCA, 0x86, 0xCE, 0xB1, 0xCC, 0x93, 0xCC, 0x81,
+	0xCA, 0x86, 0xCE, 0xB1, 0xCC, 0x93, 0xCD, 0x82,
+	0xCA, 0x86, 0xCE, 0xB1, 0xCC, 0x94, 0xCC, 0x80,
+	0xCA, 0x86, 0xCE, 0xB1, 0xCC, 0x94, 0xCC, 0x81,
+	// Bytes 4980 - 49bf
+	0xCA, 0x86, 0xCE, 0xB1, 0xCC, 0x94, 0xCD, 0x82,
+	0xCA, 0x86, 0xCE, 0xB7, 0xCC, 0x93, 0xCC, 0x80,
+	0xCA, 0x86, 0xCE, 0xB7, 0xCC, 0x93, 0xCC, 0x81,
+	0xCA, 0x86, 0xCE, 0xB7, 0xCC, 0x93, 0xCD, 0x82,
+	0xCA, 0x86, 0xCE, 0xB7, 0xCC, 0x94, 0xCC, 0x80,
+	0xCA, 0x86, 0xCE, 0xB7, 0xCC, 0x94, 0xCC, 0x81,
+	0xCA, 0x86, 0xCE, 0xB7, 0xCC, 0x94, 0xCD, 0x82,
+	0xCA, 0x86, 0xCF, 0x89, 0xCC, 0x93, 0xCC, 0x80,
+	// Bytes 49c0 - 49ff
+	0xCA, 0x86, 0xCF, 0x89, 0xCC, 0x93, 0xCC, 0x81,
+	0xCA, 0x86, 0xCF, 0x89, 0xCC, 0x93, 0xCD, 0x82,
+	0xCA, 0x86, 0xCF, 0x89, 0xCC, 0x94, 0xCC, 0x80,
+	0xCA, 0x86, 0xCF, 0x89, 0xCC, 0x94, 0xCC, 0x81,
+	0xCA, 0x86, 0xCF, 0x89, 0xCC, 0x94, 0xCD, 0x82,
+	0xCA, 0x42, 0xCC, 0x80, 0xC9, 0x32, 0x42, 0xCC,
+	0x81, 0xC9, 0x32, 0x42, 0xCC, 0x93, 0xC9, 0x32,
+	0x44, 0xCC, 0x88, 0xCC, 0x81, 0xCA, 0x32, 0x43,
+	// Bytes 4a00 - 4a3f
+	0xE3, 0x82, 0x99, 0x0D, 0x03, 0x43, 0xE3, 0x82,
+	0x9A, 0x0D, 0x03, 0x46, 0xE0, 0xBD, 0xB1, 0xE0,
+	0xBD, 0xB2, 0x9E, 0x26, 0x46, 0xE0, 0xBD, 0xB1,
+	0xE0, 0xBD, 0xB4, 0xA2, 0x26, 0x46, 0xE0, 0xBD,
+	0xB1, 0xE0, 0xBE, 0x80, 0x9E, 0x26, 0x00, 0x01,
+}
+
+// lookup returns the trie value for the first UTF-8 encoding in s and
+// the width in bytes of this encoding. The size will be 0 if s does not
+// hold enough bytes to complete the encoding. len(s) must be greater than 0.
+func (t *nfcTrie) lookup(s []byte) (v uint16, sz int) {
+	c0 := s[0]
+	switch {
+	case c0 < 0x80: // is ASCII
+		return nfcValues[c0], 1
+	case c0 < 0xC0:
+		return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
+	case c0 < 0xE0: // 2-byte UTF-8
+		if len(s) < 2 {
+			return 0, 0
+		}
+		i := nfcIndex[c0]
+		c1 := s[1]
+		if c1 < 0x80 || 0xC0 <= c1 {
+			return 0, 1 // Illegal UTF-8: not a continuation byte.
+		}
+		return t.lookupValue(uint32(i), c1), 2
+	case c0 < 0xF0: // 3-byte UTF-8
+		if len(s) < 3 {
+			return 0, 0
+		}
+		i := nfcIndex[c0]
+		c1 := s[1]
+		if c1 < 0x80 || 0xC0 <= c1 {
+			return 0, 1 // Illegal UTF-8: not a continuation byte.
+		}
+		o := uint32(i)<<6 + uint32(c1)
+		i = nfcIndex[o]
+		c2 := s[2]
+		if c2 < 0x80 || 0xC0 <= c2 {
+			return 0, 2 // Illegal UTF-8: not a continuation byte.
+		}
+		return t.lookupValue(uint32(i), c2), 3
+	case c0 < 0xF8: // 4-byte UTF-8
+		if len(s) < 4 {
+			return 0, 0
+		}
+		i := nfcIndex[c0]
+		c1 := s[1]
+		if c1 < 0x80 || 0xC0 <= c1 {
+			return 0, 1 // Illegal UTF-8: not a continuation byte.
+		}
+		o := uint32(i)<<6 + uint32(c1)
+		i = nfcIndex[o]
+		c2 := s[2]
+		if c2 < 0x80 || 0xC0 <= c2 {
+			return 0, 2 // Illegal UTF-8: not a continuation byte.
+		}
+		o = uint32(i)<<6 + uint32(c2)
+		i = nfcIndex[o]
+		c3 := s[3]
+		if c3 < 0x80 || 0xC0 <= c3 {
+			return 0, 3 // Illegal UTF-8: not a continuation byte.
+		}
+		return t.lookupValue(uint32(i), c3), 4
+	}
+	// Illegal rune
+	return 0, 1
+}
+
+// lookupUnsafe returns the trie value for the first UTF-8 encoding in s.
+// s must start with a full and valid UTF-8 encoded rune.
+func (t *nfcTrie) lookupUnsafe(s []byte) uint16 {
+	c0 := s[0]
+	if c0 < 0x80 { // is ASCII
+		return nfcValues[c0]
+	}
+	i := nfcIndex[c0]
+	if c0 < 0xE0 { // 2-byte UTF-8
+		return t.lookupValue(uint32(i), s[1])
+	}
+	i = nfcIndex[uint32(i)<<6+uint32(s[1])]
+	if c0 < 0xF0 { // 3-byte UTF-8
+		return t.lookupValue(uint32(i), s[2])
+	}
+	i = nfcIndex[uint32(i)<<6+uint32(s[2])]
+	if c0 < 0xF8 { // 4-byte UTF-8
+		return t.lookupValue(uint32(i), s[3])
+	}
+	return 0
+}
+
+// lookupString returns the trie value for the first UTF-8 encoding in s and
+// the width in bytes of this encoding. The size will be 0 if s does not
+// hold enough bytes to complete the encoding. len(s) must be greater than 0.
+func (t *nfcTrie) lookupString(s string) (v uint16, sz int) {
+	c0 := s[0]
+	switch {
+	case c0 < 0x80: // is ASCII
+		return nfcValues[c0], 1
+	case c0 < 0xC0:
+		return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
+	case c0 < 0xE0: // 2-byte UTF-8
+		if len(s) < 2 {
+			return 0, 0
+		}
+		i := nfcIndex[c0]
+		c1 := s[1]
+		if c1 < 0x80 || 0xC0 <= c1 {
+			return 0, 1 // Illegal UTF-8: not a continuation byte.
+		}
+		return t.lookupValue(uint32(i), c1), 2
+	case c0 < 0xF0: // 3-byte UTF-8
+		if len(s) < 3 {
+			return 0, 0
+		}
+		i := nfcIndex[c0]
+		c1 := s[1]
+		if c1 < 0x80 || 0xC0 <= c1 {
+			return 0, 1 // Illegal UTF-8: not a continuation byte.
+		}
+		o := uint32(i)<<6 + uint32(c1)
+		i = nfcIndex[o]
+		c2 := s[2]
+		if c2 < 0x80 || 0xC0 <= c2 {
+			return 0, 2 // Illegal UTF-8: not a continuation byte.
+		}
+		return t.lookupValue(uint32(i), c2), 3
+	case c0 < 0xF8: // 4-byte UTF-8
+		if len(s) < 4 {
+			return 0, 0
+		}
+		i := nfcIndex[c0]
+		c1 := s[1]
+		if c1 < 0x80 || 0xC0 <= c1 {
+			return 0, 1 // Illegal UTF-8: not a continuation byte.
+		}
+		o := uint32(i)<<6 + uint32(c1)
+		i = nfcIndex[o]
+		c2 := s[2]
+		if c2 < 0x80 || 0xC0 <= c2 {
+			return 0, 2 // Illegal UTF-8: not a continuation byte.
+		}
+		o = uint32(i)<<6 + uint32(c2)
+		i = nfcIndex[o]
+		c3 := s[3]
+		if c3 < 0x80 || 0xC0 <= c3 {
+			return 0, 3 // Illegal UTF-8: not a continuation byte.
+		}
+		return t.lookupValue(uint32(i), c3), 4
+	}
+	// Illegal rune
+	return 0, 1
+}
+
+// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s.
+// s must start with a full and valid UTF-8 encoded rune.
+func (t *nfcTrie) lookupStringUnsafe(s string) uint16 {
+	c0 := s[0]
+	if c0 < 0x80 { // is ASCII
+		return nfcValues[c0]
+	}
+	i := nfcIndex[c0]
+	if c0 < 0xE0 { // 2-byte UTF-8
+		return t.lookupValue(uint32(i), s[1])
+	}
+	i = nfcIndex[uint32(i)<<6+uint32(s[1])]
+	if c0 < 0xF0 { // 3-byte UTF-8
+		return t.lookupValue(uint32(i), s[2])
+	}
+	i = nfcIndex[uint32(i)<<6+uint32(s[2])]
+	if c0 < 0xF8 { // 4-byte UTF-8
+		return t.lookupValue(uint32(i), s[3])
+	}
+	return 0
+}
+
+// nfcTrie. Total size: 10176 bytes (9.94 KiB). Checksum: d7c74933ce923a3f.
+type nfcTrie struct{}
+
+func newNfcTrie(i int) *nfcTrie {
+	return &nfcTrie{}
+}
+
+// lookupValue determines the type of block n and looks up the value for b.
+func (t *nfcTrie) lookupValue(n uint32, b byte) uint16 {
+	switch {
+	case n < 44:
+		return uint16(nfcValues[n<<6+uint32(b)])
+	default:
+		n -= 44
+		return uint16(nfcSparse.lookup(n, b))
+	}
+}
+
+// nfcValues: 46 blocks, 2944 entries, 5888 bytes
+// The third block is the zero block.
+var nfcValues = [2944]uint16{
+	// Block 0x0, offset 0x0
+	0x3c: 0xa000, 0x3d: 0xa000, 0x3e: 0xa000,
+	// Block 0x1, offset 0x40
+	0x41: 0xa000, 0x42: 0xa000, 0x43: 0xa000, 0x44: 0xa000, 0x45: 0xa000,
+	0x46: 0xa000, 0x47: 0xa000, 0x48: 0xa000, 0x49: 0xa000, 0x4a: 0xa000, 0x4b: 0xa000,
+	0x4c: 0xa000, 0x4d: 0xa000, 0x4e: 0xa000, 0x4f: 0xa000, 0x50: 0xa000,
+	0x52: 0xa000, 0x53: 0xa000, 0x54: 0xa000, 0x55: 0xa000, 0x56: 0xa000, 0x57: 0xa000,
+	0x58: 0xa000, 0x59: 0xa000, 0x5a: 0xa000,
+	0x61: 0xa000, 0x62: 0xa000, 0x63: 0xa000,
+	0x64: 0xa000, 0x65: 0xa000, 0x66: 0xa000, 0x67: 0xa000, 0x68: 0xa000, 0x69: 0xa000,
+	0x6a: 0xa000, 0x6b: 0xa000, 0x6c: 0xa000, 0x6d: 0xa000, 0x6e: 0xa000, 0x6f: 0xa000,
+	0x70: 0xa000, 0x72: 0xa000, 0x73: 0xa000, 0x74: 0xa000, 0x75: 0xa000,
+	0x76: 0xa000, 0x77: 0xa000, 0x78: 0xa000, 0x79: 0xa000, 0x7a: 0xa000,
+	// Block 0x2, offset 0x80
+	// Block 0x3, offset 0xc0
+	0xc0: 0x2faa, 0xc1: 0x2faf, 0xc2: 0x46c3, 0xc3: 0x2fb4, 0xc4: 0x46d2, 0xc5: 0x46d7,
+	0xc6: 0xa000, 0xc7: 0x46e1, 0xc8: 0x301d, 0xc9: 0x3022, 0xca: 0x46e6, 0xcb: 0x3036,
+	0xcc: 0x30a9, 0xcd: 0x30ae, 0xce: 0x30b3, 0xcf: 0x46fa, 0xd1: 0x313f,
+	0xd2: 0x3162, 0xd3: 0x3167, 0xd4: 0x4704, 0xd5: 0x4709, 0xd6: 0x4718,
+	0xd8: 0xa000, 0xd9: 0x31ee, 0xda: 0x31f3, 0xdb: 0x31f8, 0xdc: 0x474a, 0xdd: 0x3270,
+	0xe0: 0x32b6, 0xe1: 0x32bb, 0xe2: 0x4754, 0xe3: 0x32c0,
+	0xe4: 0x4763, 0xe5: 0x4768, 0xe6: 0xa000, 0xe7: 0x4772, 0xe8: 0x3329, 0xe9: 0x332e,
+	0xea: 0x4777, 0xeb: 0x3342, 0xec: 0x33ba, 0xed: 0x33bf, 0xee: 0x33c4, 0xef: 0x478b,
+	0xf1: 0x3450, 0xf2: 0x3473, 0xf3: 0x3478, 0xf4: 0x4795, 0xf5: 0x479a,
+	0xf6: 0x47a9, 0xf8: 0xa000, 0xf9: 0x3504, 0xfa: 0x3509, 0xfb: 0x350e,
+	0xfc: 0x47db, 0xfd: 0x358b, 0xff: 0x35a4,
+	// Block 0x4, offset 0x100
+	0x100: 0x2fb9, 0x101: 0x32c5, 0x102: 0x46c8, 0x103: 0x4759, 0x104: 0x2fd7, 0x105: 0x32e3,
+	0x106: 0x2feb, 0x107: 0x32f7, 0x108: 0x2ff0, 0x109: 0x32fc, 0x10a: 0x2ff5, 0x10b: 0x3301,
+	0x10c: 0x2ffa, 0x10d: 0x3306, 0x10e: 0x3004, 0x10f: 0x3310,
+	0x112: 0x46eb, 0x113: 0x477c, 0x114: 0x302c, 0x115: 0x3338, 0x116: 0x3031, 0x117: 0x333d,
+	0x118: 0x304f, 0x119: 0x335b, 0x11a: 0x3040, 0x11b: 0x334c, 0x11c: 0x3068, 0x11d: 0x3374,
+	0x11e: 0x3072, 0x11f: 0x337e, 0x120: 0x3077, 0x121: 0x3383, 0x122: 0x3081, 0x123: 0x338d,
+	0x124: 0x3086, 0x125: 0x3392, 0x128: 0x30b8, 0x129: 0x33c9,
+	0x12a: 0x30bd, 0x12b: 0x33ce, 0x12c: 0x30c2, 0x12d: 0x33d3, 0x12e: 0x30e5, 0x12f: 0x33f1,
+	0x130: 0x30c7, 0x134: 0x30ef, 0x135: 0x33fb,
+	0x136: 0x3103, 0x137: 0x3414, 0x139: 0x310d, 0x13a: 0x341e, 0x13b: 0x3117,
+	0x13c: 0x3428, 0x13d: 0x3112, 0x13e: 0x3423,
+	// Block 0x5, offset 0x140
+	0x143: 0x313a, 0x144: 0x344b, 0x145: 0x3153,
+	0x146: 0x3464, 0x147: 0x3149, 0x148: 0x345a,
+	0x14c: 0x470e, 0x14d: 0x479f, 0x14e: 0x316c, 0x14f: 0x347d, 0x150: 0x3176, 0x151: 0x3487,
+	0x154: 0x3194, 0x155: 0x34a5, 0x156: 0x31ad, 0x157: 0x34be,
+	0x158: 0x319e, 0x159: 0x34af, 0x15a: 0x4731, 0x15b: 0x47c2, 0x15c: 0x31b7, 0x15d: 0x34c8,
+	0x15e: 0x31c6, 0x15f: 0x34d7, 0x160: 0x4736, 0x161: 0x47c7, 0x162: 0x31df, 0x163: 0x34f5,
+	0x164: 0x31d0, 0x165: 0x34e6, 0x168: 0x4740, 0x169: 0x47d1,
+	0x16a: 0x4745, 0x16b: 0x47d6, 0x16c: 0x31fd, 0x16d: 0x3513, 0x16e: 0x3207, 0x16f: 0x351d,
+	0x170: 0x320c, 0x171: 0x3522, 0x172: 0x322a, 0x173: 0x3540, 0x174: 0x324d, 0x175: 0x3563,
+	0x176: 0x3275, 0x177: 0x3590, 0x178: 0x3289, 0x179: 0x3298, 0x17a: 0x35b8, 0x17b: 0x32a2,
+	0x17c: 0x35c2, 0x17d: 0x32a7, 0x17e: 0x35c7, 0x17f: 0xa000,
+	// Block 0x6, offset 0x180
+	0x184: 0x8100, 0x185: 0x8100,
+	0x186: 0x8100,
+	0x18d: 0x2fc3, 0x18e: 0x32cf, 0x18f: 0x30d1, 0x190: 0x33dd, 0x191: 0x317b,
+	0x192: 0x348c, 0x193: 0x3211, 0x194: 0x3527, 0x195: 0x3a0a, 0x196: 0x3b99, 0x197: 0x3a03,
+	0x198: 0x3b92, 0x199: 0x3a11, 0x19a: 0x3ba0, 0x19b: 0x39fc, 0x19c: 0x3b8b,
+	0x19e: 0x38eb, 0x19f: 0x3a7a, 0x1a0: 0x38e4, 0x1a1: 0x3a73, 0x1a2: 0x35ee, 0x1a3: 0x3600,
+	0x1a6: 0x307c, 0x1a7: 0x3388, 0x1a8: 0x30f9, 0x1a9: 0x340a,
+	0x1aa: 0x4727, 0x1ab: 0x47b8, 0x1ac: 0x39cb, 0x1ad: 0x3b5a, 0x1ae: 0x3612, 0x1af: 0x3618,
+	0x1b0: 0x3400, 0x1b4: 0x3063, 0x1b5: 0x336f,
+	0x1b8: 0x3135, 0x1b9: 0x3446, 0x1ba: 0x38f2, 0x1bb: 0x3a81,
+	0x1bc: 0x35e8, 0x1bd: 0x35fa, 0x1be: 0x35f4, 0x1bf: 0x3606,
+	// Block 0x7, offset 0x1c0
+	0x1c0: 0x2fc8, 0x1c1: 0x32d4, 0x1c2: 0x2fcd, 0x1c3: 0x32d9, 0x1c4: 0x3045, 0x1c5: 0x3351,
+	0x1c6: 0x304a, 0x1c7: 0x3356, 0x1c8: 0x30d6, 0x1c9: 0x33e2, 0x1ca: 0x30db, 0x1cb: 0x33e7,
+	0x1cc: 0x3180, 0x1cd: 0x3491, 0x1ce: 0x3185, 0x1cf: 0x3496, 0x1d0: 0x31a3, 0x1d1: 0x34b4,
+	0x1d2: 0x31a8, 0x1d3: 0x34b9, 0x1d4: 0x3216, 0x1d5: 0x352c, 0x1d6: 0x321b, 0x1d7: 0x3531,
+	0x1d8: 0x31c1, 0x1d9: 0x34d2, 0x1da: 0x31da, 0x1db: 0x34f0,
+	0x1de: 0x3095, 0x1df: 0x33a1,
+	0x1e6: 0x46cd, 0x1e7: 0x475e, 0x1e8: 0x46f5, 0x1e9: 0x4786,
+	0x1ea: 0x399a, 0x1eb: 0x3b29, 0x1ec: 0x3977, 0x1ed: 0x3b06, 0x1ee: 0x4713, 0x1ef: 0x47a4,
+	0x1f0: 0x3993, 0x1f1: 0x3b22, 0x1f2: 0x327f, 0x1f3: 0x359a,
+	// Block 0x8, offset 0x200
+	0x200: 0x9932, 0x201: 0x9932, 0x202: 0x9932, 0x203: 0x9932, 0x204: 0x9932, 0x205: 0x8132,
+	0x206: 0x9932, 0x207: 0x9932, 0x208: 0x9932, 0x209: 0x9932, 0x20a: 0x9932, 0x20b: 0x9932,
+	0x20c: 0x9932, 0x20d: 0x8132, 0x20e: 0x8132, 0x20f: 0x9932, 0x210: 0x8132, 0x211: 0x9932,
+	0x212: 0x8132, 0x213: 0x9932, 0x214: 0x9932, 0x215: 0x8133, 0x216: 0x812d, 0x217: 0x812d,
+	0x218: 0x812d, 0x219: 0x812d, 0x21a: 0x8133, 0x21b: 0x992b, 0x21c: 0x812d, 0x21d: 0x812d,
+	0x21e: 0x812d, 0x21f: 0x812d, 0x220: 0x812d, 0x221: 0x8129, 0x222: 0x8129, 0x223: 0x992d,
+	0x224: 0x992d, 0x225: 0x992d, 0x226: 0x992d, 0x227: 0x9929, 0x228: 0x9929, 0x229: 0x812d,
+	0x22a: 0x812d, 0x22b: 0x812d, 0x22c: 0x812d, 0x22d: 0x992d, 0x22e: 0x992d, 0x22f: 0x812d,
+	0x230: 0x992d, 0x231: 0x992d, 0x232: 0x812d, 0x233: 0x812d, 0x234: 0x8101, 0x235: 0x8101,
+	0x236: 0x8101, 0x237: 0x8101, 0x238: 0x9901, 0x239: 0x812d, 0x23a: 0x812d, 0x23b: 0x812d,
+	0x23c: 0x812d, 0x23d: 0x8132, 0x23e: 0x8132, 0x23f: 0x8132,
+	// Block 0x9, offset 0x240
+	0x240: 0x49e9, 0x241: 0x49ee, 0x242: 0x9932, 0x243: 0x49f3, 0x244: 0x49f8, 0x245: 0x9936,
+	0x246: 0x8132, 0x247: 0x812d, 0x248: 0x812d, 0x249: 0x812d, 0x24a: 0x8132, 0x24b: 0x8132,
+	0x24c: 0x8132, 0x24d: 0x812d, 0x24e: 0x812d, 0x250: 0x8132, 0x251: 0x8132,
+	0x252: 0x8132, 0x253: 0x812d, 0x254: 0x812d, 0x255: 0x812d, 0x256: 0x812d, 0x257: 0x8132,
+	0x258: 0x8133, 0x259: 0x812d, 0x25a: 0x812d, 0x25b: 0x8132, 0x25c: 0x8134, 0x25d: 0x8135,
+	0x25e: 0x8135, 0x25f: 0x8134, 0x260: 0x8135, 0x261: 0x8135, 0x262: 0x8134, 0x263: 0x8132,
+	0x264: 0x8132, 0x265: 0x8132, 0x266: 0x8132, 0x267: 0x8132, 0x268: 0x8132, 0x269: 0x8132,
+	0x26a: 0x8132, 0x26b: 0x8132, 0x26c: 0x8132, 0x26d: 0x8132, 0x26e: 0x8132, 0x26f: 0x8132,
+	0x274: 0x0170,
+	0x27a: 0x8100,
+	0x27e: 0x0037,
+	// Block 0xa, offset 0x280
+	0x284: 0x8100, 0x285: 0x35dc,
+	0x286: 0x3624, 0x287: 0x00ce, 0x288: 0x3642, 0x289: 0x364e, 0x28a: 0x3660,
+	0x28c: 0x367e, 0x28e: 0x3690, 0x28f: 0x36ae, 0x290: 0x3e43, 0x291: 0xa000,
+	0x295: 0xa000, 0x297: 0xa000,
+	0x299: 0xa000,
+	0x29f: 0xa000, 0x2a1: 0xa000,
+	0x2a5: 0xa000, 0x2a9: 0xa000,
+	0x2aa: 0x3672, 0x2ab: 0x36a2, 0x2ac: 0x4839, 0x2ad: 0x36d2, 0x2ae: 0x4863, 0x2af: 0x36e4,
+	0x2b0: 0x3eab, 0x2b1: 0xa000, 0x2b5: 0xa000,
+	0x2b7: 0xa000, 0x2b9: 0xa000,
+	0x2bf: 0xa000,
+	// Block 0xb, offset 0x2c0
+	0x2c0: 0x375c, 0x2c1: 0x3768, 0x2c3: 0x3756,
+	0x2c6: 0xa000, 0x2c7: 0x3744,
+	0x2cc: 0x3798, 0x2cd: 0x3780, 0x2ce: 0x37aa, 0x2d0: 0xa000,
+	0x2d3: 0xa000, 0x2d5: 0xa000, 0x2d6: 0xa000, 0x2d7: 0xa000,
+	0x2d8: 0xa000, 0x2d9: 0x378c, 0x2da: 0xa000,
+	0x2de: 0xa000, 0x2e3: 0xa000,
+	0x2e7: 0xa000,
+	0x2eb: 0xa000, 0x2ed: 0xa000,
+	0x2f0: 0xa000, 0x2f3: 0xa000, 0x2f5: 0xa000,
+	0x2f6: 0xa000, 0x2f7: 0xa000, 0x2f8: 0xa000, 0x2f9: 0x3810, 0x2fa: 0xa000,
+	0x2fe: 0xa000,
+	// Block 0xc, offset 0x300
+	0x301: 0x376e, 0x302: 0x37f2,
+	0x310: 0x374a, 0x311: 0x37ce,
+	0x312: 0x3750, 0x313: 0x37d4, 0x316: 0x3762, 0x317: 0x37e6,
+	0x318: 0xa000, 0x319: 0xa000, 0x31a: 0x3864, 0x31b: 0x386a, 0x31c: 0x3774, 0x31d: 0x37f8,
+	0x31e: 0x377a, 0x31f: 0x37fe, 0x322: 0x3786, 0x323: 0x380a,
+	0x324: 0x3792, 0x325: 0x3816, 0x326: 0x379e, 0x327: 0x3822, 0x328: 0xa000, 0x329: 0xa000,
+	0x32a: 0x3870, 0x32b: 0x3876, 0x32c: 0x37c8, 0x32d: 0x384c, 0x32e: 0x37a4, 0x32f: 0x3828,
+	0x330: 0x37b0, 0x331: 0x3834, 0x332: 0x37b6, 0x333: 0x383a, 0x334: 0x37bc, 0x335: 0x3840,
+	0x338: 0x37c2, 0x339: 0x3846,
+	// Block 0xd, offset 0x340
+	0x351: 0x812d,
+	0x352: 0x8132, 0x353: 0x8132, 0x354: 0x8132, 0x355: 0x8132, 0x356: 0x812d, 0x357: 0x8132,
+	0x358: 0x8132, 0x359: 0x8132, 0x35a: 0x812e, 0x35b: 0x812d, 0x35c: 0x8132, 0x35d: 0x8132,
+	0x35e: 0x8132, 0x35f: 0x8132, 0x360: 0x8132, 0x361: 0x8132, 0x362: 0x812d, 0x363: 0x812d,
+	0x364: 0x812d, 0x365: 0x812d, 0x366: 0x812d, 0x367: 0x812d, 0x368: 0x8132, 0x369: 0x8132,
+	0x36a: 0x812d, 0x36b: 0x8132, 0x36c: 0x8132, 0x36d: 0x812e, 0x36e: 0x8131, 0x36f: 0x8132,
+	0x370: 0x8105, 0x371: 0x8106, 0x372: 0x8107, 0x373: 0x8108, 0x374: 0x8109, 0x375: 0x810a,
+	0x376: 0x810b, 0x377: 0x810c, 0x378: 0x810d, 0x379: 0x810e, 0x37a: 0x810e, 0x37b: 0x810f,
+	0x37c: 0x8110, 0x37d: 0x8111, 0x37f: 0x8112,
+	// Block 0xe, offset 0x380
+	0x388: 0xa000, 0x38a: 0xa000, 0x38b: 0x8116,
+	0x38c: 0x8117, 0x38d: 0x8118, 0x38e: 0x8119, 0x38f: 0x811a, 0x390: 0x811b, 0x391: 0x811c,
+	0x392: 0x811d, 0x393: 0x9932, 0x394: 0x9932, 0x395: 0x992d, 0x396: 0x812d, 0x397: 0x8132,
+	0x398: 0x8132, 0x399: 0x8132, 0x39a: 0x8132, 0x39b: 0x8132, 0x39c: 0x812d, 0x39d: 0x8132,
+	0x39e: 0x8132, 0x39f: 0x812d,
+	0x3b0: 0x811e,
+	// Block 0xf, offset 0x3c0
+	0x3c5: 0xa000,
+	0x3c6: 0x1958, 0x3c7: 0xa000, 0x3c8: 0x195f, 0x3c9: 0xa000, 0x3ca: 0x1966, 0x3cb: 0xa000,
+	0x3cc: 0x196d, 0x3cd: 0xa000, 0x3ce: 0x1974, 0x3d1: 0xa000,
+	0x3d2: 0x197b,
+	0x3f4: 0x8102, 0x3f5: 0x9900,
+	0x3fa: 0xa000, 0x3fb: 0x1982,
+	0x3fc: 0xa000, 0x3fd: 0x1989, 0x3fe: 0xa000, 0x3ff: 0xa000,
+	// Block 0x10, offset 0x400
+	0x400: 0x2fd2, 0x401: 0x32de, 0x402: 0x2fdc, 0x403: 0x32e8, 0x404: 0x2fe1, 0x405: 0x32ed,
+	0x406: 0x2fe6, 0x407: 0x32f2, 0x408: 0x3907, 0x409: 0x3a96, 0x40a: 0x2fff, 0x40b: 0x330b,
+	0x40c: 0x3009, 0x40d: 0x3315, 0x40e: 0x3018, 0x40f: 0x3324, 0x410: 0x300e, 0x411: 0x331a,
+	0x412: 0x3013, 0x413: 0x331f, 0x414: 0x392a, 0x415: 0x3ab9, 0x416: 0x3931, 0x417: 0x3ac0,
+	0x418: 0x3054, 0x419: 0x3360, 0x41a: 0x3059, 0x41b: 0x3365, 0x41c: 0x393f, 0x41d: 0x3ace,
+	0x41e: 0x305e, 0x41f: 0x336a, 0x420: 0x306d, 0x421: 0x3379, 0x422: 0x308b, 0x423: 0x3397,
+	0x424: 0x309a, 0x425: 0x33a6, 0x426: 0x3090, 0x427: 0x339c, 0x428: 0x309f, 0x429: 0x33ab,
+	0x42a: 0x30a4, 0x42b: 0x33b0, 0x42c: 0x30ea, 0x42d: 0x33f6, 0x42e: 0x3946, 0x42f: 0x3ad5,
+	0x430: 0x30f4, 0x431: 0x3405, 0x432: 0x30fe, 0x433: 0x340f, 0x434: 0x3108, 0x435: 0x3419,
+	0x436: 0x46ff, 0x437: 0x4790, 0x438: 0x394d, 0x439: 0x3adc, 0x43a: 0x3121, 0x43b: 0x3432,
+	0x43c: 0x311c, 0x43d: 0x342d, 0x43e: 0x3126, 0x43f: 0x3437,
+	// Block 0x11, offset 0x440
+	0x440: 0x312b, 0x441: 0x343c, 0x442: 0x3130, 0x443: 0x3441, 0x444: 0x3144, 0x445: 0x3455,
+	0x446: 0x314e, 0x447: 0x345f, 0x448: 0x315d, 0x449: 0x346e, 0x44a: 0x3158, 0x44b: 0x3469,
+	0x44c: 0x3970, 0x44d: 0x3aff, 0x44e: 0x397e, 0x44f: 0x3b0d, 0x450: 0x3985, 0x451: 0x3b14,
+	0x452: 0x398c, 0x453: 0x3b1b, 0x454: 0x318a, 0x455: 0x349b, 0x456: 0x318f, 0x457: 0x34a0,
+	0x458: 0x3199, 0x459: 0x34aa, 0x45a: 0x472c, 0x45b: 0x47bd, 0x45c: 0x39d2, 0x45d: 0x3b61,
+	0x45e: 0x31b2, 0x45f: 0x34c3, 0x460: 0x31bc, 0x461: 0x34cd, 0x462: 0x473b, 0x463: 0x47cc,
+	0x464: 0x39d9, 0x465: 0x3b68, 0x466: 0x39e0, 0x467: 0x3b6f, 0x468: 0x39e7, 0x469: 0x3b76,
+	0x46a: 0x31cb, 0x46b: 0x34dc, 0x46c: 0x31d5, 0x46d: 0x34eb, 0x46e: 0x31e9, 0x46f: 0x34ff,
+	0x470: 0x31e4, 0x471: 0x34fa, 0x472: 0x3225, 0x473: 0x353b, 0x474: 0x3234, 0x475: 0x354a,
+	0x476: 0x322f, 0x477: 0x3545, 0x478: 0x39ee, 0x479: 0x3b7d, 0x47a: 0x39f5, 0x47b: 0x3b84,
+	0x47c: 0x3239, 0x47d: 0x354f, 0x47e: 0x323e, 0x47f: 0x3554,
+	// Block 0x12, offset 0x480
+	0x480: 0x3243, 0x481: 0x3559, 0x482: 0x3248, 0x483: 0x355e, 0x484: 0x3257, 0x485: 0x356d,
+	0x486: 0x3252, 0x487: 0x3568, 0x488: 0x325c, 0x489: 0x3577, 0x48a: 0x3261, 0x48b: 0x357c,
+	0x48c: 0x3266, 0x48d: 0x3581, 0x48e: 0x3284, 0x48f: 0x359f, 0x490: 0x329d, 0x491: 0x35bd,
+	0x492: 0x32ac, 0x493: 0x35cc, 0x494: 0x32b1, 0x495: 0x35d1, 0x496: 0x33b5, 0x497: 0x34e1,
+	0x498: 0x3572, 0x499: 0x35ae, 0x49b: 0x360c,
+	0x4a0: 0x46dc, 0x4a1: 0x476d, 0x4a2: 0x2fbe, 0x4a3: 0x32ca,
+	0x4a4: 0x38b3, 0x4a5: 0x3a42, 0x4a6: 0x38ac, 0x4a7: 0x3a3b, 0x4a8: 0x38c1, 0x4a9: 0x3a50,
+	0x4aa: 0x38ba, 0x4ab: 0x3a49, 0x4ac: 0x38f9, 0x4ad: 0x3a88, 0x4ae: 0x38cf, 0x4af: 0x3a5e,
+	0x4b0: 0x38c8, 0x4b1: 0x3a57, 0x4b2: 0x38dd, 0x4b3: 0x3a6c, 0x4b4: 0x38d6, 0x4b5: 0x3a65,
+	0x4b6: 0x3900, 0x4b7: 0x3a8f, 0x4b8: 0x46f0, 0x4b9: 0x4781, 0x4ba: 0x303b, 0x4bb: 0x3347,
+	0x4bc: 0x3027, 0x4bd: 0x3333, 0x4be: 0x3915, 0x4bf: 0x3aa4,
+	// Block 0x13, offset 0x4c0
+	0x4c0: 0x390e, 0x4c1: 0x3a9d, 0x4c2: 0x3923, 0x4c3: 0x3ab2, 0x4c4: 0x391c, 0x4c5: 0x3aab,
+	0x4c6: 0x3938, 0x4c7: 0x3ac7, 0x4c8: 0x30cc, 0x4c9: 0x33d8, 0x4ca: 0x30e0, 0x4cb: 0x33ec,
+	0x4cc: 0x4722, 0x4cd: 0x47b3, 0x4ce: 0x3171, 0x4cf: 0x3482, 0x4d0: 0x395b, 0x4d1: 0x3aea,
+	0x4d2: 0x3954, 0x4d3: 0x3ae3, 0x4d4: 0x3969, 0x4d5: 0x3af8, 0x4d6: 0x3962, 0x4d7: 0x3af1,
+	0x4d8: 0x39c4, 0x4d9: 0x3b53, 0x4da: 0x39a8, 0x4db: 0x3b37, 0x4dc: 0x39a1, 0x4dd: 0x3b30,
+	0x4de: 0x39b6, 0x4df: 0x3b45, 0x4e0: 0x39af, 0x4e1: 0x3b3e, 0x4e2: 0x39bd, 0x4e3: 0x3b4c,
+	0x4e4: 0x3220, 0x4e5: 0x3536, 0x4e6: 0x3202, 0x4e7: 0x3518, 0x4e8: 0x3a1f, 0x4e9: 0x3bae,
+	0x4ea: 0x3a18, 0x4eb: 0x3ba7, 0x4ec: 0x3a2d, 0x4ed: 0x3bbc, 0x4ee: 0x3a26, 0x4ef: 0x3bb5,
+	0x4f0: 0x3a34, 0x4f1: 0x3bc3, 0x4f2: 0x326b, 0x4f3: 0x3586, 0x4f4: 0x3293, 0x4f5: 0x35b3,
+	0x4f6: 0x328e, 0x4f7: 0x35a9, 0x4f8: 0x327a, 0x4f9: 0x3595,
+	// Block 0x14, offset 0x500
+	0x500: 0x483f, 0x501: 0x4845, 0x502: 0x4959, 0x503: 0x4971, 0x504: 0x4961, 0x505: 0x4979,
+	0x506: 0x4969, 0x507: 0x4981, 0x508: 0x47e5, 0x509: 0x47eb, 0x50a: 0x48c9, 0x50b: 0x48e1,
+	0x50c: 0x48d1, 0x50d: 0x48e9, 0x50e: 0x48d9, 0x50f: 0x48f1, 0x510: 0x4851, 0x511: 0x4857,
+	0x512: 0x3df3, 0x513: 0x3e03, 0x514: 0x3dfb, 0x515: 0x3e0b,
+	0x518: 0x47f1, 0x519: 0x47f7, 0x51a: 0x3d23, 0x51b: 0x3d33, 0x51c: 0x3d2b, 0x51d: 0x3d3b,
+	0x520: 0x4869, 0x521: 0x486f, 0x522: 0x4989, 0x523: 0x49a1,
+	0x524: 0x4991, 0x525: 0x49a9, 0x526: 0x4999, 0x527: 0x49b1, 0x528: 0x47fd, 0x529: 0x4803,
+	0x52a: 0x48f9, 0x52b: 0x4911, 0x52c: 0x4901, 0x52d: 0x4919, 0x52e: 0x4909, 0x52f: 0x4921,
+	0x530: 0x4881, 0x531: 0x4887, 0x532: 0x3e53, 0x533: 0x3e6b, 0x534: 0x3e5b, 0x535: 0x3e73,
+	0x536: 0x3e63, 0x537: 0x3e7b, 0x538: 0x4809, 0x539: 0x480f, 0x53a: 0x3d53, 0x53b: 0x3d6b,
+	0x53c: 0x3d5b, 0x53d: 0x3d73, 0x53e: 0x3d63, 0x53f: 0x3d7b,
+	// Block 0x15, offset 0x540
+	0x540: 0x488d, 0x541: 0x4893, 0x542: 0x3e83, 0x543: 0x3e93, 0x544: 0x3e8b, 0x545: 0x3e9b,
+	0x548: 0x4815, 0x549: 0x481b, 0x54a: 0x3d83, 0x54b: 0x3d93,
+	0x54c: 0x3d8b, 0x54d: 0x3d9b, 0x550: 0x489f, 0x551: 0x48a5,
+	0x552: 0x3ebb, 0x553: 0x3ed3, 0x554: 0x3ec3, 0x555: 0x3edb, 0x556: 0x3ecb, 0x557: 0x3ee3,
+	0x559: 0x4821, 0x55b: 0x3da3, 0x55d: 0x3dab,
+	0x55f: 0x3db3, 0x560: 0x48b7, 0x561: 0x48bd, 0x562: 0x49b9, 0x563: 0x49d1,
+	0x564: 0x49c1, 0x565: 0x49d9, 0x566: 0x49c9, 0x567: 0x49e1, 0x568: 0x4827, 0x569: 0x482d,
+	0x56a: 0x4929, 0x56b: 0x4941, 0x56c: 0x4931, 0x56d: 0x4949, 0x56e: 0x4939, 0x56f: 0x4951,
+	0x570: 0x4833, 0x571: 0x4359, 0x572: 0x36cc, 0x573: 0x435f, 0x574: 0x485d, 0x575: 0x4365,
+	0x576: 0x36de, 0x577: 0x436b, 0x578: 0x36fc, 0x579: 0x4371, 0x57a: 0x3714, 0x57b: 0x4377,
+	0x57c: 0x48ab, 0x57d: 0x437d,
+	// Block 0x16, offset 0x580
+	0x580: 0x3ddb, 0x581: 0x3de3, 0x582: 0x41bf, 0x583: 0x41dd, 0x584: 0x41c9, 0x585: 0x41e7,
+	0x586: 0x41d3, 0x587: 0x41f1, 0x588: 0x3d13, 0x589: 0x3d1b, 0x58a: 0x410b, 0x58b: 0x4129,
+	0x58c: 0x4115, 0x58d: 0x4133, 0x58e: 0x411f, 0x58f: 0x413d, 0x590: 0x3e23, 0x591: 0x3e2b,
+	0x592: 0x41fb, 0x593: 0x4219, 0x594: 0x4205, 0x595: 0x4223, 0x596: 0x420f, 0x597: 0x422d,
+	0x598: 0x3d43, 0x599: 0x3d4b, 0x59a: 0x4147, 0x59b: 0x4165, 0x59c: 0x4151, 0x59d: 0x416f,
+	0x59e: 0x415b, 0x59f: 0x4179, 0x5a0: 0x3efb, 0x5a1: 0x3f03, 0x5a2: 0x4237, 0x5a3: 0x4255,
+	0x5a4: 0x4241, 0x5a5: 0x425f, 0x5a6: 0x424b, 0x5a7: 0x4269, 0x5a8: 0x3dbb, 0x5a9: 0x3dc3,
+	0x5aa: 0x4183, 0x5ab: 0x41a1, 0x5ac: 0x418d, 0x5ad: 0x41ab, 0x5ae: 0x4197, 0x5af: 0x41b5,
+	0x5b0: 0x36c0, 0x5b1: 0x36ba, 0x5b2: 0x3dcb, 0x5b3: 0x36c6, 0x5b4: 0x3dd3,
+	0x5b6: 0x484b, 0x5b7: 0x3deb, 0x5b8: 0x3630, 0x5b9: 0x362a, 0x5ba: 0x361e, 0x5bb: 0x4329,
+	0x5bc: 0x3636, 0x5bd: 0x8100, 0x5be: 0x01d3, 0x5bf: 0xa100,
+	// Block 0x17, offset 0x5c0
+	0x5c0: 0x8100, 0x5c1: 0x35e2, 0x5c2: 0x3e13, 0x5c3: 0x36d8, 0x5c4: 0x3e1b,
+	0x5c6: 0x4875, 0x5c7: 0x3e33, 0x5c8: 0x363c, 0x5c9: 0x432f, 0x5ca: 0x3648, 0x5cb: 0x4335,
+	0x5cc: 0x3654, 0x5cd: 0x3bca, 0x5ce: 0x3bd1, 0x5cf: 0x3bd8, 0x5d0: 0x36f0, 0x5d1: 0x36ea,
+	0x5d2: 0x3e3b, 0x5d3: 0x451f, 0x5d6: 0x36f6, 0x5d7: 0x3e4b,
+	0x5d8: 0x366c, 0x5d9: 0x3666, 0x5da: 0x365a, 0x5db: 0x433b, 0x5dd: 0x3bdf,
+	0x5de: 0x3be6, 0x5df: 0x3bed, 0x5e0: 0x3726, 0x5e1: 0x3720, 0x5e2: 0x3ea3, 0x5e3: 0x4527,
+	0x5e4: 0x3708, 0x5e5: 0x370e, 0x5e6: 0x372c, 0x5e7: 0x3eb3, 0x5e8: 0x369c, 0x5e9: 0x3696,
+	0x5ea: 0x368a, 0x5eb: 0x4347, 0x5ec: 0x3684, 0x5ed: 0x35d6, 0x5ee: 0x4323, 0x5ef: 0x0081,
+	0x5f2: 0x3eeb, 0x5f3: 0x3732, 0x5f4: 0x3ef3,
+	0x5f6: 0x48c3, 0x5f7: 0x3f0b, 0x5f8: 0x3678, 0x5f9: 0x4341, 0x5fa: 0x36a8, 0x5fb: 0x4353,
+	0x5fc: 0x36b4, 0x5fd: 0x4291, 0x5fe: 0xa100,
+	// Block 0x18, offset 0x600
+	0x601: 0x3c41, 0x603: 0xa000, 0x604: 0x3c48, 0x605: 0xa000,
+	0x607: 0x3c4f, 0x608: 0xa000, 0x609: 0x3c56,
+	0x60d: 0xa000,
+	0x620: 0x2fa0, 0x621: 0xa000, 0x622: 0x3c64,
+	0x624: 0xa000, 0x625: 0xa000,
+	0x62d: 0x3c5d, 0x62e: 0x2f9b, 0x62f: 0x2fa5,
+	0x630: 0x3c6b, 0x631: 0x3c72, 0x632: 0xa000, 0x633: 0xa000, 0x634: 0x3c79, 0x635: 0x3c80,
+	0x636: 0xa000, 0x637: 0xa000, 0x638: 0x3c87, 0x639: 0x3c8e, 0x63a: 0xa000, 0x63b: 0xa000,
+	0x63c: 0xa000, 0x63d: 0xa000,
+	// Block 0x19, offset 0x640
+	0x640: 0x3c95, 0x641: 0x3c9c, 0x642: 0xa000, 0x643: 0xa000, 0x644: 0x3cb1, 0x645: 0x3cb8,
+	0x646: 0xa000, 0x647: 0xa000, 0x648: 0x3cbf, 0x649: 0x3cc6,
+	0x651: 0xa000,
+	0x652: 0xa000,
+	0x662: 0xa000,
+	0x668: 0xa000, 0x669: 0xa000,
+	0x66b: 0xa000, 0x66c: 0x3cdb, 0x66d: 0x3ce2, 0x66e: 0x3ce9, 0x66f: 0x3cf0,
+	0x672: 0xa000, 0x673: 0xa000, 0x674: 0xa000, 0x675: 0xa000,
+	// Block 0x1a, offset 0x680
+	0x686: 0xa000, 0x68b: 0xa000,
+	0x68c: 0x3f43, 0x68d: 0xa000, 0x68e: 0x3f4b, 0x68f: 0xa000, 0x690: 0x3f53, 0x691: 0xa000,
+	0x692: 0x3f5b, 0x693: 0xa000, 0x694: 0x3f63, 0x695: 0xa000, 0x696: 0x3f6b, 0x697: 0xa000,
+	0x698: 0x3f73, 0x699: 0xa000, 0x69a: 0x3f7b, 0x69b: 0xa000, 0x69c: 0x3f83, 0x69d: 0xa000,
+	0x69e: 0x3f8b, 0x69f: 0xa000, 0x6a0: 0x3f93, 0x6a1: 0xa000, 0x6a2: 0x3f9b,
+	0x6a4: 0xa000, 0x6a5: 0x3fa3, 0x6a6: 0xa000, 0x6a7: 0x3fab, 0x6a8: 0xa000, 0x6a9: 0x3fb3,
+	0x6af: 0xa000,
+	0x6b0: 0x3fbb, 0x6b1: 0x3fc3, 0x6b2: 0xa000, 0x6b3: 0x3fcb, 0x6b4: 0x3fd3, 0x6b5: 0xa000,
+	0x6b6: 0x3fdb, 0x6b7: 0x3fe3, 0x6b8: 0xa000, 0x6b9: 0x3feb, 0x6ba: 0x3ff3, 0x6bb: 0xa000,
+	0x6bc: 0x3ffb, 0x6bd: 0x4003,
+	// Block 0x1b, offset 0x6c0
+	0x6d4: 0x3f3b,
+	0x6d9: 0x9903, 0x6da: 0x9903, 0x6db: 0x8100, 0x6dc: 0x8100, 0x6dd: 0xa000,
+	0x6de: 0x400b,
+	0x6e6: 0xa000,
+	0x6eb: 0xa000, 0x6ec: 0x401b, 0x6ed: 0xa000, 0x6ee: 0x4023, 0x6ef: 0xa000,
+	0x6f0: 0x402b, 0x6f1: 0xa000, 0x6f2: 0x4033, 0x6f3: 0xa000, 0x6f4: 0x403b, 0x6f5: 0xa000,
+	0x6f6: 0x4043, 0x6f7: 0xa000, 0x6f8: 0x404b, 0x6f9: 0xa000, 0x6fa: 0x4053, 0x6fb: 0xa000,
+	0x6fc: 0x405b, 0x6fd: 0xa000, 0x6fe: 0x4063, 0x6ff: 0xa000,
+	// Block 0x1c, offset 0x700
+	0x700: 0x406b, 0x701: 0xa000, 0x702: 0x4073, 0x704: 0xa000, 0x705: 0x407b,
+	0x706: 0xa000, 0x707: 0x4083, 0x708: 0xa000, 0x709: 0x408b,
+	0x70f: 0xa000, 0x710: 0x4093, 0x711: 0x409b,
+	0x712: 0xa000, 0x713: 0x40a3, 0x714: 0x40ab, 0x715: 0xa000, 0x716: 0x40b3, 0x717: 0x40bb,
+	0x718: 0xa000, 0x719: 0x40c3, 0x71a: 0x40cb, 0x71b: 0xa000, 0x71c: 0x40d3, 0x71d: 0x40db,
+	0x72f: 0xa000,
+	0x730: 0xa000, 0x731: 0xa000, 0x732: 0xa000, 0x734: 0x4013,
+	0x737: 0x40e3, 0x738: 0x40eb, 0x739: 0x40f3, 0x73a: 0x40fb,
+	0x73d: 0xa000, 0x73e: 0x4103,
+	// Block 0x1d, offset 0x740
+	0x740: 0x13ef, 0x741: 0x0d73, 0x742: 0x144b, 0x743: 0x1417, 0x744: 0x0ecf, 0x745: 0x0763,
+	0x746: 0x0957, 0x747: 0x169f, 0x748: 0x169f, 0x749: 0x0a83, 0x74a: 0x14d3, 0x74b: 0x09bb,
+	0x74c: 0x0a7f, 0x74d: 0x0c67, 0x74e: 0x1047, 0x74f: 0x11d7, 0x750: 0x130f, 0x751: 0x134b,
+	0x752: 0x137f, 0x753: 0x1493, 0x754: 0x0deb, 0x755: 0x0e77, 0x756: 0x0f23, 0x757: 0x0fbb,
+	0x758: 0x12d7, 0x759: 0x14bb, 0x75a: 0x15e7, 0x75b: 0x0787, 0x75c: 0x092b, 0x75d: 0x0dff,
+	0x75e: 0x0f47, 0x75f: 0x130b, 0x760: 0x1637, 0x761: 0x0b2b, 0x762: 0x0eef, 0x763: 0x12fb,
+	0x764: 0x138f, 0x765: 0x0c9b, 0x766: 0x1233, 0x767: 0x1357, 0x768: 0x0b97, 0x769: 0x0d87,
+	0x76a: 0x0e8f, 0x76b: 0x0f93, 0x76c: 0x149f, 0x76d: 0x07c7, 0x76e: 0x085f, 0x76f: 0x08cb,
+	0x770: 0x0d03, 0x771: 0x0df7, 0x772: 0x0f43, 0x773: 0x1067, 0x774: 0x11ef, 0x775: 0x1303,
+	0x776: 0x131b, 0x777: 0x143f, 0x778: 0x1563, 0x779: 0x1617, 0x77a: 0x1633, 0x77b: 0x10a3,
+	0x77c: 0x10e3, 0x77d: 0x119b, 0x77e: 0x12bb, 0x77f: 0x14ef,
+	// Block 0x1e, offset 0x780
+	0x780: 0x163f, 0x781: 0x13c3, 0x782: 0x0a3f, 0x783: 0x0bb3, 0x784: 0x1153, 0x785: 0x1213,
+	0x786: 0x0f77, 0x787: 0x10ab, 0x788: 0x140f, 0x789: 0x155b, 0x78a: 0x0a3b, 0x78b: 0x0b07,
+	0x78c: 0x0def, 0x78d: 0x0ea3, 0x78e: 0x0ed7, 0x78f: 0x118b, 0x790: 0x11b3, 0x791: 0x151b,
+	0x792: 0x08c7, 0x793: 0x121f, 0x794: 0x086b, 0x795: 0x0867, 0x796: 0x110f, 0x797: 0x119f,
+	0x798: 0x12d3, 0x799: 0x1523, 0x79a: 0x13df, 0x79b: 0x0c9f, 0x79c: 0x0deb, 0x79d: 0x13cf,
+	0x79e: 0x076f, 0x79f: 0x0adb, 0x7a0: 0x0c0b, 0x7a1: 0x0fa7, 0x7a2: 0x1027, 0x7a3: 0x08eb,
+	0x7a4: 0x10b3, 0x7a5: 0x07d7, 0x7a6: 0x0bef, 0x7a7: 0x074f, 0x7a8: 0x0e63, 0x7a9: 0x0d1b,
+	0x7aa: 0x1187, 0x7ab: 0x093f, 0x7ac: 0x0a2b, 0x7ad: 0x1073, 0x7ae: 0x12db, 0x7af: 0x13b3,
+	0x7b0: 0x0e2f, 0x7b1: 0x146f, 0x7b2: 0x0e5b, 0x7b3: 0x0caf, 0x7b4: 0x1293, 0x7b5: 0x0ccf,
+	0x7b6: 0x1023, 0x7b7: 0x07a3, 0x7b8: 0x081f, 0x7b9: 0x0863, 0x7ba: 0x0dcb, 0x7bb: 0x1173,
+	0x7bc: 0x126b, 0x7bd: 0x13bf, 0x7be: 0x14cf, 0x7bf: 0x08d3,
+	// Block 0x1f, offset 0x7c0
+	0x7c0: 0x0987, 0x7c1: 0x0a8f, 0x7c2: 0x0ba7, 0x7c3: 0x0d37, 0x7c4: 0x0ef3, 0x7c5: 0x10b7,
+	0x7c6: 0x150b, 0x7c7: 0x15ef, 0x7c8: 0x1643, 0x7c9: 0x165b, 0x7ca: 0x08af, 0x7cb: 0x0d6b,
+	0x7cc: 0x0e1b, 0x7cd: 0x1463, 0x7ce: 0x0b73, 0x7cf: 0x0c4f, 0x7d0: 0x0c6b, 0x7d1: 0x0cfb,
+	0x7d2: 0x0ee3, 0x7d3: 0x0f2f, 0x7d4: 0x0fdf, 0x7d5: 0x1103, 0x7d6: 0x11a7, 0x7d7: 0x120b,
+	0x7d8: 0x1453, 0x7d9: 0x12e3, 0x7da: 0x147b, 0x7db: 0x14f3, 0x7dc: 0x0887, 0x7dd: 0x08b3,
+	0x7de: 0x099b, 0x7df: 0x0f1f, 0x7e0: 0x136b, 0x7e1: 0x13b3, 0x7e2: 0x0b93, 0x7e3: 0x0c03,
+	0x7e4: 0x0cc7, 0x7e5: 0x0e27, 0x7e6: 0x114f, 0x7e7: 0x0f9b, 0x7e8: 0x07b3, 0x7e9: 0x09f7,
+	0x7ea: 0x0adb, 0x7eb: 0x0b3f, 0x7ec: 0x0c0f, 0x7ed: 0x0fb7, 0x7ee: 0x0fd3, 0x7ef: 0x11e3,
+	0x7f0: 0x1203, 0x7f1: 0x14d7, 0x7f2: 0x1557, 0x7f3: 0x1567, 0x7f4: 0x15a3, 0x7f5: 0x07cb,
+	0x7f6: 0x10f7, 0x7f7: 0x14c3, 0x7f8: 0x153f, 0x7f9: 0x0c27, 0x7fa: 0x078f, 0x7fb: 0x07ef,
+	0x7fc: 0x0adf, 0x7fd: 0x0aff, 0x7fe: 0x0d27, 0x7ff: 0x0deb,
+	// Block 0x20, offset 0x800
+	0x800: 0x0f3b, 0x801: 0x1043, 0x802: 0x12ef, 0x803: 0x148f, 0x804: 0x1697, 0x805: 0x0d5b,
+	0x806: 0x1517, 0x807: 0x08ab, 0x808: 0x0da7, 0x809: 0x0db3, 0x80a: 0x0e87, 0x80b: 0x0ebf,
+	0x80c: 0x0fc3, 0x80d: 0x101f, 0x80e: 0x109f, 0x80f: 0x1183, 0x810: 0x15af, 0x811: 0x0827,
+	0x812: 0x0c7b, 0x813: 0x1527, 0x814: 0x07df, 0x815: 0x0b23, 0x816: 0x0ea7, 0x817: 0x1457,
+	0x818: 0x0bdf, 0x819: 0x0c2f, 0x81a: 0x0dbb, 0x81b: 0x0fa7, 0x81c: 0x152f, 0x81d: 0x088f,
+	0x81e: 0x0977, 0x81f: 0x0b0f, 0x820: 0x0d4b, 0x821: 0x0d97, 0x822: 0x0dd7, 0x823: 0x0e6b,
+	0x824: 0x0fbf, 0x825: 0x1033, 0x826: 0x11cf, 0x827: 0x136f, 0x828: 0x137b, 0x829: 0x14cb,
+	0x82a: 0x154b, 0x82b: 0x08fb, 0x82c: 0x0ec3, 0x82d: 0x097b, 0x82e: 0x0f3f, 0x82f: 0x0fe3,
+	0x830: 0x12ff, 0x831: 0x1533, 0x832: 0x161f, 0x833: 0x1647, 0x834: 0x0daf, 0x835: 0x0e9f,
+	0x836: 0x123b, 0x837: 0x112f, 0x838: 0x113b, 0x839: 0x115f, 0x83a: 0x0f8f, 0x83b: 0x0f17,
+	0x83c: 0x13db, 0x83d: 0x07ab, 0x83e: 0x12a3, 0x83f: 0x0893,
+	// Block 0x21, offset 0x840
+	0x840: 0x0883, 0x841: 0x0b83, 0x842: 0x0ca3, 0x843: 0x116b, 0x844: 0x0acb, 0x845: 0x0e7b,
+	0x846: 0x0d67, 0x847: 0x145f, 0x848: 0x135f, 0x849: 0x151f, 0x84a: 0x139b, 0x84b: 0x0b9f,
+	0x84c: 0x07ff, 0x84d: 0x09d3, 0x850: 0x0a27,
+	0x852: 0x0d57, 0x855: 0x086f, 0x856: 0x0f97, 0x857: 0x105b,
+	0x858: 0x10bf, 0x859: 0x10db, 0x85a: 0x10df, 0x85b: 0x10f3, 0x85c: 0x156f, 0x85d: 0x1163,
+	0x85e: 0x11e7, 0x860: 0x1307, 0x862: 0x13cb,
+	0x865: 0x147f, 0x866: 0x14ab,
+	0x86a: 0x15c3, 0x86b: 0x15c7, 0x86c: 0x15cb, 0x86d: 0x162f, 0x86e: 0x14a3, 0x86f: 0x153b,
+	0x870: 0x07cf, 0x871: 0x07f3, 0x872: 0x0807, 0x873: 0x08c3, 0x874: 0x08cf, 0x875: 0x090f,
+	0x876: 0x09c3, 0x877: 0x09df, 0x878: 0x09e7, 0x879: 0x0a23, 0x87a: 0x0a2f, 0x87b: 0x0b0b,
+	0x87c: 0x0b13, 0x87d: 0x0c1b, 0x87e: 0x0c43, 0x87f: 0x0c4b,
+	// Block 0x22, offset 0x880
+	0x880: 0x0c63, 0x881: 0x0d0f, 0x882: 0x0d3f, 0x883: 0x0d5f, 0x884: 0x0dcf, 0x885: 0x0e93,
+	0x886: 0x0eaf, 0x887: 0x0edf, 0x888: 0x0f33, 0x889: 0x0f53, 0x88a: 0x0fc7, 0x88b: 0x10a7,
+	0x88c: 0x10c3, 0x88d: 0x10cb, 0x88e: 0x10c7, 0x88f: 0x10cf, 0x890: 0x10d3, 0x891: 0x10d7,
+	0x892: 0x10eb, 0x893: 0x10ef, 0x894: 0x1113, 0x895: 0x1127, 0x896: 0x1143, 0x897: 0x11a7,
+	0x898: 0x11af, 0x899: 0x11b7, 0x89a: 0x11cb, 0x89b: 0x11f3, 0x89c: 0x1243, 0x89d: 0x1277,
+	0x89e: 0x1277, 0x89f: 0x12df, 0x8a0: 0x1387, 0x8a1: 0x139f, 0x8a2: 0x13d3, 0x8a3: 0x13d7,
+	0x8a4: 0x141b, 0x8a5: 0x141f, 0x8a6: 0x1477, 0x8a7: 0x147f, 0x8a8: 0x154f, 0x8a9: 0x1593,
+	0x8aa: 0x15ab, 0x8ab: 0x0c13, 0x8ac: 0x1792, 0x8ad: 0x125b,
+	0x8b0: 0x0757, 0x8b1: 0x085b, 0x8b2: 0x081b, 0x8b3: 0x07c3, 0x8b4: 0x0803, 0x8b5: 0x082f,
+	0x8b6: 0x08bf, 0x8b7: 0x08db, 0x8b8: 0x09c3, 0x8b9: 0x09af, 0x8ba: 0x09bf, 0x8bb: 0x09db,
+	0x8bc: 0x0a27, 0x8bd: 0x0a37, 0x8be: 0x0a7b, 0x8bf: 0x0a87,
+	// Block 0x23, offset 0x8c0
+	0x8c0: 0x0aa3, 0x8c1: 0x0ab3, 0x8c2: 0x0b9b, 0x8c3: 0x0ba3, 0x8c4: 0x0bd3, 0x8c5: 0x0bf3,
+	0x8c6: 0x0c23, 0x8c7: 0x0c3b, 0x8c8: 0x0c2b, 0x8c9: 0x0c4b, 0x8ca: 0x0c3f, 0x8cb: 0x0c63,
+	0x8cc: 0x0c7f, 0x8cd: 0x0cd7, 0x8ce: 0x0ce3, 0x8cf: 0x0ceb, 0x8d0: 0x0d13, 0x8d1: 0x0d57,
+	0x8d2: 0x0d87, 0x8d3: 0x0d8b, 0x8d4: 0x0d9f, 0x8d5: 0x0e1f, 0x8d6: 0x0e2f, 0x8d7: 0x0e87,
+	0x8d8: 0x0ed3, 0x8d9: 0x0ecb, 0x8da: 0x0edf, 0x8db: 0x0efb, 0x8dc: 0x0f33, 0x8dd: 0x108b,
+	0x8de: 0x0f57, 0x8df: 0x0f8b, 0x8e0: 0x0f97, 0x8e1: 0x0fd7, 0x8e2: 0x0ff3, 0x8e3: 0x1017,
+	0x8e4: 0x103b, 0x8e5: 0x103f, 0x8e6: 0x105b, 0x8e7: 0x105f, 0x8e8: 0x106f, 0x8e9: 0x1083,
+	0x8ea: 0x107f, 0x8eb: 0x10af, 0x8ec: 0x112b, 0x8ed: 0x1143, 0x8ee: 0x115b, 0x8ef: 0x1193,
+	0x8f0: 0x11a7, 0x8f1: 0x11c3, 0x8f2: 0x11f3, 0x8f3: 0x12a7, 0x8f4: 0x12cf, 0x8f5: 0x1343,
+	0x8f6: 0x138b, 0x8f7: 0x1397, 0x8f8: 0x139f, 0x8f9: 0x13b7, 0x8fa: 0x13cb, 0x8fb: 0x13bb,
+	0x8fc: 0x13d3, 0x8fd: 0x13cf, 0x8fe: 0x13c7, 0x8ff: 0x13d7,
+	// Block 0x24, offset 0x900
+	0x900: 0x13e3, 0x901: 0x141f, 0x902: 0x145b, 0x903: 0x148b, 0x904: 0x14bf, 0x905: 0x14df,
+	0x906: 0x152b, 0x907: 0x154f, 0x908: 0x156f, 0x909: 0x1583, 0x90a: 0x1593, 0x90b: 0x159f,
+	0x90c: 0x15ab, 0x90d: 0x15ff, 0x90e: 0x169f, 0x90f: 0x1729, 0x910: 0x1724, 0x911: 0x1756,
+	0x912: 0x067f, 0x913: 0x06a7, 0x914: 0x06ab, 0x915: 0x17d8, 0x916: 0x1805, 0x917: 0x187d,
+	0x918: 0x168b, 0x919: 0x169b,
+	// Block 0x25, offset 0x940
+	0x940: 0x0773, 0x941: 0x076b, 0x942: 0x077b, 0x943: 0x16bb, 0x944: 0x07bf, 0x945: 0x07cf,
+	0x946: 0x07d3, 0x947: 0x07db, 0x948: 0x07e3, 0x949: 0x07e7, 0x94a: 0x07f3, 0x94b: 0x07eb,
+	0x94c: 0x062b, 0x94d: 0x16cf, 0x94e: 0x0807, 0x94f: 0x080b, 0x950: 0x080f, 0x951: 0x082b,
+	0x952: 0x16c0, 0x953: 0x062f, 0x954: 0x0817, 0x955: 0x0837, 0x956: 0x16ca, 0x957: 0x0847,
+	0x958: 0x084f, 0x959: 0x07af, 0x95a: 0x0857, 0x95b: 0x085b, 0x95c: 0x18a5, 0x95d: 0x0877,
+	0x95e: 0x087f, 0x95f: 0x0637, 0x960: 0x0897, 0x961: 0x089b, 0x962: 0x08a3, 0x963: 0x08a7,
+	0x964: 0x063b, 0x965: 0x08bf, 0x966: 0x08c3, 0x967: 0x08cf, 0x968: 0x08db, 0x969: 0x08df,
+	0x96a: 0x08e3, 0x96b: 0x08eb, 0x96c: 0x090b, 0x96d: 0x090f, 0x96e: 0x0917, 0x96f: 0x0927,
+	0x970: 0x092f, 0x971: 0x0933, 0x972: 0x0933, 0x973: 0x0933, 0x974: 0x16de, 0x975: 0x0f0b,
+	0x976: 0x0947, 0x977: 0x094f, 0x978: 0x16e3, 0x979: 0x095b, 0x97a: 0x0963, 0x97b: 0x096b,
+	0x97c: 0x0993, 0x97d: 0x097f, 0x97e: 0x098b, 0x97f: 0x098f,
+	// Block 0x26, offset 0x980
+	0x980: 0x0997, 0x981: 0x099f, 0x982: 0x09a3, 0x983: 0x09ab, 0x984: 0x09b3, 0x985: 0x09b7,
+	0x986: 0x09b7, 0x987: 0x09bf, 0x988: 0x09c7, 0x989: 0x09cb, 0x98a: 0x09d7, 0x98b: 0x09fb,
+	0x98c: 0x09df, 0x98d: 0x09ff, 0x98e: 0x09e3, 0x98f: 0x09eb, 0x990: 0x0883, 0x991: 0x0a47,
+	0x992: 0x0a0f, 0x993: 0x0a13, 0x994: 0x0a17, 0x995: 0x0a0b, 0x996: 0x0a1f, 0x997: 0x0a1b,
+	0x998: 0x0a33, 0x999: 0x16e8, 0x99a: 0x0a4f, 0x99b: 0x0a53, 0x99c: 0x0a5b, 0x99d: 0x0a67,
+	0x99e: 0x0a6f, 0x99f: 0x0a8b, 0x9a0: 0x16ed, 0x9a1: 0x16f2, 0x9a2: 0x0a97, 0x9a3: 0x0a9b,
+	0x9a4: 0x0a9f, 0x9a5: 0x0a93, 0x9a6: 0x0aa7, 0x9a7: 0x063f, 0x9a8: 0x0643, 0x9a9: 0x0aaf,
+	0x9aa: 0x0ab7, 0x9ab: 0x0ab7, 0x9ac: 0x16f7, 0x9ad: 0x0ad3, 0x9ae: 0x0ad7, 0x9af: 0x0adb,
+	0x9b0: 0x0ae3, 0x9b1: 0x16fc, 0x9b2: 0x0aeb, 0x9b3: 0x0aef, 0x9b4: 0x0bc7, 0x9b5: 0x0af7,
+	0x9b6: 0x0647, 0x9b7: 0x0b03, 0x9b8: 0x0b13, 0x9b9: 0x0b1f, 0x9ba: 0x0b1b, 0x9bb: 0x1706,
+	0x9bc: 0x0b27, 0x9bd: 0x170b, 0x9be: 0x0b33, 0x9bf: 0x0b2f,
+	// Block 0x27, offset 0x9c0
+	0x9c0: 0x0b37, 0x9c1: 0x0b47, 0x9c2: 0x0b4b, 0x9c3: 0x064b, 0x9c4: 0x0b5b, 0x9c5: 0x0b63,
+	0x9c6: 0x0b67, 0x9c7: 0x0b6b, 0x9c8: 0x064f, 0x9c9: 0x1710, 0x9ca: 0x0653, 0x9cb: 0x0b87,
+	0x9cc: 0x0b8b, 0x9cd: 0x0b8f, 0x9ce: 0x0b97, 0x9cf: 0x18d7, 0x9d0: 0x0baf, 0x9d1: 0x171a,
+	0x9d2: 0x171a, 0x9d3: 0x124f, 0x9d4: 0x0bbf, 0x9d5: 0x0bbf, 0x9d6: 0x0657, 0x9d7: 0x173d,
+	0x9d8: 0x180f, 0x9d9: 0x0bcf, 0x9da: 0x0bd7, 0x9db: 0x065b, 0x9dc: 0x0beb, 0x9dd: 0x0bfb,
+	0x9de: 0x0bff, 0x9df: 0x0c07, 0x9e0: 0x0c17, 0x9e1: 0x0663, 0x9e2: 0x065f, 0x9e3: 0x0c1b,
+	0x9e4: 0x171f, 0x9e5: 0x0c1f, 0x9e6: 0x0c33, 0x9e7: 0x0c37, 0x9e8: 0x0c3b, 0x9e9: 0x0c37,
+	0x9ea: 0x0c47, 0x9eb: 0x0c4b, 0x9ec: 0x0c5b, 0x9ed: 0x0c53, 0x9ee: 0x0c57, 0x9ef: 0x0c5f,
+	0x9f0: 0x0c63, 0x9f1: 0x0c67, 0x9f2: 0x0c73, 0x9f3: 0x0c77, 0x9f4: 0x0c8f, 0x9f5: 0x0c97,
+	0x9f6: 0x0ca7, 0x9f7: 0x0cbb, 0x9f8: 0x172e, 0x9f9: 0x0cb7, 0x9fa: 0x0cab, 0x9fb: 0x0cc3,
+	0x9fc: 0x0ccb, 0x9fd: 0x0cdf, 0x9fe: 0x1733, 0x9ff: 0x0ce7,
+	// Block 0x28, offset 0xa00
+	0xa00: 0x0cdb, 0xa01: 0x0cd3, 0xa02: 0x0667, 0xa03: 0x0cef, 0xa04: 0x0cf7, 0xa05: 0x0cff,
+	0xa06: 0x0cf3, 0xa07: 0x066b, 0xa08: 0x0d0f, 0xa09: 0x0d17, 0xa0a: 0x1738, 0xa0b: 0x0d43,
+	0xa0c: 0x0d77, 0xa0d: 0x0d53, 0xa0e: 0x0677, 0xa0f: 0x0d5f, 0xa10: 0x0673, 0xa11: 0x066f,
+	0xa12: 0x083b, 0xa13: 0x083f, 0xa14: 0x0d7b, 0xa15: 0x0d63, 0xa16: 0x1223, 0xa17: 0x06db,
+	0xa18: 0x0d87, 0xa19: 0x0d8b, 0xa1a: 0x0d8f, 0xa1b: 0x0da3, 0xa1c: 0x0d9b, 0xa1d: 0x1751,
+	0xa1e: 0x067b, 0xa1f: 0x0db7, 0xa20: 0x0dab, 0xa21: 0x0dc7, 0xa22: 0x0dcf, 0xa23: 0x175b,
+	0xa24: 0x0dd3, 0xa25: 0x0dbf, 0xa26: 0x0ddb, 0xa27: 0x067f, 0xa28: 0x0ddf, 0xa29: 0x0de3,
+	0xa2a: 0x0de7, 0xa2b: 0x0df3, 0xa2c: 0x1760, 0xa2d: 0x0dfb, 0xa2e: 0x0683, 0xa2f: 0x0e07,
+	0xa30: 0x1765, 0xa31: 0x0e0b, 0xa32: 0x0687, 0xa33: 0x0e17, 0xa34: 0x0e23, 0xa35: 0x0e2f,
+	0xa36: 0x0e33, 0xa37: 0x176a, 0xa38: 0x1701, 0xa39: 0x176f, 0xa3a: 0x0e53, 0xa3b: 0x1774,
+	0xa3c: 0x0e5f, 0xa3d: 0x0e67, 0xa3e: 0x0e57, 0xa3f: 0x0e73,
+	// Block 0x29, offset 0xa40
+	0xa40: 0x0e83, 0xa41: 0x0e93, 0xa42: 0x0e87, 0xa43: 0x0e8b, 0xa44: 0x0e97, 0xa45: 0x0e9b,
+	0xa46: 0x1779, 0xa47: 0x0e7f, 0xa48: 0x0eb3, 0xa49: 0x0eb7, 0xa4a: 0x068b, 0xa4b: 0x0ecb,
+	0xa4c: 0x0ec7, 0xa4d: 0x177e, 0xa4e: 0x0eab, 0xa4f: 0x0ee7, 0xa50: 0x1783, 0xa51: 0x1788,
+	0xa52: 0x0eeb, 0xa53: 0x0eff, 0xa54: 0x0efb, 0xa55: 0x0ef7, 0xa56: 0x068f, 0xa57: 0x0f03,
+	0xa58: 0x0f13, 0xa59: 0x0f0f, 0xa5a: 0x0f1b, 0xa5b: 0x16c5, 0xa5c: 0x0f2b, 0xa5d: 0x178d,
+	0xa5e: 0x0f37, 0xa5f: 0x1797, 0xa60: 0x0f4b, 0xa61: 0x0f57, 0xa62: 0x0f6b, 0xa63: 0x179c,
+	0xa64: 0x0f7f, 0xa65: 0x0f83, 0xa66: 0x17a1, 0xa67: 0x17a6, 0xa68: 0x0f9f, 0xa69: 0x0faf,
+	0xa6a: 0x0693, 0xa6b: 0x0fb3, 0xa6c: 0x0697, 0xa6d: 0x0697, 0xa6e: 0x0fcb, 0xa6f: 0x0fcf,
+	0xa70: 0x0fd7, 0xa71: 0x0fdb, 0xa72: 0x0fe7, 0xa73: 0x069b, 0xa74: 0x0fff, 0xa75: 0x17ab,
+	0xa76: 0x101b, 0xa77: 0x17b0, 0xa78: 0x1027, 0xa79: 0x1715, 0xa7a: 0x1037, 0xa7b: 0x17b5,
+	0xa7c: 0x17ba, 0xa7d: 0x17bf, 0xa7e: 0x069f, 0xa7f: 0x06a3,
+	// Block 0x2a, offset 0xa80
+	0xa80: 0x106f, 0xa81: 0x17c9, 0xa82: 0x17c4, 0xa83: 0x17ce, 0xa84: 0x17d3, 0xa85: 0x1077,
+	0xa86: 0x107b, 0xa87: 0x107b, 0xa88: 0x1083, 0xa89: 0x06ab, 0xa8a: 0x1087, 0xa8b: 0x06af,
+	0xa8c: 0x06b3, 0xa8d: 0x17dd, 0xa8e: 0x109b, 0xa8f: 0x10a3, 0xa90: 0x10af, 0xa91: 0x06b7,
+	0xa92: 0x17e2, 0xa93: 0x10d3, 0xa94: 0x17e7, 0xa95: 0x17ec, 0xa96: 0x10f3, 0xa97: 0x110b,
+	0xa98: 0x06bb, 0xa99: 0x1113, 0xa9a: 0x1117, 0xa9b: 0x111b, 0xa9c: 0x17f1, 0xa9d: 0x17f6,
+	0xa9e: 0x17f6, 0xa9f: 0x1133, 0xaa0: 0x06bf, 0xaa1: 0x17fb, 0xaa2: 0x1147, 0xaa3: 0x114b,
+	0xaa4: 0x06c3, 0xaa5: 0x1800, 0xaa6: 0x1167, 0xaa7: 0x06c7, 0xaa8: 0x1177, 0xaa9: 0x116f,
+	0xaaa: 0x117f, 0xaab: 0x180a, 0xaac: 0x1197, 0xaad: 0x06cb, 0xaae: 0x11a3, 0xaaf: 0x11ab,
+	0xab0: 0x11bb, 0xab1: 0x06cf, 0xab2: 0x1814, 0xab3: 0x1819, 0xab4: 0x06d3, 0xab5: 0x181e,
+	0xab6: 0x11d3, 0xab7: 0x1823, 0xab8: 0x11df, 0xab9: 0x11eb, 0xaba: 0x11f3, 0xabb: 0x1828,
+	0xabc: 0x182d, 0xabd: 0x1207, 0xabe: 0x1832, 0xabf: 0x120f,
+	// Block 0x2b, offset 0xac0
+	0xac0: 0x1742, 0xac1: 0x06d7, 0xac2: 0x1227, 0xac3: 0x122b, 0xac4: 0x06df, 0xac5: 0x122f,
+	0xac6: 0x0aab, 0xac7: 0x1837, 0xac8: 0x183c, 0xac9: 0x1747, 0xaca: 0x174c, 0xacb: 0x124f,
+	0xacc: 0x1253, 0xacd: 0x146b, 0xace: 0x06e3, 0xacf: 0x127f, 0xad0: 0x127b, 0xad1: 0x1283,
+	0xad2: 0x08b7, 0xad3: 0x1287, 0xad4: 0x128b, 0xad5: 0x128f, 0xad6: 0x1297, 0xad7: 0x1841,
+	0xad8: 0x1293, 0xad9: 0x129b, 0xada: 0x12af, 0xadb: 0x12b3, 0xadc: 0x129f, 0xadd: 0x12b7,
+	0xade: 0x12cb, 0xadf: 0x12df, 0xae0: 0x12ab, 0xae1: 0x12bf, 0xae2: 0x12c3, 0xae3: 0x12c7,
+	0xae4: 0x1846, 0xae5: 0x1850, 0xae6: 0x184b, 0xae7: 0x06e7, 0xae8: 0x12e7, 0xae9: 0x12eb,
+	0xaea: 0x12f3, 0xaeb: 0x1864, 0xaec: 0x12f7, 0xaed: 0x1855, 0xaee: 0x06eb, 0xaef: 0x06ef,
+	0xaf0: 0x185a, 0xaf1: 0x185f, 0xaf2: 0x06f3, 0xaf3: 0x1317, 0xaf4: 0x131b, 0xaf5: 0x131f,
+	0xaf6: 0x1323, 0xaf7: 0x132f, 0xaf8: 0x132b, 0xaf9: 0x1337, 0xafa: 0x1333, 0xafb: 0x1343,
+	0xafc: 0x133b, 0xafd: 0x133f, 0xafe: 0x1347, 0xaff: 0x06f7,
+	// Block 0x2c, offset 0xb00
+	0xb00: 0x134f, 0xb01: 0x1353, 0xb02: 0x06fb, 0xb03: 0x1363, 0xb04: 0x1367, 0xb05: 0x1869,
+	0xb06: 0x1373, 0xb07: 0x1377, 0xb08: 0x06ff, 0xb09: 0x1383, 0xb0a: 0x0633, 0xb0b: 0x186e,
+	0xb0c: 0x1873, 0xb0d: 0x0703, 0xb0e: 0x0707, 0xb0f: 0x13af, 0xb10: 0x13c7, 0xb11: 0x13e3,
+	0xb12: 0x13f3, 0xb13: 0x1878, 0xb14: 0x1407, 0xb15: 0x140b, 0xb16: 0x1423, 0xb17: 0x142f,
+	0xb18: 0x1882, 0xb19: 0x16d4, 0xb1a: 0x143b, 0xb1b: 0x1437, 0xb1c: 0x1443, 0xb1d: 0x16d9,
+	0xb1e: 0x144f, 0xb1f: 0x145b, 0xb20: 0x1887, 0xb21: 0x188c, 0xb22: 0x149b, 0xb23: 0x14a7,
+	0xb24: 0x14af, 0xb25: 0x1891, 0xb26: 0x14b3, 0xb27: 0x14db, 0xb28: 0x14e7, 0xb29: 0x14eb,
+	0xb2a: 0x14e3, 0xb2b: 0x14f7, 0xb2c: 0x14fb, 0xb2d: 0x1896, 0xb2e: 0x1507, 0xb2f: 0x070b,
+	0xb30: 0x150f, 0xb31: 0x189b, 0xb32: 0x070f, 0xb33: 0x1547, 0xb34: 0x0b3b, 0xb35: 0x155f,
+	0xb36: 0x18a0, 0xb37: 0x18aa, 0xb38: 0x0713, 0xb39: 0x0717, 0xb3a: 0x1587, 0xb3b: 0x18af,
+	0xb3c: 0x071b, 0xb3d: 0x18b4, 0xb3e: 0x159f, 0xb3f: 0x159f,
+	// Block 0x2d, offset 0xb40
+	0xb40: 0x15a7, 0xb41: 0x18b9, 0xb42: 0x15bf, 0xb43: 0x071f, 0xb44: 0x15cf, 0xb45: 0x15db,
+	0xb46: 0x15e3, 0xb47: 0x15eb, 0xb48: 0x0723, 0xb49: 0x18be, 0xb4a: 0x15ff, 0xb4b: 0x161b,
+	0xb4c: 0x1627, 0xb4d: 0x0727, 0xb4e: 0x072b, 0xb4f: 0x162b, 0xb50: 0x18c3, 0xb51: 0x072f,
+	0xb52: 0x18c8, 0xb53: 0x18cd, 0xb54: 0x18d2, 0xb55: 0x164f, 0xb56: 0x0733, 0xb57: 0x1663,
+	0xb58: 0x166b, 0xb59: 0x166f, 0xb5a: 0x1677, 0xb5b: 0x167f, 0xb5c: 0x1687, 0xb5d: 0x18dc,
+}
+
+// nfcIndex: 22 blocks, 1408 entries, 1408 bytes
+// Block 0 is the zero block.
+var nfcIndex = [1408]uint8{
+	// Block 0x0, offset 0x0
+	// Block 0x1, offset 0x40
+	// Block 0x2, offset 0x80
+	// Block 0x3, offset 0xc0
+	0xc2: 0x2c, 0xc3: 0x01, 0xc4: 0x02, 0xc5: 0x03, 0xc6: 0x2d, 0xc7: 0x04,
+	0xc8: 0x05, 0xca: 0x2e, 0xcb: 0x2f, 0xcc: 0x06, 0xcd: 0x07, 0xce: 0x08, 0xcf: 0x30,
+	0xd0: 0x09, 0xd1: 0x31, 0xd2: 0x32, 0xd3: 0x0a, 0xd6: 0x0b, 0xd7: 0x33,
+	0xd8: 0x34, 0xd9: 0x0c, 0xdb: 0x35, 0xdc: 0x36, 0xdd: 0x37, 0xdf: 0x38,
+	0xe0: 0x02, 0xe1: 0x03, 0xe2: 0x04, 0xe3: 0x05,
+	0xea: 0x06, 0xeb: 0x07, 0xec: 0x08, 0xed: 0x09, 0xef: 0x0a,
+	0xf0: 0x13,
+	// Block 0x4, offset 0x100
+	0x120: 0x39, 0x121: 0x3a, 0x123: 0x3b, 0x124: 0x3c, 0x125: 0x3d, 0x126: 0x3e, 0x127: 0x3f,
+	0x128: 0x40, 0x129: 0x41, 0x12a: 0x42, 0x12b: 0x43, 0x12c: 0x3e, 0x12d: 0x44, 0x12e: 0x45, 0x12f: 0x46,
+	0x131: 0x47, 0x132: 0x48, 0x133: 0x49, 0x134: 0x4a, 0x135: 0x4b, 0x137: 0x4c,
+	0x138: 0x4d, 0x139: 0x4e, 0x13a: 0x4f, 0x13b: 0x50, 0x13c: 0x51, 0x13d: 0x52, 0x13e: 0x53, 0x13f: 0x54,
+	// Block 0x5, offset 0x140
+	0x140: 0x55, 0x142: 0x56, 0x144: 0x57, 0x145: 0x58, 0x146: 0x59, 0x147: 0x5a,
+	0x14d: 0x5b,
+	0x15c: 0x5c, 0x15f: 0x5d,
+	0x162: 0x5e, 0x164: 0x5f,
+	0x168: 0x60, 0x169: 0x61, 0x16a: 0x62, 0x16c: 0x0d, 0x16d: 0x63, 0x16e: 0x64, 0x16f: 0x65,
+	0x170: 0x66, 0x173: 0x67, 0x177: 0x68,
+	0x178: 0x0e, 0x179: 0x0f, 0x17a: 0x10, 0x17b: 0x11, 0x17c: 0x12, 0x17d: 0x13, 0x17e: 0x14, 0x17f: 0x15,
+	// Block 0x6, offset 0x180
+	0x180: 0x69, 0x183: 0x6a, 0x184: 0x6b, 0x186: 0x6c, 0x187: 0x6d,
+	0x188: 0x6e, 0x189: 0x16, 0x18a: 0x17, 0x18b: 0x6f, 0x18c: 0x70,
+	0x1ab: 0x71,
+	0x1b3: 0x72, 0x1b5: 0x73, 0x1b7: 0x74,
+	// Block 0x7, offset 0x1c0
+	0x1c0: 0x75, 0x1c1: 0x18, 0x1c2: 0x19, 0x1c3: 0x1a,
+	0x1cc: 0x76, 0x1cd: 0x77,
+	// Block 0x8, offset 0x200
+	0x219: 0x78, 0x21a: 0x79, 0x21b: 0x7a,
+	0x220: 0x7b, 0x223: 0x7c, 0x224: 0x7d, 0x225: 0x7e, 0x226: 0x7f, 0x227: 0x80,
+	0x22a: 0x81, 0x22b: 0x82, 0x22f: 0x83,
+	0x230: 0x84, 0x231: 0x85, 0x232: 0x86, 0x233: 0x87, 0x234: 0x88, 0x235: 0x89, 0x236: 0x8a, 0x237: 0x84,
+	0x238: 0x85, 0x239: 0x86, 0x23a: 0x87, 0x23b: 0x88, 0x23c: 0x89, 0x23d: 0x8a, 0x23e: 0x84, 0x23f: 0x85,
+	// Block 0x9, offset 0x240
+	0x240: 0x86, 0x241: 0x87, 0x242: 0x88, 0x243: 0x89, 0x244: 0x8a, 0x245: 0x84, 0x246: 0x85, 0x247: 0x86,
+	0x248: 0x87, 0x249: 0x88, 0x24a: 0x89, 0x24b: 0x8a, 0x24c: 0x84, 0x24d: 0x85, 0x24e: 0x86, 0x24f: 0x87,
+	0x250: 0x88, 0x251: 0x89, 0x252: 0x8a, 0x253: 0x84, 0x254: 0x85, 0x255: 0x86, 0x256: 0x87, 0x257: 0x88,
+	0x258: 0x89, 0x259: 0x8a, 0x25a: 0x84, 0x25b: 0x85, 0x25c: 0x86, 0x25d: 0x87, 0x25e: 0x88, 0x25f: 0x89,
+	0x260: 0x8a, 0x261: 0x84, 0x262: 0x85, 0x263: 0x86, 0x264: 0x87, 0x265: 0x88, 0x266: 0x89, 0x267: 0x8a,
+	0x268: 0x84, 0x269: 0x85, 0x26a: 0x86, 0x26b: 0x87, 0x26c: 0x88, 0x26d: 0x89, 0x26e: 0x8a, 0x26f: 0x84,
+	0x270: 0x85, 0x271: 0x86, 0x272: 0x87, 0x273: 0x88, 0x274: 0x89, 0x275: 0x8a, 0x276: 0x84, 0x277: 0x85,
+	0x278: 0x86, 0x279: 0x87, 0x27a: 0x88, 0x27b: 0x89, 0x27c: 0x8a, 0x27d: 0x84, 0x27e: 0x85, 0x27f: 0x86,
+	// Block 0xa, offset 0x280
+	0x280: 0x87, 0x281: 0x88, 0x282: 0x89, 0x283: 0x8a, 0x284: 0x84, 0x285: 0x85, 0x286: 0x86, 0x287: 0x87,
+	0x288: 0x88, 0x289: 0x89, 0x28a: 0x8a, 0x28b: 0x84, 0x28c: 0x85, 0x28d: 0x86, 0x28e: 0x87, 0x28f: 0x88,
+	0x290: 0x89, 0x291: 0x8a, 0x292: 0x84, 0x293: 0x85, 0x294: 0x86, 0x295: 0x87, 0x296: 0x88, 0x297: 0x89,
+	0x298: 0x8a, 0x299: 0x84, 0x29a: 0x85, 0x29b: 0x86, 0x29c: 0x87, 0x29d: 0x88, 0x29e: 0x89, 0x29f: 0x8a,
+	0x2a0: 0x84, 0x2a1: 0x85, 0x2a2: 0x86, 0x2a3: 0x87, 0x2a4: 0x88, 0x2a5: 0x89, 0x2a6: 0x8a, 0x2a7: 0x84,
+	0x2a8: 0x85, 0x2a9: 0x86, 0x2aa: 0x87, 0x2ab: 0x88, 0x2ac: 0x89, 0x2ad: 0x8a, 0x2ae: 0x84, 0x2af: 0x85,
+	0x2b0: 0x86, 0x2b1: 0x87, 0x2b2: 0x88, 0x2b3: 0x89, 0x2b4: 0x8a, 0x2b5: 0x84, 0x2b6: 0x85, 0x2b7: 0x86,
+	0x2b8: 0x87, 0x2b9: 0x88, 0x2ba: 0x89, 0x2bb: 0x8a, 0x2bc: 0x84, 0x2bd: 0x85, 0x2be: 0x86, 0x2bf: 0x87,
+	// Block 0xb, offset 0x2c0
+	0x2c0: 0x88, 0x2c1: 0x89, 0x2c2: 0x8a, 0x2c3: 0x84, 0x2c4: 0x85, 0x2c5: 0x86, 0x2c6: 0x87, 0x2c7: 0x88,
+	0x2c8: 0x89, 0x2c9: 0x8a, 0x2ca: 0x84, 0x2cb: 0x85, 0x2cc: 0x86, 0x2cd: 0x87, 0x2ce: 0x88, 0x2cf: 0x89,
+	0x2d0: 0x8a, 0x2d1: 0x84, 0x2d2: 0x85, 0x2d3: 0x86, 0x2d4: 0x87, 0x2d5: 0x88, 0x2d6: 0x89, 0x2d7: 0x8a,
+	0x2d8: 0x84, 0x2d9: 0x85, 0x2da: 0x86, 0x2db: 0x87, 0x2dc: 0x88, 0x2dd: 0x89, 0x2de: 0x8b,
+	// Block 0xc, offset 0x300
+	0x324: 0x1b, 0x325: 0x1c, 0x326: 0x1d, 0x327: 0x1e,
+	0x328: 0x1f, 0x329: 0x20, 0x32a: 0x21, 0x32b: 0x22, 0x32c: 0x8c, 0x32d: 0x8d, 0x32e: 0x8e,
+	0x331: 0x8f, 0x332: 0x90, 0x333: 0x91, 0x334: 0x92,
+	0x338: 0x93, 0x339: 0x94, 0x33a: 0x95, 0x33b: 0x96, 0x33e: 0x97, 0x33f: 0x98,
+	// Block 0xd, offset 0x340
+	0x347: 0x99,
+	0x34b: 0x9a, 0x34d: 0x9b,
+	0x368: 0x9c, 0x36b: 0x9d,
+	// Block 0xe, offset 0x380
+	0x381: 0x9e, 0x382: 0x9f, 0x384: 0xa0, 0x385: 0x7f, 0x387: 0x80,
+	0x388: 0xa1, 0x38b: 0xa2, 0x38c: 0x3e, 0x38d: 0xa3,
+	0x392: 0xa4, 0x393: 0xa5, 0x396: 0xa6, 0x397: 0xa7,
+	0x398: 0x73, 0x39a: 0xa8,
+	// Block 0xf, offset 0x3c0
+	0x3eb: 0xa9, 0x3ec: 0xaa,
+	// Block 0x10, offset 0x400
+	0x432: 0xab,
+	// Block 0x11, offset 0x440
+	0x445: 0xac, 0x446: 0xad, 0x447: 0xae,
+	0x449: 0xaf,
+	// Block 0x12, offset 0x480
+	0x4a3: 0xb0,
+	// Block 0x13, offset 0x4c0
+	0x4c8: 0xb1,
+	// Block 0x14, offset 0x500
+	0x520: 0x23, 0x521: 0x24, 0x522: 0x25, 0x523: 0x26, 0x524: 0x27, 0x525: 0x28, 0x526: 0x29, 0x527: 0x2a,
+	0x528: 0x2b,
+	// Block 0x15, offset 0x540
+	0x550: 0x0b, 0x551: 0x0c, 0x556: 0x0d,
+	0x55b: 0x0e, 0x55d: 0x0f, 0x55e: 0x10, 0x55f: 0x11,
+	0x56f: 0x12,
+}
+
+// nfcSparseOffset: 134 entries, 268 bytes
+var nfcSparseOffset = []uint16{0x0, 0x5, 0x9, 0xb, 0xd, 0x18, 0x28, 0x2a, 0x2f, 0x3a, 0x49, 0x56, 0x5e, 0x62, 0x67, 0x69, 0x78, 0x80, 0x87, 0x8a, 0x92, 0x96, 0x9a, 0x9c, 0x9e, 0xa7, 0xab, 0xb2, 0xb7, 0xba, 0xc4, 0xc6, 0xcd, 0xd5, 0xd8, 0xda, 0xdc, 0xde, 0xe3, 0xf4, 0x100, 0x102, 0x108, 0x10a, 0x10c, 0x10e, 0x110, 0x112, 0x114, 0x117, 0x11a, 0x11c, 0x11f, 0x122, 0x126, 0x12b, 0x134, 0x136, 0x139, 0x13b, 0x146, 0x155, 0x159, 0x167, 0x16a, 0x170, 0x176, 0x181, 0x185, 0x187, 0x189, 0x18b, 0x18d, 0x18f, 0x195, 0x19d, 0x1a1, 0x1a4, 0x1a6, 0x1a8, 0x1aa, 0x1ad, 0x1af, 0x1b1, 0x1b3, 0x1b5, 0x1bb, 0x1be, 0x1c0, 0x1c7, 0x1cd, 0x1d3, 0x1db, 0x1e1, 0x1e7, 0x1ed, 0x1f1, 0x1ff, 0x208, 0x20b, 0x20e, 0x210, 0x213, 0x215, 0x218, 0x21d, 0x21f, 0x221, 0x223, 0x225, 0x227, 0x229, 0x22b, 0x231, 0x234, 0x237, 0x23f, 0x246, 0x249, 0x24b, 0x253, 0x25a, 0x25d, 0x263, 0x265, 0x268, 0x26a, 0x26c, 0x26e, 0x27b, 0x285, 0x287, 0x289, 0x28b}
+
+// nfcSparseValues: 653 entries, 2612 bytes
+var nfcSparseValues = [653]valueRange{
+	// Block 0x0, offset 0x0
+	{value: 0x0000, lo: 0x04},
+	{value: 0xa100, lo: 0xa8, hi: 0xa8},
+	{value: 0x8100, lo: 0xaf, hi: 0xaf},
+	{value: 0x8100, lo: 0xb4, hi: 0xb4},
+	{value: 0x8100, lo: 0xb8, hi: 0xb8},
+	// Block 0x1, offset 0x5
+	{value: 0x0091, lo: 0x03},
+	{value: 0x471d, lo: 0xa0, hi: 0xa1},
+	{value: 0x474f, lo: 0xaf, hi: 0xb0},
+	{value: 0xa000, lo: 0xb7, hi: 0xb7},
+	// Block 0x2, offset 0x9
+	{value: 0x0000, lo: 0x01},
+	{value: 0xa000, lo: 0x92, hi: 0x92},
+	// Block 0x3, offset 0xb
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8100, lo: 0x98, hi: 0x9d},
+	// Block 0x4, offset 0xd
+	{value: 0x0006, lo: 0x0a},
+	{value: 0xa000, lo: 0x81, hi: 0x81},
+	{value: 0xa000, lo: 0x85, hi: 0x85},
+	{value: 0xa000, lo: 0x89, hi: 0x89},
+	{value: 0x487b, lo: 0x8a, hi: 0x8a},
+	{value: 0x4899, lo: 0x8b, hi: 0x8b},
+	{value: 0x3702, lo: 0x8c, hi: 0x8c},
+	{value: 0x371a, lo: 0x8d, hi: 0x8d},
+	{value: 0x48b1, lo: 0x8e, hi: 0x8e},
+	{value: 0xa000, lo: 0x92, hi: 0x92},
+	{value: 0x3738, lo: 0x93, hi: 0x94},
+	// Block 0x5, offset 0x18
+	{value: 0x0000, lo: 0x0f},
+	{value: 0xa000, lo: 0x83, hi: 0x83},
+	{value: 0xa000, lo: 0x87, hi: 0x87},
+	{value: 0xa000, lo: 0x8b, hi: 0x8b},
+	{value: 0xa000, lo: 0x8d, hi: 0x8d},
+	{value: 0x37e0, lo: 0x90, hi: 0x90},
+	{value: 0x37ec, lo: 0x91, hi: 0x91},
+	{value: 0x37da, lo: 0x93, hi: 0x93},
+	{value: 0xa000, lo: 0x96, hi: 0x96},
+	{value: 0x3852, lo: 0x97, hi: 0x97},
+	{value: 0x381c, lo: 0x9c, hi: 0x9c},
+	{value: 0x3804, lo: 0x9d, hi: 0x9d},
+	{value: 0x382e, lo: 0x9e, hi: 0x9e},
+	{value: 0xa000, lo: 0xb4, hi: 0xb5},
+	{value: 0x3858, lo: 0xb6, hi: 0xb6},
+	{value: 0x385e, lo: 0xb7, hi: 0xb7},
+	// Block 0x6, offset 0x28
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8132, lo: 0x83, hi: 0x87},
+	// Block 0x7, offset 0x2a
+	{value: 0x0001, lo: 0x04},
+	{value: 0x8113, lo: 0x81, hi: 0x82},
+	{value: 0x8132, lo: 0x84, hi: 0x84},
+	{value: 0x812d, lo: 0x85, hi: 0x85},
+	{value: 0x810d, lo: 0x87, hi: 0x87},
+	// Block 0x8, offset 0x2f
+	{value: 0x0000, lo: 0x0a},
+	{value: 0x8132, lo: 0x90, hi: 0x97},
+	{value: 0x8119, lo: 0x98, hi: 0x98},
+	{value: 0x811a, lo: 0x99, hi: 0x99},
+	{value: 0x811b, lo: 0x9a, hi: 0x9a},
+	{value: 0x387c, lo: 0xa2, hi: 0xa2},
+	{value: 0x3882, lo: 0xa3, hi: 0xa3},
+	{value: 0x388e, lo: 0xa4, hi: 0xa4},
+	{value: 0x3888, lo: 0xa5, hi: 0xa5},
+	{value: 0x3894, lo: 0xa6, hi: 0xa6},
+	{value: 0xa000, lo: 0xa7, hi: 0xa7},
+	// Block 0x9, offset 0x3a
+	{value: 0x0000, lo: 0x0e},
+	{value: 0x38a6, lo: 0x80, hi: 0x80},
+	{value: 0xa000, lo: 0x81, hi: 0x81},
+	{value: 0x389a, lo: 0x82, hi: 0x82},
+	{value: 0xa000, lo: 0x92, hi: 0x92},
+	{value: 0x38a0, lo: 0x93, hi: 0x93},
+	{value: 0xa000, lo: 0x95, hi: 0x95},
+	{value: 0x8132, lo: 0x96, hi: 0x9c},
+	{value: 0x8132, lo: 0x9f, hi: 0xa2},
+	{value: 0x812d, lo: 0xa3, hi: 0xa3},
+	{value: 0x8132, lo: 0xa4, hi: 0xa4},
+	{value: 0x8132, lo: 0xa7, hi: 0xa8},
+	{value: 0x812d, lo: 0xaa, hi: 0xaa},
+	{value: 0x8132, lo: 0xab, hi: 0xac},
+	{value: 0x812d, lo: 0xad, hi: 0xad},
+	// Block 0xa, offset 0x49
+	{value: 0x0000, lo: 0x0c},
+	{value: 0x811f, lo: 0x91, hi: 0x91},
+	{value: 0x8132, lo: 0xb0, hi: 0xb0},
+	{value: 0x812d, lo: 0xb1, hi: 0xb1},
+	{value: 0x8132, lo: 0xb2, hi: 0xb3},
+	{value: 0x812d, lo: 0xb4, hi: 0xb4},
+	{value: 0x8132, lo: 0xb5, hi: 0xb6},
+	{value: 0x812d, lo: 0xb7, hi: 0xb9},
+	{value: 0x8132, lo: 0xba, hi: 0xba},
+	{value: 0x812d, lo: 0xbb, hi: 0xbc},
+	{value: 0x8132, lo: 0xbd, hi: 0xbd},
+	{value: 0x812d, lo: 0xbe, hi: 0xbe},
+	{value: 0x8132, lo: 0xbf, hi: 0xbf},
+	// Block 0xb, offset 0x56
+	{value: 0x0005, lo: 0x07},
+	{value: 0x8132, lo: 0x80, hi: 0x80},
+	{value: 0x8132, lo: 0x81, hi: 0x81},
+	{value: 0x812d, lo: 0x82, hi: 0x83},
+	{value: 0x812d, lo: 0x84, hi: 0x85},
+	{value: 0x812d, lo: 0x86, hi: 0x87},
+	{value: 0x812d, lo: 0x88, hi: 0x89},
+	{value: 0x8132, lo: 0x8a, hi: 0x8a},
+	// Block 0xc, offset 0x5e
+	{value: 0x0000, lo: 0x03},
+	{value: 0x8132, lo: 0xab, hi: 0xb1},
+	{value: 0x812d, lo: 0xb2, hi: 0xb2},
+	{value: 0x8132, lo: 0xb3, hi: 0xb3},
+	// Block 0xd, offset 0x62
+	{value: 0x0000, lo: 0x04},
+	{value: 0x8132, lo: 0x96, hi: 0x99},
+	{value: 0x8132, lo: 0x9b, hi: 0xa3},
+	{value: 0x8132, lo: 0xa5, hi: 0xa7},
+	{value: 0x8132, lo: 0xa9, hi: 0xad},
+	// Block 0xe, offset 0x67
+	{value: 0x0000, lo: 0x01},
+	{value: 0x812d, lo: 0x99, hi: 0x9b},
+	// Block 0xf, offset 0x69
+	{value: 0x0000, lo: 0x0e},
+	{value: 0x8132, lo: 0xa4, hi: 0xa5},
+	{value: 0x812d, lo: 0xa6, hi: 0xa6},
+	{value: 0x8132, lo: 0xa7, hi: 0xa8},
+	{value: 0x812d, lo: 0xa9, hi: 0xa9},
+	{value: 0x8132, lo: 0xaa, hi: 0xac},
+	{value: 0x812d, lo: 0xad, hi: 0xaf},
+	{value: 0x8116, lo: 0xb0, hi: 0xb0},
+	{value: 0x8117, lo: 0xb1, hi: 0xb1},
+	{value: 0x8118, lo: 0xb2, hi: 0xb2},
+	{value: 0x8132, lo: 0xb3, hi: 0xb5},
+	{value: 0x812d, lo: 0xb6, hi: 0xb6},
+	{value: 0x8132, lo: 0xb7, hi: 0xb8},
+	{value: 0x812d, lo: 0xb9, hi: 0xba},
+	{value: 0x8132, lo: 0xbb, hi: 0xbf},
+	// Block 0x10, offset 0x78
+	{value: 0x0000, lo: 0x07},
+	{value: 0xa000, lo: 0xa8, hi: 0xa8},
+	{value: 0x3f13, lo: 0xa9, hi: 0xa9},
+	{value: 0xa000, lo: 0xb0, hi: 0xb0},
+	{value: 0x3f1b, lo: 0xb1, hi: 0xb1},
+	{value: 0xa000, lo: 0xb3, hi: 0xb3},
+	{value: 0x3f23, lo: 0xb4, hi: 0xb4},
+	{value: 0x9902, lo: 0xbc, hi: 0xbc},
+	// Block 0x11, offset 0x80
+	{value: 0x0008, lo: 0x06},
+	{value: 0x8104, lo: 0x8d, hi: 0x8d},
+	{value: 0x8132, lo: 0x91, hi: 0x91},
+	{value: 0x812d, lo: 0x92, hi: 0x92},
+	{value: 0x8132, lo: 0x93, hi: 0x93},
+	{value: 0x8132, lo: 0x94, hi: 0x94},
+	{value: 0x4557, lo: 0x98, hi: 0x9f},
+	// Block 0x12, offset 0x87
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8102, lo: 0xbc, hi: 0xbc},
+	{value: 0x9900, lo: 0xbe, hi: 0xbe},
+	// Block 0x13, offset 0x8a
+	{value: 0x0007, lo: 0x07},
+	{value: 0xa000, lo: 0x87, hi: 0x87},
+	{value: 0x18e1, lo: 0x8b, hi: 0x8c},
+	{value: 0x8104, lo: 0x8d, hi: 0x8d},
+	{value: 0x9900, lo: 0x97, hi: 0x97},
+	{value: 0x4597, lo: 0x9c, hi: 0x9c},
+	{value: 0x459f, lo: 0x9d, hi: 0x9d},
+	{value: 0x45a7, lo: 0x9f, hi: 0x9f},
+	// Block 0x14, offset 0x92
+	{value: 0x0000, lo: 0x03},
+	{value: 0x45cf, lo: 0xb3, hi: 0xb3},
+	{value: 0x45d7, lo: 0xb6, hi: 0xb6},
+	{value: 0x8102, lo: 0xbc, hi: 0xbc},
+	// Block 0x15, offset 0x96
+	{value: 0x0008, lo: 0x03},
+	{value: 0x8104, lo: 0x8d, hi: 0x8d},
+	{value: 0x45af, lo: 0x99, hi: 0x9b},
+	{value: 0x45c7, lo: 0x9e, hi: 0x9e},
+	// Block 0x16, offset 0x9a
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8102, lo: 0xbc, hi: 0xbc},
+	// Block 0x17, offset 0x9c
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8104, lo: 0x8d, hi: 0x8d},
+	// Block 0x18, offset 0x9e
+	{value: 0x0000, lo: 0x08},
+	{value: 0xa000, lo: 0x87, hi: 0x87},
+	{value: 0x18f6, lo: 0x88, hi: 0x88},
+	{value: 0x18ef, lo: 0x8b, hi: 0x8b},
+	{value: 0x18fd, lo: 0x8c, hi: 0x8c},
+	{value: 0x8104, lo: 0x8d, hi: 0x8d},
+	{value: 0x9900, lo: 0x96, hi: 0x97},
+	{value: 0x45df, lo: 0x9c, hi: 0x9c},
+	{value: 0x45e7, lo: 0x9d, hi: 0x9d},
+	// Block 0x19, offset 0xa7
+	{value: 0x0000, lo: 0x03},
+	{value: 0xa000, lo: 0x92, hi: 0x92},
+	{value: 0x1904, lo: 0x94, hi: 0x94},
+	{value: 0x9900, lo: 0xbe, hi: 0xbe},
+	// Block 0x1a, offset 0xab
+	{value: 0x0000, lo: 0x06},
+	{value: 0xa000, lo: 0x86, hi: 0x87},
+	{value: 0x190b, lo: 0x8a, hi: 0x8a},
+	{value: 0x1919, lo: 0x8b, hi: 0x8b},
+	{value: 0x1912, lo: 0x8c, hi: 0x8c},
+	{value: 0x8104, lo: 0x8d, hi: 0x8d},
+	{value: 0x9900, lo: 0x97, hi: 0x97},
+	// Block 0x1b, offset 0xb2
+	{value: 0x1801, lo: 0x04},
+	{value: 0xa000, lo: 0x86, hi: 0x86},
+	{value: 0x3f2b, lo: 0x88, hi: 0x88},
+	{value: 0x8104, lo: 0x8d, hi: 0x8d},
+	{value: 0x8120, lo: 0x95, hi: 0x96},
+	// Block 0x1c, offset 0xb7
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8102, lo: 0xbc, hi: 0xbc},
+	{value: 0xa000, lo: 0xbf, hi: 0xbf},
+	// Block 0x1d, offset 0xba
+	{value: 0x0000, lo: 0x09},
+	{value: 0x1920, lo: 0x80, hi: 0x80},
+	{value: 0x9900, lo: 0x82, hi: 0x82},
+	{value: 0xa000, lo: 0x86, hi: 0x86},
+	{value: 0x1927, lo: 0x87, hi: 0x87},
+	{value: 0x192e, lo: 0x88, hi: 0x88},
+	{value: 0x2eb7, lo: 0x8a, hi: 0x8a},
+	{value: 0x19f6, lo: 0x8b, hi: 0x8b},
+	{value: 0x8104, lo: 0x8d, hi: 0x8d},
+	{value: 0x9900, lo: 0x95, hi: 0x96},
+	// Block 0x1e, offset 0xc4
+	{value: 0x0000, lo: 0x01},
+	{value: 0x9900, lo: 0xbe, hi: 0xbe},
+	// Block 0x1f, offset 0xc6
+	{value: 0x0000, lo: 0x06},
+	{value: 0xa000, lo: 0x86, hi: 0x87},
+	{value: 0x1935, lo: 0x8a, hi: 0x8a},
+	{value: 0x1943, lo: 0x8b, hi: 0x8b},
+	{value: 0x193c, lo: 0x8c, hi: 0x8c},
+	{value: 0x8104, lo: 0x8d, hi: 0x8d},
+	{value: 0x9900, lo: 0x97, hi: 0x97},
+	// Block 0x20, offset 0xcd
+	{value: 0x0007, lo: 0x07},
+	{value: 0x9904, lo: 0x8a, hi: 0x8a},
+	{value: 0x9900, lo: 0x8f, hi: 0x8f},
+	{value: 0xa000, lo: 0x99, hi: 0x99},
+	{value: 0x3f33, lo: 0x9a, hi: 0x9a},
+	{value: 0x2ebe, lo: 0x9c, hi: 0x9d},
+	{value: 0x194a, lo: 0x9e, hi: 0x9e},
+	{value: 0x9900, lo: 0x9f, hi: 0x9f},
+	// Block 0x21, offset 0xd5
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8122, lo: 0xb8, hi: 0xb9},
+	{value: 0x8104, lo: 0xba, hi: 0xba},
+	// Block 0x22, offset 0xd8
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8123, lo: 0x88, hi: 0x8b},
+	// Block 0x23, offset 0xda
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8124, lo: 0xb8, hi: 0xb9},
+	// Block 0x24, offset 0xdc
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8125, lo: 0x88, hi: 0x8b},
+	// Block 0x25, offset 0xde
+	{value: 0x0000, lo: 0x04},
+	{value: 0x812d, lo: 0x98, hi: 0x99},
+	{value: 0x812d, lo: 0xb5, hi: 0xb5},
+	{value: 0x812d, lo: 0xb7, hi: 0xb7},
+	{value: 0x812b, lo: 0xb9, hi: 0xb9},
+	// Block 0x26, offset 0xe3
+	{value: 0x0000, lo: 0x10},
+	{value: 0x27d7, lo: 0x83, hi: 0x83},
+	{value: 0x27de, lo: 0x8d, hi: 0x8d},
+	{value: 0x27e5, lo: 0x92, hi: 0x92},
+	{value: 0x27ec, lo: 0x97, hi: 0x97},
+	{value: 0x27f3, lo: 0x9c, hi: 0x9c},
+	{value: 0x27d0, lo: 0xa9, hi: 0xa9},
+	{value: 0x8126, lo: 0xb1, hi: 0xb1},
+	{value: 0x8127, lo: 0xb2, hi: 0xb2},
+	{value: 0x4a0b, lo: 0xb3, hi: 0xb3},
+	{value: 0x8128, lo: 0xb4, hi: 0xb4},
+	{value: 0x4a14, lo: 0xb5, hi: 0xb5},
+	{value: 0x45ef, lo: 0xb6, hi: 0xb6},
+	{value: 0x8200, lo: 0xb7, hi: 0xb7},
+	{value: 0x45f7, lo: 0xb8, hi: 0xb8},
+	{value: 0x8200, lo: 0xb9, hi: 0xb9},
+	{value: 0x8127, lo: 0xba, hi: 0xbd},
+	// Block 0x27, offset 0xf4
+	{value: 0x0000, lo: 0x0b},
+	{value: 0x8127, lo: 0x80, hi: 0x80},
+	{value: 0x4a1d, lo: 0x81, hi: 0x81},
+	{value: 0x8132, lo: 0x82, hi: 0x83},
+	{value: 0x8104, lo: 0x84, hi: 0x84},
+	{value: 0x8132, lo: 0x86, hi: 0x87},
+	{value: 0x2801, lo: 0x93, hi: 0x93},
+	{value: 0x2808, lo: 0x9d, hi: 0x9d},
+	{value: 0x280f, lo: 0xa2, hi: 0xa2},
+	{value: 0x2816, lo: 0xa7, hi: 0xa7},
+	{value: 0x281d, lo: 0xac, hi: 0xac},
+	{value: 0x27fa, lo: 0xb9, hi: 0xb9},
+	// Block 0x28, offset 0x100
+	{value: 0x0000, lo: 0x01},
+	{value: 0x812d, lo: 0x86, hi: 0x86},
+	// Block 0x29, offset 0x102
+	{value: 0x0000, lo: 0x05},
+	{value: 0xa000, lo: 0xa5, hi: 0xa5},
+	{value: 0x1951, lo: 0xa6, hi: 0xa6},
+	{value: 0x9900, lo: 0xae, hi: 0xae},
+	{value: 0x8102, lo: 0xb7, hi: 0xb7},
+	{value: 0x8104, lo: 0xb9, hi: 0xba},
+	// Block 0x2a, offset 0x108
+	{value: 0x0000, lo: 0x01},
+	{value: 0x812d, lo: 0x8d, hi: 0x8d},
+	// Block 0x2b, offset 0x10a
+	{value: 0x0000, lo: 0x01},
+	{value: 0xa000, lo: 0x80, hi: 0x92},
+	// Block 0x2c, offset 0x10c
+	{value: 0x0000, lo: 0x01},
+	{value: 0xb900, lo: 0xa1, hi: 0xb5},
+	// Block 0x2d, offset 0x10e
+	{value: 0x0000, lo: 0x01},
+	{value: 0x9900, lo: 0xa8, hi: 0xbf},
+	// Block 0x2e, offset 0x110
+	{value: 0x0000, lo: 0x01},
+	{value: 0x9900, lo: 0x80, hi: 0x82},
+	// Block 0x2f, offset 0x112
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8132, lo: 0x9d, hi: 0x9f},
+	// Block 0x30, offset 0x114
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8104, lo: 0x94, hi: 0x94},
+	{value: 0x8104, lo: 0xb4, hi: 0xb4},
+	// Block 0x31, offset 0x117
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8104, lo: 0x92, hi: 0x92},
+	{value: 0x8132, lo: 0x9d, hi: 0x9d},
+	// Block 0x32, offset 0x11a
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8131, lo: 0xa9, hi: 0xa9},
+	// Block 0x33, offset 0x11c
+	{value: 0x0004, lo: 0x02},
+	{value: 0x812e, lo: 0xb9, hi: 0xba},
+	{value: 0x812d, lo: 0xbb, hi: 0xbb},
+	// Block 0x34, offset 0x11f
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8132, lo: 0x97, hi: 0x97},
+	{value: 0x812d, lo: 0x98, hi: 0x98},
+	// Block 0x35, offset 0x122
+	{value: 0x0000, lo: 0x03},
+	{value: 0x8104, lo: 0xa0, hi: 0xa0},
+	{value: 0x8132, lo: 0xb5, hi: 0xbc},
+	{value: 0x812d, lo: 0xbf, hi: 0xbf},
+	// Block 0x36, offset 0x126
+	{value: 0x0000, lo: 0x04},
+	{value: 0x8132, lo: 0xb0, hi: 0xb4},
+	{value: 0x812d, lo: 0xb5, hi: 0xba},
+	{value: 0x8132, lo: 0xbb, hi: 0xbc},
+	{value: 0x812d, lo: 0xbd, hi: 0xbd},
+	// Block 0x37, offset 0x12b
+	{value: 0x0000, lo: 0x08},
+	{value: 0x1990, lo: 0x80, hi: 0x80},
+	{value: 0x1997, lo: 0x81, hi: 0x81},
+	{value: 0xa000, lo: 0x82, hi: 0x82},
+	{value: 0x199e, lo: 0x83, hi: 0x83},
+	{value: 0x8104, lo: 0x84, hi: 0x84},
+	{value: 0x8132, lo: 0xab, hi: 0xab},
+	{value: 0x812d, lo: 0xac, hi: 0xac},
+	{value: 0x8132, lo: 0xad, hi: 0xb3},
+	// Block 0x38, offset 0x134
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8104, lo: 0xaa, hi: 0xab},
+	// Block 0x39, offset 0x136
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8102, lo: 0xa6, hi: 0xa6},
+	{value: 0x8104, lo: 0xb2, hi: 0xb3},
+	// Block 0x3a, offset 0x139
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8102, lo: 0xb7, hi: 0xb7},
+	// Block 0x3b, offset 0x13b
+	{value: 0x0000, lo: 0x0a},
+	{value: 0x8132, lo: 0x90, hi: 0x92},
+	{value: 0x8101, lo: 0x94, hi: 0x94},
+	{value: 0x812d, lo: 0x95, hi: 0x99},
+	{value: 0x8132, lo: 0x9a, hi: 0x9b},
+	{value: 0x812d, lo: 0x9c, hi: 0x9f},
+	{value: 0x8132, lo: 0xa0, hi: 0xa0},
+	{value: 0x8101, lo: 0xa2, hi: 0xa8},
+	{value: 0x812d, lo: 0xad, hi: 0xad},
+	{value: 0x8132, lo: 0xb4, hi: 0xb4},
+	{value: 0x8132, lo: 0xb8, hi: 0xb9},
+	// Block 0x3c, offset 0x146
+	{value: 0x0000, lo: 0x0e},
+	{value: 0x8132, lo: 0x80, hi: 0x81},
+	{value: 0x812d, lo: 0x82, hi: 0x82},
+	{value: 0x8132, lo: 0x83, hi: 0x89},
+	{value: 0x812d, lo: 0x8a, hi: 0x8a},
+	{value: 0x8132, lo: 0x8b, hi: 0x8c},
+	{value: 0x8135, lo: 0x8d, hi: 0x8d},
+	{value: 0x812a, lo: 0x8e, hi: 0x8e},
+	{value: 0x812d, lo: 0x8f, hi: 0x8f},
+	{value: 0x8129, lo: 0x90, hi: 0x90},
+	{value: 0x8132, lo: 0x91, hi: 0xb5},
+	{value: 0x8134, lo: 0xbc, hi: 0xbc},
+	{value: 0x812d, lo: 0xbd, hi: 0xbd},
+	{value: 0x8132, lo: 0xbe, hi: 0xbe},
+	{value: 0x812d, lo: 0xbf, hi: 0xbf},
+	// Block 0x3d, offset 0x155
+	{value: 0x0004, lo: 0x03},
+	{value: 0x04ab, lo: 0x80, hi: 0x81},
+	{value: 0x8100, lo: 0x97, hi: 0x97},
+	{value: 0x8100, lo: 0xbe, hi: 0xbe},
+	// Block 0x3e, offset 0x159
+	{value: 0x0000, lo: 0x0d},
+	{value: 0x8132, lo: 0x90, hi: 0x91},
+	{value: 0x8101, lo: 0x92, hi: 0x93},
+	{value: 0x8132, lo: 0x94, hi: 0x97},
+	{value: 0x8101, lo: 0x98, hi: 0x9a},
+	{value: 0x8132, lo: 0x9b, hi: 0x9c},
+	{value: 0x8132, lo: 0xa1, hi: 0xa1},
+	{value: 0x8101, lo: 0xa5, hi: 0xa6},
+	{value: 0x8132, lo: 0xa7, hi: 0xa7},
+	{value: 0x812d, lo: 0xa8, hi: 0xa8},
+	{value: 0x8132, lo: 0xa9, hi: 0xa9},
+	{value: 0x8101, lo: 0xaa, hi: 0xab},
+	{value: 0x812d, lo: 0xac, hi: 0xaf},
+	{value: 0x8132, lo: 0xb0, hi: 0xb0},
+	// Block 0x3f, offset 0x167
+	{value: 0x42b6, lo: 0x02},
+	{value: 0x01b8, lo: 0xa6, hi: 0xa6},
+	{value: 0x0057, lo: 0xaa, hi: 0xab},
+	// Block 0x40, offset 0x16a
+	{value: 0x0007, lo: 0x05},
+	{value: 0xa000, lo: 0x90, hi: 0x90},
+	{value: 0xa000, lo: 0x92, hi: 0x92},
+	{value: 0xa000, lo: 0x94, hi: 0x94},
+	{value: 0x3bf4, lo: 0x9a, hi: 0x9b},
+	{value: 0x3c02, lo: 0xae, hi: 0xae},
+	// Block 0x41, offset 0x170
+	{value: 0x000e, lo: 0x05},
+	{value: 0x3c09, lo: 0x8d, hi: 0x8e},
+	{value: 0x3c10, lo: 0x8f, hi: 0x8f},
+	{value: 0xa000, lo: 0x90, hi: 0x90},
+	{value: 0xa000, lo: 0x92, hi: 0x92},
+	{value: 0xa000, lo: 0x94, hi: 0x94},
+	// Block 0x42, offset 0x176
+	{value: 0x63cd, lo: 0x0a},
+	{value: 0xa000, lo: 0x83, hi: 0x83},
+	{value: 0x3c1e, lo: 0x84, hi: 0x84},
+	{value: 0xa000, lo: 0x88, hi: 0x88},
+	{value: 0x3c25, lo: 0x89, hi: 0x89},
+	{value: 0xa000, lo: 0x8b, hi: 0x8b},
+	{value: 0x3c2c, lo: 0x8c, hi: 0x8c},
+	{value: 0xa000, lo: 0xa3, hi: 0xa3},
+	{value: 0x3c33, lo: 0xa4, hi: 0xa5},
+	{value: 0x3c3a, lo: 0xa6, hi: 0xa6},
+	{value: 0xa000, lo: 0xbc, hi: 0xbc},
+	// Block 0x43, offset 0x181
+	{value: 0x0007, lo: 0x03},
+	{value: 0x3ca3, lo: 0xa0, hi: 0xa1},
+	{value: 0x3ccd, lo: 0xa2, hi: 0xa3},
+	{value: 0x3cf7, lo: 0xaa, hi: 0xad},
+	// Block 0x44, offset 0x185
+	{value: 0x0004, lo: 0x01},
+	{value: 0x0503, lo: 0xa9, hi: 0xaa},
+	// Block 0x45, offset 0x187
+	{value: 0x0000, lo: 0x01},
+	{value: 0x4518, lo: 0x9c, hi: 0x9c},
+	// Block 0x46, offset 0x189
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8132, lo: 0xaf, hi: 0xb1},
+	// Block 0x47, offset 0x18b
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8104, lo: 0xbf, hi: 0xbf},
+	// Block 0x48, offset 0x18d
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8132, lo: 0xa0, hi: 0xbf},
+	// Block 0x49, offset 0x18f
+	{value: 0x0000, lo: 0x05},
+	{value: 0x812c, lo: 0xaa, hi: 0xaa},
+	{value: 0x8131, lo: 0xab, hi: 0xab},
+	{value: 0x8133, lo: 0xac, hi: 0xac},
+	{value: 0x812e, lo: 0xad, hi: 0xad},
+	{value: 0x812f, lo: 0xae, hi: 0xaf},
+	// Block 0x4a, offset 0x195
+	{value: 0x0000, lo: 0x07},
+	{value: 0x8100, lo: 0x84, hi: 0x84},
+	{value: 0x8100, lo: 0x87, hi: 0x87},
+	{value: 0x8100, lo: 0x90, hi: 0x90},
+	{value: 0x8100, lo: 0x9e, hi: 0x9e},
+	{value: 0x8100, lo: 0xa1, hi: 0xa1},
+	{value: 0x8100, lo: 0xb2, hi: 0xb2},
+	{value: 0x8100, lo: 0xbb, hi: 0xbb},
+	// Block 0x4b, offset 0x19d
+	{value: 0x0000, lo: 0x03},
+	{value: 0x8100, lo: 0x80, hi: 0x80},
+	{value: 0x8100, lo: 0x8b, hi: 0x8b},
+	{value: 0x8100, lo: 0x8e, hi: 0x8e},
+	// Block 0x4c, offset 0x1a1
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8132, lo: 0xaf, hi: 0xaf},
+	{value: 0x8132, lo: 0xb4, hi: 0xbd},
+	// Block 0x4d, offset 0x1a4
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8132, lo: 0x9f, hi: 0x9f},
+	// Block 0x4e, offset 0x1a6
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8132, lo: 0xb0, hi: 0xb1},
+	// Block 0x4f, offset 0x1a8
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8104, lo: 0x86, hi: 0x86},
+	// Block 0x50, offset 0x1aa
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8104, lo: 0x84, hi: 0x84},
+	{value: 0x8132, lo: 0xa0, hi: 0xb1},
+	// Block 0x51, offset 0x1ad
+	{value: 0x0000, lo: 0x01},
+	{value: 0x812d, lo: 0xab, hi: 0xad},
+	// Block 0x52, offset 0x1af
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8104, lo: 0x93, hi: 0x93},
+	// Block 0x53, offset 0x1b1
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8102, lo: 0xb3, hi: 0xb3},
+	// Block 0x54, offset 0x1b3
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8104, lo: 0x80, hi: 0x80},
+	// Block 0x55, offset 0x1b5
+	{value: 0x0000, lo: 0x05},
+	{value: 0x8132, lo: 0xb0, hi: 0xb0},
+	{value: 0x8132, lo: 0xb2, hi: 0xb3},
+	{value: 0x812d, lo: 0xb4, hi: 0xb4},
+	{value: 0x8132, lo: 0xb7, hi: 0xb8},
+	{value: 0x8132, lo: 0xbe, hi: 0xbf},
+	// Block 0x56, offset 0x1bb
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8132, lo: 0x81, hi: 0x81},
+	{value: 0x8104, lo: 0xb6, hi: 0xb6},
+	// Block 0x57, offset 0x1be
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8104, lo: 0xad, hi: 0xad},
+	// Block 0x58, offset 0x1c0
+	{value: 0x0000, lo: 0x06},
+	{value: 0xe500, lo: 0x80, hi: 0x80},
+	{value: 0xc600, lo: 0x81, hi: 0x9b},
+	{value: 0xe500, lo: 0x9c, hi: 0x9c},
+	{value: 0xc600, lo: 0x9d, hi: 0xb7},
+	{value: 0xe500, lo: 0xb8, hi: 0xb8},
+	{value: 0xc600, lo: 0xb9, hi: 0xbf},
+	// Block 0x59, offset 0x1c7
+	{value: 0x0000, lo: 0x05},
+	{value: 0xc600, lo: 0x80, hi: 0x93},
+	{value: 0xe500, lo: 0x94, hi: 0x94},
+	{value: 0xc600, lo: 0x95, hi: 0xaf},
+	{value: 0xe500, lo: 0xb0, hi: 0xb0},
+	{value: 0xc600, lo: 0xb1, hi: 0xbf},
+	// Block 0x5a, offset 0x1cd
+	{value: 0x0000, lo: 0x05},
+	{value: 0xc600, lo: 0x80, hi: 0x8b},
+	{value: 0xe500, lo: 0x8c, hi: 0x8c},
+	{value: 0xc600, lo: 0x8d, hi: 0xa7},
+	{value: 0xe500, lo: 0xa8, hi: 0xa8},
+	{value: 0xc600, lo: 0xa9, hi: 0xbf},
+	// Block 0x5b, offset 0x1d3
+	{value: 0x0000, lo: 0x07},
+	{value: 0xc600, lo: 0x80, hi: 0x83},
+	{value: 0xe500, lo: 0x84, hi: 0x84},
+	{value: 0xc600, lo: 0x85, hi: 0x9f},
+	{value: 0xe500, lo: 0xa0, hi: 0xa0},
+	{value: 0xc600, lo: 0xa1, hi: 0xbb},
+	{value: 0xe500, lo: 0xbc, hi: 0xbc},
+	{value: 0xc600, lo: 0xbd, hi: 0xbf},
+	// Block 0x5c, offset 0x1db
+	{value: 0x0000, lo: 0x05},
+	{value: 0xc600, lo: 0x80, hi: 0x97},
+	{value: 0xe500, lo: 0x98, hi: 0x98},
+	{value: 0xc600, lo: 0x99, hi: 0xb3},
+	{value: 0xe500, lo: 0xb4, hi: 0xb4},
+	{value: 0xc600, lo: 0xb5, hi: 0xbf},
+	// Block 0x5d, offset 0x1e1
+	{value: 0x0000, lo: 0x05},
+	{value: 0xc600, lo: 0x80, hi: 0x8f},
+	{value: 0xe500, lo: 0x90, hi: 0x90},
+	{value: 0xc600, lo: 0x91, hi: 0xab},
+	{value: 0xe500, lo: 0xac, hi: 0xac},
+	{value: 0xc600, lo: 0xad, hi: 0xbf},
+	// Block 0x5e, offset 0x1e7
+	{value: 0x0000, lo: 0x05},
+	{value: 0xc600, lo: 0x80, hi: 0x87},
+	{value: 0xe500, lo: 0x88, hi: 0x88},
+	{value: 0xc600, lo: 0x89, hi: 0xa3},
+	{value: 0xe500, lo: 0xa4, hi: 0xa4},
+	{value: 0xc600, lo: 0xa5, hi: 0xbf},
+	// Block 0x5f, offset 0x1ed
+	{value: 0x0000, lo: 0x03},
+	{value: 0xc600, lo: 0x80, hi: 0x87},
+	{value: 0xe500, lo: 0x88, hi: 0x88},
+	{value: 0xc600, lo: 0x89, hi: 0xa3},
+	// Block 0x60, offset 0x1f1
+	{value: 0x0006, lo: 0x0d},
+	{value: 0x43cb, lo: 0x9d, hi: 0x9d},
+	{value: 0x8115, lo: 0x9e, hi: 0x9e},
+	{value: 0x443d, lo: 0x9f, hi: 0x9f},
+	{value: 0x442b, lo: 0xaa, hi: 0xab},
+	{value: 0x452f, lo: 0xac, hi: 0xac},
+	{value: 0x4537, lo: 0xad, hi: 0xad},
+	{value: 0x4383, lo: 0xae, hi: 0xb1},
+	{value: 0x43a1, lo: 0xb2, hi: 0xb4},
+	{value: 0x43b9, lo: 0xb5, hi: 0xb6},
+	{value: 0x43c5, lo: 0xb8, hi: 0xb8},
+	{value: 0x43d1, lo: 0xb9, hi: 0xbb},
+	{value: 0x43e9, lo: 0xbc, hi: 0xbc},
+	{value: 0x43ef, lo: 0xbe, hi: 0xbe},
+	// Block 0x61, offset 0x1ff
+	{value: 0x0006, lo: 0x08},
+	{value: 0x43f5, lo: 0x80, hi: 0x81},
+	{value: 0x4401, lo: 0x83, hi: 0x84},
+	{value: 0x4413, lo: 0x86, hi: 0x89},
+	{value: 0x4437, lo: 0x8a, hi: 0x8a},
+	{value: 0x43b3, lo: 0x8b, hi: 0x8b},
+	{value: 0x439b, lo: 0x8c, hi: 0x8c},
+	{value: 0x43e3, lo: 0x8d, hi: 0x8d},
+	{value: 0x440d, lo: 0x8e, hi: 0x8e},
+	// Block 0x62, offset 0x208
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8100, lo: 0xa4, hi: 0xa5},
+	{value: 0x8100, lo: 0xb0, hi: 0xb1},
+	// Block 0x63, offset 0x20b
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8100, lo: 0x9b, hi: 0x9d},
+	{value: 0x8200, lo: 0x9e, hi: 0xa3},
+	// Block 0x64, offset 0x20e
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8100, lo: 0x90, hi: 0x90},
+	// Block 0x65, offset 0x210
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8100, lo: 0x99, hi: 0x99},
+	{value: 0x8200, lo: 0xb2, hi: 0xb4},
+	// Block 0x66, offset 0x213
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8100, lo: 0xbc, hi: 0xbd},
+	// Block 0x67, offset 0x215
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8132, lo: 0xa0, hi: 0xa6},
+	{value: 0x812d, lo: 0xa7, hi: 0xad},
+	// Block 0x68, offset 0x218
+	{value: 0x0000, lo: 0x04},
+	{value: 0x8100, lo: 0x89, hi: 0x8c},
+	{value: 0x8100, lo: 0xb0, hi: 0xb2},
+	{value: 0x8100, lo: 0xb4, hi: 0xb4},
+	{value: 0x8100, lo: 0xb6, hi: 0xbf},
+	// Block 0x69, offset 0x21d
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8100, lo: 0x81, hi: 0x8c},
+	// Block 0x6a, offset 0x21f
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8100, lo: 0xb5, hi: 0xba},
+	// Block 0x6b, offset 0x221
+	{value: 0x0000, lo: 0x01},
+	{value: 0x4a26, lo: 0x9e, hi: 0x9f},
+	// Block 0x6c, offset 0x223
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8100, lo: 0xa3, hi: 0xa3},
+	// Block 0x6d, offset 0x225
+	{value: 0x0000, lo: 0x01},
+	{value: 0x812d, lo: 0xbd, hi: 0xbd},
+	// Block 0x6e, offset 0x227
+	{value: 0x0000, lo: 0x01},
+	{value: 0x812d, lo: 0xa0, hi: 0xa0},
+	// Block 0x6f, offset 0x229
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8132, lo: 0xb6, hi: 0xba},
+	// Block 0x70, offset 0x22b
+	{value: 0x002c, lo: 0x05},
+	{value: 0x812d, lo: 0x8d, hi: 0x8d},
+	{value: 0x8132, lo: 0x8f, hi: 0x8f},
+	{value: 0x8132, lo: 0xb8, hi: 0xb8},
+	{value: 0x8101, lo: 0xb9, hi: 0xba},
+	{value: 0x8104, lo: 0xbf, hi: 0xbf},
+	// Block 0x71, offset 0x231
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8132, lo: 0xa5, hi: 0xa5},
+	{value: 0x812d, lo: 0xa6, hi: 0xa6},
+	// Block 0x72, offset 0x234
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8104, lo: 0x86, hi: 0x86},
+	{value: 0x8104, lo: 0xbf, hi: 0xbf},
+	// Block 0x73, offset 0x237
+	{value: 0x17fe, lo: 0x07},
+	{value: 0xa000, lo: 0x99, hi: 0x99},
+	{value: 0x4273, lo: 0x9a, hi: 0x9a},
+	{value: 0xa000, lo: 0x9b, hi: 0x9b},
+	{value: 0x427d, lo: 0x9c, hi: 0x9c},
+	{value: 0xa000, lo: 0xa5, hi: 0xa5},
+	{value: 0x4287, lo: 0xab, hi: 0xab},
+	{value: 0x8104, lo: 0xb9, hi: 0xba},
+	// Block 0x74, offset 0x23f
+	{value: 0x0000, lo: 0x06},
+	{value: 0x8132, lo: 0x80, hi: 0x82},
+	{value: 0x9900, lo: 0xa7, hi: 0xa7},
+	{value: 0x19a5, lo: 0xae, hi: 0xae},
+	{value: 0x19ae, lo: 0xaf, hi: 0xaf},
+	{value: 0xa000, lo: 0xb1, hi: 0xb2},
+	{value: 0x8104, lo: 0xb3, hi: 0xb4},
+	// Block 0x75, offset 0x246
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8104, lo: 0xb5, hi: 0xb5},
+	{value: 0x8102, lo: 0xb6, hi: 0xb6},
+	// Block 0x76, offset 0x249
+	{value: 0x0002, lo: 0x01},
+	{value: 0x8102, lo: 0xa9, hi: 0xaa},
+	// Block 0x77, offset 0x24b
+	{value: 0x0000, lo: 0x07},
+	{value: 0xa000, lo: 0x87, hi: 0x87},
+	{value: 0x19b7, lo: 0x8b, hi: 0x8b},
+	{value: 0x19c0, lo: 0x8c, hi: 0x8c},
+	{value: 0x8104, lo: 0x8d, hi: 0x8d},
+	{value: 0x9900, lo: 0x97, hi: 0x97},
+	{value: 0x8132, lo: 0xa6, hi: 0xac},
+	{value: 0x8132, lo: 0xb0, hi: 0xb4},
+	// Block 0x78, offset 0x253
+	{value: 0x7f37, lo: 0x06},
+	{value: 0x9900, lo: 0xb0, hi: 0xb0},
+	{value: 0xa000, lo: 0xb9, hi: 0xb9},
+	{value: 0x9900, lo: 0xba, hi: 0xba},
+	{value: 0x19d2, lo: 0xbb, hi: 0xbb},
+	{value: 0x19c9, lo: 0xbc, hi: 0xbd},
+	{value: 0x19db, lo: 0xbe, hi: 0xbe},
+	// Block 0x79, offset 0x25a
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8104, lo: 0x82, hi: 0x82},
+	{value: 0x8102, lo: 0x83, hi: 0x83},
+	// Block 0x7a, offset 0x25d
+	{value: 0x0000, lo: 0x05},
+	{value: 0x9900, lo: 0xaf, hi: 0xaf},
+	{value: 0xa000, lo: 0xb8, hi: 0xb9},
+	{value: 0x19e4, lo: 0xba, hi: 0xba},
+	{value: 0x19ed, lo: 0xbb, hi: 0xbb},
+	{value: 0x8104, lo: 0xbf, hi: 0xbf},
+	// Block 0x7b, offset 0x263
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8102, lo: 0x80, hi: 0x80},
+	// Block 0x7c, offset 0x265
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8104, lo: 0xb6, hi: 0xb6},
+	{value: 0x8102, lo: 0xb7, hi: 0xb7},
+	// Block 0x7d, offset 0x268
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8101, lo: 0xb0, hi: 0xb4},
+	// Block 0x7e, offset 0x26a
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8132, lo: 0xb0, hi: 0xb6},
+	// Block 0x7f, offset 0x26c
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8101, lo: 0x9e, hi: 0x9e},
+	// Block 0x80, offset 0x26e
+	{value: 0x0000, lo: 0x0c},
+	{value: 0x4607, lo: 0x9e, hi: 0x9e},
+	{value: 0x4611, lo: 0x9f, hi: 0x9f},
+	{value: 0x4645, lo: 0xa0, hi: 0xa0},
+	{value: 0x4653, lo: 0xa1, hi: 0xa1},
+	{value: 0x4661, lo: 0xa2, hi: 0xa2},
+	{value: 0x466f, lo: 0xa3, hi: 0xa3},
+	{value: 0x467d, lo: 0xa4, hi: 0xa4},
+	{value: 0x812b, lo: 0xa5, hi: 0xa6},
+	{value: 0x8101, lo: 0xa7, hi: 0xa9},
+	{value: 0x8130, lo: 0xad, hi: 0xad},
+	{value: 0x812b, lo: 0xae, hi: 0xb2},
+	{value: 0x812d, lo: 0xbb, hi: 0xbf},
+	// Block 0x81, offset 0x27b
+	{value: 0x0000, lo: 0x09},
+	{value: 0x812d, lo: 0x80, hi: 0x82},
+	{value: 0x8132, lo: 0x85, hi: 0x89},
+	{value: 0x812d, lo: 0x8a, hi: 0x8b},
+	{value: 0x8132, lo: 0xaa, hi: 0xad},
+	{value: 0x461b, lo: 0xbb, hi: 0xbb},
+	{value: 0x4625, lo: 0xbc, hi: 0xbc},
+	{value: 0x468b, lo: 0xbd, hi: 0xbd},
+	{value: 0x46a7, lo: 0xbe, hi: 0xbe},
+	{value: 0x4699, lo: 0xbf, hi: 0xbf},
+	// Block 0x82, offset 0x285
+	{value: 0x0000, lo: 0x01},
+	{value: 0x46b5, lo: 0x80, hi: 0x80},
+	// Block 0x83, offset 0x287
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8132, lo: 0x82, hi: 0x84},
+	// Block 0x84, offset 0x289
+	{value: 0x0000, lo: 0x01},
+	{value: 0x812d, lo: 0x90, hi: 0x96},
+	// Block 0x85, offset 0x28b
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8100, lo: 0x93, hi: 0x93},
+}
+
+// lookup returns the trie value for the first UTF-8 encoding in s and
+// the width in bytes of this encoding. The size will be 0 if s does not
+// hold enough bytes to complete the encoding. len(s) must be greater than 0.
+func (t *nfkcTrie) lookup(s []byte) (v uint16, sz int) {
+	c0 := s[0]
+	switch {
+	case c0 < 0x80: // is ASCII
+		return nfkcValues[c0], 1
+	case c0 < 0xC0:
+		return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
+	case c0 < 0xE0: // 2-byte UTF-8
+		if len(s) < 2 {
+			return 0, 0
+		}
+		i := nfkcIndex[c0]
+		c1 := s[1]
+		if c1 < 0x80 || 0xC0 <= c1 {
+			return 0, 1 // Illegal UTF-8: not a continuation byte.
+		}
+		return t.lookupValue(uint32(i), c1), 2
+	case c0 < 0xF0: // 3-byte UTF-8
+		if len(s) < 3 {
+			return 0, 0
+		}
+		i := nfkcIndex[c0]
+		c1 := s[1]
+		if c1 < 0x80 || 0xC0 <= c1 {
+			return 0, 1 // Illegal UTF-8: not a continuation byte.
+		}
+		o := uint32(i)<<6 + uint32(c1)
+		i = nfkcIndex[o]
+		c2 := s[2]
+		if c2 < 0x80 || 0xC0 <= c2 {
+			return 0, 2 // Illegal UTF-8: not a continuation byte.
+		}
+		return t.lookupValue(uint32(i), c2), 3
+	case c0 < 0xF8: // 4-byte UTF-8
+		if len(s) < 4 {
+			return 0, 0
+		}
+		i := nfkcIndex[c0]
+		c1 := s[1]
+		if c1 < 0x80 || 0xC0 <= c1 {
+			return 0, 1 // Illegal UTF-8: not a continuation byte.
+		}
+		o := uint32(i)<<6 + uint32(c1)
+		i = nfkcIndex[o]
+		c2 := s[2]
+		if c2 < 0x80 || 0xC0 <= c2 {
+			return 0, 2 // Illegal UTF-8: not a continuation byte.
+		}
+		o = uint32(i)<<6 + uint32(c2)
+		i = nfkcIndex[o]
+		c3 := s[3]
+		if c3 < 0x80 || 0xC0 <= c3 {
+			return 0, 3 // Illegal UTF-8: not a continuation byte.
+		}
+		return t.lookupValue(uint32(i), c3), 4
+	}
+	// Illegal rune
+	return 0, 1
+}
+
+// lookupUnsafe returns the trie value for the first UTF-8 encoding in s.
+// s must start with a full and valid UTF-8 encoded rune.
+func (t *nfkcTrie) lookupUnsafe(s []byte) uint16 {
+	c0 := s[0]
+	if c0 < 0x80 { // is ASCII
+		return nfkcValues[c0]
+	}
+	i := nfkcIndex[c0]
+	if c0 < 0xE0 { // 2-byte UTF-8
+		return t.lookupValue(uint32(i), s[1])
+	}
+	i = nfkcIndex[uint32(i)<<6+uint32(s[1])]
+	if c0 < 0xF0 { // 3-byte UTF-8
+		return t.lookupValue(uint32(i), s[2])
+	}
+	i = nfkcIndex[uint32(i)<<6+uint32(s[2])]
+	if c0 < 0xF8 { // 4-byte UTF-8
+		return t.lookupValue(uint32(i), s[3])
+	}
+	return 0
+}
+
+// lookupString returns the trie value for the first UTF-8 encoding in s and
+// the width in bytes of this encoding. The size will be 0 if s does not
+// hold enough bytes to complete the encoding. len(s) must be greater than 0.
+func (t *nfkcTrie) lookupString(s string) (v uint16, sz int) {
+	c0 := s[0]
+	switch {
+	case c0 < 0x80: // is ASCII
+		return nfkcValues[c0], 1
+	case c0 < 0xC0:
+		return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
+	case c0 < 0xE0: // 2-byte UTF-8
+		if len(s) < 2 {
+			return 0, 0
+		}
+		i := nfkcIndex[c0]
+		c1 := s[1]
+		if c1 < 0x80 || 0xC0 <= c1 {
+			return 0, 1 // Illegal UTF-8: not a continuation byte.
+		}
+		return t.lookupValue(uint32(i), c1), 2
+	case c0 < 0xF0: // 3-byte UTF-8
+		if len(s) < 3 {
+			return 0, 0
+		}
+		i := nfkcIndex[c0]
+		c1 := s[1]
+		if c1 < 0x80 || 0xC0 <= c1 {
+			return 0, 1 // Illegal UTF-8: not a continuation byte.
+		}
+		o := uint32(i)<<6 + uint32(c1)
+		i = nfkcIndex[o]
+		c2 := s[2]
+		if c2 < 0x80 || 0xC0 <= c2 {
+			return 0, 2 // Illegal UTF-8: not a continuation byte.
+		}
+		return t.lookupValue(uint32(i), c2), 3
+	case c0 < 0xF8: // 4-byte UTF-8
+		if len(s) < 4 {
+			return 0, 0
+		}
+		i := nfkcIndex[c0]
+		c1 := s[1]
+		if c1 < 0x80 || 0xC0 <= c1 {
+			return 0, 1 // Illegal UTF-8: not a continuation byte.
+		}
+		o := uint32(i)<<6 + uint32(c1)
+		i = nfkcIndex[o]
+		c2 := s[2]
+		if c2 < 0x80 || 0xC0 <= c2 {
+			return 0, 2 // Illegal UTF-8: not a continuation byte.
+		}
+		o = uint32(i)<<6 + uint32(c2)
+		i = nfkcIndex[o]
+		c3 := s[3]
+		if c3 < 0x80 || 0xC0 <= c3 {
+			return 0, 3 // Illegal UTF-8: not a continuation byte.
+		}
+		return t.lookupValue(uint32(i), c3), 4
+	}
+	// Illegal rune
+	return 0, 1
+}
+
+// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s.
+// s must start with a full and valid UTF-8 encoded rune.
+func (t *nfkcTrie) lookupStringUnsafe(s string) uint16 {
+	c0 := s[0]
+	if c0 < 0x80 { // is ASCII
+		return nfkcValues[c0]
+	}
+	i := nfkcIndex[c0]
+	if c0 < 0xE0 { // 2-byte UTF-8
+		return t.lookupValue(uint32(i), s[1])
+	}
+	i = nfkcIndex[uint32(i)<<6+uint32(s[1])]
+	if c0 < 0xF0 { // 3-byte UTF-8
+		return t.lookupValue(uint32(i), s[2])
+	}
+	i = nfkcIndex[uint32(i)<<6+uint32(s[2])]
+	if c0 < 0xF8 { // 4-byte UTF-8
+		return t.lookupValue(uint32(i), s[3])
+	}
+	return 0
+}
+
+// nfkcTrie. Total size: 16752 bytes (16.36 KiB). Checksum: 5cd2e697fcf78b3e.
+type nfkcTrie struct{}
+
+func newNfkcTrie(i int) *nfkcTrie {
+	return &nfkcTrie{}
+}
+
+// lookupValue determines the type of block n and looks up the value for b.
+func (t *nfkcTrie) lookupValue(n uint32, b byte) uint16 {
+	switch {
+	case n < 88:
+		return uint16(nfkcValues[n<<6+uint32(b)])
+	default:
+		n -= 88
+		return uint16(nfkcSparse.lookup(n, b))
+	}
+}
+
+// nfkcValues: 90 blocks, 5760 entries, 11520 bytes
+// The third block is the zero block.
+var nfkcValues = [5760]uint16{
+	// Block 0x0, offset 0x0
+	0x3c: 0xa000, 0x3d: 0xa000, 0x3e: 0xa000,
+	// Block 0x1, offset 0x40
+	0x41: 0xa000, 0x42: 0xa000, 0x43: 0xa000, 0x44: 0xa000, 0x45: 0xa000,
+	0x46: 0xa000, 0x47: 0xa000, 0x48: 0xa000, 0x49: 0xa000, 0x4a: 0xa000, 0x4b: 0xa000,
+	0x4c: 0xa000, 0x4d: 0xa000, 0x4e: 0xa000, 0x4f: 0xa000, 0x50: 0xa000,
+	0x52: 0xa000, 0x53: 0xa000, 0x54: 0xa000, 0x55: 0xa000, 0x56: 0xa000, 0x57: 0xa000,
+	0x58: 0xa000, 0x59: 0xa000, 0x5a: 0xa000,
+	0x61: 0xa000, 0x62: 0xa000, 0x63: 0xa000,
+	0x64: 0xa000, 0x65: 0xa000, 0x66: 0xa000, 0x67: 0xa000, 0x68: 0xa000, 0x69: 0xa000,
+	0x6a: 0xa000, 0x6b: 0xa000, 0x6c: 0xa000, 0x6d: 0xa000, 0x6e: 0xa000, 0x6f: 0xa000,
+	0x70: 0xa000, 0x72: 0xa000, 0x73: 0xa000, 0x74: 0xa000, 0x75: 0xa000,
+	0x76: 0xa000, 0x77: 0xa000, 0x78: 0xa000, 0x79: 0xa000, 0x7a: 0xa000,
+	// Block 0x2, offset 0x80
+	// Block 0x3, offset 0xc0
+	0xc0: 0x2faa, 0xc1: 0x2faf, 0xc2: 0x46c3, 0xc3: 0x2fb4, 0xc4: 0x46d2, 0xc5: 0x46d7,
+	0xc6: 0xa000, 0xc7: 0x46e1, 0xc8: 0x301d, 0xc9: 0x3022, 0xca: 0x46e6, 0xcb: 0x3036,
+	0xcc: 0x30a9, 0xcd: 0x30ae, 0xce: 0x30b3, 0xcf: 0x46fa, 0xd1: 0x313f,
+	0xd2: 0x3162, 0xd3: 0x3167, 0xd4: 0x4704, 0xd5: 0x4709, 0xd6: 0x4718,
+	0xd8: 0xa000, 0xd9: 0x31ee, 0xda: 0x31f3, 0xdb: 0x31f8, 0xdc: 0x474a, 0xdd: 0x3270,
+	0xe0: 0x32b6, 0xe1: 0x32bb, 0xe2: 0x4754, 0xe3: 0x32c0,
+	0xe4: 0x4763, 0xe5: 0x4768, 0xe6: 0xa000, 0xe7: 0x4772, 0xe8: 0x3329, 0xe9: 0x332e,
+	0xea: 0x4777, 0xeb: 0x3342, 0xec: 0x33ba, 0xed: 0x33bf, 0xee: 0x33c4, 0xef: 0x478b,
+	0xf1: 0x3450, 0xf2: 0x3473, 0xf3: 0x3478, 0xf4: 0x4795, 0xf5: 0x479a,
+	0xf6: 0x47a9, 0xf8: 0xa000, 0xf9: 0x3504, 0xfa: 0x3509, 0xfb: 0x350e,
+	0xfc: 0x47db, 0xfd: 0x358b, 0xff: 0x35a4,
+	// Block 0x4, offset 0x100
+	0x100: 0x2fb9, 0x101: 0x32c5, 0x102: 0x46c8, 0x103: 0x4759, 0x104: 0x2fd7, 0x105: 0x32e3,
+	0x106: 0x2feb, 0x107: 0x32f7, 0x108: 0x2ff0, 0x109: 0x32fc, 0x10a: 0x2ff5, 0x10b: 0x3301,
+	0x10c: 0x2ffa, 0x10d: 0x3306, 0x10e: 0x3004, 0x10f: 0x3310,
+	0x112: 0x46eb, 0x113: 0x477c, 0x114: 0x302c, 0x115: 0x3338, 0x116: 0x3031, 0x117: 0x333d,
+	0x118: 0x304f, 0x119: 0x335b, 0x11a: 0x3040, 0x11b: 0x334c, 0x11c: 0x3068, 0x11d: 0x3374,
+	0x11e: 0x3072, 0x11f: 0x337e, 0x120: 0x3077, 0x121: 0x3383, 0x122: 0x3081, 0x123: 0x338d,
+	0x124: 0x3086, 0x125: 0x3392, 0x128: 0x30b8, 0x129: 0x33c9,
+	0x12a: 0x30bd, 0x12b: 0x33ce, 0x12c: 0x30c2, 0x12d: 0x33d3, 0x12e: 0x30e5, 0x12f: 0x33f1,
+	0x130: 0x30c7, 0x132: 0x1af0, 0x133: 0x1b7a, 0x134: 0x30ef, 0x135: 0x33fb,
+	0x136: 0x3103, 0x137: 0x3414, 0x139: 0x310d, 0x13a: 0x341e, 0x13b: 0x3117,
+	0x13c: 0x3428, 0x13d: 0x3112, 0x13e: 0x3423, 0x13f: 0x1d3f,
+	// Block 0x5, offset 0x140
+	0x140: 0x1dc7, 0x143: 0x313a, 0x144: 0x344b, 0x145: 0x3153,
+	0x146: 0x3464, 0x147: 0x3149, 0x148: 0x345a, 0x149: 0x1def,
+	0x14c: 0x470e, 0x14d: 0x479f, 0x14e: 0x316c, 0x14f: 0x347d, 0x150: 0x3176, 0x151: 0x3487,
+	0x154: 0x3194, 0x155: 0x34a5, 0x156: 0x31ad, 0x157: 0x34be,
+	0x158: 0x319e, 0x159: 0x34af, 0x15a: 0x4731, 0x15b: 0x47c2, 0x15c: 0x31b7, 0x15d: 0x34c8,
+	0x15e: 0x31c6, 0x15f: 0x34d7, 0x160: 0x4736, 0x161: 0x47c7, 0x162: 0x31df, 0x163: 0x34f5,
+	0x164: 0x31d0, 0x165: 0x34e6, 0x168: 0x4740, 0x169: 0x47d1,
+	0x16a: 0x4745, 0x16b: 0x47d6, 0x16c: 0x31fd, 0x16d: 0x3513, 0x16e: 0x3207, 0x16f: 0x351d,
+	0x170: 0x320c, 0x171: 0x3522, 0x172: 0x322a, 0x173: 0x3540, 0x174: 0x324d, 0x175: 0x3563,
+	0x176: 0x3275, 0x177: 0x3590, 0x178: 0x3289, 0x179: 0x3298, 0x17a: 0x35b8, 0x17b: 0x32a2,
+	0x17c: 0x35c2, 0x17d: 0x32a7, 0x17e: 0x35c7, 0x17f: 0x00a7,
+	// Block 0x6, offset 0x180
+	0x184: 0x2ed0, 0x185: 0x2ed6,
+	0x186: 0x2edc, 0x187: 0x1b05, 0x188: 0x1b08, 0x189: 0x1b9b, 0x18a: 0x1b1a, 0x18b: 0x1b1d,
+	0x18c: 0x1bd1, 0x18d: 0x2fc3, 0x18e: 0x32cf, 0x18f: 0x30d1, 0x190: 0x33dd, 0x191: 0x317b,
+	0x192: 0x348c, 0x193: 0x3211, 0x194: 0x3527, 0x195: 0x3a0a, 0x196: 0x3b99, 0x197: 0x3a03,
+	0x198: 0x3b92, 0x199: 0x3a11, 0x19a: 0x3ba0, 0x19b: 0x39fc, 0x19c: 0x3b8b,
+	0x19e: 0x38eb, 0x19f: 0x3a7a, 0x1a0: 0x38e4, 0x1a1: 0x3a73, 0x1a2: 0x35ee, 0x1a3: 0x3600,
+	0x1a6: 0x307c, 0x1a7: 0x3388, 0x1a8: 0x30f9, 0x1a9: 0x340a,
+	0x1aa: 0x4727, 0x1ab: 0x47b8, 0x1ac: 0x39cb, 0x1ad: 0x3b5a, 0x1ae: 0x3612, 0x1af: 0x3618,
+	0x1b0: 0x3400, 0x1b1: 0x1ad5, 0x1b2: 0x1ad8, 0x1b3: 0x1b62, 0x1b4: 0x3063, 0x1b5: 0x336f,
+	0x1b8: 0x3135, 0x1b9: 0x3446, 0x1ba: 0x38f2, 0x1bb: 0x3a81,
+	0x1bc: 0x35e8, 0x1bd: 0x35fa, 0x1be: 0x35f4, 0x1bf: 0x3606,
+	// Block 0x7, offset 0x1c0
+	0x1c0: 0x2fc8, 0x1c1: 0x32d4, 0x1c2: 0x2fcd, 0x1c3: 0x32d9, 0x1c4: 0x3045, 0x1c5: 0x3351,
+	0x1c6: 0x304a, 0x1c7: 0x3356, 0x1c8: 0x30d6, 0x1c9: 0x33e2, 0x1ca: 0x30db, 0x1cb: 0x33e7,
+	0x1cc: 0x3180, 0x1cd: 0x3491, 0x1ce: 0x3185, 0x1cf: 0x3496, 0x1d0: 0x31a3, 0x1d1: 0x34b4,
+	0x1d2: 0x31a8, 0x1d3: 0x34b9, 0x1d4: 0x3216, 0x1d5: 0x352c, 0x1d6: 0x321b, 0x1d7: 0x3531,
+	0x1d8: 0x31c1, 0x1d9: 0x34d2, 0x1da: 0x31da, 0x1db: 0x34f0,
+	0x1de: 0x3095, 0x1df: 0x33a1,
+	0x1e6: 0x46cd, 0x1e7: 0x475e, 0x1e8: 0x46f5, 0x1e9: 0x4786,
+	0x1ea: 0x399a, 0x1eb: 0x3b29, 0x1ec: 0x3977, 0x1ed: 0x3b06, 0x1ee: 0x4713, 0x1ef: 0x47a4,
+	0x1f0: 0x3993, 0x1f1: 0x3b22, 0x1f2: 0x327f, 0x1f3: 0x359a,
+	// Block 0x8, offset 0x200
+	0x200: 0x9932, 0x201: 0x9932, 0x202: 0x9932, 0x203: 0x9932, 0x204: 0x9932, 0x205: 0x8132,
+	0x206: 0x9932, 0x207: 0x9932, 0x208: 0x9932, 0x209: 0x9932, 0x20a: 0x9932, 0x20b: 0x9932,
+	0x20c: 0x9932, 0x20d: 0x8132, 0x20e: 0x8132, 0x20f: 0x9932, 0x210: 0x8132, 0x211: 0x9932,
+	0x212: 0x8132, 0x213: 0x9932, 0x214: 0x9932, 0x215: 0x8133, 0x216: 0x812d, 0x217: 0x812d,
+	0x218: 0x812d, 0x219: 0x812d, 0x21a: 0x8133, 0x21b: 0x992b, 0x21c: 0x812d, 0x21d: 0x812d,
+	0x21e: 0x812d, 0x21f: 0x812d, 0x220: 0x812d, 0x221: 0x8129, 0x222: 0x8129, 0x223: 0x992d,
+	0x224: 0x992d, 0x225: 0x992d, 0x226: 0x992d, 0x227: 0x9929, 0x228: 0x9929, 0x229: 0x812d,
+	0x22a: 0x812d, 0x22b: 0x812d, 0x22c: 0x812d, 0x22d: 0x992d, 0x22e: 0x992d, 0x22f: 0x812d,
+	0x230: 0x992d, 0x231: 0x992d, 0x232: 0x812d, 0x233: 0x812d, 0x234: 0x8101, 0x235: 0x8101,
+	0x236: 0x8101, 0x237: 0x8101, 0x238: 0x9901, 0x239: 0x812d, 0x23a: 0x812d, 0x23b: 0x812d,
+	0x23c: 0x812d, 0x23d: 0x8132, 0x23e: 0x8132, 0x23f: 0x8132,
+	// Block 0x9, offset 0x240
+	0x240: 0x49e9, 0x241: 0x49ee, 0x242: 0x9932, 0x243: 0x49f3, 0x244: 0x49f8, 0x245: 0x9936,
+	0x246: 0x8132, 0x247: 0x812d, 0x248: 0x812d, 0x249: 0x812d, 0x24a: 0x8132, 0x24b: 0x8132,
+	0x24c: 0x8132, 0x24d: 0x812d, 0x24e: 0x812d, 0x250: 0x8132, 0x251: 0x8132,
+	0x252: 0x8132, 0x253: 0x812d, 0x254: 0x812d, 0x255: 0x812d, 0x256: 0x812d, 0x257: 0x8132,
+	0x258: 0x8133, 0x259: 0x812d, 0x25a: 0x812d, 0x25b: 0x8132, 0x25c: 0x8134, 0x25d: 0x8135,
+	0x25e: 0x8135, 0x25f: 0x8134, 0x260: 0x8135, 0x261: 0x8135, 0x262: 0x8134, 0x263: 0x8132,
+	0x264: 0x8132, 0x265: 0x8132, 0x266: 0x8132, 0x267: 0x8132, 0x268: 0x8132, 0x269: 0x8132,
+	0x26a: 0x8132, 0x26b: 0x8132, 0x26c: 0x8132, 0x26d: 0x8132, 0x26e: 0x8132, 0x26f: 0x8132,
+	0x274: 0x0170,
+	0x27a: 0x42e0,
+	0x27e: 0x0037,
+	// Block 0xa, offset 0x280
+	0x284: 0x4295, 0x285: 0x44b6,
+	0x286: 0x3624, 0x287: 0x00ce, 0x288: 0x3642, 0x289: 0x364e, 0x28a: 0x3660,
+	0x28c: 0x367e, 0x28e: 0x3690, 0x28f: 0x36ae, 0x290: 0x3e43, 0x291: 0xa000,
+	0x295: 0xa000, 0x297: 0xa000,
+	0x299: 0xa000,
+	0x29f: 0xa000, 0x2a1: 0xa000,
+	0x2a5: 0xa000, 0x2a9: 0xa000,
+	0x2aa: 0x3672, 0x2ab: 0x36a2, 0x2ac: 0x4839, 0x2ad: 0x36d2, 0x2ae: 0x4863, 0x2af: 0x36e4,
+	0x2b0: 0x3eab, 0x2b1: 0xa000, 0x2b5: 0xa000,
+	0x2b7: 0xa000, 0x2b9: 0xa000,
+	0x2bf: 0xa000,
+	// Block 0xb, offset 0x2c0
+	0x2c1: 0xa000, 0x2c5: 0xa000,
+	0x2c9: 0xa000, 0x2ca: 0x487b, 0x2cb: 0x4899,
+	0x2cc: 0x3702, 0x2cd: 0x371a, 0x2ce: 0x48b1, 0x2d0: 0x01be, 0x2d1: 0x01d0,
+	0x2d2: 0x01ac, 0x2d3: 0x4347, 0x2d4: 0x434d, 0x2d5: 0x01fa, 0x2d6: 0x01e8,
+	0x2f0: 0x01d6, 0x2f1: 0x01eb, 0x2f2: 0x01ee, 0x2f4: 0x0188, 0x2f5: 0x01c7,
+	0x2f9: 0x01a6,
+	// Block 0xc, offset 0x300
+	0x300: 0x375c, 0x301: 0x3768, 0x303: 0x3756,
+	0x306: 0xa000, 0x307: 0x3744,
+	0x30c: 0x3798, 0x30d: 0x3780, 0x30e: 0x37aa, 0x310: 0xa000,
+	0x313: 0xa000, 0x315: 0xa000, 0x316: 0xa000, 0x317: 0xa000,
+	0x318: 0xa000, 0x319: 0x378c, 0x31a: 0xa000,
+	0x31e: 0xa000, 0x323: 0xa000,
+	0x327: 0xa000,
+	0x32b: 0xa000, 0x32d: 0xa000,
+	0x330: 0xa000, 0x333: 0xa000, 0x335: 0xa000,
+	0x336: 0xa000, 0x337: 0xa000, 0x338: 0xa000, 0x339: 0x3810, 0x33a: 0xa000,
+	0x33e: 0xa000,
+	// Block 0xd, offset 0x340
+	0x341: 0x376e, 0x342: 0x37f2,
+	0x350: 0x374a, 0x351: 0x37ce,
+	0x352: 0x3750, 0x353: 0x37d4, 0x356: 0x3762, 0x357: 0x37e6,
+	0x358: 0xa000, 0x359: 0xa000, 0x35a: 0x3864, 0x35b: 0x386a, 0x35c: 0x3774, 0x35d: 0x37f8,
+	0x35e: 0x377a, 0x35f: 0x37fe, 0x362: 0x3786, 0x363: 0x380a,
+	0x364: 0x3792, 0x365: 0x3816, 0x366: 0x379e, 0x367: 0x3822, 0x368: 0xa000, 0x369: 0xa000,
+	0x36a: 0x3870, 0x36b: 0x3876, 0x36c: 0x37c8, 0x36d: 0x384c, 0x36e: 0x37a4, 0x36f: 0x3828,
+	0x370: 0x37b0, 0x371: 0x3834, 0x372: 0x37b6, 0x373: 0x383a, 0x374: 0x37bc, 0x375: 0x3840,
+	0x378: 0x37c2, 0x379: 0x3846,
+	// Block 0xe, offset 0x380
+	0x387: 0x1ef4,
+	0x391: 0x812d,
+	0x392: 0x8132, 0x393: 0x8132, 0x394: 0x8132, 0x395: 0x8132, 0x396: 0x812d, 0x397: 0x8132,
+	0x398: 0x8132, 0x399: 0x8132, 0x39a: 0x812e, 0x39b: 0x812d, 0x39c: 0x8132, 0x39d: 0x8132,
+	0x39e: 0x8132, 0x39f: 0x8132, 0x3a0: 0x8132, 0x3a1: 0x8132, 0x3a2: 0x812d, 0x3a3: 0x812d,
+	0x3a4: 0x812d, 0x3a5: 0x812d, 0x3a6: 0x812d, 0x3a7: 0x812d, 0x3a8: 0x8132, 0x3a9: 0x8132,
+	0x3aa: 0x812d, 0x3ab: 0x8132, 0x3ac: 0x8132, 0x3ad: 0x812e, 0x3ae: 0x8131, 0x3af: 0x8132,
+	0x3b0: 0x8105, 0x3b1: 0x8106, 0x3b2: 0x8107, 0x3b3: 0x8108, 0x3b4: 0x8109, 0x3b5: 0x810a,
+	0x3b6: 0x810b, 0x3b7: 0x810c, 0x3b8: 0x810d, 0x3b9: 0x810e, 0x3ba: 0x810e, 0x3bb: 0x810f,
+	0x3bc: 0x8110, 0x3bd: 0x8111, 0x3bf: 0x8112,
+	// Block 0xf, offset 0x3c0
+	0x3c8: 0xa000, 0x3ca: 0xa000, 0x3cb: 0x8116,
+	0x3cc: 0x8117, 0x3cd: 0x8118, 0x3ce: 0x8119, 0x3cf: 0x811a, 0x3d0: 0x811b, 0x3d1: 0x811c,
+	0x3d2: 0x811d, 0x3d3: 0x9932, 0x3d4: 0x9932, 0x3d5: 0x992d, 0x3d6: 0x812d, 0x3d7: 0x8132,
+	0x3d8: 0x8132, 0x3d9: 0x8132, 0x3da: 0x8132, 0x3db: 0x8132, 0x3dc: 0x812d, 0x3dd: 0x8132,
+	0x3de: 0x8132, 0x3df: 0x812d,
+	0x3f0: 0x811e, 0x3f5: 0x1f17,
+	0x3f6: 0x21a6, 0x3f7: 0x21e2, 0x3f8: 0x21dd,
+	// Block 0x10, offset 0x400
+	0x405: 0xa000,
+	0x406: 0x1958, 0x407: 0xa000, 0x408: 0x195f, 0x409: 0xa000, 0x40a: 0x1966, 0x40b: 0xa000,
+	0x40c: 0x196d, 0x40d: 0xa000, 0x40e: 0x1974, 0x411: 0xa000,
+	0x412: 0x197b,
+	0x434: 0x8102, 0x435: 0x9900,
+	0x43a: 0xa000, 0x43b: 0x1982,
+	0x43c: 0xa000, 0x43d: 0x1989, 0x43e: 0xa000, 0x43f: 0xa000,
+	// Block 0x11, offset 0x440
+	0x440: 0x0069, 0x441: 0x006b, 0x442: 0x006f, 0x443: 0x0083, 0x444: 0x00f5, 0x445: 0x00f8,
+	0x446: 0x048b, 0x447: 0x0085, 0x448: 0x0089, 0x449: 0x008b, 0x44a: 0x0104, 0x44b: 0x0107,
+	0x44c: 0x010a, 0x44d: 0x008f, 0x44f: 0x0097, 0x450: 0x009b, 0x451: 0x00e0,
+	0x452: 0x009f, 0x453: 0x00fe, 0x454: 0x048f, 0x455: 0x0493, 0x456: 0x00a1, 0x457: 0x00a9,
+	0x458: 0x00ab, 0x459: 0x049b, 0x45a: 0x012b, 0x45b: 0x00ad, 0x45c: 0x049f, 0x45d: 0x01be,
+	0x45e: 0x01c1, 0x45f: 0x01c4, 0x460: 0x01fa, 0x461: 0x01fd, 0x462: 0x0093, 0x463: 0x00a5,
+	0x464: 0x00ab, 0x465: 0x00ad, 0x466: 0x01be, 0x467: 0x01c1, 0x468: 0x01eb, 0x469: 0x01fa,
+	0x46a: 0x01fd,
+	0x478: 0x020c,
+	// Block 0x12, offset 0x480
+	0x49b: 0x00fb, 0x49c: 0x0087, 0x49d: 0x0101,
+	0x49e: 0x00d4, 0x49f: 0x010a, 0x4a0: 0x008d, 0x4a1: 0x010d, 0x4a2: 0x0110, 0x4a3: 0x0116,
+	0x4a4: 0x011c, 0x4a5: 0x011f, 0x4a6: 0x0122, 0x4a7: 0x04a3, 0x4a8: 0x016a, 0x4a9: 0x0128,
+	0x4aa: 0x04a7, 0x4ab: 0x016d, 0x4ac: 0x0131, 0x4ad: 0x012e, 0x4ae: 0x0134, 0x4af: 0x0137,
+	0x4b0: 0x013a, 0x4b1: 0x013d, 0x4b2: 0x0140, 0x4b3: 0x014c, 0x4b4: 0x014f, 0x4b5: 0x00ec,
+	0x4b6: 0x0152, 0x4b7: 0x0155, 0x4b8: 0x0497, 0x4b9: 0x0158, 0x4ba: 0x015b, 0x4bb: 0x00b5,
+	0x4bc: 0x015e, 0x4bd: 0x0161, 0x4be: 0x0164, 0x4bf: 0x01d0,
+	// Block 0x13, offset 0x4c0
+	0x4c0: 0x2fd2, 0x4c1: 0x32de, 0x4c2: 0x2fdc, 0x4c3: 0x32e8, 0x4c4: 0x2fe1, 0x4c5: 0x32ed,
+	0x4c6: 0x2fe6, 0x4c7: 0x32f2, 0x4c8: 0x3907, 0x4c9: 0x3a96, 0x4ca: 0x2fff, 0x4cb: 0x330b,
+	0x4cc: 0x3009, 0x4cd: 0x3315, 0x4ce: 0x3018, 0x4cf: 0x3324, 0x4d0: 0x300e, 0x4d1: 0x331a,
+	0x4d2: 0x3013, 0x4d3: 0x331f, 0x4d4: 0x392a, 0x4d5: 0x3ab9, 0x4d6: 0x3931, 0x4d7: 0x3ac0,
+	0x4d8: 0x3054, 0x4d9: 0x3360, 0x4da: 0x3059, 0x4db: 0x3365, 0x4dc: 0x393f, 0x4dd: 0x3ace,
+	0x4de: 0x305e, 0x4df: 0x336a, 0x4e0: 0x306d, 0x4e1: 0x3379, 0x4e2: 0x308b, 0x4e3: 0x3397,
+	0x4e4: 0x309a, 0x4e5: 0x33a6, 0x4e6: 0x3090, 0x4e7: 0x339c, 0x4e8: 0x309f, 0x4e9: 0x33ab,
+	0x4ea: 0x30a4, 0x4eb: 0x33b0, 0x4ec: 0x30ea, 0x4ed: 0x33f6, 0x4ee: 0x3946, 0x4ef: 0x3ad5,
+	0x4f0: 0x30f4, 0x4f1: 0x3405, 0x4f2: 0x30fe, 0x4f3: 0x340f, 0x4f4: 0x3108, 0x4f5: 0x3419,
+	0x4f6: 0x46ff, 0x4f7: 0x4790, 0x4f8: 0x394d, 0x4f9: 0x3adc, 0x4fa: 0x3121, 0x4fb: 0x3432,
+	0x4fc: 0x311c, 0x4fd: 0x342d, 0x4fe: 0x3126, 0x4ff: 0x3437,
+	// Block 0x14, offset 0x500
+	0x500: 0x312b, 0x501: 0x343c, 0x502: 0x3130, 0x503: 0x3441, 0x504: 0x3144, 0x505: 0x3455,
+	0x506: 0x314e, 0x507: 0x345f, 0x508: 0x315d, 0x509: 0x346e, 0x50a: 0x3158, 0x50b: 0x3469,
+	0x50c: 0x3970, 0x50d: 0x3aff, 0x50e: 0x397e, 0x50f: 0x3b0d, 0x510: 0x3985, 0x511: 0x3b14,
+	0x512: 0x398c, 0x513: 0x3b1b, 0x514: 0x318a, 0x515: 0x349b, 0x516: 0x318f, 0x517: 0x34a0,
+	0x518: 0x3199, 0x519: 0x34aa, 0x51a: 0x472c, 0x51b: 0x47bd, 0x51c: 0x39d2, 0x51d: 0x3b61,
+	0x51e: 0x31b2, 0x51f: 0x34c3, 0x520: 0x31bc, 0x521: 0x34cd, 0x522: 0x473b, 0x523: 0x47cc,
+	0x524: 0x39d9, 0x525: 0x3b68, 0x526: 0x39e0, 0x527: 0x3b6f, 0x528: 0x39e7, 0x529: 0x3b76,
+	0x52a: 0x31cb, 0x52b: 0x34dc, 0x52c: 0x31d5, 0x52d: 0x34eb, 0x52e: 0x31e9, 0x52f: 0x34ff,
+	0x530: 0x31e4, 0x531: 0x34fa, 0x532: 0x3225, 0x533: 0x353b, 0x534: 0x3234, 0x535: 0x354a,
+	0x536: 0x322f, 0x537: 0x3545, 0x538: 0x39ee, 0x539: 0x3b7d, 0x53a: 0x39f5, 0x53b: 0x3b84,
+	0x53c: 0x3239, 0x53d: 0x354f, 0x53e: 0x323e, 0x53f: 0x3554,
+	// Block 0x15, offset 0x540
+	0x540: 0x3243, 0x541: 0x3559, 0x542: 0x3248, 0x543: 0x355e, 0x544: 0x3257, 0x545: 0x356d,
+	0x546: 0x3252, 0x547: 0x3568, 0x548: 0x325c, 0x549: 0x3577, 0x54a: 0x3261, 0x54b: 0x357c,
+	0x54c: 0x3266, 0x54d: 0x3581, 0x54e: 0x3284, 0x54f: 0x359f, 0x550: 0x329d, 0x551: 0x35bd,
+	0x552: 0x32ac, 0x553: 0x35cc, 0x554: 0x32b1, 0x555: 0x35d1, 0x556: 0x33b5, 0x557: 0x34e1,
+	0x558: 0x3572, 0x559: 0x35ae, 0x55a: 0x1d73, 0x55b: 0x4312,
+	0x560: 0x46dc, 0x561: 0x476d, 0x562: 0x2fbe, 0x563: 0x32ca,
+	0x564: 0x38b3, 0x565: 0x3a42, 0x566: 0x38ac, 0x567: 0x3a3b, 0x568: 0x38c1, 0x569: 0x3a50,
+	0x56a: 0x38ba, 0x56b: 0x3a49, 0x56c: 0x38f9, 0x56d: 0x3a88, 0x56e: 0x38cf, 0x56f: 0x3a5e,
+	0x570: 0x38c8, 0x571: 0x3a57, 0x572: 0x38dd, 0x573: 0x3a6c, 0x574: 0x38d6, 0x575: 0x3a65,
+	0x576: 0x3900, 0x577: 0x3a8f, 0x578: 0x46f0, 0x579: 0x4781, 0x57a: 0x303b, 0x57b: 0x3347,
+	0x57c: 0x3027, 0x57d: 0x3333, 0x57e: 0x3915, 0x57f: 0x3aa4,
+	// Block 0x16, offset 0x580
+	0x580: 0x390e, 0x581: 0x3a9d, 0x582: 0x3923, 0x583: 0x3ab2, 0x584: 0x391c, 0x585: 0x3aab,
+	0x586: 0x3938, 0x587: 0x3ac7, 0x588: 0x30cc, 0x589: 0x33d8, 0x58a: 0x30e0, 0x58b: 0x33ec,
+	0x58c: 0x4722, 0x58d: 0x47b3, 0x58e: 0x3171, 0x58f: 0x3482, 0x590: 0x395b, 0x591: 0x3aea,
+	0x592: 0x3954, 0x593: 0x3ae3, 0x594: 0x3969, 0x595: 0x3af8, 0x596: 0x3962, 0x597: 0x3af1,
+	0x598: 0x39c4, 0x599: 0x3b53, 0x59a: 0x39a8, 0x59b: 0x3b37, 0x59c: 0x39a1, 0x59d: 0x3b30,
+	0x59e: 0x39b6, 0x59f: 0x3b45, 0x5a0: 0x39af, 0x5a1: 0x3b3e, 0x5a2: 0x39bd, 0x5a3: 0x3b4c,
+	0x5a4: 0x3220, 0x5a5: 0x3536, 0x5a6: 0x3202, 0x5a7: 0x3518, 0x5a8: 0x3a1f, 0x5a9: 0x3bae,
+	0x5aa: 0x3a18, 0x5ab: 0x3ba7, 0x5ac: 0x3a2d, 0x5ad: 0x3bbc, 0x5ae: 0x3a26, 0x5af: 0x3bb5,
+	0x5b0: 0x3a34, 0x5b1: 0x3bc3, 0x5b2: 0x326b, 0x5b3: 0x3586, 0x5b4: 0x3293, 0x5b5: 0x35b3,
+	0x5b6: 0x328e, 0x5b7: 0x35a9, 0x5b8: 0x327a, 0x5b9: 0x3595,
+	// Block 0x17, offset 0x5c0
+	0x5c0: 0x483f, 0x5c1: 0x4845, 0x5c2: 0x4959, 0x5c3: 0x4971, 0x5c4: 0x4961, 0x5c5: 0x4979,
+	0x5c6: 0x4969, 0x5c7: 0x4981, 0x5c8: 0x47e5, 0x5c9: 0x47eb, 0x5ca: 0x48c9, 0x5cb: 0x48e1,
+	0x5cc: 0x48d1, 0x5cd: 0x48e9, 0x5ce: 0x48d9, 0x5cf: 0x48f1, 0x5d0: 0x4851, 0x5d1: 0x4857,
+	0x5d2: 0x3df3, 0x5d3: 0x3e03, 0x5d4: 0x3dfb, 0x5d5: 0x3e0b,
+	0x5d8: 0x47f1, 0x5d9: 0x47f7, 0x5da: 0x3d23, 0x5db: 0x3d33, 0x5dc: 0x3d2b, 0x5dd: 0x3d3b,
+	0x5e0: 0x4869, 0x5e1: 0x486f, 0x5e2: 0x4989, 0x5e3: 0x49a1,
+	0x5e4: 0x4991, 0x5e5: 0x49a9, 0x5e6: 0x4999, 0x5e7: 0x49b1, 0x5e8: 0x47fd, 0x5e9: 0x4803,
+	0x5ea: 0x48f9, 0x5eb: 0x4911, 0x5ec: 0x4901, 0x5ed: 0x4919, 0x5ee: 0x4909, 0x5ef: 0x4921,
+	0x5f0: 0x4881, 0x5f1: 0x4887, 0x5f2: 0x3e53, 0x5f3: 0x3e6b, 0x5f4: 0x3e5b, 0x5f5: 0x3e73,
+	0x5f6: 0x3e63, 0x5f7: 0x3e7b, 0x5f8: 0x4809, 0x5f9: 0x480f, 0x5fa: 0x3d53, 0x5fb: 0x3d6b,
+	0x5fc: 0x3d5b, 0x5fd: 0x3d73, 0x5fe: 0x3d63, 0x5ff: 0x3d7b,
+	// Block 0x18, offset 0x600
+	0x600: 0x488d, 0x601: 0x4893, 0x602: 0x3e83, 0x603: 0x3e93, 0x604: 0x3e8b, 0x605: 0x3e9b,
+	0x608: 0x4815, 0x609: 0x481b, 0x60a: 0x3d83, 0x60b: 0x3d93,
+	0x60c: 0x3d8b, 0x60d: 0x3d9b, 0x610: 0x489f, 0x611: 0x48a5,
+	0x612: 0x3ebb, 0x613: 0x3ed3, 0x614: 0x3ec3, 0x615: 0x3edb, 0x616: 0x3ecb, 0x617: 0x3ee3,
+	0x619: 0x4821, 0x61b: 0x3da3, 0x61d: 0x3dab,
+	0x61f: 0x3db3, 0x620: 0x48b7, 0x621: 0x48bd, 0x622: 0x49b9, 0x623: 0x49d1,
+	0x624: 0x49c1, 0x625: 0x49d9, 0x626: 0x49c9, 0x627: 0x49e1, 0x628: 0x4827, 0x629: 0x482d,
+	0x62a: 0x4929, 0x62b: 0x4941, 0x62c: 0x4931, 0x62d: 0x4949, 0x62e: 0x4939, 0x62f: 0x4951,
+	0x630: 0x4833, 0x631: 0x4359, 0x632: 0x36cc, 0x633: 0x435f, 0x634: 0x485d, 0x635: 0x4365,
+	0x636: 0x36de, 0x637: 0x436b, 0x638: 0x36fc, 0x639: 0x4371, 0x63a: 0x3714, 0x63b: 0x4377,
+	0x63c: 0x48ab, 0x63d: 0x437d,
+	// Block 0x19, offset 0x640
+	0x640: 0x3ddb, 0x641: 0x3de3, 0x642: 0x41bf, 0x643: 0x41dd, 0x644: 0x41c9, 0x645: 0x41e7,
+	0x646: 0x41d3, 0x647: 0x41f1, 0x648: 0x3d13, 0x649: 0x3d1b, 0x64a: 0x410b, 0x64b: 0x4129,
+	0x64c: 0x4115, 0x64d: 0x4133, 0x64e: 0x411f, 0x64f: 0x413d, 0x650: 0x3e23, 0x651: 0x3e2b,
+	0x652: 0x41fb, 0x653: 0x4219, 0x654: 0x4205, 0x655: 0x4223, 0x656: 0x420f, 0x657: 0x422d,
+	0x658: 0x3d43, 0x659: 0x3d4b, 0x65a: 0x4147, 0x65b: 0x4165, 0x65c: 0x4151, 0x65d: 0x416f,
+	0x65e: 0x415b, 0x65f: 0x4179, 0x660: 0x3efb, 0x661: 0x3f03, 0x662: 0x4237, 0x663: 0x4255,
+	0x664: 0x4241, 0x665: 0x425f, 0x666: 0x424b, 0x667: 0x4269, 0x668: 0x3dbb, 0x669: 0x3dc3,
+	0x66a: 0x4183, 0x66b: 0x41a1, 0x66c: 0x418d, 0x66d: 0x41ab, 0x66e: 0x4197, 0x66f: 0x41b5,
+	0x670: 0x36c0, 0x671: 0x36ba, 0x672: 0x3dcb, 0x673: 0x36c6, 0x674: 0x3dd3,
+	0x676: 0x484b, 0x677: 0x3deb, 0x678: 0x3630, 0x679: 0x362a, 0x67a: 0x361e, 0x67b: 0x4329,
+	0x67c: 0x3636, 0x67d: 0x42c2, 0x67e: 0x01d3, 0x67f: 0x42c2,
+	// Block 0x1a, offset 0x680
+	0x680: 0x42db, 0x681: 0x44bd, 0x682: 0x3e13, 0x683: 0x36d8, 0x684: 0x3e1b,
+	0x686: 0x4875, 0x687: 0x3e33, 0x688: 0x363c, 0x689: 0x432f, 0x68a: 0x3648, 0x68b: 0x4335,
+	0x68c: 0x3654, 0x68d: 0x44c4, 0x68e: 0x44cb, 0x68f: 0x44d2, 0x690: 0x36f0, 0x691: 0x36ea,
+	0x692: 0x3e3b, 0x693: 0x451f, 0x696: 0x36f6, 0x697: 0x3e4b,
+	0x698: 0x366c, 0x699: 0x3666, 0x69a: 0x365a, 0x69b: 0x433b, 0x69d: 0x44d9,
+	0x69e: 0x44e0, 0x69f: 0x44e7, 0x6a0: 0x3726, 0x6a1: 0x3720, 0x6a2: 0x3ea3, 0x6a3: 0x4527,
+	0x6a4: 0x3708, 0x6a5: 0x370e, 0x6a6: 0x372c, 0x6a7: 0x3eb3, 0x6a8: 0x369c, 0x6a9: 0x3696,
+	0x6aa: 0x368a, 0x6ab: 0x4347, 0x6ac: 0x3684, 0x6ad: 0x44af, 0x6ae: 0x44b6, 0x6af: 0x0081,
+	0x6b2: 0x3eeb, 0x6b3: 0x3732, 0x6b4: 0x3ef3,
+	0x6b6: 0x48c3, 0x6b7: 0x3f0b, 0x6b8: 0x3678, 0x6b9: 0x4341, 0x6ba: 0x36a8, 0x6bb: 0x4353,
+	0x6bc: 0x36b4, 0x6bd: 0x4295, 0x6be: 0x42c7,
+	// Block 0x1b, offset 0x6c0
+	0x6c0: 0x1d6b, 0x6c1: 0x1d6f, 0x6c2: 0x0047, 0x6c3: 0x1de7, 0x6c5: 0x1d7b,
+	0x6c6: 0x1d7f, 0x6c7: 0x00e9, 0x6c9: 0x1deb, 0x6ca: 0x008f, 0x6cb: 0x0051,
+	0x6cc: 0x0051, 0x6cd: 0x0051, 0x6ce: 0x0091, 0x6cf: 0x00da, 0x6d0: 0x0053, 0x6d1: 0x0053,
+	0x6d2: 0x0059, 0x6d3: 0x0099, 0x6d5: 0x005d, 0x6d6: 0x1b20,
+	0x6d9: 0x0061, 0x6da: 0x0063, 0x6db: 0x0065, 0x6dc: 0x0065, 0x6dd: 0x0065,
+	0x6e0: 0x1b32, 0x6e1: 0x1d5b, 0x6e2: 0x1b3b,
+	0x6e4: 0x0075, 0x6e6: 0x01b8, 0x6e8: 0x0075,
+	0x6ea: 0x0057, 0x6eb: 0x430d, 0x6ec: 0x0045, 0x6ed: 0x0047, 0x6ef: 0x008b,
+	0x6f0: 0x004b, 0x6f1: 0x004d, 0x6f3: 0x005b, 0x6f4: 0x009f, 0x6f5: 0x0215,
+	0x6f6: 0x0218, 0x6f7: 0x021b, 0x6f8: 0x021e, 0x6f9: 0x0093, 0x6fb: 0x1d2b,
+	0x6fc: 0x01e8, 0x6fd: 0x01c1, 0x6fe: 0x0179, 0x6ff: 0x01a0,
+	// Block 0x1c, offset 0x700
+	0x700: 0x04db, 0x705: 0x0049,
+	0x706: 0x0089, 0x707: 0x008b, 0x708: 0x0093, 0x709: 0x0095,
+	0x710: 0x23c1, 0x711: 0x23cd,
+	0x712: 0x2481, 0x713: 0x23a9, 0x714: 0x242d, 0x715: 0x23b5, 0x716: 0x2433, 0x717: 0x244b,
+	0x718: 0x2457, 0x719: 0x23bb, 0x71a: 0x245d, 0x71b: 0x23c7, 0x71c: 0x2451, 0x71d: 0x2463,
+	0x71e: 0x2469, 0x71f: 0x1e4f, 0x720: 0x0053, 0x721: 0x1aed, 0x722: 0x1d37, 0x723: 0x1af6,
+	0x724: 0x006d, 0x725: 0x1b3e, 0x726: 0x1d63, 0x727: 0x1edb, 0x728: 0x1af9, 0x729: 0x0071,
+	0x72a: 0x1b4a, 0x72b: 0x1d67, 0x72c: 0x0059, 0x72d: 0x0047, 0x72e: 0x0049, 0x72f: 0x005b,
+	0x730: 0x0093, 0x731: 0x1b77, 0x732: 0x1dab, 0x733: 0x1b80, 0x734: 0x00ad, 0x735: 0x1bf5,
+	0x736: 0x1ddf, 0x737: 0x1eef, 0x738: 0x1b83, 0x739: 0x00b1, 0x73a: 0x1bf8, 0x73b: 0x1de3,
+	0x73c: 0x0099, 0x73d: 0x0087, 0x73e: 0x0089, 0x73f: 0x009b,
+	// Block 0x1d, offset 0x740
+	0x741: 0x3c41, 0x743: 0xa000, 0x744: 0x3c48, 0x745: 0xa000,
+	0x747: 0x3c4f, 0x748: 0xa000, 0x749: 0x3c56,
+	0x74d: 0xa000,
+	0x760: 0x2fa0, 0x761: 0xa000, 0x762: 0x3c64,
+	0x764: 0xa000, 0x765: 0xa000,
+	0x76d: 0x3c5d, 0x76e: 0x2f9b, 0x76f: 0x2fa5,
+	0x770: 0x3c6b, 0x771: 0x3c72, 0x772: 0xa000, 0x773: 0xa000, 0x774: 0x3c79, 0x775: 0x3c80,
+	0x776: 0xa000, 0x777: 0xa000, 0x778: 0x3c87, 0x779: 0x3c8e, 0x77a: 0xa000, 0x77b: 0xa000,
+	0x77c: 0xa000, 0x77d: 0xa000,
+	// Block 0x1e, offset 0x780
+	0x780: 0x3c95, 0x781: 0x3c9c, 0x782: 0xa000, 0x783: 0xa000, 0x784: 0x3cb1, 0x785: 0x3cb8,
+	0x786: 0xa000, 0x787: 0xa000, 0x788: 0x3cbf, 0x789: 0x3cc6,
+	0x791: 0xa000,
+	0x792: 0xa000,
+	0x7a2: 0xa000,
+	0x7a8: 0xa000, 0x7a9: 0xa000,
+	0x7ab: 0xa000, 0x7ac: 0x3cdb, 0x7ad: 0x3ce2, 0x7ae: 0x3ce9, 0x7af: 0x3cf0,
+	0x7b2: 0xa000, 0x7b3: 0xa000, 0x7b4: 0xa000, 0x7b5: 0xa000,
+	// Block 0x1f, offset 0x7c0
+	0x7e0: 0x0023, 0x7e1: 0x0025, 0x7e2: 0x0027, 0x7e3: 0x0029,
+	0x7e4: 0x002b, 0x7e5: 0x002d, 0x7e6: 0x002f, 0x7e7: 0x0031, 0x7e8: 0x0033, 0x7e9: 0x1a15,
+	0x7ea: 0x1a18, 0x7eb: 0x1a1b, 0x7ec: 0x1a1e, 0x7ed: 0x1a21, 0x7ee: 0x1a24, 0x7ef: 0x1a27,
+	0x7f0: 0x1a2a, 0x7f1: 0x1a2d, 0x7f2: 0x1a30, 0x7f3: 0x1a39, 0x7f4: 0x1bfb, 0x7f5: 0x1bff,
+	0x7f6: 0x1c03, 0x7f7: 0x1c07, 0x7f8: 0x1c0b, 0x7f9: 0x1c0f, 0x7fa: 0x1c13, 0x7fb: 0x1c17,
+	0x7fc: 0x1c1b, 0x7fd: 0x1e13, 0x7fe: 0x1e18, 0x7ff: 0x1e1d,
+	// Block 0x20, offset 0x800
+	0x800: 0x1e22, 0x801: 0x1e27, 0x802: 0x1e2c, 0x803: 0x1e31, 0x804: 0x1e36, 0x805: 0x1e3b,
+	0x806: 0x1e40, 0x807: 0x1e45, 0x808: 0x1a12, 0x809: 0x1a36, 0x80a: 0x1a5a, 0x80b: 0x1a7e,
+	0x80c: 0x1aa2, 0x80d: 0x1aab, 0x80e: 0x1ab1, 0x80f: 0x1ab7, 0x810: 0x1abd, 0x811: 0x1cf3,
+	0x812: 0x1cf7, 0x813: 0x1cfb, 0x814: 0x1cff, 0x815: 0x1d03, 0x816: 0x1d07, 0x817: 0x1d0b,
+	0x818: 0x1d0f, 0x819: 0x1d13, 0x81a: 0x1d17, 0x81b: 0x1d1b, 0x81c: 0x1c87, 0x81d: 0x1c8b,
+	0x81e: 0x1c8f, 0x81f: 0x1c93, 0x820: 0x1c97, 0x821: 0x1c9b, 0x822: 0x1c9f, 0x823: 0x1ca3,
+	0x824: 0x1ca7, 0x825: 0x1cab, 0x826: 0x1caf, 0x827: 0x1cb3, 0x828: 0x1cb7, 0x829: 0x1cbb,
+	0x82a: 0x1cbf, 0x82b: 0x1cc3, 0x82c: 0x1cc7, 0x82d: 0x1ccb, 0x82e: 0x1ccf, 0x82f: 0x1cd3,
+	0x830: 0x1cd7, 0x831: 0x1cdb, 0x832: 0x1cdf, 0x833: 0x1ce3, 0x834: 0x1ce7, 0x835: 0x1ceb,
+	0x836: 0x0043, 0x837: 0x0045, 0x838: 0x0047, 0x839: 0x0049, 0x83a: 0x004b, 0x83b: 0x004d,
+	0x83c: 0x004f, 0x83d: 0x0051, 0x83e: 0x0053, 0x83f: 0x0055,
+	// Block 0x21, offset 0x840
+	0x840: 0x0737, 0x841: 0x075b, 0x842: 0x0767, 0x843: 0x0777, 0x844: 0x077f, 0x845: 0x078b,
+	0x846: 0x0793, 0x847: 0x079b, 0x848: 0x07a7, 0x849: 0x07fb, 0x84a: 0x0813, 0x84b: 0x0823,
+	0x84c: 0x0833, 0x84d: 0x0843, 0x84e: 0x0853, 0x84f: 0x0873, 0x850: 0x0877, 0x851: 0x087b,
+	0x852: 0x08af, 0x853: 0x08d7, 0x854: 0x08e7, 0x855: 0x08ef, 0x856: 0x08f3, 0x857: 0x08ff,
+	0x858: 0x091b, 0x859: 0x091f, 0x85a: 0x0937, 0x85b: 0x093b, 0x85c: 0x0943, 0x85d: 0x0953,
+	0x85e: 0x09ef, 0x85f: 0x0a03, 0x860: 0x0a43, 0x861: 0x0a57, 0x862: 0x0a5f, 0x863: 0x0a63,
+	0x864: 0x0a73, 0x865: 0x0a8f, 0x866: 0x0abb, 0x867: 0x0ac7, 0x868: 0x0ae7, 0x869: 0x0af3,
+	0x86a: 0x0af7, 0x86b: 0x0afb, 0x86c: 0x0b13, 0x86d: 0x0b17, 0x86e: 0x0b43, 0x86f: 0x0b4f,
+	0x870: 0x0b57, 0x871: 0x0b5f, 0x872: 0x0b6f, 0x873: 0x0b77, 0x874: 0x0b7f, 0x875: 0x0bab,
+	0x876: 0x0baf, 0x877: 0x0bb7, 0x878: 0x0bbb, 0x879: 0x0bc3, 0x87a: 0x0bcb, 0x87b: 0x0bdb,
+	0x87c: 0x0bf7, 0x87d: 0x0c6f, 0x87e: 0x0c83, 0x87f: 0x0c87,
+	// Block 0x22, offset 0x880
+	0x880: 0x0d07, 0x881: 0x0d0b, 0x882: 0x0d1f, 0x883: 0x0d23, 0x884: 0x0d2b, 0x885: 0x0d33,
+	0x886: 0x0d3b, 0x887: 0x0d47, 0x888: 0x0d6f, 0x889: 0x0d7f, 0x88a: 0x0d93, 0x88b: 0x0e03,
+	0x88c: 0x0e0f, 0x88d: 0x0e1f, 0x88e: 0x0e2b, 0x88f: 0x0e37, 0x890: 0x0e3f, 0x891: 0x0e43,
+	0x892: 0x0e47, 0x893: 0x0e4b, 0x894: 0x0e4f, 0x895: 0x0f07, 0x896: 0x0f4f, 0x897: 0x0f5b,
+	0x898: 0x0f5f, 0x899: 0x0f63, 0x89a: 0x0f67, 0x89b: 0x0f6f, 0x89c: 0x0f73, 0x89d: 0x0f87,
+	0x89e: 0x0fa3, 0x89f: 0x0fab, 0x8a0: 0x0feb, 0x8a1: 0x0fef, 0x8a2: 0x0ff7, 0x8a3: 0x0ffb,
+	0x8a4: 0x1003, 0x8a5: 0x1007, 0x8a6: 0x102b, 0x8a7: 0x102f, 0x8a8: 0x104b, 0x8a9: 0x104f,
+	0x8aa: 0x1053, 0x8ab: 0x1057, 0x8ac: 0x106b, 0x8ad: 0x108f, 0x8ae: 0x1093, 0x8af: 0x1097,
+	0x8b0: 0x10bb, 0x8b1: 0x10fb, 0x8b2: 0x10ff, 0x8b3: 0x111f, 0x8b4: 0x112f, 0x8b5: 0x1137,
+	0x8b6: 0x1157, 0x8b7: 0x117b, 0x8b8: 0x11bf, 0x8b9: 0x11c7, 0x8ba: 0x11db, 0x8bb: 0x11e7,
+	0x8bc: 0x11ef, 0x8bd: 0x11f7, 0x8be: 0x11fb, 0x8bf: 0x11ff,
+	// Block 0x23, offset 0x8c0
+	0x8c0: 0x1217, 0x8c1: 0x121b, 0x8c2: 0x1237, 0x8c3: 0x123f, 0x8c4: 0x1247, 0x8c5: 0x124b,
+	0x8c6: 0x1257, 0x8c7: 0x125f, 0x8c8: 0x1263, 0x8c9: 0x1267, 0x8ca: 0x126f, 0x8cb: 0x1273,
+	0x8cc: 0x1313, 0x8cd: 0x1327, 0x8ce: 0x135b, 0x8cf: 0x135f, 0x8d0: 0x1367, 0x8d1: 0x1393,
+	0x8d2: 0x139b, 0x8d3: 0x13a3, 0x8d4: 0x13ab, 0x8d5: 0x13e7, 0x8d6: 0x13eb, 0x8d7: 0x13f3,
+	0x8d8: 0x13f7, 0x8d9: 0x13fb, 0x8da: 0x1427, 0x8db: 0x142b, 0x8dc: 0x1433, 0x8dd: 0x1447,
+	0x8de: 0x144b, 0x8df: 0x1467, 0x8e0: 0x146f, 0x8e1: 0x1473, 0x8e2: 0x1497, 0x8e3: 0x14b7,
+	0x8e4: 0x14c7, 0x8e5: 0x14cb, 0x8e6: 0x14d3, 0x8e7: 0x14ff, 0x8e8: 0x1503, 0x8e9: 0x1513,
+	0x8ea: 0x1537, 0x8eb: 0x1543, 0x8ec: 0x1553, 0x8ed: 0x156b, 0x8ee: 0x1573, 0x8ef: 0x1577,
+	0x8f0: 0x157b, 0x8f1: 0x157f, 0x8f2: 0x158b, 0x8f3: 0x158f, 0x8f4: 0x1597, 0x8f5: 0x15b3,
+	0x8f6: 0x15b7, 0x8f7: 0x15bb, 0x8f8: 0x15d3, 0x8f9: 0x15d7, 0x8fa: 0x15df, 0x8fb: 0x15f3,
+	0x8fc: 0x15f7, 0x8fd: 0x15fb, 0x8fe: 0x1603, 0x8ff: 0x1607,
+	// Block 0x24, offset 0x900
+	0x906: 0xa000, 0x90b: 0xa000,
+	0x90c: 0x3f43, 0x90d: 0xa000, 0x90e: 0x3f4b, 0x90f: 0xa000, 0x910: 0x3f53, 0x911: 0xa000,
+	0x912: 0x3f5b, 0x913: 0xa000, 0x914: 0x3f63, 0x915: 0xa000, 0x916: 0x3f6b, 0x917: 0xa000,
+	0x918: 0x3f73, 0x919: 0xa000, 0x91a: 0x3f7b, 0x91b: 0xa000, 0x91c: 0x3f83, 0x91d: 0xa000,
+	0x91e: 0x3f8b, 0x91f: 0xa000, 0x920: 0x3f93, 0x921: 0xa000, 0x922: 0x3f9b,
+	0x924: 0xa000, 0x925: 0x3fa3, 0x926: 0xa000, 0x927: 0x3fab, 0x928: 0xa000, 0x929: 0x3fb3,
+	0x92f: 0xa000,
+	0x930: 0x3fbb, 0x931: 0x3fc3, 0x932: 0xa000, 0x933: 0x3fcb, 0x934: 0x3fd3, 0x935: 0xa000,
+	0x936: 0x3fdb, 0x937: 0x3fe3, 0x938: 0xa000, 0x939: 0x3feb, 0x93a: 0x3ff3, 0x93b: 0xa000,
+	0x93c: 0x3ffb, 0x93d: 0x4003,
+	// Block 0x25, offset 0x940
+	0x954: 0x3f3b,
+	0x959: 0x9903, 0x95a: 0x9903, 0x95b: 0x4317, 0x95c: 0x431d, 0x95d: 0xa000,
+	0x95e: 0x400b, 0x95f: 0x28b0,
+	0x966: 0xa000,
+	0x96b: 0xa000, 0x96c: 0x401b, 0x96d: 0xa000, 0x96e: 0x4023, 0x96f: 0xa000,
+	0x970: 0x402b, 0x971: 0xa000, 0x972: 0x4033, 0x973: 0xa000, 0x974: 0x403b, 0x975: 0xa000,
+	0x976: 0x4043, 0x977: 0xa000, 0x978: 0x404b, 0x979: 0xa000, 0x97a: 0x4053, 0x97b: 0xa000,
+	0x97c: 0x405b, 0x97d: 0xa000, 0x97e: 0x4063, 0x97f: 0xa000,
+	// Block 0x26, offset 0x980
+	0x980: 0x406b, 0x981: 0xa000, 0x982: 0x4073, 0x984: 0xa000, 0x985: 0x407b,
+	0x986: 0xa000, 0x987: 0x4083, 0x988: 0xa000, 0x989: 0x408b,
+	0x98f: 0xa000, 0x990: 0x4093, 0x991: 0x409b,
+	0x992: 0xa000, 0x993: 0x40a3, 0x994: 0x40ab, 0x995: 0xa000, 0x996: 0x40b3, 0x997: 0x40bb,
+	0x998: 0xa000, 0x999: 0x40c3, 0x99a: 0x40cb, 0x99b: 0xa000, 0x99c: 0x40d3, 0x99d: 0x40db,
+	0x9af: 0xa000,
+	0x9b0: 0xa000, 0x9b1: 0xa000, 0x9b2: 0xa000, 0x9b4: 0x4013,
+	0x9b7: 0x40e3, 0x9b8: 0x40eb, 0x9b9: 0x40f3, 0x9ba: 0x40fb,
+	0x9bd: 0xa000, 0x9be: 0x4103, 0x9bf: 0x28c5,
+	// Block 0x27, offset 0x9c0
+	0x9c0: 0x03af, 0x9c1: 0x03b3, 0x9c2: 0x0483, 0x9c3: 0x0487, 0x9c4: 0x03b7, 0x9c5: 0x03bb,
+	0x9c6: 0x03bf, 0x9c7: 0x041b, 0x9c8: 0x041f, 0x9c9: 0x0423, 0x9ca: 0x0427, 0x9cb: 0x042b,
+	0x9cc: 0x042f, 0x9cd: 0x0433, 0x9ce: 0x0437,
+	0x9d2: 0x0737, 0x9d3: 0x0793, 0x9d4: 0x0743, 0x9d5: 0x09f3, 0x9d6: 0x0747, 0x9d7: 0x075f,
+	0x9d8: 0x074b, 0x9d9: 0x100b, 0x9da: 0x077f, 0x9db: 0x0753, 0x9dc: 0x073b, 0x9dd: 0x0a77,
+	0x9de: 0x0a07, 0x9df: 0x07a7,
+	// Block 0x28, offset 0xa00
+	0xa00: 0x21e7, 0xa01: 0x21ed, 0xa02: 0x21f3, 0xa03: 0x21f9, 0xa04: 0x21ff, 0xa05: 0x2205,
+	0xa06: 0x220b, 0xa07: 0x2211, 0xa08: 0x2217, 0xa09: 0x221d, 0xa0a: 0x2223, 0xa0b: 0x2229,
+	0xa0c: 0x222f, 0xa0d: 0x2235, 0xa0e: 0x2922, 0xa0f: 0x292b, 0xa10: 0x2934, 0xa11: 0x293d,
+	0xa12: 0x2946, 0xa13: 0x294f, 0xa14: 0x2958, 0xa15: 0x2961, 0xa16: 0x296a, 0xa17: 0x297c,
+	0xa18: 0x2985, 0xa19: 0x298e, 0xa1a: 0x2997, 0xa1b: 0x29a0, 0xa1c: 0x2973, 0xa1d: 0x2dc5,
+	0xa1e: 0x2cf6, 0xa20: 0x223b, 0xa21: 0x2253, 0xa22: 0x2247, 0xa23: 0x229b,
+	0xa24: 0x2259, 0xa25: 0x2277, 0xa26: 0x2241, 0xa27: 0x2271, 0xa28: 0x224d, 0xa29: 0x2283,
+	0xa2a: 0x22b3, 0xa2b: 0x22d1, 0xa2c: 0x22cb, 0xa2d: 0x22bf, 0xa2e: 0x230d, 0xa2f: 0x22a1,
+	0xa30: 0x22ad, 0xa31: 0x22c5, 0xa32: 0x22b9, 0xa33: 0x22e3, 0xa34: 0x228f, 0xa35: 0x22d7,
+	0xa36: 0x2301, 0xa37: 0x22e9, 0xa38: 0x227d, 0xa39: 0x225f, 0xa3a: 0x2295, 0xa3b: 0x22a7,
+	0xa3c: 0x22dd, 0xa3d: 0x2265, 0xa3e: 0x2307, 0xa3f: 0x2289,
+	// Block 0x29, offset 0xa40
+	0xa40: 0x22ef, 0xa41: 0x226b, 0xa42: 0x22f5, 0xa43: 0x22fb, 0xa44: 0x09a7, 0xa45: 0x0b7b,
+	0xa46: 0x0d1f, 0xa47: 0x113f,
+	0xa50: 0x1d57, 0xa51: 0x1a3c,
+	0xa52: 0x1a3f, 0xa53: 0x1a42, 0xa54: 0x1a45, 0xa55: 0x1a48, 0xa56: 0x1a4b, 0xa57: 0x1a4e,
+	0xa58: 0x1a51, 0xa59: 0x1a54, 0xa5a: 0x1a5d, 0xa5b: 0x1a60, 0xa5c: 0x1a63, 0xa5d: 0x1a66,
+	0xa5e: 0x1a69, 0xa5f: 0x1a6c, 0xa60: 0x0313, 0xa61: 0x031b, 0xa62: 0x031f, 0xa63: 0x0327,
+	0xa64: 0x032b, 0xa65: 0x032f, 0xa66: 0x0337, 0xa67: 0x033f, 0xa68: 0x0343, 0xa69: 0x034b,
+	0xa6a: 0x034f, 0xa6b: 0x0353, 0xa6c: 0x0357, 0xa6d: 0x035b, 0xa6e: 0x2824, 0xa6f: 0x282b,
+	0xa70: 0x2832, 0xa71: 0x2839, 0xa72: 0x2840, 0xa73: 0x2847, 0xa74: 0x284e, 0xa75: 0x2855,
+	0xa76: 0x2863, 0xa77: 0x286a, 0xa78: 0x2871, 0xa79: 0x2878, 0xa7a: 0x287f, 0xa7b: 0x2886,
+	0xa7c: 0x2d15, 0xa7d: 0x2b8a, 0xa7e: 0x285c,
+	// Block 0x2a, offset 0xa80
+	0xa80: 0x0737, 0xa81: 0x0793, 0xa82: 0x0743, 0xa83: 0x09f3, 0xa84: 0x0797, 0xa85: 0x0827,
+	0xa86: 0x073f, 0xa87: 0x0823, 0xa88: 0x0783, 0xa89: 0x08ff, 0xa8a: 0x0d7f, 0xa8b: 0x0f07,
+	0xa8c: 0x0e4f, 0xa8d: 0x0d93, 0xa8e: 0x14d3, 0xa8f: 0x0a03, 0xa90: 0x0d47, 0xa91: 0x0dc3,
+	0xa92: 0x0d83, 0xa93: 0x10c3, 0xa94: 0x0973, 0xa95: 0x0f7b, 0xa96: 0x13ff, 0xa97: 0x10d7,
+	0xa98: 0x08bb, 0xa99: 0x1107, 0xa9a: 0x1013, 0xa9b: 0x0a8f, 0xa9c: 0x1487, 0xa9d: 0x07f7,
+	0xa9e: 0x0923, 0xa9f: 0x0e6f, 0xaa0: 0x159b, 0xaa1: 0x07bb, 0xaa2: 0x084b, 0xaa3: 0x0e13,
+	0xaa4: 0x0747, 0xaa5: 0x075f, 0xaa6: 0x074b, 0xaa7: 0x0b53, 0xaa8: 0x0967, 0xaa9: 0x08f7,
+	0xaaa: 0x0acf, 0xaab: 0x0ac3, 0xaac: 0x1063, 0xaad: 0x07b7, 0xaae: 0x1413, 0xaaf: 0x0913,
+	0xab0: 0x0a6b, 0xab1: 0x1a6f, 0xab2: 0x1a72, 0xab3: 0x1a75, 0xab4: 0x1a78, 0xab5: 0x1a81,
+	0xab6: 0x1a84, 0xab7: 0x1a87, 0xab8: 0x1a8a, 0xab9: 0x1a8d, 0xaba: 0x1a90, 0xabb: 0x1a93,
+	0xabc: 0x1a96, 0xabd: 0x1a99, 0xabe: 0x1a9c, 0xabf: 0x1aa5,
+	// Block 0x2b, offset 0xac0
+	0xac0: 0x1e59, 0xac1: 0x1e68, 0xac2: 0x1e77, 0xac3: 0x1e86, 0xac4: 0x1e95, 0xac5: 0x1ea4,
+	0xac6: 0x1eb3, 0xac7: 0x1ec2, 0xac8: 0x1ed1, 0xac9: 0x231f, 0xaca: 0x2331, 0xacb: 0x2343,
+	0xacc: 0x1ae7, 0xacd: 0x1d97, 0xace: 0x1b65, 0xacf: 0x1d3b, 0xad0: 0x0543, 0xad1: 0x054b,
+	0xad2: 0x0553, 0xad3: 0x055b, 0xad4: 0x0563, 0xad5: 0x0567, 0xad6: 0x056b, 0xad7: 0x056f,
+	0xad8: 0x0573, 0xad9: 0x0577, 0xada: 0x057b, 0xadb: 0x057f, 0xadc: 0x0583, 0xadd: 0x0587,
+	0xade: 0x058b, 0xadf: 0x058f, 0xae0: 0x0593, 0xae1: 0x059b, 0xae2: 0x059f, 0xae3: 0x05a3,
+	0xae4: 0x05a7, 0xae5: 0x05ab, 0xae6: 0x05af, 0xae7: 0x05b3, 0xae8: 0x05b7, 0xae9: 0x05bb,
+	0xaea: 0x05bf, 0xaeb: 0x05c3, 0xaec: 0x05c7, 0xaed: 0x05cb, 0xaee: 0x05cf, 0xaef: 0x05d3,
+	0xaf0: 0x05d7, 0xaf1: 0x05db, 0xaf2: 0x05df, 0xaf3: 0x05e7, 0xaf4: 0x05ef, 0xaf5: 0x05f7,
+	0xaf6: 0x05fb, 0xaf7: 0x05ff, 0xaf8: 0x0603, 0xaf9: 0x0607, 0xafa: 0x060b, 0xafb: 0x060f,
+	0xafc: 0x0613, 0xafd: 0x0617, 0xafe: 0x061b,
+	// Block 0x2c, offset 0xb00
+	0xb00: 0x2d25, 0xb01: 0x2bb1, 0xb02: 0x2d35, 0xb03: 0x2a7c, 0xb04: 0x2f2f, 0xb05: 0x2a86,
+	0xb06: 0x2a90, 0xb07: 0x2f73, 0xb08: 0x2bbe, 0xb09: 0x2a9a, 0xb0a: 0x2aa4, 0xb0b: 0x2aae,
+	0xb0c: 0x2be5, 0xb0d: 0x2bf2, 0xb0e: 0x2bcb, 0xb0f: 0x2bd8, 0xb10: 0x2f05, 0xb11: 0x2bff,
+	0xb12: 0x2c0c, 0xb13: 0x2dd7, 0xb14: 0x28b7, 0xb15: 0x2dea, 0xb16: 0x2dfd, 0xb17: 0x2d45,
+	0xb18: 0x2c19, 0xb19: 0x2e10, 0xb1a: 0x2e23, 0xb1b: 0x2c26, 0xb1c: 0x2ab8, 0xb1d: 0x2ac2,
+	0xb1e: 0x2f13, 0xb1f: 0x2c33, 0xb20: 0x2d55, 0xb21: 0x2f40, 0xb22: 0x2acc, 0xb23: 0x2ad6,
+	0xb24: 0x2c40, 0xb25: 0x2ae0, 0xb26: 0x2aea, 0xb27: 0x28cc, 0xb28: 0x28d3, 0xb29: 0x2af4,
+	0xb2a: 0x2afe, 0xb2b: 0x2e36, 0xb2c: 0x2c4d, 0xb2d: 0x2d65, 0xb2e: 0x2e49, 0xb2f: 0x2c5a,
+	0xb30: 0x2b12, 0xb31: 0x2b08, 0xb32: 0x2f87, 0xb33: 0x2c67, 0xb34: 0x2e5c, 0xb35: 0x2b1c,
+	0xb36: 0x2d75, 0xb37: 0x2b26, 0xb38: 0x2c81, 0xb39: 0x2b30, 0xb3a: 0x2c8e, 0xb3b: 0x2f51,
+	0xb3c: 0x2c74, 0xb3d: 0x2d85, 0xb3e: 0x2c9b, 0xb3f: 0x28da,
+	// Block 0x2d, offset 0xb40
+	0xb40: 0x2f62, 0xb41: 0x2b3a, 0xb42: 0x2b44, 0xb43: 0x2ca8, 0xb44: 0x2b4e, 0xb45: 0x2b58,
+	0xb46: 0x2b62, 0xb47: 0x2d95, 0xb48: 0x2cb5, 0xb49: 0x28e1, 0xb4a: 0x2e6f, 0xb4b: 0x2efa,
+	0xb4c: 0x2da5, 0xb4d: 0x2cc2, 0xb4e: 0x2f21, 0xb4f: 0x2b6c, 0xb50: 0x2b76, 0xb51: 0x2ccf,
+	0xb52: 0x28e8, 0xb53: 0x2cdc, 0xb54: 0x2db5, 0xb55: 0x28ef, 0xb56: 0x2e82, 0xb57: 0x2b80,
+	0xb58: 0x1e4a, 0xb59: 0x1e5e, 0xb5a: 0x1e6d, 0xb5b: 0x1e7c, 0xb5c: 0x1e8b, 0xb5d: 0x1e9a,
+	0xb5e: 0x1ea9, 0xb5f: 0x1eb8, 0xb60: 0x1ec7, 0xb61: 0x1ed6, 0xb62: 0x2325, 0xb63: 0x2337,
+	0xb64: 0x2349, 0xb65: 0x2355, 0xb66: 0x2361, 0xb67: 0x236d, 0xb68: 0x2379, 0xb69: 0x2385,
+	0xb6a: 0x2391, 0xb6b: 0x239d, 0xb6c: 0x23d9, 0xb6d: 0x23e5, 0xb6e: 0x23f1, 0xb6f: 0x23fd,
+	0xb70: 0x2409, 0xb71: 0x1da7, 0xb72: 0x1b59, 0xb73: 0x1ac9, 0xb74: 0x1d77, 0xb75: 0x1bda,
+	0xb76: 0x1be9, 0xb77: 0x1b5f, 0xb78: 0x1d8f, 0xb79: 0x1d93, 0xb7a: 0x1af3, 0xb7b: 0x28fd,
+	0xb7c: 0x290b, 0xb7d: 0x28f6, 0xb7e: 0x2904, 0xb7f: 0x2ce9,
+	// Block 0x2e, offset 0xb80
+	0xb80: 0x1bdd, 0xb81: 0x1bc5, 0xb82: 0x1df3, 0xb83: 0x1bad, 0xb84: 0x1b86, 0xb85: 0x1afc,
+	0xb86: 0x1b0b, 0xb87: 0x1adb, 0xb88: 0x1d83, 0xb89: 0x1ee5, 0xb8a: 0x1be0, 0xb8b: 0x1bc8,
+	0xb8c: 0x1df7, 0xb8d: 0x1e03, 0xb8e: 0x1bb9, 0xb8f: 0x1b8f, 0xb90: 0x1aea, 0xb91: 0x1daf,
+	0xb92: 0x1d43, 0xb93: 0x1d2f, 0xb94: 0x1d5f, 0xb95: 0x1e07, 0xb96: 0x1bbc, 0xb97: 0x1b5c,
+	0xb98: 0x1b92, 0xb99: 0x1b71, 0xb9a: 0x1bd4, 0xb9b: 0x1e0b, 0xb9c: 0x1bbf, 0xb9d: 0x1b53,
+	0xb9e: 0x1b95, 0xb9f: 0x1dcf, 0xba0: 0x1d87, 0xba1: 0x1ba7, 0xba2: 0x1db7, 0xba3: 0x1dd3,
+	0xba4: 0x1d8b, 0xba5: 0x1baa, 0xba6: 0x1dbb, 0xba7: 0x247b, 0xba8: 0x248f, 0xba9: 0x1b29,
+	0xbaa: 0x1db3, 0xbab: 0x1d47, 0xbac: 0x1d33, 0xbad: 0x1ddb, 0xbae: 0x2912, 0xbaf: 0x29a9,
+	0xbb0: 0x1bec, 0xbb1: 0x1bd7, 0xbb2: 0x1e0f, 0xbb3: 0x1bc2, 0xbb4: 0x1be3, 0xbb5: 0x1bcb,
+	0xbb6: 0x1dfb, 0xbb7: 0x1bb0, 0xbb8: 0x1b89, 0xbb9: 0x1b14, 0xbba: 0x1be6, 0xbbb: 0x1bce,
+	0xbbc: 0x1dff, 0xbbd: 0x1bb3, 0xbbe: 0x1b8c, 0xbbf: 0x1b17,
+	// Block 0x2f, offset 0xbc0
+	0xbc0: 0x1dbf, 0xbc1: 0x1d4b, 0xbc2: 0x1ee0, 0xbc3: 0x1acc, 0xbc4: 0x1b4d, 0xbc5: 0x1b50,
+	0xbc6: 0x2488, 0xbc7: 0x1d27, 0xbc8: 0x1b56, 0xbc9: 0x1ade, 0xbca: 0x1b74, 0xbcb: 0x1ae1,
+	0xbcc: 0x1b7d, 0xbcd: 0x1aff, 0xbce: 0x1b02, 0xbcf: 0x1b98, 0xbd0: 0x1b9e, 0xbd1: 0x1ba1,
+	0xbd2: 0x1dc3, 0xbd3: 0x1ba4, 0xbd4: 0x1bb6, 0xbd5: 0x1dcb, 0xbd6: 0x1dd7, 0xbd7: 0x1b23,
+	0xbd8: 0x1eea, 0xbd9: 0x1d4f, 0xbda: 0x1b26, 0xbdb: 0x1bef, 0xbdc: 0x1b38, 0xbdd: 0x1b47,
+	0xbde: 0x2475, 0xbdf: 0x246f, 0xbe0: 0x1e54, 0xbe1: 0x1e63, 0xbe2: 0x1e72, 0xbe3: 0x1e81,
+	0xbe4: 0x1e90, 0xbe5: 0x1e9f, 0xbe6: 0x1eae, 0xbe7: 0x1ebd, 0xbe8: 0x1ecc, 0xbe9: 0x2319,
+	0xbea: 0x232b, 0xbeb: 0x233d, 0xbec: 0x234f, 0xbed: 0x235b, 0xbee: 0x2367, 0xbef: 0x2373,
+	0xbf0: 0x237f, 0xbf1: 0x238b, 0xbf2: 0x2397, 0xbf3: 0x23d3, 0xbf4: 0x23df, 0xbf5: 0x23eb,
+	0xbf6: 0x23f7, 0xbf7: 0x2403, 0xbf8: 0x240f, 0xbf9: 0x2415, 0xbfa: 0x241b, 0xbfb: 0x2421,
+	0xbfc: 0x2427, 0xbfd: 0x2439, 0xbfe: 0x243f, 0xbff: 0x1da3,
+	// Block 0x30, offset 0xc00
+	0xc00: 0x13ef, 0xc01: 0x0d73, 0xc02: 0x144b, 0xc03: 0x1417, 0xc04: 0x0ecf, 0xc05: 0x0763,
+	0xc06: 0x0957, 0xc07: 0x169f, 0xc08: 0x169f, 0xc09: 0x0a83, 0xc0a: 0x14d3, 0xc0b: 0x09bb,
+	0xc0c: 0x0a7f, 0xc0d: 0x0c67, 0xc0e: 0x1047, 0xc0f: 0x11d7, 0xc10: 0x130f, 0xc11: 0x134b,
+	0xc12: 0x137f, 0xc13: 0x1493, 0xc14: 0x0deb, 0xc15: 0x0e77, 0xc16: 0x0f23, 0xc17: 0x0fbb,
+	0xc18: 0x12d7, 0xc19: 0x14bb, 0xc1a: 0x15e7, 0xc1b: 0x0787, 0xc1c: 0x092b, 0xc1d: 0x0dff,
+	0xc1e: 0x0f47, 0xc1f: 0x130b, 0xc20: 0x1637, 0xc21: 0x0b2b, 0xc22: 0x0eef, 0xc23: 0x12fb,
+	0xc24: 0x138f, 0xc25: 0x0c9b, 0xc26: 0x1233, 0xc27: 0x1357, 0xc28: 0x0b97, 0xc29: 0x0d87,
+	0xc2a: 0x0e8f, 0xc2b: 0x0f93, 0xc2c: 0x149f, 0xc2d: 0x07c7, 0xc2e: 0x085f, 0xc2f: 0x08cb,
+	0xc30: 0x0d03, 0xc31: 0x0df7, 0xc32: 0x0f43, 0xc33: 0x1067, 0xc34: 0x11ef, 0xc35: 0x1303,
+	0xc36: 0x131b, 0xc37: 0x143f, 0xc38: 0x1563, 0xc39: 0x1617, 0xc3a: 0x1633, 0xc3b: 0x10a3,
+	0xc3c: 0x10e3, 0xc3d: 0x119b, 0xc3e: 0x12bb, 0xc3f: 0x14ef,
+	// Block 0x31, offset 0xc40
+	0xc40: 0x163f, 0xc41: 0x13c3, 0xc42: 0x0a3f, 0xc43: 0x0bb3, 0xc44: 0x1153, 0xc45: 0x1213,
+	0xc46: 0x0f77, 0xc47: 0x10ab, 0xc48: 0x140f, 0xc49: 0x155b, 0xc4a: 0x0a3b, 0xc4b: 0x0b07,
+	0xc4c: 0x0def, 0xc4d: 0x0ea3, 0xc4e: 0x0ed7, 0xc4f: 0x118b, 0xc50: 0x11b3, 0xc51: 0x151b,
+	0xc52: 0x08c7, 0xc53: 0x121f, 0xc54: 0x086b, 0xc55: 0x0867, 0xc56: 0x110f, 0xc57: 0x119f,
+	0xc58: 0x12d3, 0xc59: 0x1523, 0xc5a: 0x13df, 0xc5b: 0x0c9f, 0xc5c: 0x0deb, 0xc5d: 0x13cf,
+	0xc5e: 0x076f, 0xc5f: 0x0adb, 0xc60: 0x0c0b, 0xc61: 0x0fa7, 0xc62: 0x1027, 0xc63: 0x08eb,
+	0xc64: 0x10b3, 0xc65: 0x07d7, 0xc66: 0x0bef, 0xc67: 0x074f, 0xc68: 0x0e63, 0xc69: 0x0d1b,
+	0xc6a: 0x1187, 0xc6b: 0x093f, 0xc6c: 0x0a2b, 0xc6d: 0x1073, 0xc6e: 0x12db, 0xc6f: 0x13b3,
+	0xc70: 0x0e2f, 0xc71: 0x146f, 0xc72: 0x0e5b, 0xc73: 0x0caf, 0xc74: 0x1293, 0xc75: 0x0ccf,
+	0xc76: 0x1023, 0xc77: 0x07a3, 0xc78: 0x081f, 0xc79: 0x0863, 0xc7a: 0x0dcb, 0xc7b: 0x1173,
+	0xc7c: 0x126b, 0xc7d: 0x13bf, 0xc7e: 0x14cf, 0xc7f: 0x08d3,
+	// Block 0x32, offset 0xc80
+	0xc80: 0x0987, 0xc81: 0x0a8f, 0xc82: 0x0ba7, 0xc83: 0x0d37, 0xc84: 0x0ef3, 0xc85: 0x10b7,
+	0xc86: 0x150b, 0xc87: 0x15ef, 0xc88: 0x1643, 0xc89: 0x165b, 0xc8a: 0x08af, 0xc8b: 0x0d6b,
+	0xc8c: 0x0e1b, 0xc8d: 0x1463, 0xc8e: 0x0b73, 0xc8f: 0x0c4f, 0xc90: 0x0c6b, 0xc91: 0x0cfb,
+	0xc92: 0x0ee3, 0xc93: 0x0f2f, 0xc94: 0x0fdf, 0xc95: 0x1103, 0xc96: 0x11a7, 0xc97: 0x120b,
+	0xc98: 0x1453, 0xc99: 0x12e3, 0xc9a: 0x147b, 0xc9b: 0x14f3, 0xc9c: 0x0887, 0xc9d: 0x08b3,
+	0xc9e: 0x099b, 0xc9f: 0x0f1f, 0xca0: 0x136b, 0xca1: 0x13b3, 0xca2: 0x0b93, 0xca3: 0x0c03,
+	0xca4: 0x0cc7, 0xca5: 0x0e27, 0xca6: 0x114f, 0xca7: 0x0f9b, 0xca8: 0x07b3, 0xca9: 0x09f7,
+	0xcaa: 0x0adb, 0xcab: 0x0b3f, 0xcac: 0x0c0f, 0xcad: 0x0fb7, 0xcae: 0x0fd3, 0xcaf: 0x11e3,
+	0xcb0: 0x1203, 0xcb1: 0x14d7, 0xcb2: 0x1557, 0xcb3: 0x1567, 0xcb4: 0x15a3, 0xcb5: 0x07cb,
+	0xcb6: 0x10f7, 0xcb7: 0x14c3, 0xcb8: 0x153f, 0xcb9: 0x0c27, 0xcba: 0x078f, 0xcbb: 0x07ef,
+	0xcbc: 0x0adf, 0xcbd: 0x0aff, 0xcbe: 0x0d27, 0xcbf: 0x0deb,
+	// Block 0x33, offset 0xcc0
+	0xcc0: 0x0f3b, 0xcc1: 0x1043, 0xcc2: 0x12ef, 0xcc3: 0x148f, 0xcc4: 0x1697, 0xcc5: 0x0d5b,
+	0xcc6: 0x1517, 0xcc7: 0x08ab, 0xcc8: 0x0da7, 0xcc9: 0x0db3, 0xcca: 0x0e87, 0xccb: 0x0ebf,
+	0xccc: 0x0fc3, 0xccd: 0x101f, 0xcce: 0x109f, 0xccf: 0x1183, 0xcd0: 0x15af, 0xcd1: 0x0827,
+	0xcd2: 0x0c7b, 0xcd3: 0x1527, 0xcd4: 0x07df, 0xcd5: 0x0b23, 0xcd6: 0x0ea7, 0xcd7: 0x1457,
+	0xcd8: 0x0bdf, 0xcd9: 0x0c2f, 0xcda: 0x0dbb, 0xcdb: 0x0fa7, 0xcdc: 0x152f, 0xcdd: 0x088f,
+	0xcde: 0x0977, 0xcdf: 0x0b0f, 0xce0: 0x0d4b, 0xce1: 0x0d97, 0xce2: 0x0dd7, 0xce3: 0x0e6b,
+	0xce4: 0x0fbf, 0xce5: 0x1033, 0xce6: 0x11cf, 0xce7: 0x136f, 0xce8: 0x137b, 0xce9: 0x14cb,
+	0xcea: 0x154b, 0xceb: 0x08fb, 0xcec: 0x0ec3, 0xced: 0x097b, 0xcee: 0x0f3f, 0xcef: 0x0fe3,
+	0xcf0: 0x12ff, 0xcf1: 0x1533, 0xcf2: 0x161f, 0xcf3: 0x1647, 0xcf4: 0x0daf, 0xcf5: 0x0e9f,
+	0xcf6: 0x123b, 0xcf7: 0x112f, 0xcf8: 0x113b, 0xcf9: 0x115f, 0xcfa: 0x0f8f, 0xcfb: 0x0f17,
+	0xcfc: 0x13db, 0xcfd: 0x07ab, 0xcfe: 0x12a3, 0xcff: 0x0893,
+	// Block 0x34, offset 0xd00
+	0xd00: 0x0883, 0xd01: 0x0b83, 0xd02: 0x0ca3, 0xd03: 0x116b, 0xd04: 0x0acb, 0xd05: 0x0e7b,
+	0xd06: 0x0d67, 0xd07: 0x145f, 0xd08: 0x135f, 0xd09: 0x151f, 0xd0a: 0x139b, 0xd0b: 0x0b9f,
+	0xd0c: 0x07ff, 0xd0d: 0x09d3, 0xd10: 0x0a27,
+	0xd12: 0x0d57, 0xd15: 0x086f, 0xd16: 0x0f97, 0xd17: 0x105b,
+	0xd18: 0x10bf, 0xd19: 0x10db, 0xd1a: 0x10df, 0xd1b: 0x10f3, 0xd1c: 0x156f, 0xd1d: 0x1163,
+	0xd1e: 0x11e7, 0xd20: 0x1307, 0xd22: 0x13cb,
+	0xd25: 0x147f, 0xd26: 0x14ab,
+	0xd2a: 0x15c3, 0xd2b: 0x15c7, 0xd2c: 0x15cb, 0xd2d: 0x162f, 0xd2e: 0x14a3, 0xd2f: 0x153b,
+	0xd30: 0x07cf, 0xd31: 0x07f3, 0xd32: 0x0807, 0xd33: 0x08c3, 0xd34: 0x08cf, 0xd35: 0x090f,
+	0xd36: 0x09c3, 0xd37: 0x09df, 0xd38: 0x09e7, 0xd39: 0x0a23, 0xd3a: 0x0a2f, 0xd3b: 0x0b0b,
+	0xd3c: 0x0b13, 0xd3d: 0x0c1b, 0xd3e: 0x0c43, 0xd3f: 0x0c4b,
+	// Block 0x35, offset 0xd40
+	0xd40: 0x0c63, 0xd41: 0x0d0f, 0xd42: 0x0d3f, 0xd43: 0x0d5f, 0xd44: 0x0dcf, 0xd45: 0x0e93,
+	0xd46: 0x0eaf, 0xd47: 0x0edf, 0xd48: 0x0f33, 0xd49: 0x0f53, 0xd4a: 0x0fc7, 0xd4b: 0x10a7,
+	0xd4c: 0x10c3, 0xd4d: 0x10cb, 0xd4e: 0x10c7, 0xd4f: 0x10cf, 0xd50: 0x10d3, 0xd51: 0x10d7,
+	0xd52: 0x10eb, 0xd53: 0x10ef, 0xd54: 0x1113, 0xd55: 0x1127, 0xd56: 0x1143, 0xd57: 0x11a7,
+	0xd58: 0x11af, 0xd59: 0x11b7, 0xd5a: 0x11cb, 0xd5b: 0x11f3, 0xd5c: 0x1243, 0xd5d: 0x1277,
+	0xd5e: 0x1277, 0xd5f: 0x12df, 0xd60: 0x1387, 0xd61: 0x139f, 0xd62: 0x13d3, 0xd63: 0x13d7,
+	0xd64: 0x141b, 0xd65: 0x141f, 0xd66: 0x1477, 0xd67: 0x147f, 0xd68: 0x154f, 0xd69: 0x1593,
+	0xd6a: 0x15ab, 0xd6b: 0x0c13, 0xd6c: 0x1792, 0xd6d: 0x125b,
+	0xd70: 0x0757, 0xd71: 0x085b, 0xd72: 0x081b, 0xd73: 0x07c3, 0xd74: 0x0803, 0xd75: 0x082f,
+	0xd76: 0x08bf, 0xd77: 0x08db, 0xd78: 0x09c3, 0xd79: 0x09af, 0xd7a: 0x09bf, 0xd7b: 0x09db,
+	0xd7c: 0x0a27, 0xd7d: 0x0a37, 0xd7e: 0x0a7b, 0xd7f: 0x0a87,
+	// Block 0x36, offset 0xd80
+	0xd80: 0x0aa3, 0xd81: 0x0ab3, 0xd82: 0x0b9b, 0xd83: 0x0ba3, 0xd84: 0x0bd3, 0xd85: 0x0bf3,
+	0xd86: 0x0c23, 0xd87: 0x0c3b, 0xd88: 0x0c2b, 0xd89: 0x0c4b, 0xd8a: 0x0c3f, 0xd8b: 0x0c63,
+	0xd8c: 0x0c7f, 0xd8d: 0x0cd7, 0xd8e: 0x0ce3, 0xd8f: 0x0ceb, 0xd90: 0x0d13, 0xd91: 0x0d57,
+	0xd92: 0x0d87, 0xd93: 0x0d8b, 0xd94: 0x0d9f, 0xd95: 0x0e1f, 0xd96: 0x0e2f, 0xd97: 0x0e87,
+	0xd98: 0x0ed3, 0xd99: 0x0ecb, 0xd9a: 0x0edf, 0xd9b: 0x0efb, 0xd9c: 0x0f33, 0xd9d: 0x108b,
+	0xd9e: 0x0f57, 0xd9f: 0x0f8b, 0xda0: 0x0f97, 0xda1: 0x0fd7, 0xda2: 0x0ff3, 0xda3: 0x1017,
+	0xda4: 0x103b, 0xda5: 0x103f, 0xda6: 0x105b, 0xda7: 0x105f, 0xda8: 0x106f, 0xda9: 0x1083,
+	0xdaa: 0x107f, 0xdab: 0x10af, 0xdac: 0x112b, 0xdad: 0x1143, 0xdae: 0x115b, 0xdaf: 0x1193,
+	0xdb0: 0x11a7, 0xdb1: 0x11c3, 0xdb2: 0x11f3, 0xdb3: 0x12a7, 0xdb4: 0x12cf, 0xdb5: 0x1343,
+	0xdb6: 0x138b, 0xdb7: 0x1397, 0xdb8: 0x139f, 0xdb9: 0x13b7, 0xdba: 0x13cb, 0xdbb: 0x13bb,
+	0xdbc: 0x13d3, 0xdbd: 0x13cf, 0xdbe: 0x13c7, 0xdbf: 0x13d7,
+	// Block 0x37, offset 0xdc0
+	0xdc0: 0x13e3, 0xdc1: 0x141f, 0xdc2: 0x145b, 0xdc3: 0x148b, 0xdc4: 0x14bf, 0xdc5: 0x14df,
+	0xdc6: 0x152b, 0xdc7: 0x154f, 0xdc8: 0x156f, 0xdc9: 0x1583, 0xdca: 0x1593, 0xdcb: 0x159f,
+	0xdcc: 0x15ab, 0xdcd: 0x15ff, 0xdce: 0x169f, 0xdcf: 0x1729, 0xdd0: 0x1724, 0xdd1: 0x1756,
+	0xdd2: 0x067f, 0xdd3: 0x06a7, 0xdd4: 0x06ab, 0xdd5: 0x17d8, 0xdd6: 0x1805, 0xdd7: 0x187d,
+	0xdd8: 0x168b, 0xdd9: 0x169b,
+	// Block 0x38, offset 0xe00
+	0xe00: 0x1b68, 0xe01: 0x1b6b, 0xe02: 0x1b6e, 0xe03: 0x1d9b, 0xe04: 0x1d9f, 0xe05: 0x1bf2,
+	0xe06: 0x1bf2,
+	0xe13: 0x1f08, 0xe14: 0x1ef9, 0xe15: 0x1efe, 0xe16: 0x1f0d, 0xe17: 0x1f03,
+	0xe1d: 0x43cb,
+	0xe1e: 0x8115, 0xe1f: 0x443d, 0xe20: 0x022d, 0xe21: 0x0215, 0xe22: 0x021e, 0xe23: 0x0221,
+	0xe24: 0x0224, 0xe25: 0x0227, 0xe26: 0x022a, 0xe27: 0x0230, 0xe28: 0x0233, 0xe29: 0x0017,
+	0xe2a: 0x442b, 0xe2b: 0x4431, 0xe2c: 0x452f, 0xe2d: 0x4537, 0xe2e: 0x4383, 0xe2f: 0x4389,
+	0xe30: 0x438f, 0xe31: 0x4395, 0xe32: 0x43a1, 0xe33: 0x43a7, 0xe34: 0x43ad, 0xe35: 0x43b9,
+	0xe36: 0x43bf, 0xe38: 0x43c5, 0xe39: 0x43d1, 0xe3a: 0x43d7, 0xe3b: 0x43dd,
+	0xe3c: 0x43e9, 0xe3e: 0x43ef,
+	// Block 0x39, offset 0xe40
+	0xe40: 0x43f5, 0xe41: 0x43fb, 0xe43: 0x4401, 0xe44: 0x4407,
+	0xe46: 0x4413, 0xe47: 0x4419, 0xe48: 0x441f, 0xe49: 0x4425, 0xe4a: 0x4437, 0xe4b: 0x43b3,
+	0xe4c: 0x439b, 0xe4d: 0x43e3, 0xe4e: 0x440d, 0xe4f: 0x1f12, 0xe50: 0x0299, 0xe51: 0x0299,
+	0xe52: 0x02a2, 0xe53: 0x02a2, 0xe54: 0x02a2, 0xe55: 0x02a2, 0xe56: 0x02a5, 0xe57: 0x02a5,
+	0xe58: 0x02a5, 0xe59: 0x02a5, 0xe5a: 0x02ab, 0xe5b: 0x02ab, 0xe5c: 0x02ab, 0xe5d: 0x02ab,
+	0xe5e: 0x029f, 0xe5f: 0x029f, 0xe60: 0x029f, 0xe61: 0x029f, 0xe62: 0x02a8, 0xe63: 0x02a8,
+	0xe64: 0x02a8, 0xe65: 0x02a8, 0xe66: 0x029c, 0xe67: 0x029c, 0xe68: 0x029c, 0xe69: 0x029c,
+	0xe6a: 0x02cf, 0xe6b: 0x02cf, 0xe6c: 0x02cf, 0xe6d: 0x02cf, 0xe6e: 0x02d2, 0xe6f: 0x02d2,
+	0xe70: 0x02d2, 0xe71: 0x02d2, 0xe72: 0x02b1, 0xe73: 0x02b1, 0xe74: 0x02b1, 0xe75: 0x02b1,
+	0xe76: 0x02ae, 0xe77: 0x02ae, 0xe78: 0x02ae, 0xe79: 0x02ae, 0xe7a: 0x02b4, 0xe7b: 0x02b4,
+	0xe7c: 0x02b4, 0xe7d: 0x02b4, 0xe7e: 0x02b7, 0xe7f: 0x02b7,
+	// Block 0x3a, offset 0xe80
+	0xe80: 0x02b7, 0xe81: 0x02b7, 0xe82: 0x02c0, 0xe83: 0x02c0, 0xe84: 0x02bd, 0xe85: 0x02bd,
+	0xe86: 0x02c3, 0xe87: 0x02c3, 0xe88: 0x02ba, 0xe89: 0x02ba, 0xe8a: 0x02c9, 0xe8b: 0x02c9,
+	0xe8c: 0x02c6, 0xe8d: 0x02c6, 0xe8e: 0x02d5, 0xe8f: 0x02d5, 0xe90: 0x02d5, 0xe91: 0x02d5,
+	0xe92: 0x02db, 0xe93: 0x02db, 0xe94: 0x02db, 0xe95: 0x02db, 0xe96: 0x02e1, 0xe97: 0x02e1,
+	0xe98: 0x02e1, 0xe99: 0x02e1, 0xe9a: 0x02de, 0xe9b: 0x02de, 0xe9c: 0x02de, 0xe9d: 0x02de,
+	0xe9e: 0x02e4, 0xe9f: 0x02e4, 0xea0: 0x02e7, 0xea1: 0x02e7, 0xea2: 0x02e7, 0xea3: 0x02e7,
+	0xea4: 0x44a9, 0xea5: 0x44a9, 0xea6: 0x02ed, 0xea7: 0x02ed, 0xea8: 0x02ed, 0xea9: 0x02ed,
+	0xeaa: 0x02ea, 0xeab: 0x02ea, 0xeac: 0x02ea, 0xead: 0x02ea, 0xeae: 0x0308, 0xeaf: 0x0308,
+	0xeb0: 0x44a3, 0xeb1: 0x44a3,
+	// Block 0x3b, offset 0xec0
+	0xed3: 0x02d8, 0xed4: 0x02d8, 0xed5: 0x02d8, 0xed6: 0x02d8, 0xed7: 0x02f6,
+	0xed8: 0x02f6, 0xed9: 0x02f3, 0xeda: 0x02f3, 0xedb: 0x02f9, 0xedc: 0x02f9, 0xedd: 0x21e2,
+	0xede: 0x02ff, 0xedf: 0x02ff, 0xee0: 0x02f0, 0xee1: 0x02f0, 0xee2: 0x02fc, 0xee3: 0x02fc,
+	0xee4: 0x0305, 0xee5: 0x0305, 0xee6: 0x0305, 0xee7: 0x0305, 0xee8: 0x028d, 0xee9: 0x028d,
+	0xeea: 0x273d, 0xeeb: 0x273d, 0xeec: 0x27ad, 0xeed: 0x27ad, 0xeee: 0x277c, 0xeef: 0x277c,
+	0xef0: 0x2798, 0xef1: 0x2798, 0xef2: 0x2791, 0xef3: 0x2791, 0xef4: 0x279f, 0xef5: 0x279f,
+	0xef6: 0x27a6, 0xef7: 0x27a6, 0xef8: 0x27a6, 0xef9: 0x2783, 0xefa: 0x2783, 0xefb: 0x2783,
+	0xefc: 0x0302, 0xefd: 0x0302, 0xefe: 0x0302, 0xeff: 0x0302,
+	// Block 0x3c, offset 0xf00
+	0xf00: 0x2744, 0xf01: 0x274b, 0xf02: 0x2767, 0xf03: 0x2783, 0xf04: 0x278a, 0xf05: 0x1f1c,
+	0xf06: 0x1f21, 0xf07: 0x1f26, 0xf08: 0x1f35, 0xf09: 0x1f44, 0xf0a: 0x1f49, 0xf0b: 0x1f4e,
+	0xf0c: 0x1f53, 0xf0d: 0x1f58, 0xf0e: 0x1f67, 0xf0f: 0x1f76, 0xf10: 0x1f7b, 0xf11: 0x1f80,
+	0xf12: 0x1f8f, 0xf13: 0x1f9e, 0xf14: 0x1fa3, 0xf15: 0x1fa8, 0xf16: 0x1fad, 0xf17: 0x1fbc,
+	0xf18: 0x1fc1, 0xf19: 0x1fd0, 0xf1a: 0x1fd5, 0xf1b: 0x1fda, 0xf1c: 0x1fe9, 0xf1d: 0x1fee,
+	0xf1e: 0x1ff3, 0xf1f: 0x1ffd, 0xf20: 0x2039, 0xf21: 0x2048, 0xf22: 0x2057, 0xf23: 0x205c,
+	0xf24: 0x2061, 0xf25: 0x206b, 0xf26: 0x207a, 0xf27: 0x207f, 0xf28: 0x208e, 0xf29: 0x2093,
+	0xf2a: 0x2098, 0xf2b: 0x20a7, 0xf2c: 0x20ac, 0xf2d: 0x20bb, 0xf2e: 0x20c0, 0xf2f: 0x20c5,
+	0xf30: 0x20ca, 0xf31: 0x20cf, 0xf32: 0x20d4, 0xf33: 0x20d9, 0xf34: 0x20de, 0xf35: 0x20e3,
+	0xf36: 0x20e8, 0xf37: 0x20ed, 0xf38: 0x20f2, 0xf39: 0x20f7, 0xf3a: 0x20fc, 0xf3b: 0x2101,
+	0xf3c: 0x2106, 0xf3d: 0x210b, 0xf3e: 0x2110, 0xf3f: 0x211a,
+	// Block 0x3d, offset 0xf40
+	0xf40: 0x211f, 0xf41: 0x2124, 0xf42: 0x2129, 0xf43: 0x2133, 0xf44: 0x2138, 0xf45: 0x2142,
+	0xf46: 0x2147, 0xf47: 0x214c, 0xf48: 0x2151, 0xf49: 0x2156, 0xf4a: 0x215b, 0xf4b: 0x2160,
+	0xf4c: 0x2165, 0xf4d: 0x216a, 0xf4e: 0x2179, 0xf4f: 0x2188, 0xf50: 0x218d, 0xf51: 0x2192,
+	0xf52: 0x2197, 0xf53: 0x219c, 0xf54: 0x21a1, 0xf55: 0x21ab, 0xf56: 0x21b0, 0xf57: 0x21b5,
+	0xf58: 0x21c4, 0xf59: 0x21d3, 0xf5a: 0x21d8, 0xf5b: 0x445b, 0xf5c: 0x4461, 0xf5d: 0x4497,
+	0xf5e: 0x44ee, 0xf5f: 0x44f5, 0xf60: 0x44fc, 0xf61: 0x4503, 0xf62: 0x450a, 0xf63: 0x4511,
+	0xf64: 0x2759, 0xf65: 0x2760, 0xf66: 0x2767, 0xf67: 0x276e, 0xf68: 0x2783, 0xf69: 0x278a,
+	0xf6a: 0x1f2b, 0xf6b: 0x1f30, 0xf6c: 0x1f35, 0xf6d: 0x1f3a, 0xf6e: 0x1f44, 0xf6f: 0x1f49,
+	0xf70: 0x1f5d, 0xf71: 0x1f62, 0xf72: 0x1f67, 0xf73: 0x1f6c, 0xf74: 0x1f76, 0xf75: 0x1f7b,
+	0xf76: 0x1f85, 0xf77: 0x1f8a, 0xf78: 0x1f8f, 0xf79: 0x1f94, 0xf7a: 0x1f9e, 0xf7b: 0x1fa3,
+	0xf7c: 0x20cf, 0xf7d: 0x20d4, 0xf7e: 0x20e3, 0xf7f: 0x20e8,
+	// Block 0x3e, offset 0xf80
+	0xf80: 0x20ed, 0xf81: 0x2101, 0xf82: 0x2106, 0xf83: 0x210b, 0xf84: 0x2110, 0xf85: 0x2129,
+	0xf86: 0x2133, 0xf87: 0x2138, 0xf88: 0x213d, 0xf89: 0x2151, 0xf8a: 0x216f, 0xf8b: 0x2174,
+	0xf8c: 0x2179, 0xf8d: 0x217e, 0xf8e: 0x2188, 0xf8f: 0x218d, 0xf90: 0x4497, 0xf91: 0x21ba,
+	0xf92: 0x21bf, 0xf93: 0x21c4, 0xf94: 0x21c9, 0xf95: 0x21d3, 0xf96: 0x21d8, 0xf97: 0x2744,
+	0xf98: 0x274b, 0xf99: 0x2752, 0xf9a: 0x2767, 0xf9b: 0x2775, 0xf9c: 0x1f1c, 0xf9d: 0x1f21,
+	0xf9e: 0x1f26, 0xf9f: 0x1f35, 0xfa0: 0x1f3f, 0xfa1: 0x1f4e, 0xfa2: 0x1f53, 0xfa3: 0x1f58,
+	0xfa4: 0x1f67, 0xfa5: 0x1f71, 0xfa6: 0x1f8f, 0xfa7: 0x1fa8, 0xfa8: 0x1fad, 0xfa9: 0x1fbc,
+	0xfaa: 0x1fc1, 0xfab: 0x1fd0, 0xfac: 0x1fda, 0xfad: 0x1fe9, 0xfae: 0x1fee, 0xfaf: 0x1ff3,
+	0xfb0: 0x1ffd, 0xfb1: 0x2039, 0xfb2: 0x203e, 0xfb3: 0x2048, 0xfb4: 0x2057, 0xfb5: 0x205c,
+	0xfb6: 0x2061, 0xfb7: 0x206b, 0xfb8: 0x207a, 0xfb9: 0x208e, 0xfba: 0x2093, 0xfbb: 0x2098,
+	0xfbc: 0x20a7, 0xfbd: 0x20ac, 0xfbe: 0x20bb, 0xfbf: 0x20c0,
+	// Block 0x3f, offset 0xfc0
+	0xfc0: 0x20c5, 0xfc1: 0x20ca, 0xfc2: 0x20d9, 0xfc3: 0x20de, 0xfc4: 0x20f2, 0xfc5: 0x20f7,
+	0xfc6: 0x20fc, 0xfc7: 0x2101, 0xfc8: 0x2106, 0xfc9: 0x211a, 0xfca: 0x211f, 0xfcb: 0x2124,
+	0xfcc: 0x2129, 0xfcd: 0x212e, 0xfce: 0x2142, 0xfcf: 0x2147, 0xfd0: 0x214c, 0xfd1: 0x2151,
+	0xfd2: 0x2160, 0xfd3: 0x2165, 0xfd4: 0x216a, 0xfd5: 0x2179, 0xfd6: 0x2183, 0xfd7: 0x2192,
+	0xfd8: 0x2197, 0xfd9: 0x448b, 0xfda: 0x21ab, 0xfdb: 0x21b0, 0xfdc: 0x21b5, 0xfdd: 0x21c4,
+	0xfde: 0x21ce, 0xfdf: 0x2767, 0xfe0: 0x2775, 0xfe1: 0x1f35, 0xfe2: 0x1f3f, 0xfe3: 0x1f67,
+	0xfe4: 0x1f71, 0xfe5: 0x1f8f, 0xfe6: 0x1f99, 0xfe7: 0x1ffd, 0xfe8: 0x2002, 0xfe9: 0x2025,
+	0xfea: 0x202a, 0xfeb: 0x2101, 0xfec: 0x2106, 0xfed: 0x2129, 0xfee: 0x2179, 0xfef: 0x2183,
+	0xff0: 0x21c4, 0xff1: 0x21ce, 0xff2: 0x453f, 0xff3: 0x4547, 0xff4: 0x454f, 0xff5: 0x2084,
+	0xff6: 0x2089, 0xff7: 0x209d, 0xff8: 0x20a2, 0xff9: 0x20b1, 0xffa: 0x20b6, 0xffb: 0x2007,
+	0xffc: 0x200c, 0xffd: 0x202f, 0xffe: 0x2034, 0xfff: 0x1fc6,
+	// Block 0x40, offset 0x1000
+	0x1000: 0x1fcb, 0x1001: 0x1fb2, 0x1002: 0x1fb7, 0x1003: 0x1fdf, 0x1004: 0x1fe4, 0x1005: 0x204d,
+	0x1006: 0x2052, 0x1007: 0x2070, 0x1008: 0x2075, 0x1009: 0x2011, 0x100a: 0x2016, 0x100b: 0x201b,
+	0x100c: 0x2025, 0x100d: 0x2020, 0x100e: 0x1ff8, 0x100f: 0x2043, 0x1010: 0x2066, 0x1011: 0x2084,
+	0x1012: 0x2089, 0x1013: 0x209d, 0x1014: 0x20a2, 0x1015: 0x20b1, 0x1016: 0x20b6, 0x1017: 0x2007,
+	0x1018: 0x200c, 0x1019: 0x202f, 0x101a: 0x2034, 0x101b: 0x1fc6, 0x101c: 0x1fcb, 0x101d: 0x1fb2,
+	0x101e: 0x1fb7, 0x101f: 0x1fdf, 0x1020: 0x1fe4, 0x1021: 0x204d, 0x1022: 0x2052, 0x1023: 0x2070,
+	0x1024: 0x2075, 0x1025: 0x2011, 0x1026: 0x2016, 0x1027: 0x201b, 0x1028: 0x2025, 0x1029: 0x2020,
+	0x102a: 0x1ff8, 0x102b: 0x2043, 0x102c: 0x2066, 0x102d: 0x2011, 0x102e: 0x2016, 0x102f: 0x201b,
+	0x1030: 0x2025, 0x1031: 0x2002, 0x1032: 0x202a, 0x1033: 0x207f, 0x1034: 0x1fe9, 0x1035: 0x1fee,
+	0x1036: 0x1ff3, 0x1037: 0x2011, 0x1038: 0x2016, 0x1039: 0x201b, 0x103a: 0x207f, 0x103b: 0x208e,
+	0x103c: 0x4443, 0x103d: 0x4443,
+	// Block 0x41, offset 0x1040
+	0x1050: 0x24a4, 0x1051: 0x24b9,
+	0x1052: 0x24b9, 0x1053: 0x24c0, 0x1054: 0x24c7, 0x1055: 0x24dc, 0x1056: 0x24e3, 0x1057: 0x24ea,
+	0x1058: 0x250d, 0x1059: 0x250d, 0x105a: 0x2530, 0x105b: 0x2529, 0x105c: 0x2545, 0x105d: 0x2537,
+	0x105e: 0x253e, 0x105f: 0x2561, 0x1060: 0x2561, 0x1061: 0x255a, 0x1062: 0x2568, 0x1063: 0x2568,
+	0x1064: 0x2592, 0x1065: 0x2592, 0x1066: 0x25ae, 0x1067: 0x2576, 0x1068: 0x2576, 0x1069: 0x256f,
+	0x106a: 0x2584, 0x106b: 0x2584, 0x106c: 0x258b, 0x106d: 0x258b, 0x106e: 0x25b5, 0x106f: 0x25c3,
+	0x1070: 0x25c3, 0x1071: 0x25ca, 0x1072: 0x25ca, 0x1073: 0x25d1, 0x1074: 0x25d8, 0x1075: 0x25df,
+	0x1076: 0x25e6, 0x1077: 0x25e6, 0x1078: 0x25ed, 0x1079: 0x25fb, 0x107a: 0x2609, 0x107b: 0x2602,
+	0x107c: 0x2610, 0x107d: 0x2610, 0x107e: 0x2625, 0x107f: 0x262c,
+	// Block 0x42, offset 0x1080
+	0x1080: 0x265d, 0x1081: 0x266b, 0x1082: 0x2664, 0x1083: 0x2648, 0x1084: 0x2648, 0x1085: 0x2672,
+	0x1086: 0x2672, 0x1087: 0x2679, 0x1088: 0x2679, 0x1089: 0x26a3, 0x108a: 0x26aa, 0x108b: 0x26b1,
+	0x108c: 0x2687, 0x108d: 0x2695, 0x108e: 0x26b8, 0x108f: 0x26bf,
+	0x1092: 0x268e, 0x1093: 0x2713, 0x1094: 0x271a, 0x1095: 0x26f0, 0x1096: 0x26f7, 0x1097: 0x26db,
+	0x1098: 0x26db, 0x1099: 0x26e2, 0x109a: 0x270c, 0x109b: 0x2705, 0x109c: 0x272f, 0x109d: 0x272f,
+	0x109e: 0x249d, 0x109f: 0x24b2, 0x10a0: 0x24ab, 0x10a1: 0x24d5, 0x10a2: 0x24ce, 0x10a3: 0x24f8,
+	0x10a4: 0x24f1, 0x10a5: 0x251b, 0x10a6: 0x24ff, 0x10a7: 0x2514, 0x10a8: 0x254c, 0x10a9: 0x2599,
+	0x10aa: 0x257d, 0x10ab: 0x25bc, 0x10ac: 0x2656, 0x10ad: 0x2680, 0x10ae: 0x2728, 0x10af: 0x2721,
+	0x10b0: 0x2736, 0x10b1: 0x26cd, 0x10b2: 0x2633, 0x10b3: 0x26fe, 0x10b4: 0x2625, 0x10b5: 0x265d,
+	0x10b6: 0x25f4, 0x10b7: 0x2641, 0x10b8: 0x26d4, 0x10b9: 0x26c6, 0x10ba: 0x264f, 0x10bb: 0x263a,
+	0x10bc: 0x264f, 0x10bd: 0x26d4, 0x10be: 0x2506, 0x10bf: 0x2522,
+	// Block 0x43, offset 0x10c0
+	0x10c0: 0x269c, 0x10c1: 0x2617, 0x10c2: 0x2496, 0x10c3: 0x263a, 0x10c4: 0x25df, 0x10c5: 0x25ae,
+	0x10c6: 0x2553, 0x10c7: 0x26e9,
+	0x10f0: 0x25a7, 0x10f1: 0x261e, 0x10f2: 0x29bb, 0x10f3: 0x29b2, 0x10f4: 0x29e8, 0x10f5: 0x29d6,
+	0x10f6: 0x29c4, 0x10f7: 0x29df, 0x10f8: 0x29f1, 0x10f9: 0x25a0, 0x10fa: 0x2e95, 0x10fb: 0x2d05,
+	0x10fc: 0x29cd,
+	// Block 0x44, offset 0x1100
+	0x1110: 0x0019, 0x1111: 0x04fb,
+	0x1112: 0x04ff, 0x1113: 0x0035, 0x1114: 0x0037, 0x1115: 0x0003, 0x1116: 0x003f, 0x1117: 0x0537,
+	0x1118: 0x053b, 0x1119: 0x1cef,
+	0x1120: 0x8132, 0x1121: 0x8132, 0x1122: 0x8132, 0x1123: 0x8132,
+	0x1124: 0x8132, 0x1125: 0x8132, 0x1126: 0x8132, 0x1127: 0x812d, 0x1128: 0x812d, 0x1129: 0x812d,
+	0x112a: 0x812d, 0x112b: 0x812d, 0x112c: 0x812d, 0x112d: 0x812d,
+	0x1130: 0x1a06, 0x1131: 0x04bb, 0x1132: 0x04b7, 0x1133: 0x007f, 0x1134: 0x007f, 0x1135: 0x0011,
+	0x1136: 0x0013, 0x1137: 0x00b7, 0x1138: 0x00bb, 0x1139: 0x052f, 0x113a: 0x0533, 0x113b: 0x0523,
+	0x113c: 0x0527, 0x113d: 0x050b, 0x113e: 0x050f, 0x113f: 0x0503,
+	// Block 0x45, offset 0x1140
+	0x1140: 0x0507, 0x1141: 0x0513, 0x1142: 0x0517, 0x1143: 0x051b, 0x1144: 0x051f,
+	0x1147: 0x0077, 0x1148: 0x007b, 0x1149: 0x42a4, 0x114a: 0x42a4, 0x114b: 0x42a4,
+	0x114c: 0x42a4, 0x114d: 0x007f, 0x114e: 0x007f, 0x114f: 0x007f, 0x1150: 0x0019, 0x1151: 0x04fb,
+	0x1152: 0x001d, 0x1154: 0x0037, 0x1155: 0x0035, 0x1156: 0x003f, 0x1157: 0x0003,
+	0x1158: 0x04bb, 0x1159: 0x0011, 0x115a: 0x0013, 0x115b: 0x00b7, 0x115c: 0x00bb, 0x115d: 0x052f,
+	0x115e: 0x0533, 0x115f: 0x0007, 0x1160: 0x000d, 0x1161: 0x0015, 0x1162: 0x0017, 0x1163: 0x001b,
+	0x1164: 0x0039, 0x1165: 0x003d, 0x1166: 0x003b, 0x1168: 0x0079, 0x1169: 0x0009,
+	0x116a: 0x000b, 0x116b: 0x0041,
+	0x1170: 0x42e5, 0x1171: 0x4467, 0x1172: 0x42ea, 0x1174: 0x42ef,
+	0x1176: 0x42f4, 0x1177: 0x446d, 0x1178: 0x42f9, 0x1179: 0x4473, 0x117a: 0x42fe, 0x117b: 0x4479,
+	0x117c: 0x4303, 0x117d: 0x447f, 0x117e: 0x4308, 0x117f: 0x4485,
+	// Block 0x46, offset 0x1180
+	0x1180: 0x0236, 0x1181: 0x4449, 0x1182: 0x4449, 0x1183: 0x444f, 0x1184: 0x444f, 0x1185: 0x4491,
+	0x1186: 0x4491, 0x1187: 0x4455, 0x1188: 0x4455, 0x1189: 0x449d, 0x118a: 0x449d, 0x118b: 0x449d,
+	0x118c: 0x449d, 0x118d: 0x0239, 0x118e: 0x0239, 0x118f: 0x023c, 0x1190: 0x023c, 0x1191: 0x023c,
+	0x1192: 0x023c, 0x1193: 0x023f, 0x1194: 0x023f, 0x1195: 0x0242, 0x1196: 0x0242, 0x1197: 0x0242,
+	0x1198: 0x0242, 0x1199: 0x0245, 0x119a: 0x0245, 0x119b: 0x0245, 0x119c: 0x0245, 0x119d: 0x0248,
+	0x119e: 0x0248, 0x119f: 0x0248, 0x11a0: 0x0248, 0x11a1: 0x024b, 0x11a2: 0x024b, 0x11a3: 0x024b,
+	0x11a4: 0x024b, 0x11a5: 0x024e, 0x11a6: 0x024e, 0x11a7: 0x024e, 0x11a8: 0x024e, 0x11a9: 0x0251,
+	0x11aa: 0x0251, 0x11ab: 0x0254, 0x11ac: 0x0254, 0x11ad: 0x0257, 0x11ae: 0x0257, 0x11af: 0x025a,
+	0x11b0: 0x025a, 0x11b1: 0x025d, 0x11b2: 0x025d, 0x11b3: 0x025d, 0x11b4: 0x025d, 0x11b5: 0x0260,
+	0x11b6: 0x0260, 0x11b7: 0x0260, 0x11b8: 0x0260, 0x11b9: 0x0263, 0x11ba: 0x0263, 0x11bb: 0x0263,
+	0x11bc: 0x0263, 0x11bd: 0x0266, 0x11be: 0x0266, 0x11bf: 0x0266,
+	// Block 0x47, offset 0x11c0
+	0x11c0: 0x0266, 0x11c1: 0x0269, 0x11c2: 0x0269, 0x11c3: 0x0269, 0x11c4: 0x0269, 0x11c5: 0x026c,
+	0x11c6: 0x026c, 0x11c7: 0x026c, 0x11c8: 0x026c, 0x11c9: 0x026f, 0x11ca: 0x026f, 0x11cb: 0x026f,
+	0x11cc: 0x026f, 0x11cd: 0x0272, 0x11ce: 0x0272, 0x11cf: 0x0272, 0x11d0: 0x0272, 0x11d1: 0x0275,
+	0x11d2: 0x0275, 0x11d3: 0x0275, 0x11d4: 0x0275, 0x11d5: 0x0278, 0x11d6: 0x0278, 0x11d7: 0x0278,
+	0x11d8: 0x0278, 0x11d9: 0x027b, 0x11da: 0x027b, 0x11db: 0x027b, 0x11dc: 0x027b, 0x11dd: 0x027e,
+	0x11de: 0x027e, 0x11df: 0x027e, 0x11e0: 0x027e, 0x11e1: 0x0281, 0x11e2: 0x0281, 0x11e3: 0x0281,
+	0x11e4: 0x0281, 0x11e5: 0x0284, 0x11e6: 0x0284, 0x11e7: 0x0284, 0x11e8: 0x0284, 0x11e9: 0x0287,
+	0x11ea: 0x0287, 0x11eb: 0x0287, 0x11ec: 0x0287, 0x11ed: 0x028a, 0x11ee: 0x028a, 0x11ef: 0x028d,
+	0x11f0: 0x028d, 0x11f1: 0x0290, 0x11f2: 0x0290, 0x11f3: 0x0290, 0x11f4: 0x0290, 0x11f5: 0x2ee2,
+	0x11f6: 0x2ee2, 0x11f7: 0x2eea, 0x11f8: 0x2eea, 0x11f9: 0x2ef2, 0x11fa: 0x2ef2, 0x11fb: 0x2115,
+	0x11fc: 0x2115,
+	// Block 0x48, offset 0x1200
+	0x1200: 0x0081, 0x1201: 0x0083, 0x1202: 0x0085, 0x1203: 0x0087, 0x1204: 0x0089, 0x1205: 0x008b,
+	0x1206: 0x008d, 0x1207: 0x008f, 0x1208: 0x0091, 0x1209: 0x0093, 0x120a: 0x0095, 0x120b: 0x0097,
+	0x120c: 0x0099, 0x120d: 0x009b, 0x120e: 0x009d, 0x120f: 0x009f, 0x1210: 0x00a1, 0x1211: 0x00a3,
+	0x1212: 0x00a5, 0x1213: 0x00a7, 0x1214: 0x00a9, 0x1215: 0x00ab, 0x1216: 0x00ad, 0x1217: 0x00af,
+	0x1218: 0x00b1, 0x1219: 0x00b3, 0x121a: 0x00b5, 0x121b: 0x00b7, 0x121c: 0x00b9, 0x121d: 0x00bb,
+	0x121e: 0x00bd, 0x121f: 0x04ef, 0x1220: 0x04f3, 0x1221: 0x04ff, 0x1222: 0x0513, 0x1223: 0x0517,
+	0x1224: 0x04fb, 0x1225: 0x0623, 0x1226: 0x061b, 0x1227: 0x053f, 0x1228: 0x0547, 0x1229: 0x054f,
+	0x122a: 0x0557, 0x122b: 0x055f, 0x122c: 0x05e3, 0x122d: 0x05eb, 0x122e: 0x05f3, 0x122f: 0x0597,
+	0x1230: 0x0627, 0x1231: 0x0543, 0x1232: 0x054b, 0x1233: 0x0553, 0x1234: 0x055b, 0x1235: 0x0563,
+	0x1236: 0x0567, 0x1237: 0x056b, 0x1238: 0x056f, 0x1239: 0x0573, 0x123a: 0x0577, 0x123b: 0x057b,
+	0x123c: 0x057f, 0x123d: 0x0583, 0x123e: 0x0587, 0x123f: 0x058b,
+	// Block 0x49, offset 0x1240
+	0x1240: 0x058f, 0x1241: 0x0593, 0x1242: 0x059b, 0x1243: 0x059f, 0x1244: 0x05a3, 0x1245: 0x05a7,
+	0x1246: 0x05ab, 0x1247: 0x05af, 0x1248: 0x05b3, 0x1249: 0x05b7, 0x124a: 0x05bb, 0x124b: 0x05bf,
+	0x124c: 0x05c3, 0x124d: 0x05c7, 0x124e: 0x05cb, 0x124f: 0x05cf, 0x1250: 0x05d3, 0x1251: 0x05d7,
+	0x1252: 0x05db, 0x1253: 0x05df, 0x1254: 0x05e7, 0x1255: 0x05ef, 0x1256: 0x05f7, 0x1257: 0x05fb,
+	0x1258: 0x05ff, 0x1259: 0x0603, 0x125a: 0x0607, 0x125b: 0x060b, 0x125c: 0x060f, 0x125d: 0x061f,
+	0x125e: 0x49ff, 0x125f: 0x4a05, 0x1260: 0x03c3, 0x1261: 0x0313, 0x1262: 0x0317, 0x1263: 0x043b,
+	0x1264: 0x031b, 0x1265: 0x043f, 0x1266: 0x0443, 0x1267: 0x031f, 0x1268: 0x0323, 0x1269: 0x0327,
+	0x126a: 0x0447, 0x126b: 0x044b, 0x126c: 0x044f, 0x126d: 0x0453, 0x126e: 0x0457, 0x126f: 0x045b,
+	0x1270: 0x0367, 0x1271: 0x032b, 0x1272: 0x032f, 0x1273: 0x0333, 0x1274: 0x037b, 0x1275: 0x0337,
+	0x1276: 0x033b, 0x1277: 0x033f, 0x1278: 0x0343, 0x1279: 0x0347, 0x127a: 0x034b, 0x127b: 0x034f,
+	0x127c: 0x0353, 0x127d: 0x0357, 0x127e: 0x035b,
+	// Block 0x4a, offset 0x1280
+	0x1280: 0x0063, 0x1281: 0x0065, 0x1282: 0x0067, 0x1283: 0x0069, 0x1284: 0x006b, 0x1285: 0x006d,
+	0x1286: 0x006f, 0x1287: 0x0071, 0x1288: 0x0073, 0x1289: 0x0075, 0x128a: 0x0083, 0x128b: 0x0085,
+	0x128c: 0x0087, 0x128d: 0x0089, 0x128e: 0x008b, 0x128f: 0x008d, 0x1290: 0x008f, 0x1291: 0x0091,
+	0x1292: 0x0093, 0x1293: 0x0095, 0x1294: 0x0097, 0x1295: 0x0099, 0x1296: 0x009b, 0x1297: 0x009d,
+	0x1298: 0x009f, 0x1299: 0x00a1, 0x129a: 0x00a3, 0x129b: 0x00a5, 0x129c: 0x00a7, 0x129d: 0x00a9,
+	0x129e: 0x00ab, 0x129f: 0x00ad, 0x12a0: 0x00af, 0x12a1: 0x00b1, 0x12a2: 0x00b3, 0x12a3: 0x00b5,
+	0x12a4: 0x00dd, 0x12a5: 0x00f2, 0x12a8: 0x0173, 0x12a9: 0x0176,
+	0x12aa: 0x0179, 0x12ab: 0x017c, 0x12ac: 0x017f, 0x12ad: 0x0182, 0x12ae: 0x0185, 0x12af: 0x0188,
+	0x12b0: 0x018b, 0x12b1: 0x018e, 0x12b2: 0x0191, 0x12b3: 0x0194, 0x12b4: 0x0197, 0x12b5: 0x019a,
+	0x12b6: 0x019d, 0x12b7: 0x01a0, 0x12b8: 0x01a3, 0x12b9: 0x0188, 0x12ba: 0x01a6, 0x12bb: 0x01a9,
+	0x12bc: 0x01ac, 0x12bd: 0x01af, 0x12be: 0x01b2, 0x12bf: 0x01b5,
+	// Block 0x4b, offset 0x12c0
+	0x12c0: 0x01fd, 0x12c1: 0x0200, 0x12c2: 0x0203, 0x12c3: 0x04d3, 0x12c4: 0x01c7, 0x12c5: 0x01d0,
+	0x12c6: 0x01d6, 0x12c7: 0x01fa, 0x12c8: 0x01eb, 0x12c9: 0x01e8, 0x12ca: 0x0206, 0x12cb: 0x0209,
+	0x12ce: 0x0021, 0x12cf: 0x0023, 0x12d0: 0x0025, 0x12d1: 0x0027,
+	0x12d2: 0x0029, 0x12d3: 0x002b, 0x12d4: 0x002d, 0x12d5: 0x002f, 0x12d6: 0x0031, 0x12d7: 0x0033,
+	0x12d8: 0x0021, 0x12d9: 0x0023, 0x12da: 0x0025, 0x12db: 0x0027, 0x12dc: 0x0029, 0x12dd: 0x002b,
+	0x12de: 0x002d, 0x12df: 0x002f, 0x12e0: 0x0031, 0x12e1: 0x0033, 0x12e2: 0x0021, 0x12e3: 0x0023,
+	0x12e4: 0x0025, 0x12e5: 0x0027, 0x12e6: 0x0029, 0x12e7: 0x002b, 0x12e8: 0x002d, 0x12e9: 0x002f,
+	0x12ea: 0x0031, 0x12eb: 0x0033, 0x12ec: 0x0021, 0x12ed: 0x0023, 0x12ee: 0x0025, 0x12ef: 0x0027,
+	0x12f0: 0x0029, 0x12f1: 0x002b, 0x12f2: 0x002d, 0x12f3: 0x002f, 0x12f4: 0x0031, 0x12f5: 0x0033,
+	0x12f6: 0x0021, 0x12f7: 0x0023, 0x12f8: 0x0025, 0x12f9: 0x0027, 0x12fa: 0x0029, 0x12fb: 0x002b,
+	0x12fc: 0x002d, 0x12fd: 0x002f, 0x12fe: 0x0031, 0x12ff: 0x0033,
+	// Block 0x4c, offset 0x1300
+	0x1300: 0x0239, 0x1301: 0x023c, 0x1302: 0x0248, 0x1303: 0x0251, 0x1305: 0x028a,
+	0x1306: 0x025a, 0x1307: 0x024b, 0x1308: 0x0269, 0x1309: 0x0290, 0x130a: 0x027b, 0x130b: 0x027e,
+	0x130c: 0x0281, 0x130d: 0x0284, 0x130e: 0x025d, 0x130f: 0x026f, 0x1310: 0x0275, 0x1311: 0x0263,
+	0x1312: 0x0278, 0x1313: 0x0257, 0x1314: 0x0260, 0x1315: 0x0242, 0x1316: 0x0245, 0x1317: 0x024e,
+	0x1318: 0x0254, 0x1319: 0x0266, 0x131a: 0x026c, 0x131b: 0x0272, 0x131c: 0x0293, 0x131d: 0x02e4,
+	0x131e: 0x02cc, 0x131f: 0x0296, 0x1321: 0x023c, 0x1322: 0x0248,
+	0x1324: 0x0287, 0x1327: 0x024b, 0x1329: 0x0290,
+	0x132a: 0x027b, 0x132b: 0x027e, 0x132c: 0x0281, 0x132d: 0x0284, 0x132e: 0x025d, 0x132f: 0x026f,
+	0x1330: 0x0275, 0x1331: 0x0263, 0x1332: 0x0278, 0x1334: 0x0260, 0x1335: 0x0242,
+	0x1336: 0x0245, 0x1337: 0x024e, 0x1339: 0x0266, 0x133b: 0x0272,
+	// Block 0x4d, offset 0x1340
+	0x1342: 0x0248,
+	0x1347: 0x024b, 0x1349: 0x0290, 0x134b: 0x027e,
+	0x134d: 0x0284, 0x134e: 0x025d, 0x134f: 0x026f, 0x1351: 0x0263,
+	0x1352: 0x0278, 0x1354: 0x0260, 0x1357: 0x024e,
+	0x1359: 0x0266, 0x135b: 0x0272, 0x135d: 0x02e4,
+	0x135f: 0x0296, 0x1361: 0x023c, 0x1362: 0x0248,
+	0x1364: 0x0287, 0x1367: 0x024b, 0x1368: 0x0269, 0x1369: 0x0290,
+	0x136a: 0x027b, 0x136c: 0x0281, 0x136d: 0x0284, 0x136e: 0x025d, 0x136f: 0x026f,
+	0x1370: 0x0275, 0x1371: 0x0263, 0x1372: 0x0278, 0x1374: 0x0260, 0x1375: 0x0242,
+	0x1376: 0x0245, 0x1377: 0x024e, 0x1379: 0x0266, 0x137a: 0x026c, 0x137b: 0x0272,
+	0x137c: 0x0293, 0x137e: 0x02cc,
+	// Block 0x4e, offset 0x1380
+	0x1380: 0x0239, 0x1381: 0x023c, 0x1382: 0x0248, 0x1383: 0x0251, 0x1384: 0x0287, 0x1385: 0x028a,
+	0x1386: 0x025a, 0x1387: 0x024b, 0x1388: 0x0269, 0x1389: 0x0290, 0x138b: 0x027e,
+	0x138c: 0x0281, 0x138d: 0x0284, 0x138e: 0x025d, 0x138f: 0x026f, 0x1390: 0x0275, 0x1391: 0x0263,
+	0x1392: 0x0278, 0x1393: 0x0257, 0x1394: 0x0260, 0x1395: 0x0242, 0x1396: 0x0245, 0x1397: 0x024e,
+	0x1398: 0x0254, 0x1399: 0x0266, 0x139a: 0x026c, 0x139b: 0x0272,
+	0x13a1: 0x023c, 0x13a2: 0x0248, 0x13a3: 0x0251,
+	0x13a5: 0x028a, 0x13a6: 0x025a, 0x13a7: 0x024b, 0x13a8: 0x0269, 0x13a9: 0x0290,
+	0x13ab: 0x027e, 0x13ac: 0x0281, 0x13ad: 0x0284, 0x13ae: 0x025d, 0x13af: 0x026f,
+	0x13b0: 0x0275, 0x13b1: 0x0263, 0x13b2: 0x0278, 0x13b3: 0x0257, 0x13b4: 0x0260, 0x13b5: 0x0242,
+	0x13b6: 0x0245, 0x13b7: 0x024e, 0x13b8: 0x0254, 0x13b9: 0x0266, 0x13ba: 0x026c, 0x13bb: 0x0272,
+	// Block 0x4f, offset 0x13c0
+	0x13c0: 0x1a0c, 0x13c1: 0x1a09, 0x13c2: 0x1a0f, 0x13c3: 0x1a33, 0x13c4: 0x1a57, 0x13c5: 0x1a7b,
+	0x13c6: 0x1a9f, 0x13c7: 0x1aa8, 0x13c8: 0x1aae, 0x13c9: 0x1ab4, 0x13ca: 0x1aba,
+	0x13d0: 0x1c1f, 0x13d1: 0x1c23,
+	0x13d2: 0x1c27, 0x13d3: 0x1c2b, 0x13d4: 0x1c2f, 0x13d5: 0x1c33, 0x13d6: 0x1c37, 0x13d7: 0x1c3b,
+	0x13d8: 0x1c3f, 0x13d9: 0x1c43, 0x13da: 0x1c47, 0x13db: 0x1c4b, 0x13dc: 0x1c4f, 0x13dd: 0x1c53,
+	0x13de: 0x1c57, 0x13df: 0x1c5b, 0x13e0: 0x1c5f, 0x13e1: 0x1c63, 0x13e2: 0x1c67, 0x13e3: 0x1c6b,
+	0x13e4: 0x1c6f, 0x13e5: 0x1c73, 0x13e6: 0x1c77, 0x13e7: 0x1c7b, 0x13e8: 0x1c7f, 0x13e9: 0x1c83,
+	0x13ea: 0x291a, 0x13eb: 0x0047, 0x13ec: 0x0065, 0x13ed: 0x1acf, 0x13ee: 0x1b44,
+	0x13f0: 0x0043, 0x13f1: 0x0045, 0x13f2: 0x0047, 0x13f3: 0x0049, 0x13f4: 0x004b, 0x13f5: 0x004d,
+	0x13f6: 0x004f, 0x13f7: 0x0051, 0x13f8: 0x0053, 0x13f9: 0x0055, 0x13fa: 0x0057, 0x13fb: 0x0059,
+	0x13fc: 0x005b, 0x13fd: 0x005d, 0x13fe: 0x005f, 0x13ff: 0x0061,
+	// Block 0x50, offset 0x1400
+	0x1400: 0x28a9, 0x1401: 0x28be, 0x1402: 0x057b,
+	0x1410: 0x0c87, 0x1411: 0x0abf,
+	0x1412: 0x094b, 0x1413: 0x45ff, 0x1414: 0x0793, 0x1415: 0x0a67, 0x1416: 0x13a7, 0x1417: 0x0a77,
+	0x1418: 0x079f, 0x1419: 0x0d4f, 0x141a: 0x0f27, 0x141b: 0x0d27, 0x141c: 0x089f, 0x141d: 0x0be3,
+	0x141e: 0x0837, 0x141f: 0x0d2f, 0x1420: 0x088b, 0x1421: 0x118f, 0x1422: 0x0ffb, 0x1423: 0x1403,
+	0x1424: 0x0a4b, 0x1425: 0x0983, 0x1426: 0x0edb, 0x1427: 0x0c93, 0x1428: 0x0cbf, 0x1429: 0x0737,
+	0x142a: 0x0743, 0x142b: 0x1483, 0x142c: 0x0b53, 0x142d: 0x075f, 0x142e: 0x0967, 0x142f: 0x0cb3,
+	0x1430: 0x142b, 0x1431: 0x0c8b, 0x1432: 0x10e7, 0x1433: 0x1123, 0x1434: 0x096f, 0x1435: 0x0ebb,
+	0x1436: 0x0d83, 0x1437: 0x0d7f, 0x1438: 0x100f, 0x1439: 0x08a3, 0x143a: 0x09cf,
+	// Block 0x51, offset 0x1440
+	0x1440: 0x0773, 0x1441: 0x076b, 0x1442: 0x077b, 0x1443: 0x16bb, 0x1444: 0x07bf, 0x1445: 0x07cf,
+	0x1446: 0x07d3, 0x1447: 0x07db, 0x1448: 0x07e3, 0x1449: 0x07e7, 0x144a: 0x07f3, 0x144b: 0x07eb,
+	0x144c: 0x062b, 0x144d: 0x16cf, 0x144e: 0x0807, 0x144f: 0x080b, 0x1450: 0x080f, 0x1451: 0x082b,
+	0x1452: 0x16c0, 0x1453: 0x062f, 0x1454: 0x0817, 0x1455: 0x0837, 0x1456: 0x16ca, 0x1457: 0x0847,
+	0x1458: 0x084f, 0x1459: 0x07af, 0x145a: 0x0857, 0x145b: 0x085b, 0x145c: 0x18a5, 0x145d: 0x0877,
+	0x145e: 0x087f, 0x145f: 0x0637, 0x1460: 0x0897, 0x1461: 0x089b, 0x1462: 0x08a3, 0x1463: 0x08a7,
+	0x1464: 0x063b, 0x1465: 0x08bf, 0x1466: 0x08c3, 0x1467: 0x08cf, 0x1468: 0x08db, 0x1469: 0x08df,
+	0x146a: 0x08e3, 0x146b: 0x08eb, 0x146c: 0x090b, 0x146d: 0x090f, 0x146e: 0x0917, 0x146f: 0x0927,
+	0x1470: 0x092f, 0x1471: 0x0933, 0x1472: 0x0933, 0x1473: 0x0933, 0x1474: 0x16de, 0x1475: 0x0f0b,
+	0x1476: 0x0947, 0x1477: 0x094f, 0x1478: 0x16e3, 0x1479: 0x095b, 0x147a: 0x0963, 0x147b: 0x096b,
+	0x147c: 0x0993, 0x147d: 0x097f, 0x147e: 0x098b, 0x147f: 0x098f,
+	// Block 0x52, offset 0x1480
+	0x1480: 0x0997, 0x1481: 0x099f, 0x1482: 0x09a3, 0x1483: 0x09ab, 0x1484: 0x09b3, 0x1485: 0x09b7,
+	0x1486: 0x09b7, 0x1487: 0x09bf, 0x1488: 0x09c7, 0x1489: 0x09cb, 0x148a: 0x09d7, 0x148b: 0x09fb,
+	0x148c: 0x09df, 0x148d: 0x09ff, 0x148e: 0x09e3, 0x148f: 0x09eb, 0x1490: 0x0883, 0x1491: 0x0a47,
+	0x1492: 0x0a0f, 0x1493: 0x0a13, 0x1494: 0x0a17, 0x1495: 0x0a0b, 0x1496: 0x0a1f, 0x1497: 0x0a1b,
+	0x1498: 0x0a33, 0x1499: 0x16e8, 0x149a: 0x0a4f, 0x149b: 0x0a53, 0x149c: 0x0a5b, 0x149d: 0x0a67,
+	0x149e: 0x0a6f, 0x149f: 0x0a8b, 0x14a0: 0x16ed, 0x14a1: 0x16f2, 0x14a2: 0x0a97, 0x14a3: 0x0a9b,
+	0x14a4: 0x0a9f, 0x14a5: 0x0a93, 0x14a6: 0x0aa7, 0x14a7: 0x063f, 0x14a8: 0x0643, 0x14a9: 0x0aaf,
+	0x14aa: 0x0ab7, 0x14ab: 0x0ab7, 0x14ac: 0x16f7, 0x14ad: 0x0ad3, 0x14ae: 0x0ad7, 0x14af: 0x0adb,
+	0x14b0: 0x0ae3, 0x14b1: 0x16fc, 0x14b2: 0x0aeb, 0x14b3: 0x0aef, 0x14b4: 0x0bc7, 0x14b5: 0x0af7,
+	0x14b6: 0x0647, 0x14b7: 0x0b03, 0x14b8: 0x0b13, 0x14b9: 0x0b1f, 0x14ba: 0x0b1b, 0x14bb: 0x1706,
+	0x14bc: 0x0b27, 0x14bd: 0x170b, 0x14be: 0x0b33, 0x14bf: 0x0b2f,
+	// Block 0x53, offset 0x14c0
+	0x14c0: 0x0b37, 0x14c1: 0x0b47, 0x14c2: 0x0b4b, 0x14c3: 0x064b, 0x14c4: 0x0b5b, 0x14c5: 0x0b63,
+	0x14c6: 0x0b67, 0x14c7: 0x0b6b, 0x14c8: 0x064f, 0x14c9: 0x1710, 0x14ca: 0x0653, 0x14cb: 0x0b87,
+	0x14cc: 0x0b8b, 0x14cd: 0x0b8f, 0x14ce: 0x0b97, 0x14cf: 0x18d7, 0x14d0: 0x0baf, 0x14d1: 0x171a,
+	0x14d2: 0x171a, 0x14d3: 0x124f, 0x14d4: 0x0bbf, 0x14d5: 0x0bbf, 0x14d6: 0x0657, 0x14d7: 0x173d,
+	0x14d8: 0x180f, 0x14d9: 0x0bcf, 0x14da: 0x0bd7, 0x14db: 0x065b, 0x14dc: 0x0beb, 0x14dd: 0x0bfb,
+	0x14de: 0x0bff, 0x14df: 0x0c07, 0x14e0: 0x0c17, 0x14e1: 0x0663, 0x14e2: 0x065f, 0x14e3: 0x0c1b,
+	0x14e4: 0x171f, 0x14e5: 0x0c1f, 0x14e6: 0x0c33, 0x14e7: 0x0c37, 0x14e8: 0x0c3b, 0x14e9: 0x0c37,
+	0x14ea: 0x0c47, 0x14eb: 0x0c4b, 0x14ec: 0x0c5b, 0x14ed: 0x0c53, 0x14ee: 0x0c57, 0x14ef: 0x0c5f,
+	0x14f0: 0x0c63, 0x14f1: 0x0c67, 0x14f2: 0x0c73, 0x14f3: 0x0c77, 0x14f4: 0x0c8f, 0x14f5: 0x0c97,
+	0x14f6: 0x0ca7, 0x14f7: 0x0cbb, 0x14f8: 0x172e, 0x14f9: 0x0cb7, 0x14fa: 0x0cab, 0x14fb: 0x0cc3,
+	0x14fc: 0x0ccb, 0x14fd: 0x0cdf, 0x14fe: 0x1733, 0x14ff: 0x0ce7,
+	// Block 0x54, offset 0x1500
+	0x1500: 0x0cdb, 0x1501: 0x0cd3, 0x1502: 0x0667, 0x1503: 0x0cef, 0x1504: 0x0cf7, 0x1505: 0x0cff,
+	0x1506: 0x0cf3, 0x1507: 0x066b, 0x1508: 0x0d0f, 0x1509: 0x0d17, 0x150a: 0x1738, 0x150b: 0x0d43,
+	0x150c: 0x0d77, 0x150d: 0x0d53, 0x150e: 0x0677, 0x150f: 0x0d5f, 0x1510: 0x0673, 0x1511: 0x066f,
+	0x1512: 0x083b, 0x1513: 0x083f, 0x1514: 0x0d7b, 0x1515: 0x0d63, 0x1516: 0x1223, 0x1517: 0x06db,
+	0x1518: 0x0d87, 0x1519: 0x0d8b, 0x151a: 0x0d8f, 0x151b: 0x0da3, 0x151c: 0x0d9b, 0x151d: 0x1751,
+	0x151e: 0x067b, 0x151f: 0x0db7, 0x1520: 0x0dab, 0x1521: 0x0dc7, 0x1522: 0x0dcf, 0x1523: 0x175b,
+	0x1524: 0x0dd3, 0x1525: 0x0dbf, 0x1526: 0x0ddb, 0x1527: 0x067f, 0x1528: 0x0ddf, 0x1529: 0x0de3,
+	0x152a: 0x0de7, 0x152b: 0x0df3, 0x152c: 0x1760, 0x152d: 0x0dfb, 0x152e: 0x0683, 0x152f: 0x0e07,
+	0x1530: 0x1765, 0x1531: 0x0e0b, 0x1532: 0x0687, 0x1533: 0x0e17, 0x1534: 0x0e23, 0x1535: 0x0e2f,
+	0x1536: 0x0e33, 0x1537: 0x176a, 0x1538: 0x1701, 0x1539: 0x176f, 0x153a: 0x0e53, 0x153b: 0x1774,
+	0x153c: 0x0e5f, 0x153d: 0x0e67, 0x153e: 0x0e57, 0x153f: 0x0e73,
+	// Block 0x55, offset 0x1540
+	0x1540: 0x0e83, 0x1541: 0x0e93, 0x1542: 0x0e87, 0x1543: 0x0e8b, 0x1544: 0x0e97, 0x1545: 0x0e9b,
+	0x1546: 0x1779, 0x1547: 0x0e7f, 0x1548: 0x0eb3, 0x1549: 0x0eb7, 0x154a: 0x068b, 0x154b: 0x0ecb,
+	0x154c: 0x0ec7, 0x154d: 0x177e, 0x154e: 0x0eab, 0x154f: 0x0ee7, 0x1550: 0x1783, 0x1551: 0x1788,
+	0x1552: 0x0eeb, 0x1553: 0x0eff, 0x1554: 0x0efb, 0x1555: 0x0ef7, 0x1556: 0x068f, 0x1557: 0x0f03,
+	0x1558: 0x0f13, 0x1559: 0x0f0f, 0x155a: 0x0f1b, 0x155b: 0x16c5, 0x155c: 0x0f2b, 0x155d: 0x178d,
+	0x155e: 0x0f37, 0x155f: 0x1797, 0x1560: 0x0f4b, 0x1561: 0x0f57, 0x1562: 0x0f6b, 0x1563: 0x179c,
+	0x1564: 0x0f7f, 0x1565: 0x0f83, 0x1566: 0x17a1, 0x1567: 0x17a6, 0x1568: 0x0f9f, 0x1569: 0x0faf,
+	0x156a: 0x0693, 0x156b: 0x0fb3, 0x156c: 0x0697, 0x156d: 0x0697, 0x156e: 0x0fcb, 0x156f: 0x0fcf,
+	0x1570: 0x0fd7, 0x1571: 0x0fdb, 0x1572: 0x0fe7, 0x1573: 0x069b, 0x1574: 0x0fff, 0x1575: 0x17ab,
+	0x1576: 0x101b, 0x1577: 0x17b0, 0x1578: 0x1027, 0x1579: 0x1715, 0x157a: 0x1037, 0x157b: 0x17b5,
+	0x157c: 0x17ba, 0x157d: 0x17bf, 0x157e: 0x069f, 0x157f: 0x06a3,
+	// Block 0x56, offset 0x1580
+	0x1580: 0x106f, 0x1581: 0x17c9, 0x1582: 0x17c4, 0x1583: 0x17ce, 0x1584: 0x17d3, 0x1585: 0x1077,
+	0x1586: 0x107b, 0x1587: 0x107b, 0x1588: 0x1083, 0x1589: 0x06ab, 0x158a: 0x1087, 0x158b: 0x06af,
+	0x158c: 0x06b3, 0x158d: 0x17dd, 0x158e: 0x109b, 0x158f: 0x10a3, 0x1590: 0x10af, 0x1591: 0x06b7,
+	0x1592: 0x17e2, 0x1593: 0x10d3, 0x1594: 0x17e7, 0x1595: 0x17ec, 0x1596: 0x10f3, 0x1597: 0x110b,
+	0x1598: 0x06bb, 0x1599: 0x1113, 0x159a: 0x1117, 0x159b: 0x111b, 0x159c: 0x17f1, 0x159d: 0x17f6,
+	0x159e: 0x17f6, 0x159f: 0x1133, 0x15a0: 0x06bf, 0x15a1: 0x17fb, 0x15a2: 0x1147, 0x15a3: 0x114b,
+	0x15a4: 0x06c3, 0x15a5: 0x1800, 0x15a6: 0x1167, 0x15a7: 0x06c7, 0x15a8: 0x1177, 0x15a9: 0x116f,
+	0x15aa: 0x117f, 0x15ab: 0x180a, 0x15ac: 0x1197, 0x15ad: 0x06cb, 0x15ae: 0x11a3, 0x15af: 0x11ab,
+	0x15b0: 0x11bb, 0x15b1: 0x06cf, 0x15b2: 0x1814, 0x15b3: 0x1819, 0x15b4: 0x06d3, 0x15b5: 0x181e,
+	0x15b6: 0x11d3, 0x15b7: 0x1823, 0x15b8: 0x11df, 0x15b9: 0x11eb, 0x15ba: 0x11f3, 0x15bb: 0x1828,
+	0x15bc: 0x182d, 0x15bd: 0x1207, 0x15be: 0x1832, 0x15bf: 0x120f,
+	// Block 0x57, offset 0x15c0
+	0x15c0: 0x1742, 0x15c1: 0x06d7, 0x15c2: 0x1227, 0x15c3: 0x122b, 0x15c4: 0x06df, 0x15c5: 0x122f,
+	0x15c6: 0x0aab, 0x15c7: 0x1837, 0x15c8: 0x183c, 0x15c9: 0x1747, 0x15ca: 0x174c, 0x15cb: 0x124f,
+	0x15cc: 0x1253, 0x15cd: 0x146b, 0x15ce: 0x06e3, 0x15cf: 0x127f, 0x15d0: 0x127b, 0x15d1: 0x1283,
+	0x15d2: 0x08b7, 0x15d3: 0x1287, 0x15d4: 0x128b, 0x15d5: 0x128f, 0x15d6: 0x1297, 0x15d7: 0x1841,
+	0x15d8: 0x1293, 0x15d9: 0x129b, 0x15da: 0x12af, 0x15db: 0x12b3, 0x15dc: 0x129f, 0x15dd: 0x12b7,
+	0x15de: 0x12cb, 0x15df: 0x12df, 0x15e0: 0x12ab, 0x15e1: 0x12bf, 0x15e2: 0x12c3, 0x15e3: 0x12c7,
+	0x15e4: 0x1846, 0x15e5: 0x1850, 0x15e6: 0x184b, 0x15e7: 0x06e7, 0x15e8: 0x12e7, 0x15e9: 0x12eb,
+	0x15ea: 0x12f3, 0x15eb: 0x1864, 0x15ec: 0x12f7, 0x15ed: 0x1855, 0x15ee: 0x06eb, 0x15ef: 0x06ef,
+	0x15f0: 0x185a, 0x15f1: 0x185f, 0x15f2: 0x06f3, 0x15f3: 0x1317, 0x15f4: 0x131b, 0x15f5: 0x131f,
+	0x15f6: 0x1323, 0x15f7: 0x132f, 0x15f8: 0x132b, 0x15f9: 0x1337, 0x15fa: 0x1333, 0x15fb: 0x1343,
+	0x15fc: 0x133b, 0x15fd: 0x133f, 0x15fe: 0x1347, 0x15ff: 0x06f7,
+	// Block 0x58, offset 0x1600
+	0x1600: 0x134f, 0x1601: 0x1353, 0x1602: 0x06fb, 0x1603: 0x1363, 0x1604: 0x1367, 0x1605: 0x1869,
+	0x1606: 0x1373, 0x1607: 0x1377, 0x1608: 0x06ff, 0x1609: 0x1383, 0x160a: 0x0633, 0x160b: 0x186e,
+	0x160c: 0x1873, 0x160d: 0x0703, 0x160e: 0x0707, 0x160f: 0x13af, 0x1610: 0x13c7, 0x1611: 0x13e3,
+	0x1612: 0x13f3, 0x1613: 0x1878, 0x1614: 0x1407, 0x1615: 0x140b, 0x1616: 0x1423, 0x1617: 0x142f,
+	0x1618: 0x1882, 0x1619: 0x16d4, 0x161a: 0x143b, 0x161b: 0x1437, 0x161c: 0x1443, 0x161d: 0x16d9,
+	0x161e: 0x144f, 0x161f: 0x145b, 0x1620: 0x1887, 0x1621: 0x188c, 0x1622: 0x149b, 0x1623: 0x14a7,
+	0x1624: 0x14af, 0x1625: 0x1891, 0x1626: 0x14b3, 0x1627: 0x14db, 0x1628: 0x14e7, 0x1629: 0x14eb,
+	0x162a: 0x14e3, 0x162b: 0x14f7, 0x162c: 0x14fb, 0x162d: 0x1896, 0x162e: 0x1507, 0x162f: 0x070b,
+	0x1630: 0x150f, 0x1631: 0x189b, 0x1632: 0x070f, 0x1633: 0x1547, 0x1634: 0x0b3b, 0x1635: 0x155f,
+	0x1636: 0x18a0, 0x1637: 0x18aa, 0x1638: 0x0713, 0x1639: 0x0717, 0x163a: 0x1587, 0x163b: 0x18af,
+	0x163c: 0x071b, 0x163d: 0x18b4, 0x163e: 0x159f, 0x163f: 0x159f,
+	// Block 0x59, offset 0x1640
+	0x1640: 0x15a7, 0x1641: 0x18b9, 0x1642: 0x15bf, 0x1643: 0x071f, 0x1644: 0x15cf, 0x1645: 0x15db,
+	0x1646: 0x15e3, 0x1647: 0x15eb, 0x1648: 0x0723, 0x1649: 0x18be, 0x164a: 0x15ff, 0x164b: 0x161b,
+	0x164c: 0x1627, 0x164d: 0x0727, 0x164e: 0x072b, 0x164f: 0x162b, 0x1650: 0x18c3, 0x1651: 0x072f,
+	0x1652: 0x18c8, 0x1653: 0x18cd, 0x1654: 0x18d2, 0x1655: 0x164f, 0x1656: 0x0733, 0x1657: 0x1663,
+	0x1658: 0x166b, 0x1659: 0x166f, 0x165a: 0x1677, 0x165b: 0x167f, 0x165c: 0x1687, 0x165d: 0x18dc,
+}
+
+// nfkcIndex: 22 blocks, 1408 entries, 1408 bytes
+// Block 0 is the zero block.
+var nfkcIndex = [1408]uint8{
+	// Block 0x0, offset 0x0
+	// Block 0x1, offset 0x40
+	// Block 0x2, offset 0x80
+	// Block 0x3, offset 0xc0
+	0xc2: 0x58, 0xc3: 0x01, 0xc4: 0x02, 0xc5: 0x03, 0xc6: 0x59, 0xc7: 0x04,
+	0xc8: 0x05, 0xca: 0x5a, 0xcb: 0x5b, 0xcc: 0x06, 0xcd: 0x07, 0xce: 0x08, 0xcf: 0x09,
+	0xd0: 0x0a, 0xd1: 0x5c, 0xd2: 0x5d, 0xd3: 0x0b, 0xd6: 0x0c, 0xd7: 0x5e,
+	0xd8: 0x5f, 0xd9: 0x0d, 0xdb: 0x60, 0xdc: 0x61, 0xdd: 0x62, 0xdf: 0x63,
+	0xe0: 0x02, 0xe1: 0x03, 0xe2: 0x04, 0xe3: 0x05,
+	0xea: 0x06, 0xeb: 0x07, 0xec: 0x08, 0xed: 0x09, 0xef: 0x0a,
+	0xf0: 0x13,
+	// Block 0x4, offset 0x100
+	0x120: 0x64, 0x121: 0x65, 0x123: 0x66, 0x124: 0x67, 0x125: 0x68, 0x126: 0x69, 0x127: 0x6a,
+	0x128: 0x6b, 0x129: 0x6c, 0x12a: 0x6d, 0x12b: 0x6e, 0x12c: 0x69, 0x12d: 0x6f, 0x12e: 0x70, 0x12f: 0x71,
+	0x131: 0x72, 0x132: 0x73, 0x133: 0x74, 0x134: 0x75, 0x135: 0x76, 0x137: 0x77,
+	0x138: 0x78, 0x139: 0x79, 0x13a: 0x7a, 0x13b: 0x7b, 0x13c: 0x7c, 0x13d: 0x7d, 0x13e: 0x7e, 0x13f: 0x7f,
+	// Block 0x5, offset 0x140
+	0x140: 0x80, 0x142: 0x81, 0x143: 0x82, 0x144: 0x83, 0x145: 0x84, 0x146: 0x85, 0x147: 0x86,
+	0x14d: 0x87,
+	0x15c: 0x88, 0x15f: 0x89,
+	0x162: 0x8a, 0x164: 0x8b,
+	0x168: 0x8c, 0x169: 0x8d, 0x16a: 0x8e, 0x16c: 0x0e, 0x16d: 0x8f, 0x16e: 0x90, 0x16f: 0x91,
+	0x170: 0x92, 0x173: 0x93, 0x174: 0x94, 0x175: 0x0f, 0x176: 0x10, 0x177: 0x95,
+	0x178: 0x11, 0x179: 0x12, 0x17a: 0x13, 0x17b: 0x14, 0x17c: 0x15, 0x17d: 0x16, 0x17e: 0x17, 0x17f: 0x18,
+	// Block 0x6, offset 0x180
+	0x180: 0x96, 0x181: 0x97, 0x182: 0x98, 0x183: 0x99, 0x184: 0x19, 0x185: 0x1a, 0x186: 0x9a, 0x187: 0x9b,
+	0x188: 0x9c, 0x189: 0x1b, 0x18a: 0x1c, 0x18b: 0x9d, 0x18c: 0x9e,
+	0x191: 0x1d, 0x192: 0x1e, 0x193: 0x9f,
+	0x1a8: 0xa0, 0x1a9: 0xa1, 0x1ab: 0xa2,
+	0x1b1: 0xa3, 0x1b3: 0xa4, 0x1b5: 0xa5, 0x1b7: 0xa6,
+	0x1ba: 0xa7, 0x1bb: 0xa8, 0x1bc: 0x1f, 0x1bd: 0x20, 0x1be: 0x21, 0x1bf: 0xa9,
+	// Block 0x7, offset 0x1c0
+	0x1c0: 0xaa, 0x1c1: 0x22, 0x1c2: 0x23, 0x1c3: 0x24, 0x1c4: 0xab, 0x1c5: 0xac, 0x1c6: 0x25,
+	0x1c8: 0x26, 0x1c9: 0x27, 0x1ca: 0x28, 0x1cb: 0x29, 0x1cc: 0x2a, 0x1cd: 0x2b, 0x1ce: 0x2c, 0x1cf: 0x2d,
+	// Block 0x8, offset 0x200
+	0x219: 0xad, 0x21a: 0xae, 0x21b: 0xaf, 0x21d: 0xb0, 0x21f: 0xb1,
+	0x220: 0xb2, 0x223: 0xb3, 0x224: 0xb4, 0x225: 0xb5, 0x226: 0xb6, 0x227: 0xb7,
+	0x22a: 0xb8, 0x22b: 0xb9, 0x22d: 0xba, 0x22f: 0xbb,
+	0x230: 0xbc, 0x231: 0xbd, 0x232: 0xbe, 0x233: 0xbf, 0x234: 0xc0, 0x235: 0xc1, 0x236: 0xc2, 0x237: 0xbc,
+	0x238: 0xbd, 0x239: 0xbe, 0x23a: 0xbf, 0x23b: 0xc0, 0x23c: 0xc1, 0x23d: 0xc2, 0x23e: 0xbc, 0x23f: 0xbd,
+	// Block 0x9, offset 0x240
+	0x240: 0xbe, 0x241: 0xbf, 0x242: 0xc0, 0x243: 0xc1, 0x244: 0xc2, 0x245: 0xbc, 0x246: 0xbd, 0x247: 0xbe,
+	0x248: 0xbf, 0x249: 0xc0, 0x24a: 0xc1, 0x24b: 0xc2, 0x24c: 0xbc, 0x24d: 0xbd, 0x24e: 0xbe, 0x24f: 0xbf,
+	0x250: 0xc0, 0x251: 0xc1, 0x252: 0xc2, 0x253: 0xbc, 0x254: 0xbd, 0x255: 0xbe, 0x256: 0xbf, 0x257: 0xc0,
+	0x258: 0xc1, 0x259: 0xc2, 0x25a: 0xbc, 0x25b: 0xbd, 0x25c: 0xbe, 0x25d: 0xbf, 0x25e: 0xc0, 0x25f: 0xc1,
+	0x260: 0xc2, 0x261: 0xbc, 0x262: 0xbd, 0x263: 0xbe, 0x264: 0xbf, 0x265: 0xc0, 0x266: 0xc1, 0x267: 0xc2,
+	0x268: 0xbc, 0x269: 0xbd, 0x26a: 0xbe, 0x26b: 0xbf, 0x26c: 0xc0, 0x26d: 0xc1, 0x26e: 0xc2, 0x26f: 0xbc,
+	0x270: 0xbd, 0x271: 0xbe, 0x272: 0xbf, 0x273: 0xc0, 0x274: 0xc1, 0x275: 0xc2, 0x276: 0xbc, 0x277: 0xbd,
+	0x278: 0xbe, 0x279: 0xbf, 0x27a: 0xc0, 0x27b: 0xc1, 0x27c: 0xc2, 0x27d: 0xbc, 0x27e: 0xbd, 0x27f: 0xbe,
+	// Block 0xa, offset 0x280
+	0x280: 0xbf, 0x281: 0xc0, 0x282: 0xc1, 0x283: 0xc2, 0x284: 0xbc, 0x285: 0xbd, 0x286: 0xbe, 0x287: 0xbf,
+	0x288: 0xc0, 0x289: 0xc1, 0x28a: 0xc2, 0x28b: 0xbc, 0x28c: 0xbd, 0x28d: 0xbe, 0x28e: 0xbf, 0x28f: 0xc0,
+	0x290: 0xc1, 0x291: 0xc2, 0x292: 0xbc, 0x293: 0xbd, 0x294: 0xbe, 0x295: 0xbf, 0x296: 0xc0, 0x297: 0xc1,
+	0x298: 0xc2, 0x299: 0xbc, 0x29a: 0xbd, 0x29b: 0xbe, 0x29c: 0xbf, 0x29d: 0xc0, 0x29e: 0xc1, 0x29f: 0xc2,
+	0x2a0: 0xbc, 0x2a1: 0xbd, 0x2a2: 0xbe, 0x2a3: 0xbf, 0x2a4: 0xc0, 0x2a5: 0xc1, 0x2a6: 0xc2, 0x2a7: 0xbc,
+	0x2a8: 0xbd, 0x2a9: 0xbe, 0x2aa: 0xbf, 0x2ab: 0xc0, 0x2ac: 0xc1, 0x2ad: 0xc2, 0x2ae: 0xbc, 0x2af: 0xbd,
+	0x2b0: 0xbe, 0x2b1: 0xbf, 0x2b2: 0xc0, 0x2b3: 0xc1, 0x2b4: 0xc2, 0x2b5: 0xbc, 0x2b6: 0xbd, 0x2b7: 0xbe,
+	0x2b8: 0xbf, 0x2b9: 0xc0, 0x2ba: 0xc1, 0x2bb: 0xc2, 0x2bc: 0xbc, 0x2bd: 0xbd, 0x2be: 0xbe, 0x2bf: 0xbf,
+	// Block 0xb, offset 0x2c0
+	0x2c0: 0xc0, 0x2c1: 0xc1, 0x2c2: 0xc2, 0x2c3: 0xbc, 0x2c4: 0xbd, 0x2c5: 0xbe, 0x2c6: 0xbf, 0x2c7: 0xc0,
+	0x2c8: 0xc1, 0x2c9: 0xc2, 0x2ca: 0xbc, 0x2cb: 0xbd, 0x2cc: 0xbe, 0x2cd: 0xbf, 0x2ce: 0xc0, 0x2cf: 0xc1,
+	0x2d0: 0xc2, 0x2d1: 0xbc, 0x2d2: 0xbd, 0x2d3: 0xbe, 0x2d4: 0xbf, 0x2d5: 0xc0, 0x2d6: 0xc1, 0x2d7: 0xc2,
+	0x2d8: 0xbc, 0x2d9: 0xbd, 0x2da: 0xbe, 0x2db: 0xbf, 0x2dc: 0xc0, 0x2dd: 0xc1, 0x2de: 0xc3,
+	// Block 0xc, offset 0x300
+	0x324: 0x2e, 0x325: 0x2f, 0x326: 0x30, 0x327: 0x31,
+	0x328: 0x32, 0x329: 0x33, 0x32a: 0x34, 0x32b: 0x35, 0x32c: 0x36, 0x32d: 0x37, 0x32e: 0x38, 0x32f: 0x39,
+	0x330: 0x3a, 0x331: 0x3b, 0x332: 0x3c, 0x333: 0x3d, 0x334: 0x3e, 0x335: 0x3f, 0x336: 0x40, 0x337: 0x41,
+	0x338: 0x42, 0x339: 0x43, 0x33a: 0x44, 0x33b: 0x45, 0x33c: 0xc4, 0x33d: 0x46, 0x33e: 0x47, 0x33f: 0xc5,
+	// Block 0xd, offset 0x340
+	0x347: 0xc6,
+	0x34b: 0xc7, 0x34d: 0xc8,
+	0x368: 0xc9, 0x36b: 0xca,
+	// Block 0xe, offset 0x380
+	0x381: 0xcb, 0x382: 0xcc, 0x384: 0xcd, 0x385: 0xb6, 0x387: 0xb7,
+	0x388: 0xce, 0x38b: 0xcf, 0x38c: 0x69, 0x38d: 0xd0,
+	0x392: 0xd1, 0x393: 0xd2, 0x396: 0xd3, 0x397: 0xd4,
+	0x398: 0xd5, 0x39a: 0xd6,
+	// Block 0xf, offset 0x3c0
+	0x3eb: 0xd7, 0x3ec: 0xd8,
+	// Block 0x10, offset 0x400
+	0x432: 0xd9,
+	// Block 0x11, offset 0x440
+	0x445: 0xda, 0x446: 0xdb, 0x447: 0xdc,
+	0x449: 0xdd,
+	0x450: 0xde, 0x451: 0xdf, 0x452: 0xe0, 0x453: 0xe1, 0x454: 0xe2, 0x455: 0xe3, 0x456: 0xe4, 0x457: 0xe5,
+	0x458: 0xe6, 0x459: 0xe7, 0x45a: 0x48, 0x45b: 0xe8, 0x45c: 0xe9, 0x45d: 0xea, 0x45e: 0xeb, 0x45f: 0x49,
+	// Block 0x12, offset 0x480
+	0x4a3: 0xec,
+	0x4b8: 0x4a, 0x4b9: 0x4b, 0x4ba: 0x4c,
+	// Block 0x13, offset 0x4c0
+	0x4c4: 0x4d, 0x4c5: 0xed, 0x4c6: 0xee,
+	0x4c8: 0x4e, 0x4c9: 0xef,
+	// Block 0x14, offset 0x500
+	0x520: 0x4f, 0x521: 0x50, 0x522: 0x51, 0x523: 0x52, 0x524: 0x53, 0x525: 0x54, 0x526: 0x55, 0x527: 0x56,
+	0x528: 0x57,
+	// Block 0x15, offset 0x540
+	0x550: 0x0b, 0x551: 0x0c, 0x556: 0x0d,
+	0x55b: 0x0e, 0x55d: 0x0f, 0x55e: 0x10, 0x55f: 0x11,
+	0x56f: 0x12,
+}
+
+// nfkcSparseOffset: 152 entries, 304 bytes
+var nfkcSparseOffset = []uint16{0x0, 0xe, 0x12, 0x1b, 0x25, 0x35, 0x37, 0x3c, 0x47, 0x56, 0x63, 0x6b, 0x6f, 0x74, 0x76, 0x85, 0x8d, 0x94, 0x97, 0x9f, 0xa3, 0xa7, 0xa9, 0xab, 0xb4, 0xb8, 0xbf, 0xc4, 0xc7, 0xd1, 0xd3, 0xda, 0xe2, 0xe6, 0xe8, 0xeb, 0xef, 0xf5, 0x106, 0x112, 0x114, 0x11a, 0x11c, 0x11e, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12b, 0x12e, 0x130, 0x133, 0x136, 0x13a, 0x13f, 0x148, 0x14a, 0x14d, 0x14f, 0x15a, 0x165, 0x174, 0x182, 0x190, 0x1a0, 0x1ae, 0x1b5, 0x1bb, 0x1ca, 0x1ce, 0x1d0, 0x1d4, 0x1d6, 0x1d9, 0x1db, 0x1de, 0x1e0, 0x1e3, 0x1e5, 0x1e7, 0x1e9, 0x1f5, 0x1ff, 0x206, 0x213, 0x216, 0x219, 0x21b, 0x21d, 0x21f, 0x221, 0x224, 0x226, 0x228, 0x22a, 0x22c, 0x232, 0x235, 0x239, 0x23b, 0x242, 0x248, 0x24e, 0x256, 0x25c, 0x262, 0x268, 0x26c, 0x26e, 0x27d, 0x27f, 0x281, 0x283, 0x289, 0x28c, 0x28f, 0x297, 0x29e, 0x2a1, 0x2a3, 0x2ab, 0x2b2, 0x2b5, 0x2bb, 0x2bd, 0x2bf, 0x2c2, 0x2c4, 0x2c6, 0x2c8, 0x2d5, 0x2df, 0x2e1, 0x2e3, 0x2e7, 0x2ec, 0x2f8, 0x2fd, 0x306, 0x30c, 0x311, 0x315, 0x31a, 0x31e, 0x32e, 0x33c, 0x34a, 0x358, 0x35a, 0x364, 0x366}
+
+// nfkcSparseValues: 880 entries, 3520 bytes
+var nfkcSparseValues = [880]valueRange{
+	// Block 0x0, offset 0x0
+	{value: 0x0002, lo: 0x0d},
+	{value: 0x0001, lo: 0xa0, hi: 0xa0},
+	{value: 0x42b3, lo: 0xa8, hi: 0xa8},
+	{value: 0x0083, lo: 0xaa, hi: 0xaa},
+	{value: 0x429f, lo: 0xaf, hi: 0xaf},
+	{value: 0x0025, lo: 0xb2, hi: 0xb3},
+	{value: 0x4295, lo: 0xb4, hi: 0xb4},
+	{value: 0x01dc, lo: 0xb5, hi: 0xb5},
+	{value: 0x42cc, lo: 0xb8, hi: 0xb8},
+	{value: 0x0023, lo: 0xb9, hi: 0xb9},
+	{value: 0x009f, lo: 0xba, hi: 0xba},
+	{value: 0x23af, lo: 0xbc, hi: 0xbc},
+	{value: 0x23a3, lo: 0xbd, hi: 0xbd},
+	{value: 0x2445, lo: 0xbe, hi: 0xbe},
+	// Block 0x1, offset 0xe
+	{value: 0x0091, lo: 0x03},
+	{value: 0x471d, lo: 0xa0, hi: 0xa1},
+	{value: 0x474f, lo: 0xaf, hi: 0xb0},
+	{value: 0xa000, lo: 0xb7, hi: 0xb7},
+	// Block 0x2, offset 0x12
+	{value: 0x0003, lo: 0x08},
+	{value: 0xa000, lo: 0x92, hi: 0x92},
+	{value: 0x0091, lo: 0xb0, hi: 0xb0},
+	{value: 0x0119, lo: 0xb1, hi: 0xb1},
+	{value: 0x0095, lo: 0xb2, hi: 0xb2},
+	{value: 0x00a5, lo: 0xb3, hi: 0xb3},
+	{value: 0x0143, lo: 0xb4, hi: 0xb6},
+	{value: 0x00af, lo: 0xb7, hi: 0xb7},
+	{value: 0x00b3, lo: 0xb8, hi: 0xb8},
+	// Block 0x3, offset 0x1b
+	{value: 0x000a, lo: 0x09},
+	{value: 0x42a9, lo: 0x98, hi: 0x98},
+	{value: 0x42ae, lo: 0x99, hi: 0x9a},
+	{value: 0x42d1, lo: 0x9b, hi: 0x9b},
+	{value: 0x429a, lo: 0x9c, hi: 0x9c},
+	{value: 0x42bd, lo: 0x9d, hi: 0x9d},
+	{value: 0x0113, lo: 0xa0, hi: 0xa0},
+	{value: 0x0099, lo: 0xa1, hi: 0xa1},
+	{value: 0x00a7, lo: 0xa2, hi: 0xa3},
+	{value: 0x0167, lo: 0xa4, hi: 0xa4},
+	// Block 0x4, offset 0x25
+	{value: 0x0000, lo: 0x0f},
+	{value: 0xa000, lo: 0x83, hi: 0x83},
+	{value: 0xa000, lo: 0x87, hi: 0x87},
+	{value: 0xa000, lo: 0x8b, hi: 0x8b},
+	{value: 0xa000, lo: 0x8d, hi: 0x8d},
+	{value: 0x37e0, lo: 0x90, hi: 0x90},
+	{value: 0x37ec, lo: 0x91, hi: 0x91},
+	{value: 0x37da, lo: 0x93, hi: 0x93},
+	{value: 0xa000, lo: 0x96, hi: 0x96},
+	{value: 0x3852, lo: 0x97, hi: 0x97},
+	{value: 0x381c, lo: 0x9c, hi: 0x9c},
+	{value: 0x3804, lo: 0x9d, hi: 0x9d},
+	{value: 0x382e, lo: 0x9e, hi: 0x9e},
+	{value: 0xa000, lo: 0xb4, hi: 0xb5},
+	{value: 0x3858, lo: 0xb6, hi: 0xb6},
+	{value: 0x385e, lo: 0xb7, hi: 0xb7},
+	// Block 0x5, offset 0x35
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8132, lo: 0x83, hi: 0x87},
+	// Block 0x6, offset 0x37
+	{value: 0x0001, lo: 0x04},
+	{value: 0x8113, lo: 0x81, hi: 0x82},
+	{value: 0x8132, lo: 0x84, hi: 0x84},
+	{value: 0x812d, lo: 0x85, hi: 0x85},
+	{value: 0x810d, lo: 0x87, hi: 0x87},
+	// Block 0x7, offset 0x3c
+	{value: 0x0000, lo: 0x0a},
+	{value: 0x8132, lo: 0x90, hi: 0x97},
+	{value: 0x8119, lo: 0x98, hi: 0x98},
+	{value: 0x811a, lo: 0x99, hi: 0x99},
+	{value: 0x811b, lo: 0x9a, hi: 0x9a},
+	{value: 0x387c, lo: 0xa2, hi: 0xa2},
+	{value: 0x3882, lo: 0xa3, hi: 0xa3},
+	{value: 0x388e, lo: 0xa4, hi: 0xa4},
+	{value: 0x3888, lo: 0xa5, hi: 0xa5},
+	{value: 0x3894, lo: 0xa6, hi: 0xa6},
+	{value: 0xa000, lo: 0xa7, hi: 0xa7},
+	// Block 0x8, offset 0x47
+	{value: 0x0000, lo: 0x0e},
+	{value: 0x38a6, lo: 0x80, hi: 0x80},
+	{value: 0xa000, lo: 0x81, hi: 0x81},
+	{value: 0x389a, lo: 0x82, hi: 0x82},
+	{value: 0xa000, lo: 0x92, hi: 0x92},
+	{value: 0x38a0, lo: 0x93, hi: 0x93},
+	{value: 0xa000, lo: 0x95, hi: 0x95},
+	{value: 0x8132, lo: 0x96, hi: 0x9c},
+	{value: 0x8132, lo: 0x9f, hi: 0xa2},
+	{value: 0x812d, lo: 0xa3, hi: 0xa3},
+	{value: 0x8132, lo: 0xa4, hi: 0xa4},
+	{value: 0x8132, lo: 0xa7, hi: 0xa8},
+	{value: 0x812d, lo: 0xaa, hi: 0xaa},
+	{value: 0x8132, lo: 0xab, hi: 0xac},
+	{value: 0x812d, lo: 0xad, hi: 0xad},
+	// Block 0x9, offset 0x56
+	{value: 0x0000, lo: 0x0c},
+	{value: 0x811f, lo: 0x91, hi: 0x91},
+	{value: 0x8132, lo: 0xb0, hi: 0xb0},
+	{value: 0x812d, lo: 0xb1, hi: 0xb1},
+	{value: 0x8132, lo: 0xb2, hi: 0xb3},
+	{value: 0x812d, lo: 0xb4, hi: 0xb4},
+	{value: 0x8132, lo: 0xb5, hi: 0xb6},
+	{value: 0x812d, lo: 0xb7, hi: 0xb9},
+	{value: 0x8132, lo: 0xba, hi: 0xba},
+	{value: 0x812d, lo: 0xbb, hi: 0xbc},
+	{value: 0x8132, lo: 0xbd, hi: 0xbd},
+	{value: 0x812d, lo: 0xbe, hi: 0xbe},
+	{value: 0x8132, lo: 0xbf, hi: 0xbf},
+	// Block 0xa, offset 0x63
+	{value: 0x0005, lo: 0x07},
+	{value: 0x8132, lo: 0x80, hi: 0x80},
+	{value: 0x8132, lo: 0x81, hi: 0x81},
+	{value: 0x812d, lo: 0x82, hi: 0x83},
+	{value: 0x812d, lo: 0x84, hi: 0x85},
+	{value: 0x812d, lo: 0x86, hi: 0x87},
+	{value: 0x812d, lo: 0x88, hi: 0x89},
+	{value: 0x8132, lo: 0x8a, hi: 0x8a},
+	// Block 0xb, offset 0x6b
+	{value: 0x0000, lo: 0x03},
+	{value: 0x8132, lo: 0xab, hi: 0xb1},
+	{value: 0x812d, lo: 0xb2, hi: 0xb2},
+	{value: 0x8132, lo: 0xb3, hi: 0xb3},
+	// Block 0xc, offset 0x6f
+	{value: 0x0000, lo: 0x04},
+	{value: 0x8132, lo: 0x96, hi: 0x99},
+	{value: 0x8132, lo: 0x9b, hi: 0xa3},
+	{value: 0x8132, lo: 0xa5, hi: 0xa7},
+	{value: 0x8132, lo: 0xa9, hi: 0xad},
+	// Block 0xd, offset 0x74
+	{value: 0x0000, lo: 0x01},
+	{value: 0x812d, lo: 0x99, hi: 0x9b},
+	// Block 0xe, offset 0x76
+	{value: 0x0000, lo: 0x0e},
+	{value: 0x8132, lo: 0xa4, hi: 0xa5},
+	{value: 0x812d, lo: 0xa6, hi: 0xa6},
+	{value: 0x8132, lo: 0xa7, hi: 0xa8},
+	{value: 0x812d, lo: 0xa9, hi: 0xa9},
+	{value: 0x8132, lo: 0xaa, hi: 0xac},
+	{value: 0x812d, lo: 0xad, hi: 0xaf},
+	{value: 0x8116, lo: 0xb0, hi: 0xb0},
+	{value: 0x8117, lo: 0xb1, hi: 0xb1},
+	{value: 0x8118, lo: 0xb2, hi: 0xb2},
+	{value: 0x8132, lo: 0xb3, hi: 0xb5},
+	{value: 0x812d, lo: 0xb6, hi: 0xb6},
+	{value: 0x8132, lo: 0xb7, hi: 0xb8},
+	{value: 0x812d, lo: 0xb9, hi: 0xba},
+	{value: 0x8132, lo: 0xbb, hi: 0xbf},
+	// Block 0xf, offset 0x85
+	{value: 0x0000, lo: 0x07},
+	{value: 0xa000, lo: 0xa8, hi: 0xa8},
+	{value: 0x3f13, lo: 0xa9, hi: 0xa9},
+	{value: 0xa000, lo: 0xb0, hi: 0xb0},
+	{value: 0x3f1b, lo: 0xb1, hi: 0xb1},
+	{value: 0xa000, lo: 0xb3, hi: 0xb3},
+	{value: 0x3f23, lo: 0xb4, hi: 0xb4},
+	{value: 0x9902, lo: 0xbc, hi: 0xbc},
+	// Block 0x10, offset 0x8d
+	{value: 0x0008, lo: 0x06},
+	{value: 0x8104, lo: 0x8d, hi: 0x8d},
+	{value: 0x8132, lo: 0x91, hi: 0x91},
+	{value: 0x812d, lo: 0x92, hi: 0x92},
+	{value: 0x8132, lo: 0x93, hi: 0x93},
+	{value: 0x8132, lo: 0x94, hi: 0x94},
+	{value: 0x4557, lo: 0x98, hi: 0x9f},
+	// Block 0x11, offset 0x94
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8102, lo: 0xbc, hi: 0xbc},
+	{value: 0x9900, lo: 0xbe, hi: 0xbe},
+	// Block 0x12, offset 0x97
+	{value: 0x0007, lo: 0x07},
+	{value: 0xa000, lo: 0x87, hi: 0x87},
+	{value: 0x18e1, lo: 0x8b, hi: 0x8c},
+	{value: 0x8104, lo: 0x8d, hi: 0x8d},
+	{value: 0x9900, lo: 0x97, hi: 0x97},
+	{value: 0x4597, lo: 0x9c, hi: 0x9c},
+	{value: 0x459f, lo: 0x9d, hi: 0x9d},
+	{value: 0x45a7, lo: 0x9f, hi: 0x9f},
+	// Block 0x13, offset 0x9f
+	{value: 0x0000, lo: 0x03},
+	{value: 0x45cf, lo: 0xb3, hi: 0xb3},
+	{value: 0x45d7, lo: 0xb6, hi: 0xb6},
+	{value: 0x8102, lo: 0xbc, hi: 0xbc},
+	// Block 0x14, offset 0xa3
+	{value: 0x0008, lo: 0x03},
+	{value: 0x8104, lo: 0x8d, hi: 0x8d},
+	{value: 0x45af, lo: 0x99, hi: 0x9b},
+	{value: 0x45c7, lo: 0x9e, hi: 0x9e},
+	// Block 0x15, offset 0xa7
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8102, lo: 0xbc, hi: 0xbc},
+	// Block 0x16, offset 0xa9
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8104, lo: 0x8d, hi: 0x8d},
+	// Block 0x17, offset 0xab
+	{value: 0x0000, lo: 0x08},
+	{value: 0xa000, lo: 0x87, hi: 0x87},
+	{value: 0x18f6, lo: 0x88, hi: 0x88},
+	{value: 0x18ef, lo: 0x8b, hi: 0x8b},
+	{value: 0x18fd, lo: 0x8c, hi: 0x8c},
+	{value: 0x8104, lo: 0x8d, hi: 0x8d},
+	{value: 0x9900, lo: 0x96, hi: 0x97},
+	{value: 0x45df, lo: 0x9c, hi: 0x9c},
+	{value: 0x45e7, lo: 0x9d, hi: 0x9d},
+	// Block 0x18, offset 0xb4
+	{value: 0x0000, lo: 0x03},
+	{value: 0xa000, lo: 0x92, hi: 0x92},
+	{value: 0x1904, lo: 0x94, hi: 0x94},
+	{value: 0x9900, lo: 0xbe, hi: 0xbe},
+	// Block 0x19, offset 0xb8
+	{value: 0x0000, lo: 0x06},
+	{value: 0xa000, lo: 0x86, hi: 0x87},
+	{value: 0x190b, lo: 0x8a, hi: 0x8a},
+	{value: 0x1919, lo: 0x8b, hi: 0x8b},
+	{value: 0x1912, lo: 0x8c, hi: 0x8c},
+	{value: 0x8104, lo: 0x8d, hi: 0x8d},
+	{value: 0x9900, lo: 0x97, hi: 0x97},
+	// Block 0x1a, offset 0xbf
+	{value: 0x1801, lo: 0x04},
+	{value: 0xa000, lo: 0x86, hi: 0x86},
+	{value: 0x3f2b, lo: 0x88, hi: 0x88},
+	{value: 0x8104, lo: 0x8d, hi: 0x8d},
+	{value: 0x8120, lo: 0x95, hi: 0x96},
+	// Block 0x1b, offset 0xc4
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8102, lo: 0xbc, hi: 0xbc},
+	{value: 0xa000, lo: 0xbf, hi: 0xbf},
+	// Block 0x1c, offset 0xc7
+	{value: 0x0000, lo: 0x09},
+	{value: 0x1920, lo: 0x80, hi: 0x80},
+	{value: 0x9900, lo: 0x82, hi: 0x82},
+	{value: 0xa000, lo: 0x86, hi: 0x86},
+	{value: 0x1927, lo: 0x87, hi: 0x87},
+	{value: 0x192e, lo: 0x88, hi: 0x88},
+	{value: 0x2eb7, lo: 0x8a, hi: 0x8a},
+	{value: 0x19f6, lo: 0x8b, hi: 0x8b},
+	{value: 0x8104, lo: 0x8d, hi: 0x8d},
+	{value: 0x9900, lo: 0x95, hi: 0x96},
+	// Block 0x1d, offset 0xd1
+	{value: 0x0000, lo: 0x01},
+	{value: 0x9900, lo: 0xbe, hi: 0xbe},
+	// Block 0x1e, offset 0xd3
+	{value: 0x0000, lo: 0x06},
+	{value: 0xa000, lo: 0x86, hi: 0x87},
+	{value: 0x1935, lo: 0x8a, hi: 0x8a},
+	{value: 0x1943, lo: 0x8b, hi: 0x8b},
+	{value: 0x193c, lo: 0x8c, hi: 0x8c},
+	{value: 0x8104, lo: 0x8d, hi: 0x8d},
+	{value: 0x9900, lo: 0x97, hi: 0x97},
+	// Block 0x1f, offset 0xda
+	{value: 0x0007, lo: 0x07},
+	{value: 0x9904, lo: 0x8a, hi: 0x8a},
+	{value: 0x9900, lo: 0x8f, hi: 0x8f},
+	{value: 0xa000, lo: 0x99, hi: 0x99},
+	{value: 0x3f33, lo: 0x9a, hi: 0x9a},
+	{value: 0x2ebe, lo: 0x9c, hi: 0x9d},
+	{value: 0x194a, lo: 0x9e, hi: 0x9e},
+	{value: 0x9900, lo: 0x9f, hi: 0x9f},
+	// Block 0x20, offset 0xe2
+	{value: 0x0000, lo: 0x03},
+	{value: 0x27b4, lo: 0xb3, hi: 0xb3},
+	{value: 0x8122, lo: 0xb8, hi: 0xb9},
+	{value: 0x8104, lo: 0xba, hi: 0xba},
+	// Block 0x21, offset 0xe6
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8123, lo: 0x88, hi: 0x8b},
+	// Block 0x22, offset 0xe8
+	{value: 0x0000, lo: 0x02},
+	{value: 0x27c9, lo: 0xb3, hi: 0xb3},
+	{value: 0x8124, lo: 0xb8, hi: 0xb9},
+	// Block 0x23, offset 0xeb
+	{value: 0x0000, lo: 0x03},
+	{value: 0x8125, lo: 0x88, hi: 0x8b},
+	{value: 0x27bb, lo: 0x9c, hi: 0x9c},
+	{value: 0x27c2, lo: 0x9d, hi: 0x9d},
+	// Block 0x24, offset 0xef
+	{value: 0x0000, lo: 0x05},
+	{value: 0x030b, lo: 0x8c, hi: 0x8c},
+	{value: 0x812d, lo: 0x98, hi: 0x99},
+	{value: 0x812d, lo: 0xb5, hi: 0xb5},
+	{value: 0x812d, lo: 0xb7, hi: 0xb7},
+	{value: 0x812b, lo: 0xb9, hi: 0xb9},
+	// Block 0x25, offset 0xf5
+	{value: 0x0000, lo: 0x10},
+	{value: 0x27d7, lo: 0x83, hi: 0x83},
+	{value: 0x27de, lo: 0x8d, hi: 0x8d},
+	{value: 0x27e5, lo: 0x92, hi: 0x92},
+	{value: 0x27ec, lo: 0x97, hi: 0x97},
+	{value: 0x27f3, lo: 0x9c, hi: 0x9c},
+	{value: 0x27d0, lo: 0xa9, hi: 0xa9},
+	{value: 0x8126, lo: 0xb1, hi: 0xb1},
+	{value: 0x8127, lo: 0xb2, hi: 0xb2},
+	{value: 0x4a0b, lo: 0xb3, hi: 0xb3},
+	{value: 0x8128, lo: 0xb4, hi: 0xb4},
+	{value: 0x4a14, lo: 0xb5, hi: 0xb5},
+	{value: 0x45ef, lo: 0xb6, hi: 0xb6},
+	{value: 0x462f, lo: 0xb7, hi: 0xb7},
+	{value: 0x45f7, lo: 0xb8, hi: 0xb8},
+	{value: 0x463a, lo: 0xb9, hi: 0xb9},
+	{value: 0x8127, lo: 0xba, hi: 0xbd},
+	// Block 0x26, offset 0x106
+	{value: 0x0000, lo: 0x0b},
+	{value: 0x8127, lo: 0x80, hi: 0x80},
+	{value: 0x4a1d, lo: 0x81, hi: 0x81},
+	{value: 0x8132, lo: 0x82, hi: 0x83},
+	{value: 0x8104, lo: 0x84, hi: 0x84},
+	{value: 0x8132, lo: 0x86, hi: 0x87},
+	{value: 0x2801, lo: 0x93, hi: 0x93},
+	{value: 0x2808, lo: 0x9d, hi: 0x9d},
+	{value: 0x280f, lo: 0xa2, hi: 0xa2},
+	{value: 0x2816, lo: 0xa7, hi: 0xa7},
+	{value: 0x281d, lo: 0xac, hi: 0xac},
+	{value: 0x27fa, lo: 0xb9, hi: 0xb9},
+	// Block 0x27, offset 0x112
+	{value: 0x0000, lo: 0x01},
+	{value: 0x812d, lo: 0x86, hi: 0x86},
+	// Block 0x28, offset 0x114
+	{value: 0x0000, lo: 0x05},
+	{value: 0xa000, lo: 0xa5, hi: 0xa5},
+	{value: 0x1951, lo: 0xa6, hi: 0xa6},
+	{value: 0x9900, lo: 0xae, hi: 0xae},
+	{value: 0x8102, lo: 0xb7, hi: 0xb7},
+	{value: 0x8104, lo: 0xb9, hi: 0xba},
+	// Block 0x29, offset 0x11a
+	{value: 0x0000, lo: 0x01},
+	{value: 0x812d, lo: 0x8d, hi: 0x8d},
+	// Block 0x2a, offset 0x11c
+	{value: 0x0000, lo: 0x01},
+	{value: 0x030f, lo: 0xbc, hi: 0xbc},
+	// Block 0x2b, offset 0x11e
+	{value: 0x0000, lo: 0x01},
+	{value: 0xa000, lo: 0x80, hi: 0x92},
+	// Block 0x2c, offset 0x120
+	{value: 0x0000, lo: 0x01},
+	{value: 0xb900, lo: 0xa1, hi: 0xb5},
+	// Block 0x2d, offset 0x122
+	{value: 0x0000, lo: 0x01},
+	{value: 0x9900, lo: 0xa8, hi: 0xbf},
+	// Block 0x2e, offset 0x124
+	{value: 0x0000, lo: 0x01},
+	{value: 0x9900, lo: 0x80, hi: 0x82},
+	// Block 0x2f, offset 0x126
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8132, lo: 0x9d, hi: 0x9f},
+	// Block 0x30, offset 0x128
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8104, lo: 0x94, hi: 0x94},
+	{value: 0x8104, lo: 0xb4, hi: 0xb4},
+	// Block 0x31, offset 0x12b
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8104, lo: 0x92, hi: 0x92},
+	{value: 0x8132, lo: 0x9d, hi: 0x9d},
+	// Block 0x32, offset 0x12e
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8131, lo: 0xa9, hi: 0xa9},
+	// Block 0x33, offset 0x130
+	{value: 0x0004, lo: 0x02},
+	{value: 0x812e, lo: 0xb9, hi: 0xba},
+	{value: 0x812d, lo: 0xbb, hi: 0xbb},
+	// Block 0x34, offset 0x133
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8132, lo: 0x97, hi: 0x97},
+	{value: 0x812d, lo: 0x98, hi: 0x98},
+	// Block 0x35, offset 0x136
+	{value: 0x0000, lo: 0x03},
+	{value: 0x8104, lo: 0xa0, hi: 0xa0},
+	{value: 0x8132, lo: 0xb5, hi: 0xbc},
+	{value: 0x812d, lo: 0xbf, hi: 0xbf},
+	// Block 0x36, offset 0x13a
+	{value: 0x0000, lo: 0x04},
+	{value: 0x8132, lo: 0xb0, hi: 0xb4},
+	{value: 0x812d, lo: 0xb5, hi: 0xba},
+	{value: 0x8132, lo: 0xbb, hi: 0xbc},
+	{value: 0x812d, lo: 0xbd, hi: 0xbd},
+	// Block 0x37, offset 0x13f
+	{value: 0x0000, lo: 0x08},
+	{value: 0x1990, lo: 0x80, hi: 0x80},
+	{value: 0x1997, lo: 0x81, hi: 0x81},
+	{value: 0xa000, lo: 0x82, hi: 0x82},
+	{value: 0x199e, lo: 0x83, hi: 0x83},
+	{value: 0x8104, lo: 0x84, hi: 0x84},
+	{value: 0x8132, lo: 0xab, hi: 0xab},
+	{value: 0x812d, lo: 0xac, hi: 0xac},
+	{value: 0x8132, lo: 0xad, hi: 0xb3},
+	// Block 0x38, offset 0x148
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8104, lo: 0xaa, hi: 0xab},
+	// Block 0x39, offset 0x14a
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8102, lo: 0xa6, hi: 0xa6},
+	{value: 0x8104, lo: 0xb2, hi: 0xb3},
+	// Block 0x3a, offset 0x14d
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8102, lo: 0xb7, hi: 0xb7},
+	// Block 0x3b, offset 0x14f
+	{value: 0x0000, lo: 0x0a},
+	{value: 0x8132, lo: 0x90, hi: 0x92},
+	{value: 0x8101, lo: 0x94, hi: 0x94},
+	{value: 0x812d, lo: 0x95, hi: 0x99},
+	{value: 0x8132, lo: 0x9a, hi: 0x9b},
+	{value: 0x812d, lo: 0x9c, hi: 0x9f},
+	{value: 0x8132, lo: 0xa0, hi: 0xa0},
+	{value: 0x8101, lo: 0xa2, hi: 0xa8},
+	{value: 0x812d, lo: 0xad, hi: 0xad},
+	{value: 0x8132, lo: 0xb4, hi: 0xb4},
+	{value: 0x8132, lo: 0xb8, hi: 0xb9},
+	// Block 0x3c, offset 0x15a
+	{value: 0x0002, lo: 0x0a},
+	{value: 0x0043, lo: 0xac, hi: 0xac},
+	{value: 0x00d1, lo: 0xad, hi: 0xad},
+	{value: 0x0045, lo: 0xae, hi: 0xae},
+	{value: 0x0049, lo: 0xb0, hi: 0xb1},
+	{value: 0x00e6, lo: 0xb2, hi: 0xb2},
+	{value: 0x004f, lo: 0xb3, hi: 0xba},
+	{value: 0x005f, lo: 0xbc, hi: 0xbc},
+	{value: 0x00ef, lo: 0xbd, hi: 0xbd},
+	{value: 0x0061, lo: 0xbe, hi: 0xbe},
+	{value: 0x0065, lo: 0xbf, hi: 0xbf},
+	// Block 0x3d, offset 0x165
+	{value: 0x0000, lo: 0x0e},
+	{value: 0x8132, lo: 0x80, hi: 0x81},
+	{value: 0x812d, lo: 0x82, hi: 0x82},
+	{value: 0x8132, lo: 0x83, hi: 0x89},
+	{value: 0x812d, lo: 0x8a, hi: 0x8a},
+	{value: 0x8132, lo: 0x8b, hi: 0x8c},
+	{value: 0x8135, lo: 0x8d, hi: 0x8d},
+	{value: 0x812a, lo: 0x8e, hi: 0x8e},
+	{value: 0x812d, lo: 0x8f, hi: 0x8f},
+	{value: 0x8129, lo: 0x90, hi: 0x90},
+	{value: 0x8132, lo: 0x91, hi: 0xb5},
+	{value: 0x8134, lo: 0xbc, hi: 0xbc},
+	{value: 0x812d, lo: 0xbd, hi: 0xbd},
+	{value: 0x8132, lo: 0xbe, hi: 0xbe},
+	{value: 0x812d, lo: 0xbf, hi: 0xbf},
+	// Block 0x3e, offset 0x174
+	{value: 0x0000, lo: 0x0d},
+	{value: 0x0001, lo: 0x80, hi: 0x8a},
+	{value: 0x04b3, lo: 0x91, hi: 0x91},
+	{value: 0x42d6, lo: 0x97, hi: 0x97},
+	{value: 0x001d, lo: 0xa4, hi: 0xa4},
+	{value: 0x1a06, lo: 0xa5, hi: 0xa5},
+	{value: 0x1cef, lo: 0xa6, hi: 0xa6},
+	{value: 0x0001, lo: 0xaf, hi: 0xaf},
+	{value: 0x288d, lo: 0xb3, hi: 0xb3},
+	{value: 0x29fa, lo: 0xb4, hi: 0xb4},
+	{value: 0x2894, lo: 0xb6, hi: 0xb6},
+	{value: 0x2a04, lo: 0xb7, hi: 0xb7},
+	{value: 0x1a00, lo: 0xbc, hi: 0xbc},
+	{value: 0x42a4, lo: 0xbe, hi: 0xbe},
+	// Block 0x3f, offset 0x182
+	{value: 0x0002, lo: 0x0d},
+	{value: 0x1ac6, lo: 0x87, hi: 0x87},
+	{value: 0x1ac3, lo: 0x88, hi: 0x88},
+	{value: 0x1a03, lo: 0x89, hi: 0x89},
+	{value: 0x2b97, lo: 0x97, hi: 0x97},
+	{value: 0x0001, lo: 0x9f, hi: 0x9f},
+	{value: 0x0021, lo: 0xb0, hi: 0xb0},
+	{value: 0x0093, lo: 0xb1, hi: 0xb1},
+	{value: 0x0029, lo: 0xb4, hi: 0xb9},
+	{value: 0x0017, lo: 0xba, hi: 0xba},
+	{value: 0x04df, lo: 0xbb, hi: 0xbb},
+	{value: 0x003b, lo: 0xbc, hi: 0xbc},
+	{value: 0x0011, lo: 0xbd, hi: 0xbe},
+	{value: 0x009d, lo: 0xbf, hi: 0xbf},
+	// Block 0x40, offset 0x190
+	{value: 0x0002, lo: 0x0f},
+	{value: 0x0021, lo: 0x80, hi: 0x89},
+	{value: 0x0017, lo: 0x8a, hi: 0x8a},
+	{value: 0x04df, lo: 0x8b, hi: 0x8b},
+	{value: 0x003b, lo: 0x8c, hi: 0x8c},
+	{value: 0x0011, lo: 0x8d, hi: 0x8e},
+	{value: 0x0083, lo: 0x90, hi: 0x90},
+	{value: 0x008b, lo: 0x91, hi: 0x91},
+	{value: 0x009f, lo: 0x92, hi: 0x92},
+	{value: 0x00b1, lo: 0x93, hi: 0x93},
+	{value: 0x0104, lo: 0x94, hi: 0x94},
+	{value: 0x0091, lo: 0x95, hi: 0x95},
+	{value: 0x0097, lo: 0x96, hi: 0x99},
+	{value: 0x00a1, lo: 0x9a, hi: 0x9a},
+	{value: 0x00a7, lo: 0x9b, hi: 0x9c},
+	{value: 0x1b2c, lo: 0xa8, hi: 0xa8},
+	// Block 0x41, offset 0x1a0
+	{value: 0x0000, lo: 0x0d},
+	{value: 0x8132, lo: 0x90, hi: 0x91},
+	{value: 0x8101, lo: 0x92, hi: 0x93},
+	{value: 0x8132, lo: 0x94, hi: 0x97},
+	{value: 0x8101, lo: 0x98, hi: 0x9a},
+	{value: 0x8132, lo: 0x9b, hi: 0x9c},
+	{value: 0x8132, lo: 0xa1, hi: 0xa1},
+	{value: 0x8101, lo: 0xa5, hi: 0xa6},
+	{value: 0x8132, lo: 0xa7, hi: 0xa7},
+	{value: 0x812d, lo: 0xa8, hi: 0xa8},
+	{value: 0x8132, lo: 0xa9, hi: 0xa9},
+	{value: 0x8101, lo: 0xaa, hi: 0xab},
+	{value: 0x812d, lo: 0xac, hi: 0xaf},
+	{value: 0x8132, lo: 0xb0, hi: 0xb0},
+	// Block 0x42, offset 0x1ae
+	{value: 0x0007, lo: 0x06},
+	{value: 0x2313, lo: 0x89, hi: 0x89},
+	{value: 0xa000, lo: 0x90, hi: 0x90},
+	{value: 0xa000, lo: 0x92, hi: 0x92},
+	{value: 0xa000, lo: 0x94, hi: 0x94},
+	{value: 0x3bf4, lo: 0x9a, hi: 0x9b},
+	{value: 0x3c02, lo: 0xae, hi: 0xae},
+	// Block 0x43, offset 0x1b5
+	{value: 0x000e, lo: 0x05},
+	{value: 0x3c09, lo: 0x8d, hi: 0x8e},
+	{value: 0x3c10, lo: 0x8f, hi: 0x8f},
+	{value: 0xa000, lo: 0x90, hi: 0x90},
+	{value: 0xa000, lo: 0x92, hi: 0x92},
+	{value: 0xa000, lo: 0x94, hi: 0x94},
+	// Block 0x44, offset 0x1bb
+	{value: 0x0173, lo: 0x0e},
+	{value: 0xa000, lo: 0x83, hi: 0x83},
+	{value: 0x3c1e, lo: 0x84, hi: 0x84},
+	{value: 0xa000, lo: 0x88, hi: 0x88},
+	{value: 0x3c25, lo: 0x89, hi: 0x89},
+	{value: 0xa000, lo: 0x8b, hi: 0x8b},
+	{value: 0x3c2c, lo: 0x8c, hi: 0x8c},
+	{value: 0xa000, lo: 0xa3, hi: 0xa3},
+	{value: 0x3c33, lo: 0xa4, hi: 0xa4},
+	{value: 0xa000, lo: 0xa5, hi: 0xa5},
+	{value: 0x3c3a, lo: 0xa6, hi: 0xa6},
+	{value: 0x289b, lo: 0xac, hi: 0xad},
+	{value: 0x28a2, lo: 0xaf, hi: 0xaf},
+	{value: 0x2a18, lo: 0xb0, hi: 0xb0},
+	{value: 0xa000, lo: 0xbc, hi: 0xbc},
+	// Block 0x45, offset 0x1ca
+	{value: 0x0007, lo: 0x03},
+	{value: 0x3ca3, lo: 0xa0, hi: 0xa1},
+	{value: 0x3ccd, lo: 0xa2, hi: 0xa3},
+	{value: 0x3cf7, lo: 0xaa, hi: 0xad},
+	// Block 0x46, offset 0x1ce
+	{value: 0x0004, lo: 0x01},
+	{value: 0x0503, lo: 0xa9, hi: 0xaa},
+	// Block 0x47, offset 0x1d0
+	{value: 0x0002, lo: 0x03},
+	{value: 0x0057, lo: 0x80, hi: 0x8f},
+	{value: 0x0083, lo: 0x90, hi: 0xa9},
+	{value: 0x0021, lo: 0xaa, hi: 0xaa},
+	// Block 0x48, offset 0x1d4
+	{value: 0x0000, lo: 0x01},
+	{value: 0x2ba4, lo: 0x8c, hi: 0x8c},
+	// Block 0x49, offset 0x1d6
+	{value: 0x0263, lo: 0x02},
+	{value: 0x1d1f, lo: 0xb4, hi: 0xb4},
+	{value: 0x1ac0, lo: 0xb5, hi: 0xb6},
+	// Block 0x4a, offset 0x1d9
+	{value: 0x0000, lo: 0x01},
+	{value: 0x4518, lo: 0x9c, hi: 0x9c},
+	// Block 0x4b, offset 0x1db
+	{value: 0x0000, lo: 0x02},
+	{value: 0x0095, lo: 0xbc, hi: 0xbc},
+	{value: 0x006d, lo: 0xbd, hi: 0xbd},
+	// Block 0x4c, offset 0x1de
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8132, lo: 0xaf, hi: 0xb1},
+	// Block 0x4d, offset 0x1e0
+	{value: 0x0000, lo: 0x02},
+	{value: 0x04f7, lo: 0xaf, hi: 0xaf},
+	{value: 0x8104, lo: 0xbf, hi: 0xbf},
+	// Block 0x4e, offset 0x1e3
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8132, lo: 0xa0, hi: 0xbf},
+	// Block 0x4f, offset 0x1e5
+	{value: 0x0000, lo: 0x01},
+	{value: 0x0e3b, lo: 0x9f, hi: 0x9f},
+	// Block 0x50, offset 0x1e7
+	{value: 0x0000, lo: 0x01},
+	{value: 0x16a3, lo: 0xb3, hi: 0xb3},
+	// Block 0x51, offset 0x1e9
+	{value: 0x0004, lo: 0x0b},
+	{value: 0x160b, lo: 0x80, hi: 0x82},
+	{value: 0x1623, lo: 0x83, hi: 0x83},
+	{value: 0x163b, lo: 0x84, hi: 0x85},
+	{value: 0x164b, lo: 0x86, hi: 0x89},
+	{value: 0x165f, lo: 0x8a, hi: 0x8c},
+	{value: 0x1673, lo: 0x8d, hi: 0x8d},
+	{value: 0x167b, lo: 0x8e, hi: 0x8e},
+	{value: 0x1683, lo: 0x8f, hi: 0x90},
+	{value: 0x168f, lo: 0x91, hi: 0x93},
+	{value: 0x169f, lo: 0x94, hi: 0x94},
+	{value: 0x16a7, lo: 0x95, hi: 0x95},
+	// Block 0x52, offset 0x1f5
+	{value: 0x0004, lo: 0x09},
+	{value: 0x0001, lo: 0x80, hi: 0x80},
+	{value: 0x812c, lo: 0xaa, hi: 0xaa},
+	{value: 0x8131, lo: 0xab, hi: 0xab},
+	{value: 0x8133, lo: 0xac, hi: 0xac},
+	{value: 0x812e, lo: 0xad, hi: 0xad},
+	{value: 0x812f, lo: 0xae, hi: 0xae},
+	{value: 0x812f, lo: 0xaf, hi: 0xaf},
+	{value: 0x052b, lo: 0xb6, hi: 0xb6},
+	{value: 0x08ff, lo: 0xb8, hi: 0xba},
+	// Block 0x53, offset 0x1ff
+	{value: 0x0004, lo: 0x06},
+	{value: 0x0313, lo: 0xb1, hi: 0xb2},
+	{value: 0x043b, lo: 0xb3, hi: 0xb3},
+	{value: 0x031b, lo: 0xb4, hi: 0xb4},
+	{value: 0x043f, lo: 0xb5, hi: 0xb6},
+	{value: 0x031f, lo: 0xb7, hi: 0xb9},
+	{value: 0x0447, lo: 0xba, hi: 0xbf},
+	// Block 0x54, offset 0x206
+	{value: 0x0004, lo: 0x0c},
+	{value: 0x0367, lo: 0x80, hi: 0x80},
+	{value: 0x032b, lo: 0x81, hi: 0x83},
+	{value: 0x037b, lo: 0x84, hi: 0x84},
+	{value: 0x0337, lo: 0x85, hi: 0x8e},
+	{value: 0x03c7, lo: 0x8f, hi: 0xa3},
+	{value: 0x03c3, lo: 0xa4, hi: 0xa4},
+	{value: 0x035f, lo: 0xa5, hi: 0xa6},
+	{value: 0x045f, lo: 0xa7, hi: 0xad},
+	{value: 0x036b, lo: 0xae, hi: 0xae},
+	{value: 0x047b, lo: 0xaf, hi: 0xb0},
+	{value: 0x036f, lo: 0xb1, hi: 0xb3},
+	{value: 0x037f, lo: 0xb4, hi: 0xbf},
+	// Block 0x55, offset 0x213
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8132, lo: 0xaf, hi: 0xaf},
+	{value: 0x8132, lo: 0xb4, hi: 0xbd},
+	// Block 0x56, offset 0x216
+	{value: 0x0003, lo: 0x02},
+	{value: 0x020f, lo: 0x9c, hi: 0x9d},
+	{value: 0x8132, lo: 0x9f, hi: 0x9f},
+	// Block 0x57, offset 0x219
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8132, lo: 0xb0, hi: 0xb1},
+	// Block 0x58, offset 0x21b
+	{value: 0x0000, lo: 0x01},
+	{value: 0x16af, lo: 0xb0, hi: 0xb0},
+	// Block 0x59, offset 0x21d
+	{value: 0x000c, lo: 0x01},
+	{value: 0x00d7, lo: 0xb8, hi: 0xb9},
+	// Block 0x5a, offset 0x21f
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8104, lo: 0x86, hi: 0x86},
+	// Block 0x5b, offset 0x221
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8104, lo: 0x84, hi: 0x84},
+	{value: 0x8132, lo: 0xa0, hi: 0xb1},
+	// Block 0x5c, offset 0x224
+	{value: 0x0000, lo: 0x01},
+	{value: 0x812d, lo: 0xab, hi: 0xad},
+	// Block 0x5d, offset 0x226
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8104, lo: 0x93, hi: 0x93},
+	// Block 0x5e, offset 0x228
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8102, lo: 0xb3, hi: 0xb3},
+	// Block 0x5f, offset 0x22a
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8104, lo: 0x80, hi: 0x80},
+	// Block 0x60, offset 0x22c
+	{value: 0x0000, lo: 0x05},
+	{value: 0x8132, lo: 0xb0, hi: 0xb0},
+	{value: 0x8132, lo: 0xb2, hi: 0xb3},
+	{value: 0x812d, lo: 0xb4, hi: 0xb4},
+	{value: 0x8132, lo: 0xb7, hi: 0xb8},
+	{value: 0x8132, lo: 0xbe, hi: 0xbf},
+	// Block 0x61, offset 0x232
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8132, lo: 0x81, hi: 0x81},
+	{value: 0x8104, lo: 0xb6, hi: 0xb6},
+	// Block 0x62, offset 0x235
+	{value: 0x0008, lo: 0x03},
+	{value: 0x16ab, lo: 0x9c, hi: 0x9d},
+	{value: 0x0125, lo: 0x9e, hi: 0x9e},
+	{value: 0x16b7, lo: 0x9f, hi: 0x9f},
+	// Block 0x63, offset 0x239
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8104, lo: 0xad, hi: 0xad},
+	// Block 0x64, offset 0x23b
+	{value: 0x0000, lo: 0x06},
+	{value: 0xe500, lo: 0x80, hi: 0x80},
+	{value: 0xc600, lo: 0x81, hi: 0x9b},
+	{value: 0xe500, lo: 0x9c, hi: 0x9c},
+	{value: 0xc600, lo: 0x9d, hi: 0xb7},
+	{value: 0xe500, lo: 0xb8, hi: 0xb8},
+	{value: 0xc600, lo: 0xb9, hi: 0xbf},
+	// Block 0x65, offset 0x242
+	{value: 0x0000, lo: 0x05},
+	{value: 0xc600, lo: 0x80, hi: 0x93},
+	{value: 0xe500, lo: 0x94, hi: 0x94},
+	{value: 0xc600, lo: 0x95, hi: 0xaf},
+	{value: 0xe500, lo: 0xb0, hi: 0xb0},
+	{value: 0xc600, lo: 0xb1, hi: 0xbf},
+	// Block 0x66, offset 0x248
+	{value: 0x0000, lo: 0x05},
+	{value: 0xc600, lo: 0x80, hi: 0x8b},
+	{value: 0xe500, lo: 0x8c, hi: 0x8c},
+	{value: 0xc600, lo: 0x8d, hi: 0xa7},
+	{value: 0xe500, lo: 0xa8, hi: 0xa8},
+	{value: 0xc600, lo: 0xa9, hi: 0xbf},
+	// Block 0x67, offset 0x24e
+	{value: 0x0000, lo: 0x07},
+	{value: 0xc600, lo: 0x80, hi: 0x83},
+	{value: 0xe500, lo: 0x84, hi: 0x84},
+	{value: 0xc600, lo: 0x85, hi: 0x9f},
+	{value: 0xe500, lo: 0xa0, hi: 0xa0},
+	{value: 0xc600, lo: 0xa1, hi: 0xbb},
+	{value: 0xe500, lo: 0xbc, hi: 0xbc},
+	{value: 0xc600, lo: 0xbd, hi: 0xbf},
+	// Block 0x68, offset 0x256
+	{value: 0x0000, lo: 0x05},
+	{value: 0xc600, lo: 0x80, hi: 0x97},
+	{value: 0xe500, lo: 0x98, hi: 0x98},
+	{value: 0xc600, lo: 0x99, hi: 0xb3},
+	{value: 0xe500, lo: 0xb4, hi: 0xb4},
+	{value: 0xc600, lo: 0xb5, hi: 0xbf},
+	// Block 0x69, offset 0x25c
+	{value: 0x0000, lo: 0x05},
+	{value: 0xc600, lo: 0x80, hi: 0x8f},
+	{value: 0xe500, lo: 0x90, hi: 0x90},
+	{value: 0xc600, lo: 0x91, hi: 0xab},
+	{value: 0xe500, lo: 0xac, hi: 0xac},
+	{value: 0xc600, lo: 0xad, hi: 0xbf},
+	// Block 0x6a, offset 0x262
+	{value: 0x0000, lo: 0x05},
+	{value: 0xc600, lo: 0x80, hi: 0x87},
+	{value: 0xe500, lo: 0x88, hi: 0x88},
+	{value: 0xc600, lo: 0x89, hi: 0xa3},
+	{value: 0xe500, lo: 0xa4, hi: 0xa4},
+	{value: 0xc600, lo: 0xa5, hi: 0xbf},
+	// Block 0x6b, offset 0x268
+	{value: 0x0000, lo: 0x03},
+	{value: 0xc600, lo: 0x80, hi: 0x87},
+	{value: 0xe500, lo: 0x88, hi: 0x88},
+	{value: 0xc600, lo: 0x89, hi: 0xa3},
+	// Block 0x6c, offset 0x26c
+	{value: 0x0002, lo: 0x01},
+	{value: 0x0003, lo: 0x81, hi: 0xbf},
+	// Block 0x6d, offset 0x26e
+	{value: 0x0004, lo: 0x0e},
+	{value: 0x03c7, lo: 0x82, hi: 0x87},
+	{value: 0x03df, lo: 0x8a, hi: 0x8f},
+	{value: 0x03f7, lo: 0x92, hi: 0x97},
+	{value: 0x040f, lo: 0x9a, hi: 0x9c},
+	{value: 0x00bf, lo: 0xa0, hi: 0xa0},
+	{value: 0x00c2, lo: 0xa1, hi: 0xa1},
+	{value: 0x00cb, lo: 0xa2, hi: 0xa2},
+	{value: 0x429f, lo: 0xa3, hi: 0xa3},
+	{value: 0x00c8, lo: 0xa4, hi: 0xa4},
+	{value: 0x00c5, lo: 0xa5, hi: 0xa5},
+	{value: 0x04bf, lo: 0xa6, hi: 0xa6},
+	{value: 0x04e3, lo: 0xa8, hi: 0xa8},
+	{value: 0x04c3, lo: 0xa9, hi: 0xac},
+	{value: 0x04e7, lo: 0xad, hi: 0xae},
+	// Block 0x6e, offset 0x27d
+	{value: 0x0000, lo: 0x01},
+	{value: 0x812d, lo: 0xbd, hi: 0xbd},
+	// Block 0x6f, offset 0x27f
+	{value: 0x0000, lo: 0x01},
+	{value: 0x812d, lo: 0xa0, hi: 0xa0},
+	// Block 0x70, offset 0x281
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8132, lo: 0xb6, hi: 0xba},
+	// Block 0x71, offset 0x283
+	{value: 0x002c, lo: 0x05},
+	{value: 0x812d, lo: 0x8d, hi: 0x8d},
+	{value: 0x8132, lo: 0x8f, hi: 0x8f},
+	{value: 0x8132, lo: 0xb8, hi: 0xb8},
+	{value: 0x8101, lo: 0xb9, hi: 0xba},
+	{value: 0x8104, lo: 0xbf, hi: 0xbf},
+	// Block 0x72, offset 0x289
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8132, lo: 0xa5, hi: 0xa5},
+	{value: 0x812d, lo: 0xa6, hi: 0xa6},
+	// Block 0x73, offset 0x28c
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8104, lo: 0x86, hi: 0x86},
+	{value: 0x8104, lo: 0xbf, hi: 0xbf},
+	// Block 0x74, offset 0x28f
+	{value: 0x17fe, lo: 0x07},
+	{value: 0xa000, lo: 0x99, hi: 0x99},
+	{value: 0x4273, lo: 0x9a, hi: 0x9a},
+	{value: 0xa000, lo: 0x9b, hi: 0x9b},
+	{value: 0x427d, lo: 0x9c, hi: 0x9c},
+	{value: 0xa000, lo: 0xa5, hi: 0xa5},
+	{value: 0x4287, lo: 0xab, hi: 0xab},
+	{value: 0x8104, lo: 0xb9, hi: 0xba},
+	// Block 0x75, offset 0x297
+	{value: 0x0000, lo: 0x06},
+	{value: 0x8132, lo: 0x80, hi: 0x82},
+	{value: 0x9900, lo: 0xa7, hi: 0xa7},
+	{value: 0x19a5, lo: 0xae, hi: 0xae},
+	{value: 0x19ae, lo: 0xaf, hi: 0xaf},
+	{value: 0xa000, lo: 0xb1, hi: 0xb2},
+	{value: 0x8104, lo: 0xb3, hi: 0xb4},
+	// Block 0x76, offset 0x29e
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8104, lo: 0xb5, hi: 0xb5},
+	{value: 0x8102, lo: 0xb6, hi: 0xb6},
+	// Block 0x77, offset 0x2a1
+	{value: 0x0002, lo: 0x01},
+	{value: 0x8102, lo: 0xa9, hi: 0xaa},
+	// Block 0x78, offset 0x2a3
+	{value: 0x0000, lo: 0x07},
+	{value: 0xa000, lo: 0x87, hi: 0x87},
+	{value: 0x19b7, lo: 0x8b, hi: 0x8b},
+	{value: 0x19c0, lo: 0x8c, hi: 0x8c},
+	{value: 0x8104, lo: 0x8d, hi: 0x8d},
+	{value: 0x9900, lo: 0x97, hi: 0x97},
+	{value: 0x8132, lo: 0xa6, hi: 0xac},
+	{value: 0x8132, lo: 0xb0, hi: 0xb4},
+	// Block 0x79, offset 0x2ab
+	{value: 0x7f37, lo: 0x06},
+	{value: 0x9900, lo: 0xb0, hi: 0xb0},
+	{value: 0xa000, lo: 0xb9, hi: 0xb9},
+	{value: 0x9900, lo: 0xba, hi: 0xba},
+	{value: 0x19d2, lo: 0xbb, hi: 0xbb},
+	{value: 0x19c9, lo: 0xbc, hi: 0xbd},
+	{value: 0x19db, lo: 0xbe, hi: 0xbe},
+	// Block 0x7a, offset 0x2b2
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8104, lo: 0x82, hi: 0x82},
+	{value: 0x8102, lo: 0x83, hi: 0x83},
+	// Block 0x7b, offset 0x2b5
+	{value: 0x0000, lo: 0x05},
+	{value: 0x9900, lo: 0xaf, hi: 0xaf},
+	{value: 0xa000, lo: 0xb8, hi: 0xb9},
+	{value: 0x19e4, lo: 0xba, hi: 0xba},
+	{value: 0x19ed, lo: 0xbb, hi: 0xbb},
+	{value: 0x8104, lo: 0xbf, hi: 0xbf},
+	// Block 0x7c, offset 0x2bb
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8102, lo: 0x80, hi: 0x80},
+	// Block 0x7d, offset 0x2bd
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8104, lo: 0xbf, hi: 0xbf},
+	// Block 0x7e, offset 0x2bf
+	{value: 0x0000, lo: 0x02},
+	{value: 0x8104, lo: 0xb6, hi: 0xb6},
+	{value: 0x8102, lo: 0xb7, hi: 0xb7},
+	// Block 0x7f, offset 0x2c2
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8101, lo: 0xb0, hi: 0xb4},
+	// Block 0x80, offset 0x2c4
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8132, lo: 0xb0, hi: 0xb6},
+	// Block 0x81, offset 0x2c6
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8101, lo: 0x9e, hi: 0x9e},
+	// Block 0x82, offset 0x2c8
+	{value: 0x0000, lo: 0x0c},
+	{value: 0x4607, lo: 0x9e, hi: 0x9e},
+	{value: 0x4611, lo: 0x9f, hi: 0x9f},
+	{value: 0x4645, lo: 0xa0, hi: 0xa0},
+	{value: 0x4653, lo: 0xa1, hi: 0xa1},
+	{value: 0x4661, lo: 0xa2, hi: 0xa2},
+	{value: 0x466f, lo: 0xa3, hi: 0xa3},
+	{value: 0x467d, lo: 0xa4, hi: 0xa4},
+	{value: 0x812b, lo: 0xa5, hi: 0xa6},
+	{value: 0x8101, lo: 0xa7, hi: 0xa9},
+	{value: 0x8130, lo: 0xad, hi: 0xad},
+	{value: 0x812b, lo: 0xae, hi: 0xb2},
+	{value: 0x812d, lo: 0xbb, hi: 0xbf},
+	// Block 0x83, offset 0x2d5
+	{value: 0x0000, lo: 0x09},
+	{value: 0x812d, lo: 0x80, hi: 0x82},
+	{value: 0x8132, lo: 0x85, hi: 0x89},
+	{value: 0x812d, lo: 0x8a, hi: 0x8b},
+	{value: 0x8132, lo: 0xaa, hi: 0xad},
+	{value: 0x461b, lo: 0xbb, hi: 0xbb},
+	{value: 0x4625, lo: 0xbc, hi: 0xbc},
+	{value: 0x468b, lo: 0xbd, hi: 0xbd},
+	{value: 0x46a7, lo: 0xbe, hi: 0xbe},
+	{value: 0x4699, lo: 0xbf, hi: 0xbf},
+	// Block 0x84, offset 0x2df
+	{value: 0x0000, lo: 0x01},
+	{value: 0x46b5, lo: 0x80, hi: 0x80},
+	// Block 0x85, offset 0x2e1
+	{value: 0x0000, lo: 0x01},
+	{value: 0x8132, lo: 0x82, hi: 0x84},
+	// Block 0x86, offset 0x2e3
+	{value: 0x0002, lo: 0x03},
+	{value: 0x0043, lo: 0x80, hi: 0x99},
+	{value: 0x0083, lo: 0x9a, hi: 0xb3},
+	{value: 0x0043, lo: 0xb4, hi: 0xbf},
+	// Block 0x87, offset 0x2e7
+	{value: 0x0002, lo: 0x04},
+	{value: 0x005b, lo: 0x80, hi: 0x8d},
+	{value: 0x0083, lo: 0x8e, hi: 0x94},
+	{value: 0x0093, lo: 0x96, hi: 0xa7},
+	{value: 0x0043, lo: 0xa8, hi: 0xbf},
+	// Block 0x88, offset 0x2ec
+	{value: 0x0002, lo: 0x0b},
+	{value: 0x0073, lo: 0x80, hi: 0x81},
+	{value: 0x0083, lo: 0x82, hi: 0x9b},
+	{value: 0x0043, lo: 0x9c, hi: 0x9c},
+	{value: 0x0047, lo: 0x9e, hi: 0x9f},
+	{value: 0x004f, lo: 0xa2, hi: 0xa2},
+	{value: 0x0055, lo: 0xa5, hi: 0xa6},
+	{value: 0x005d, lo: 0xa9, hi: 0xac},
+	{value: 0x0067, lo: 0xae, hi: 0xb5},
+	{value: 0x0083, lo: 0xb6, hi: 0xb9},
+	{value: 0x008d, lo: 0xbb, hi: 0xbb},
+	{value: 0x0091, lo: 0xbd, hi: 0xbf},
+	// Block 0x89, offset 0x2f8
+	{value: 0x0002, lo: 0x04},
+	{value: 0x0097, lo: 0x80, hi: 0x83},
+	{value: 0x00a1, lo: 0x85, hi: 0x8f},
+	{value: 0x0043, lo: 0x90, hi: 0xa9},
+	{value: 0x0083, lo: 0xaa, hi: 0xbf},
+	// Block 0x8a, offset 0x2fd
+	{value: 0x0002, lo: 0x08},
+	{value: 0x00af, lo: 0x80, hi: 0x83},
+	{value: 0x0043, lo: 0x84, hi: 0x85},
+	{value: 0x0049, lo: 0x87, hi: 0x8a},
+	{value: 0x0055, lo: 0x8d, hi: 0x94},
+	{value: 0x0067, lo: 0x96, hi: 0x9c},
+	{value: 0x0083, lo: 0x9e, hi: 0xb7},
+	{value: 0x0043, lo: 0xb8, hi: 0xb9},
+	{value: 0x0049, lo: 0xbb, hi: 0xbe},
+	// Block 0x8b, offset 0x306
+	{value: 0x0002, lo: 0x05},
+	{value: 0x0053, lo: 0x80, hi: 0x84},
+	{value: 0x005f, lo: 0x86, hi: 0x86},
+	{value: 0x0067, lo: 0x8a, hi: 0x90},
+	{value: 0x0083, lo: 0x92, hi: 0xab},
+	{value: 0x0043, lo: 0xac, hi: 0xbf},
+	// Block 0x8c, offset 0x30c
+	{value: 0x0002, lo: 0x04},
+	{value: 0x006b, lo: 0x80, hi: 0x85},
+	{value: 0x0083, lo: 0x86, hi: 0x9f},
+	{value: 0x0043, lo: 0xa0, hi: 0xb9},
+	{value: 0x0083, lo: 0xba, hi: 0xbf},
+	// Block 0x8d, offset 0x311
+	{value: 0x0002, lo: 0x03},
+	{value: 0x008f, lo: 0x80, hi: 0x93},
+	{value: 0x0043, lo: 0x94, hi: 0xad},
+	{value: 0x0083, lo: 0xae, hi: 0xbf},
+	// Block 0x8e, offset 0x315
+	{value: 0x0002, lo: 0x04},
+	{value: 0x00a7, lo: 0x80, hi: 0x87},
+	{value: 0x0043, lo: 0x88, hi: 0xa1},
+	{value: 0x0083, lo: 0xa2, hi: 0xbb},
+	{value: 0x0043, lo: 0xbc, hi: 0xbf},
+	// Block 0x8f, offset 0x31a
+	{value: 0x0002, lo: 0x03},
+	{value: 0x004b, lo: 0x80, hi: 0x95},
+	{value: 0x0083, lo: 0x96, hi: 0xaf},
+	{value: 0x0043, lo: 0xb0, hi: 0xbf},
+	// Block 0x90, offset 0x31e
+	{value: 0x0003, lo: 0x0f},
+	{value: 0x01b8, lo: 0x80, hi: 0x80},
+	{value: 0x04d7, lo: 0x81, hi: 0x81},
+	{value: 0x01bb, lo: 0x82, hi: 0x9a},
+	{value: 0x04d3, lo: 0x9b, hi: 0x9b},
+	{value: 0x01c7, lo: 0x9c, hi: 0x9c},
+	{value: 0x01d0, lo: 0x9d, hi: 0x9d},
+	{value: 0x01d6, lo: 0x9e, hi: 0x9e},
+	{value: 0x01fa, lo: 0x9f, hi: 0x9f},
+	{value: 0x01eb, lo: 0xa0, hi: 0xa0},
+	{value: 0x01e8, lo: 0xa1, hi: 0xa1},
+	{value: 0x0173, lo: 0xa2, hi: 0xb2},
+	{value: 0x0188, lo: 0xb3, hi: 0xb3},
+	{value: 0x01a6, lo: 0xb4, hi: 0xba},
+	{value: 0x04d7, lo: 0xbb, hi: 0xbb},
+	{value: 0x01bb, lo: 0xbc, hi: 0xbf},
+	// Block 0x91, offset 0x32e
+	{value: 0x0003, lo: 0x0d},
+	{value: 0x01c7, lo: 0x80, hi: 0x94},
+	{value: 0x04d3, lo: 0x95, hi: 0x95},
+	{value: 0x01c7, lo: 0x96, hi: 0x96},
+	{value: 0x01d0, lo: 0x97, hi: 0x97},
+	{value: 0x01d6, lo: 0x98, hi: 0x98},
+	{value: 0x01fa, lo: 0x99, hi: 0x99},
+	{value: 0x01eb, lo: 0x9a, hi: 0x9a},
+	{value: 0x01e8, lo: 0x9b, hi: 0x9b},
+	{value: 0x0173, lo: 0x9c, hi: 0xac},
+	{value: 0x0188, lo: 0xad, hi: 0xad},
+	{value: 0x01a6, lo: 0xae, hi: 0xb4},
+	{value: 0x04d7, lo: 0xb5, hi: 0xb5},
+	{value: 0x01bb, lo: 0xb6, hi: 0xbf},
+	// Block 0x92, offset 0x33c
+	{value: 0x0003, lo: 0x0d},
+	{value: 0x01d9, lo: 0x80, hi: 0x8e},
+	{value: 0x04d3, lo: 0x8f, hi: 0x8f},
+	{value: 0x01c7, lo: 0x90, hi: 0x90},
+	{value: 0x01d0, lo: 0x91, hi: 0x91},
+	{value: 0x01d6, lo: 0x92, hi: 0x92},
+	{value: 0x01fa, lo: 0x93, hi: 0x93},
+	{value: 0x01eb, lo: 0x94, hi: 0x94},
+	{value: 0x01e8, lo: 0x95, hi: 0x95},
+	{value: 0x0173, lo: 0x96, hi: 0xa6},
+	{value: 0x0188, lo: 0xa7, hi: 0xa7},
+	{value: 0x01a6, lo: 0xa8, hi: 0xae},
+	{value: 0x04d7, lo: 0xaf, hi: 0xaf},
+	{value: 0x01bb, lo: 0xb0, hi: 0xbf},
+	// Block 0x93, offset 0x34a
+	{value: 0x0003, lo: 0x0d},
+	{value: 0x01eb, lo: 0x80, hi: 0x88},
+	{value: 0x04d3, lo: 0x89, hi: 0x89},
+	{value: 0x01c7, lo: 0x8a, hi: 0x8a},
+	{value: 0x01d0, lo: 0x8b, hi: 0x8b},
+	{value: 0x01d6, lo: 0x8c, hi: 0x8c},
+	{value: 0x01fa, lo: 0x8d, hi: 0x8d},
+	{value: 0x01eb, lo: 0x8e, hi: 0x8e},
+	{value: 0x01e8, lo: 0x8f, hi: 0x8f},
+	{value: 0x0173, lo: 0x90, hi: 0xa0},
+	{value: 0x0188, lo: 0xa1, hi: 0xa1},
+	{value: 0x01a6, lo: 0xa2, hi: 0xa8},
+	{value: 0x04d7, lo: 0xa9, hi: 0xa9},
+	{value: 0x01bb, lo: 0xaa, hi: 0xbf},
+	// Block 0x94, offset 0x358
+	{value: 0x0000, lo: 0x01},
+	{value: 0x812d, lo: 0x90, hi: 0x96},
+	// Block 0x95, offset 0x35a
+	{value: 0x0002, lo: 0x09},
+	{value: 0x0063, lo: 0x80, hi: 0x89},
+	{value: 0x1ae4, lo: 0x8a, hi: 0x8a},
+	{value: 0x1b14, lo: 0x8b, hi: 0x8b},
+	{value: 0x1b2f, lo: 0x8c, hi: 0x8c},
+	{value: 0x1b35, lo: 0x8d, hi: 0x8d},
+	{value: 0x1d53, lo: 0x8e, hi: 0x8e},
+	{value: 0x1b41, lo: 0x8f, hi: 0x8f},
+	{value: 0x1b0e, lo: 0xaa, hi: 0xaa},
+	{value: 0x1b11, lo: 0xab, hi: 0xab},
+	// Block 0x96, offset 0x364
+	{value: 0x0000, lo: 0x01},
+	{value: 0x1ad2, lo: 0x90, hi: 0x90},
+	// Block 0x97, offset 0x366
+	{value: 0x0028, lo: 0x09},
+	{value: 0x2a5e, lo: 0x80, hi: 0x80},
+	{value: 0x2a22, lo: 0x81, hi: 0x81},
+	{value: 0x2a2c, lo: 0x82, hi: 0x82},
+	{value: 0x2a40, lo: 0x83, hi: 0x84},
+	{value: 0x2a4a, lo: 0x85, hi: 0x86},
+	{value: 0x2a36, lo: 0x87, hi: 0x87},
+	{value: 0x2a54, lo: 0x88, hi: 0x88},
+	{value: 0x0be7, lo: 0x90, hi: 0x90},
+	{value: 0x095f, lo: 0x91, hi: 0x91},
+}
+
+// recompMap: 7520 bytes (entries only)
+var recompMap = map[uint32]rune{
+	0x00410300: 0x00C0,
+	0x00410301: 0x00C1,
+	0x00410302: 0x00C2,
+	0x00410303: 0x00C3,
+	0x00410308: 0x00C4,
+	0x0041030A: 0x00C5,
+	0x00430327: 0x00C7,
+	0x00450300: 0x00C8,
+	0x00450301: 0x00C9,
+	0x00450302: 0x00CA,
+	0x00450308: 0x00CB,
+	0x00490300: 0x00CC,
+	0x00490301: 0x00CD,
+	0x00490302: 0x00CE,
+	0x00490308: 0x00CF,
+	0x004E0303: 0x00D1,
+	0x004F0300: 0x00D2,
+	0x004F0301: 0x00D3,
+	0x004F0302: 0x00D4,
+	0x004F0303: 0x00D5,
+	0x004F0308: 0x00D6,
+	0x00550300: 0x00D9,
+	0x00550301: 0x00DA,
+	0x00550302: 0x00DB,
+	0x00550308: 0x00DC,
+	0x00590301: 0x00DD,
+	0x00610300: 0x00E0,
+	0x00610301: 0x00E1,
+	0x00610302: 0x00E2,
+	0x00610303: 0x00E3,
+	0x00610308: 0x00E4,
+	0x0061030A: 0x00E5,
+	0x00630327: 0x00E7,
+	0x00650300: 0x00E8,
+	0x00650301: 0x00E9,
+	0x00650302: 0x00EA,
+	0x00650308: 0x00EB,
+	0x00690300: 0x00EC,
+	0x00690301: 0x00ED,
+	0x00690302: 0x00EE,
+	0x00690308: 0x00EF,
+	0x006E0303: 0x00F1,
+	0x006F0300: 0x00F2,
+	0x006F0301: 0x00F3,
+	0x006F0302: 0x00F4,
+	0x006F0303: 0x00F5,
+	0x006F0308: 0x00F6,
+	0x00750300: 0x00F9,
+	0x00750301: 0x00FA,
+	0x00750302: 0x00FB,
+	0x00750308: 0x00FC,
+	0x00790301: 0x00FD,
+	0x00790308: 0x00FF,
+	0x00410304: 0x0100,
+	0x00610304: 0x0101,
+	0x00410306: 0x0102,
+	0x00610306: 0x0103,
+	0x00410328: 0x0104,
+	0x00610328: 0x0105,
+	0x00430301: 0x0106,
+	0x00630301: 0x0107,
+	0x00430302: 0x0108,
+	0x00630302: 0x0109,
+	0x00430307: 0x010A,
+	0x00630307: 0x010B,
+	0x0043030C: 0x010C,
+	0x0063030C: 0x010D,
+	0x0044030C: 0x010E,
+	0x0064030C: 0x010F,
+	0x00450304: 0x0112,
+	0x00650304: 0x0113,
+	0x00450306: 0x0114,
+	0x00650306: 0x0115,
+	0x00450307: 0x0116,
+	0x00650307: 0x0117,
+	0x00450328: 0x0118,
+	0x00650328: 0x0119,
+	0x0045030C: 0x011A,
+	0x0065030C: 0x011B,
+	0x00470302: 0x011C,
+	0x00670302: 0x011D,
+	0x00470306: 0x011E,
+	0x00670306: 0x011F,
+	0x00470307: 0x0120,
+	0x00670307: 0x0121,
+	0x00470327: 0x0122,
+	0x00670327: 0x0123,
+	0x00480302: 0x0124,
+	0x00680302: 0x0125,
+	0x00490303: 0x0128,
+	0x00690303: 0x0129,
+	0x00490304: 0x012A,
+	0x00690304: 0x012B,
+	0x00490306: 0x012C,
+	0x00690306: 0x012D,
+	0x00490328: 0x012E,
+	0x00690328: 0x012F,
+	0x00490307: 0x0130,
+	0x004A0302: 0x0134,
+	0x006A0302: 0x0135,
+	0x004B0327: 0x0136,
+	0x006B0327: 0x0137,
+	0x004C0301: 0x0139,
+	0x006C0301: 0x013A,
+	0x004C0327: 0x013B,
+	0x006C0327: 0x013C,
+	0x004C030C: 0x013D,
+	0x006C030C: 0x013E,
+	0x004E0301: 0x0143,
+	0x006E0301: 0x0144,
+	0x004E0327: 0x0145,
+	0x006E0327: 0x0146,
+	0x004E030C: 0x0147,
+	0x006E030C: 0x0148,
+	0x004F0304: 0x014C,
+	0x006F0304: 0x014D,
+	0x004F0306: 0x014E,
+	0x006F0306: 0x014F,
+	0x004F030B: 0x0150,
+	0x006F030B: 0x0151,
+	0x00520301: 0x0154,
+	0x00720301: 0x0155,
+	0x00520327: 0x0156,
+	0x00720327: 0x0157,
+	0x0052030C: 0x0158,
+	0x0072030C: 0x0159,
+	0x00530301: 0x015A,
+	0x00730301: 0x015B,
+	0x00530302: 0x015C,
+	0x00730302: 0x015D,
+	0x00530327: 0x015E,
+	0x00730327: 0x015F,
+	0x0053030C: 0x0160,
+	0x0073030C: 0x0161,
+	0x00540327: 0x0162,
+	0x00740327: 0x0163,
+	0x0054030C: 0x0164,
+	0x0074030C: 0x0165,
+	0x00550303: 0x0168,
+	0x00750303: 0x0169,
+	0x00550304: 0x016A,
+	0x00750304: 0x016B,
+	0x00550306: 0x016C,
+	0x00750306: 0x016D,
+	0x0055030A: 0x016E,
+	0x0075030A: 0x016F,
+	0x0055030B: 0x0170,
+	0x0075030B: 0x0171,
+	0x00550328: 0x0172,
+	0x00750328: 0x0173,
+	0x00570302: 0x0174,
+	0x00770302: 0x0175,
+	0x00590302: 0x0176,
+	0x00790302: 0x0177,
+	0x00590308: 0x0178,
+	0x005A0301: 0x0179,
+	0x007A0301: 0x017A,
+	0x005A0307: 0x017B,
+	0x007A0307: 0x017C,
+	0x005A030C: 0x017D,
+	0x007A030C: 0x017E,
+	0x004F031B: 0x01A0,
+	0x006F031B: 0x01A1,
+	0x0055031B: 0x01AF,
+	0x0075031B: 0x01B0,
+	0x0041030C: 0x01CD,
+	0x0061030C: 0x01CE,
+	0x0049030C: 0x01CF,
+	0x0069030C: 0x01D0,
+	0x004F030C: 0x01D1,
+	0x006F030C: 0x01D2,
+	0x0055030C: 0x01D3,
+	0x0075030C: 0x01D4,
+	0x00DC0304: 0x01D5,
+	0x00FC0304: 0x01D6,
+	0x00DC0301: 0x01D7,
+	0x00FC0301: 0x01D8,
+	0x00DC030C: 0x01D9,
+	0x00FC030C: 0x01DA,
+	0x00DC0300: 0x01DB,
+	0x00FC0300: 0x01DC,
+	0x00C40304: 0x01DE,
+	0x00E40304: 0x01DF,
+	0x02260304: 0x01E0,
+	0x02270304: 0x01E1,
+	0x00C60304: 0x01E2,
+	0x00E60304: 0x01E3,
+	0x0047030C: 0x01E6,
+	0x0067030C: 0x01E7,
+	0x004B030C: 0x01E8,
+	0x006B030C: 0x01E9,
+	0x004F0328: 0x01EA,
+	0x006F0328: 0x01EB,
+	0x01EA0304: 0x01EC,
+	0x01EB0304: 0x01ED,
+	0x01B7030C: 0x01EE,
+	0x0292030C: 0x01EF,
+	0x006A030C: 0x01F0,
+	0x00470301: 0x01F4,
+	0x00670301: 0x01F5,
+	0x004E0300: 0x01F8,
+	0x006E0300: 0x01F9,
+	0x00C50301: 0x01FA,
+	0x00E50301: 0x01FB,
+	0x00C60301: 0x01FC,
+	0x00E60301: 0x01FD,
+	0x00D80301: 0x01FE,
+	0x00F80301: 0x01FF,
+	0x0041030F: 0x0200,
+	0x0061030F: 0x0201,
+	0x00410311: 0x0202,
+	0x00610311: 0x0203,
+	0x0045030F: 0x0204,
+	0x0065030F: 0x0205,
+	0x00450311: 0x0206,
+	0x00650311: 0x0207,
+	0x0049030F: 0x0208,
+	0x0069030F: 0x0209,
+	0x00490311: 0x020A,
+	0x00690311: 0x020B,
+	0x004F030F: 0x020C,
+	0x006F030F: 0x020D,
+	0x004F0311: 0x020E,
+	0x006F0311: 0x020F,
+	0x0052030F: 0x0210,
+	0x0072030F: 0x0211,
+	0x00520311: 0x0212,
+	0x00720311: 0x0213,
+	0x0055030F: 0x0214,
+	0x0075030F: 0x0215,
+	0x00550311: 0x0216,
+	0x00750311: 0x0217,
+	0x00530326: 0x0218,
+	0x00730326: 0x0219,
+	0x00540326: 0x021A,
+	0x00740326: 0x021B,
+	0x0048030C: 0x021E,
+	0x0068030C: 0x021F,
+	0x00410307: 0x0226,
+	0x00610307: 0x0227,
+	0x00450327: 0x0228,
+	0x00650327: 0x0229,
+	0x00D60304: 0x022A,
+	0x00F60304: 0x022B,
+	0x00D50304: 0x022C,
+	0x00F50304: 0x022D,
+	0x004F0307: 0x022E,
+	0x006F0307: 0x022F,
+	0x022E0304: 0x0230,
+	0x022F0304: 0x0231,
+	0x00590304: 0x0232,
+	0x00790304: 0x0233,
+	0x00A80301: 0x0385,
+	0x03910301: 0x0386,
+	0x03950301: 0x0388,
+	0x03970301: 0x0389,
+	0x03990301: 0x038A,
+	0x039F0301: 0x038C,
+	0x03A50301: 0x038E,
+	0x03A90301: 0x038F,
+	0x03CA0301: 0x0390,
+	0x03990308: 0x03AA,
+	0x03A50308: 0x03AB,
+	0x03B10301: 0x03AC,
+	0x03B50301: 0x03AD,
+	0x03B70301: 0x03AE,
+	0x03B90301: 0x03AF,
+	0x03CB0301: 0x03B0,
+	0x03B90308: 0x03CA,
+	0x03C50308: 0x03CB,
+	0x03BF0301: 0x03CC,
+	0x03C50301: 0x03CD,
+	0x03C90301: 0x03CE,
+	0x03D20301: 0x03D3,
+	0x03D20308: 0x03D4,
+	0x04150300: 0x0400,
+	0x04150308: 0x0401,
+	0x04130301: 0x0403,
+	0x04060308: 0x0407,
+	0x041A0301: 0x040C,
+	0x04180300: 0x040D,
+	0x04230306: 0x040E,
+	0x04180306: 0x0419,
+	0x04380306: 0x0439,
+	0x04350300: 0x0450,
+	0x04350308: 0x0451,
+	0x04330301: 0x0453,
+	0x04560308: 0x0457,
+	0x043A0301: 0x045C,
+	0x04380300: 0x045D,
+	0x04430306: 0x045E,
+	0x0474030F: 0x0476,
+	0x0475030F: 0x0477,
+	0x04160306: 0x04C1,
+	0x04360306: 0x04C2,
+	0x04100306: 0x04D0,
+	0x04300306: 0x04D1,
+	0x04100308: 0x04D2,
+	0x04300308: 0x04D3,
+	0x04150306: 0x04D6,
+	0x04350306: 0x04D7,
+	0x04D80308: 0x04DA,
+	0x04D90308: 0x04DB,
+	0x04160308: 0x04DC,
+	0x04360308: 0x04DD,
+	0x04170308: 0x04DE,
+	0x04370308: 0x04DF,
+	0x04180304: 0x04E2,
+	0x04380304: 0x04E3,
+	0x04180308: 0x04E4,
+	0x04380308: 0x04E5,
+	0x041E0308: 0x04E6,
+	0x043E0308: 0x04E7,
+	0x04E80308: 0x04EA,
+	0x04E90308: 0x04EB,
+	0x042D0308: 0x04EC,
+	0x044D0308: 0x04ED,
+	0x04230304: 0x04EE,
+	0x04430304: 0x04EF,
+	0x04230308: 0x04F0,
+	0x04430308: 0x04F1,
+	0x0423030B: 0x04F2,
+	0x0443030B: 0x04F3,
+	0x04270308: 0x04F4,
+	0x04470308: 0x04F5,
+	0x042B0308: 0x04F8,
+	0x044B0308: 0x04F9,
+	0x06270653: 0x0622,
+	0x06270654: 0x0623,
+	0x06480654: 0x0624,
+	0x06270655: 0x0625,
+	0x064A0654: 0x0626,
+	0x06D50654: 0x06C0,
+	0x06C10654: 0x06C2,
+	0x06D20654: 0x06D3,
+	0x0928093C: 0x0929,
+	0x0930093C: 0x0931,
+	0x0933093C: 0x0934,
+	0x09C709BE: 0x09CB,
+	0x09C709D7: 0x09CC,
+	0x0B470B56: 0x0B48,
+	0x0B470B3E: 0x0B4B,
+	0x0B470B57: 0x0B4C,
+	0x0B920BD7: 0x0B94,
+	0x0BC60BBE: 0x0BCA,
+	0x0BC70BBE: 0x0BCB,
+	0x0BC60BD7: 0x0BCC,
+	0x0C460C56: 0x0C48,
+	0x0CBF0CD5: 0x0CC0,
+	0x0CC60CD5: 0x0CC7,
+	0x0CC60CD6: 0x0CC8,
+	0x0CC60CC2: 0x0CCA,
+	0x0CCA0CD5: 0x0CCB,
+	0x0D460D3E: 0x0D4A,
+	0x0D470D3E: 0x0D4B,
+	0x0D460D57: 0x0D4C,
+	0x0DD90DCA: 0x0DDA,
+	0x0DD90DCF: 0x0DDC,
+	0x0DDC0DCA: 0x0DDD,
+	0x0DD90DDF: 0x0DDE,
+	0x1025102E: 0x1026,
+	0x1B051B35: 0x1B06,
+	0x1B071B35: 0x1B08,
+	0x1B091B35: 0x1B0A,
+	0x1B0B1B35: 0x1B0C,
+	0x1B0D1B35: 0x1B0E,
+	0x1B111B35: 0x1B12,
+	0x1B3A1B35: 0x1B3B,
+	0x1B3C1B35: 0x1B3D,
+	0x1B3E1B35: 0x1B40,
+	0x1B3F1B35: 0x1B41,
+	0x1B421B35: 0x1B43,
+	0x00410325: 0x1E00,
+	0x00610325: 0x1E01,
+	0x00420307: 0x1E02,
+	0x00620307: 0x1E03,
+	0x00420323: 0x1E04,
+	0x00620323: 0x1E05,
+	0x00420331: 0x1E06,
+	0x00620331: 0x1E07,
+	0x00C70301: 0x1E08,
+	0x00E70301: 0x1E09,
+	0x00440307: 0x1E0A,
+	0x00640307: 0x1E0B,
+	0x00440323: 0x1E0C,
+	0x00640323: 0x1E0D,
+	0x00440331: 0x1E0E,
+	0x00640331: 0x1E0F,
+	0x00440327: 0x1E10,
+	0x00640327: 0x1E11,
+	0x0044032D: 0x1E12,
+	0x0064032D: 0x1E13,
+	0x01120300: 0x1E14,
+	0x01130300: 0x1E15,
+	0x01120301: 0x1E16,
+	0x01130301: 0x1E17,
+	0x0045032D: 0x1E18,
+	0x0065032D: 0x1E19,
+	0x00450330: 0x1E1A,
+	0x00650330: 0x1E1B,
+	0x02280306: 0x1E1C,
+	0x02290306: 0x1E1D,
+	0x00460307: 0x1E1E,
+	0x00660307: 0x1E1F,
+	0x00470304: 0x1E20,
+	0x00670304: 0x1E21,
+	0x00480307: 0x1E22,
+	0x00680307: 0x1E23,
+	0x00480323: 0x1E24,
+	0x00680323: 0x1E25,
+	0x00480308: 0x1E26,
+	0x00680308: 0x1E27,
+	0x00480327: 0x1E28,
+	0x00680327: 0x1E29,
+	0x0048032E: 0x1E2A,
+	0x0068032E: 0x1E2B,
+	0x00490330: 0x1E2C,
+	0x00690330: 0x1E2D,
+	0x00CF0301: 0x1E2E,
+	0x00EF0301: 0x1E2F,
+	0x004B0301: 0x1E30,
+	0x006B0301: 0x1E31,
+	0x004B0323: 0x1E32,
+	0x006B0323: 0x1E33,
+	0x004B0331: 0x1E34,
+	0x006B0331: 0x1E35,
+	0x004C0323: 0x1E36,
+	0x006C0323: 0x1E37,
+	0x1E360304: 0x1E38,
+	0x1E370304: 0x1E39,
+	0x004C0331: 0x1E3A,
+	0x006C0331: 0x1E3B,
+	0x004C032D: 0x1E3C,
+	0x006C032D: 0x1E3D,
+	0x004D0301: 0x1E3E,
+	0x006D0301: 0x1E3F,
+	0x004D0307: 0x1E40,
+	0x006D0307: 0x1E41,
+	0x004D0323: 0x1E42,
+	0x006D0323: 0x1E43,
+	0x004E0307: 0x1E44,
+	0x006E0307: 0x1E45,
+	0x004E0323: 0x1E46,
+	0x006E0323: 0x1E47,
+	0x004E0331: 0x1E48,
+	0x006E0331: 0x1E49,
+	0x004E032D: 0x1E4A,
+	0x006E032D: 0x1E4B,
+	0x00D50301: 0x1E4C,
+	0x00F50301: 0x1E4D,
+	0x00D50308: 0x1E4E,
+	0x00F50308: 0x1E4F,
+	0x014C0300: 0x1E50,
+	0x014D0300: 0x1E51,
+	0x014C0301: 0x1E52,
+	0x014D0301: 0x1E53,
+	0x00500301: 0x1E54,
+	0x00700301: 0x1E55,
+	0x00500307: 0x1E56,
+	0x00700307: 0x1E57,
+	0x00520307: 0x1E58,
+	0x00720307: 0x1E59,
+	0x00520323: 0x1E5A,
+	0x00720323: 0x1E5B,
+	0x1E5A0304: 0x1E5C,
+	0x1E5B0304: 0x1E5D,
+	0x00520331: 0x1E5E,
+	0x00720331: 0x1E5F,
+	0x00530307: 0x1E60,
+	0x00730307: 0x1E61,
+	0x00530323: 0x1E62,
+	0x00730323: 0x1E63,
+	0x015A0307: 0x1E64,
+	0x015B0307: 0x1E65,
+	0x01600307: 0x1E66,
+	0x01610307: 0x1E67,
+	0x1E620307: 0x1E68,
+	0x1E630307: 0x1E69,
+	0x00540307: 0x1E6A,
+	0x00740307: 0x1E6B,
+	0x00540323: 0x1E6C,
+	0x00740323: 0x1E6D,
+	0x00540331: 0x1E6E,
+	0x00740331: 0x1E6F,
+	0x0054032D: 0x1E70,
+	0x0074032D: 0x1E71,
+	0x00550324: 0x1E72,
+	0x00750324: 0x1E73,
+	0x00550330: 0x1E74,
+	0x00750330: 0x1E75,
+	0x0055032D: 0x1E76,
+	0x0075032D: 0x1E77,
+	0x01680301: 0x1E78,
+	0x01690301: 0x1E79,
+	0x016A0308: 0x1E7A,
+	0x016B0308: 0x1E7B,
+	0x00560303: 0x1E7C,
+	0x00760303: 0x1E7D,
+	0x00560323: 0x1E7E,
+	0x00760323: 0x1E7F,
+	0x00570300: 0x1E80,
+	0x00770300: 0x1E81,
+	0x00570301: 0x1E82,
+	0x00770301: 0x1E83,
+	0x00570308: 0x1E84,
+	0x00770308: 0x1E85,
+	0x00570307: 0x1E86,
+	0x00770307: 0x1E87,
+	0x00570323: 0x1E88,
+	0x00770323: 0x1E89,
+	0x00580307: 0x1E8A,
+	0x00780307: 0x1E8B,
+	0x00580308: 0x1E8C,
+	0x00780308: 0x1E8D,
+	0x00590307: 0x1E8E,
+	0x00790307: 0x1E8F,
+	0x005A0302: 0x1E90,
+	0x007A0302: 0x1E91,
+	0x005A0323: 0x1E92,
+	0x007A0323: 0x1E93,
+	0x005A0331: 0x1E94,
+	0x007A0331: 0x1E95,
+	0x00680331: 0x1E96,
+	0x00740308: 0x1E97,
+	0x0077030A: 0x1E98,
+	0x0079030A: 0x1E99,
+	0x017F0307: 0x1E9B,
+	0x00410323: 0x1EA0,
+	0x00610323: 0x1EA1,
+	0x00410309: 0x1EA2,
+	0x00610309: 0x1EA3,
+	0x00C20301: 0x1EA4,
+	0x00E20301: 0x1EA5,
+	0x00C20300: 0x1EA6,
+	0x00E20300: 0x1EA7,
+	0x00C20309: 0x1EA8,
+	0x00E20309: 0x1EA9,
+	0x00C20303: 0x1EAA,
+	0x00E20303: 0x1EAB,
+	0x1EA00302: 0x1EAC,
+	0x1EA10302: 0x1EAD,
+	0x01020301: 0x1EAE,
+	0x01030301: 0x1EAF,
+	0x01020300: 0x1EB0,
+	0x01030300: 0x1EB1,
+	0x01020309: 0x1EB2,
+	0x01030309: 0x1EB3,
+	0x01020303: 0x1EB4,
+	0x01030303: 0x1EB5,
+	0x1EA00306: 0x1EB6,
+	0x1EA10306: 0x1EB7,
+	0x00450323: 0x1EB8,
+	0x00650323: 0x1EB9,
+	0x00450309: 0x1EBA,
+	0x00650309: 0x1EBB,
+	0x00450303: 0x1EBC,
+	0x00650303: 0x1EBD,
+	0x00CA0301: 0x1EBE,
+	0x00EA0301: 0x1EBF,
+	0x00CA0300: 0x1EC0,
+	0x00EA0300: 0x1EC1,
+	0x00CA0309: 0x1EC2,
+	0x00EA0309: 0x1EC3,
+	0x00CA0303: 0x1EC4,
+	0x00EA0303: 0x1EC5,
+	0x1EB80302: 0x1EC6,
+	0x1EB90302: 0x1EC7,
+	0x00490309: 0x1EC8,
+	0x00690309: 0x1EC9,
+	0x00490323: 0x1ECA,
+	0x00690323: 0x1ECB,
+	0x004F0323: 0x1ECC,
+	0x006F0323: 0x1ECD,
+	0x004F0309: 0x1ECE,
+	0x006F0309: 0x1ECF,
+	0x00D40301: 0x1ED0,
+	0x00F40301: 0x1ED1,
+	0x00D40300: 0x1ED2,
+	0x00F40300: 0x1ED3,
+	0x00D40309: 0x1ED4,
+	0x00F40309: 0x1ED5,
+	0x00D40303: 0x1ED6,
+	0x00F40303: 0x1ED7,
+	0x1ECC0302: 0x1ED8,
+	0x1ECD0302: 0x1ED9,
+	0x01A00301: 0x1EDA,
+	0x01A10301: 0x1EDB,
+	0x01A00300: 0x1EDC,
+	0x01A10300: 0x1EDD,
+	0x01A00309: 0x1EDE,
+	0x01A10309: 0x1EDF,
+	0x01A00303: 0x1EE0,
+	0x01A10303: 0x1EE1,
+	0x01A00323: 0x1EE2,
+	0x01A10323: 0x1EE3,
+	0x00550323: 0x1EE4,
+	0x00750323: 0x1EE5,
+	0x00550309: 0x1EE6,
+	0x00750309: 0x1EE7,
+	0x01AF0301: 0x1EE8,
+	0x01B00301: 0x1EE9,
+	0x01AF0300: 0x1EEA,
+	0x01B00300: 0x1EEB,
+	0x01AF0309: 0x1EEC,
+	0x01B00309: 0x1EED,
+	0x01AF0303: 0x1EEE,
+	0x01B00303: 0x1EEF,
+	0x01AF0323: 0x1EF0,
+	0x01B00323: 0x1EF1,
+	0x00590300: 0x1EF2,
+	0x00790300: 0x1EF3,
+	0x00590323: 0x1EF4,
+	0x00790323: 0x1EF5,
+	0x00590309: 0x1EF6,
+	0x00790309: 0x1EF7,
+	0x00590303: 0x1EF8,
+	0x00790303: 0x1EF9,
+	0x03B10313: 0x1F00,
+	0x03B10314: 0x1F01,
+	0x1F000300: 0x1F02,
+	0x1F010300: 0x1F03,
+	0x1F000301: 0x1F04,
+	0x1F010301: 0x1F05,
+	0x1F000342: 0x1F06,
+	0x1F010342: 0x1F07,
+	0x03910313: 0x1F08,
+	0x03910314: 0x1F09,
+	0x1F080300: 0x1F0A,
+	0x1F090300: 0x1F0B,
+	0x1F080301: 0x1F0C,
+	0x1F090301: 0x1F0D,
+	0x1F080342: 0x1F0E,
+	0x1F090342: 0x1F0F,
+	0x03B50313: 0x1F10,
+	0x03B50314: 0x1F11,
+	0x1F100300: 0x1F12,
+	0x1F110300: 0x1F13,
+	0x1F100301: 0x1F14,
+	0x1F110301: 0x1F15,
+	0x03950313: 0x1F18,
+	0x03950314: 0x1F19,
+	0x1F180300: 0x1F1A,
+	0x1F190300: 0x1F1B,
+	0x1F180301: 0x1F1C,
+	0x1F190301: 0x1F1D,
+	0x03B70313: 0x1F20,
+	0x03B70314: 0x1F21,
+	0x1F200300: 0x1F22,
+	0x1F210300: 0x1F23,
+	0x1F200301: 0x1F24,
+	0x1F210301: 0x1F25,
+	0x1F200342: 0x1F26,
+	0x1F210342: 0x1F27,
+	0x03970313: 0x1F28,
+	0x03970314: 0x1F29,
+	0x1F280300: 0x1F2A,
+	0x1F290300: 0x1F2B,
+	0x1F280301: 0x1F2C,
+	0x1F290301: 0x1F2D,
+	0x1F280342: 0x1F2E,
+	0x1F290342: 0x1F2F,
+	0x03B90313: 0x1F30,
+	0x03B90314: 0x1F31,
+	0x1F300300: 0x1F32,
+	0x1F310300: 0x1F33,
+	0x1F300301: 0x1F34,
+	0x1F310301: 0x1F35,
+	0x1F300342: 0x1F36,
+	0x1F310342: 0x1F37,
+	0x03990313: 0x1F38,
+	0x03990314: 0x1F39,
+	0x1F380300: 0x1F3A,
+	0x1F390300: 0x1F3B,
+	0x1F380301: 0x1F3C,
+	0x1F390301: 0x1F3D,
+	0x1F380342: 0x1F3E,
+	0x1F390342: 0x1F3F,
+	0x03BF0313: 0x1F40,
+	0x03BF0314: 0x1F41,
+	0x1F400300: 0x1F42,
+	0x1F410300: 0x1F43,
+	0x1F400301: 0x1F44,
+	0x1F410301: 0x1F45,
+	0x039F0313: 0x1F48,
+	0x039F0314: 0x1F49,
+	0x1F480300: 0x1F4A,
+	0x1F490300: 0x1F4B,
+	0x1F480301: 0x1F4C,
+	0x1F490301: 0x1F4D,
+	0x03C50313: 0x1F50,
+	0x03C50314: 0x1F51,
+	0x1F500300: 0x1F52,
+	0x1F510300: 0x1F53,
+	0x1F500301: 0x1F54,
+	0x1F510301: 0x1F55,
+	0x1F500342: 0x1F56,
+	0x1F510342: 0x1F57,
+	0x03A50314: 0x1F59,
+	0x1F590300: 0x1F5B,
+	0x1F590301: 0x1F5D,
+	0x1F590342: 0x1F5F,
+	0x03C90313: 0x1F60,
+	0x03C90314: 0x1F61,
+	0x1F600300: 0x1F62,
+	0x1F610300: 0x1F63,
+	0x1F600301: 0x1F64,
+	0x1F610301: 0x1F65,
+	0x1F600342: 0x1F66,
+	0x1F610342: 0x1F67,
+	0x03A90313: 0x1F68,
+	0x03A90314: 0x1F69,
+	0x1F680300: 0x1F6A,
+	0x1F690300: 0x1F6B,
+	0x1F680301: 0x1F6C,
+	0x1F690301: 0x1F6D,
+	0x1F680342: 0x1F6E,
+	0x1F690342: 0x1F6F,
+	0x03B10300: 0x1F70,
+	0x03B50300: 0x1F72,
+	0x03B70300: 0x1F74,
+	0x03B90300: 0x1F76,
+	0x03BF0300: 0x1F78,
+	0x03C50300: 0x1F7A,
+	0x03C90300: 0x1F7C,
+	0x1F000345: 0x1F80,
+	0x1F010345: 0x1F81,
+	0x1F020345: 0x1F82,
+	0x1F030345: 0x1F83,
+	0x1F040345: 0x1F84,
+	0x1F050345: 0x1F85,
+	0x1F060345: 0x1F86,
+	0x1F070345: 0x1F87,
+	0x1F080345: 0x1F88,
+	0x1F090345: 0x1F89,
+	0x1F0A0345: 0x1F8A,
+	0x1F0B0345: 0x1F8B,
+	0x1F0C0345: 0x1F8C,
+	0x1F0D0345: 0x1F8D,
+	0x1F0E0345: 0x1F8E,
+	0x1F0F0345: 0x1F8F,
+	0x1F200345: 0x1F90,
+	0x1F210345: 0x1F91,
+	0x1F220345: 0x1F92,
+	0x1F230345: 0x1F93,
+	0x1F240345: 0x1F94,
+	0x1F250345: 0x1F95,
+	0x1F260345: 0x1F96,
+	0x1F270345: 0x1F97,
+	0x1F280345: 0x1F98,
+	0x1F290345: 0x1F99,
+	0x1F2A0345: 0x1F9A,
+	0x1F2B0345: 0x1F9B,
+	0x1F2C0345: 0x1F9C,
+	0x1F2D0345: 0x1F9D,
+	0x1F2E0345: 0x1F9E,
+	0x1F2F0345: 0x1F9F,
+	0x1F600345: 0x1FA0,
+	0x1F610345: 0x1FA1,
+	0x1F620345: 0x1FA2,
+	0x1F630345: 0x1FA3,
+	0x1F640345: 0x1FA4,
+	0x1F650345: 0x1FA5,
+	0x1F660345: 0x1FA6,
+	0x1F670345: 0x1FA7,
+	0x1F680345: 0x1FA8,
+	0x1F690345: 0x1FA9,
+	0x1F6A0345: 0x1FAA,
+	0x1F6B0345: 0x1FAB,
+	0x1F6C0345: 0x1FAC,
+	0x1F6D0345: 0x1FAD,
+	0x1F6E0345: 0x1FAE,
+	0x1F6F0345: 0x1FAF,
+	0x03B10306: 0x1FB0,
+	0x03B10304: 0x1FB1,
+	0x1F700345: 0x1FB2,
+	0x03B10345: 0x1FB3,
+	0x03AC0345: 0x1FB4,
+	0x03B10342: 0x1FB6,
+	0x1FB60345: 0x1FB7,
+	0x03910306: 0x1FB8,
+	0x03910304: 0x1FB9,
+	0x03910300: 0x1FBA,
+	0x03910345: 0x1FBC,
+	0x00A80342: 0x1FC1,
+	0x1F740345: 0x1FC2,
+	0x03B70345: 0x1FC3,
+	0x03AE0345: 0x1FC4,
+	0x03B70342: 0x1FC6,
+	0x1FC60345: 0x1FC7,
+	0x03950300: 0x1FC8,
+	0x03970300: 0x1FCA,
+	0x03970345: 0x1FCC,
+	0x1FBF0300: 0x1FCD,
+	0x1FBF0301: 0x1FCE,
+	0x1FBF0342: 0x1FCF,
+	0x03B90306: 0x1FD0,
+	0x03B90304: 0x1FD1,
+	0x03CA0300: 0x1FD2,
+	0x03B90342: 0x1FD6,
+	0x03CA0342: 0x1FD7,
+	0x03990306: 0x1FD8,
+	0x03990304: 0x1FD9,
+	0x03990300: 0x1FDA,
+	0x1FFE0300: 0x1FDD,
+	0x1FFE0301: 0x1FDE,
+	0x1FFE0342: 0x1FDF,
+	0x03C50306: 0x1FE0,
+	0x03C50304: 0x1FE1,
+	0x03CB0300: 0x1FE2,
+	0x03C10313: 0x1FE4,
+	0x03C10314: 0x1FE5,
+	0x03C50342: 0x1FE6,
+	0x03CB0342: 0x1FE7,
+	0x03A50306: 0x1FE8,
+	0x03A50304: 0x1FE9,
+	0x03A50300: 0x1FEA,
+	0x03A10314: 0x1FEC,
+	0x00A80300: 0x1FED,
+	0x1F7C0345: 0x1FF2,
+	0x03C90345: 0x1FF3,
+	0x03CE0345: 0x1FF4,
+	0x03C90342: 0x1FF6,
+	0x1FF60345: 0x1FF7,
+	0x039F0300: 0x1FF8,
+	0x03A90300: 0x1FFA,
+	0x03A90345: 0x1FFC,
+	0x21900338: 0x219A,
+	0x21920338: 0x219B,
+	0x21940338: 0x21AE,
+	0x21D00338: 0x21CD,
+	0x21D40338: 0x21CE,
+	0x21D20338: 0x21CF,
+	0x22030338: 0x2204,
+	0x22080338: 0x2209,
+	0x220B0338: 0x220C,
+	0x22230338: 0x2224,
+	0x22250338: 0x2226,
+	0x223C0338: 0x2241,
+	0x22430338: 0x2244,
+	0x22450338: 0x2247,
+	0x22480338: 0x2249,
+	0x003D0338: 0x2260,
+	0x22610338: 0x2262,
+	0x224D0338: 0x226D,
+	0x003C0338: 0x226E,
+	0x003E0338: 0x226F,
+	0x22640338: 0x2270,
+	0x22650338: 0x2271,
+	0x22720338: 0x2274,
+	0x22730338: 0x2275,
+	0x22760338: 0x2278,
+	0x22770338: 0x2279,
+	0x227A0338: 0x2280,
+	0x227B0338: 0x2281,
+	0x22820338: 0x2284,
+	0x22830338: 0x2285,
+	0x22860338: 0x2288,
+	0x22870338: 0x2289,
+	0x22A20338: 0x22AC,
+	0x22A80338: 0x22AD,
+	0x22A90338: 0x22AE,
+	0x22AB0338: 0x22AF,
+	0x227C0338: 0x22E0,
+	0x227D0338: 0x22E1,
+	0x22910338: 0x22E2,
+	0x22920338: 0x22E3,
+	0x22B20338: 0x22EA,
+	0x22B30338: 0x22EB,
+	0x22B40338: 0x22EC,
+	0x22B50338: 0x22ED,
+	0x304B3099: 0x304C,
+	0x304D3099: 0x304E,
+	0x304F3099: 0x3050,
+	0x30513099: 0x3052,
+	0x30533099: 0x3054,
+	0x30553099: 0x3056,
+	0x30573099: 0x3058,
+	0x30593099: 0x305A,
+	0x305B3099: 0x305C,
+	0x305D3099: 0x305E,
+	0x305F3099: 0x3060,
+	0x30613099: 0x3062,
+	0x30643099: 0x3065,
+	0x30663099: 0x3067,
+	0x30683099: 0x3069,
+	0x306F3099: 0x3070,
+	0x306F309A: 0x3071,
+	0x30723099: 0x3073,
+	0x3072309A: 0x3074,
+	0x30753099: 0x3076,
+	0x3075309A: 0x3077,
+	0x30783099: 0x3079,
+	0x3078309A: 0x307A,
+	0x307B3099: 0x307C,
+	0x307B309A: 0x307D,
+	0x30463099: 0x3094,
+	0x309D3099: 0x309E,
+	0x30AB3099: 0x30AC,
+	0x30AD3099: 0x30AE,
+	0x30AF3099: 0x30B0,
+	0x30B13099: 0x30B2,
+	0x30B33099: 0x30B4,
+	0x30B53099: 0x30B6,
+	0x30B73099: 0x30B8,
+	0x30B93099: 0x30BA,
+	0x30BB3099: 0x30BC,
+	0x30BD3099: 0x30BE,
+	0x30BF3099: 0x30C0,
+	0x30C13099: 0x30C2,
+	0x30C43099: 0x30C5,
+	0x30C63099: 0x30C7,
+	0x30C83099: 0x30C9,
+	0x30CF3099: 0x30D0,
+	0x30CF309A: 0x30D1,
+	0x30D23099: 0x30D3,
+	0x30D2309A: 0x30D4,
+	0x30D53099: 0x30D6,
+	0x30D5309A: 0x30D7,
+	0x30D83099: 0x30D9,
+	0x30D8309A: 0x30DA,
+	0x30DB3099: 0x30DC,
+	0x30DB309A: 0x30DD,
+	0x30A63099: 0x30F4,
+	0x30EF3099: 0x30F7,
+	0x30F03099: 0x30F8,
+	0x30F13099: 0x30F9,
+	0x30F23099: 0x30FA,
+	0x30FD3099: 0x30FE,
+	0x109910BA: 0x1109A,
+	0x109B10BA: 0x1109C,
+	0x10A510BA: 0x110AB,
+	0x11311127: 0x1112E,
+	0x11321127: 0x1112F,
+	0x1347133E: 0x1134B,
+	0x13471357: 0x1134C,
+	0x14B914BA: 0x114BB,
+	0x14B914B0: 0x114BC,
+	0x14B914BD: 0x114BE,
+	0x15B815AF: 0x115BA,
+	0x15B915AF: 0x115BB,
+}
+
+// Total size of tables: 52KB (53487 bytes)
diff --git a/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/transform.go b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/transform.go
new file mode 100644
index 0000000000000000000000000000000000000000..8589067cde48359fab37f1927bdd5def61369d25
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/transform.go
@@ -0,0 +1,88 @@
+// 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 norm
+
+import (
+	"unicode/utf8"
+
+	"golang.org/x/text/transform"
+)
+
+// Reset implements the Reset method of the transform.Transformer interface.
+func (Form) Reset() {}
+
+// Transform implements the Transform method of the transform.Transformer
+// interface. It may need to write segments of up to MaxSegmentSize at once.
+// Users should either catch ErrShortDst and allow dst to grow or have dst be at
+// least of size MaxTransformChunkSize to be guaranteed of progress.
+func (f Form) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+	n := 0
+	// Cap the maximum number of src bytes to check.
+	b := src
+	eof := atEOF
+	if ns := len(dst); ns < len(b) {
+		err = transform.ErrShortDst
+		eof = false
+		b = b[:ns]
+	}
+	i, ok := formTable[f].quickSpan(inputBytes(b), n, len(b), eof)
+	n += copy(dst[n:], b[n:i])
+	if !ok {
+		nDst, nSrc, err = f.transform(dst[n:], src[n:], atEOF)
+		return nDst + n, nSrc + n, err
+	}
+	if n < len(src) && !atEOF {
+		err = transform.ErrShortSrc
+	}
+	return n, n, err
+}
+
+func flushTransform(rb *reorderBuffer) bool {
+	// Write out (must fully fit in dst, or else it is a ErrShortDst).
+	if len(rb.out) < rb.nrune*utf8.UTFMax {
+		return false
+	}
+	rb.out = rb.out[rb.flushCopy(rb.out):]
+	return true
+}
+
+var errs = []error{nil, transform.ErrShortDst, transform.ErrShortSrc}
+
+// transform implements the transform.Transformer interface. It is only called
+// when quickSpan does not pass for a given string.
+func (f Form) transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+	// TODO: get rid of reorderBuffer. See CL 23460044.
+	rb := reorderBuffer{}
+	rb.init(f, src)
+	for {
+		// Load segment into reorder buffer.
+		rb.setFlusher(dst[nDst:], flushTransform)
+		end := decomposeSegment(&rb, nSrc, atEOF)
+		if end < 0 {
+			return nDst, nSrc, errs[-end]
+		}
+		nDst = len(dst) - len(rb.out)
+		nSrc = end
+
+		// Next quickSpan.
+		end = rb.nsrc
+		eof := atEOF
+		if n := nSrc + len(dst) - nDst; n < end {
+			err = transform.ErrShortDst
+			end = n
+			eof = false
+		}
+		end, ok := rb.f.quickSpan(rb.src, nSrc, end, eof)
+		n := copy(dst[nDst:], rb.src.bytes[nSrc:end])
+		nSrc += n
+		nDst += n
+		if ok {
+			if n < rb.nsrc && !atEOF {
+				err = transform.ErrShortSrc
+			}
+			return nDst, nSrc, err
+		}
+	}
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/transform_test.go b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/transform_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..987d680ed1a0531d20e22dd6e788ccff04a84346
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/transform_test.go
@@ -0,0 +1,101 @@
+// 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 norm
+
+import (
+	"fmt"
+	"testing"
+
+	"golang.org/x/text/transform"
+)
+
+func TestTransform(t *testing.T) {
+	tests := []struct {
+		f       Form
+		in, out string
+		eof     bool
+		dstSize int
+		err     error
+	}{
+		{NFC, "ab", "ab", true, 2, nil},
+		{NFC, "qx", "qx", true, 2, nil},
+		{NFD, "qx", "qx", true, 2, nil},
+		{NFC, "", "", true, 1, nil},
+		{NFD, "", "", true, 1, nil},
+		{NFC, "", "", false, 1, nil},
+		{NFD, "", "", false, 1, nil},
+
+		// Normalized segment does not fit in destination.
+		{NFD, "ö", "", true, 1, transform.ErrShortDst},
+		{NFD, "ö", "", true, 2, transform.ErrShortDst},
+
+		// As an artifact of the algorithm, only full segments are written.
+		// This is not strictly required, and some bytes could be written.
+		// In practice, for Transform to not block, the destination buffer
+		// should be at least MaxSegmentSize to work anyway and these edge
+		// conditions will be relatively rare.
+		{NFC, "ab", "", true, 1, transform.ErrShortDst},
+		// This is even true for inert runes.
+		{NFC, "qx", "", true, 1, transform.ErrShortDst},
+		{NFC, "a\u0300abc", "\u00e0a", true, 4, transform.ErrShortDst},
+
+		// We cannot write a segment if succesive runes could still change the result.
+		{NFD, "ö", "", false, 3, transform.ErrShortSrc},
+		{NFC, "a\u0300", "", false, 4, transform.ErrShortSrc},
+		{NFD, "a\u0300", "", false, 4, transform.ErrShortSrc},
+		{NFC, "ö", "", false, 3, transform.ErrShortSrc},
+
+		{NFC, "a\u0300", "", true, 1, transform.ErrShortDst},
+		// Theoretically could fit, but won't due to simplified checks.
+		{NFC, "a\u0300", "", true, 2, transform.ErrShortDst},
+		{NFC, "a\u0300", "", true, 3, transform.ErrShortDst},
+		{NFC, "a\u0300", "\u00e0", true, 4, nil},
+
+		{NFD, "öa\u0300", "o\u0308", false, 8, transform.ErrShortSrc},
+		{NFD, "öa\u0300ö", "o\u0308a\u0300", true, 8, transform.ErrShortDst},
+		{NFD, "öa\u0300ö", "o\u0308a\u0300", false, 12, transform.ErrShortSrc},
+
+		// Illegal input is copied verbatim.
+		{NFD, "\xbd\xb2=\xbc ", "\xbd\xb2=\xbc ", true, 8, nil},
+	}
+	b := make([]byte, 100)
+	for i, tt := range tests {
+		nDst, _, err := tt.f.Transform(b[:tt.dstSize], []byte(tt.in), tt.eof)
+		out := string(b[:nDst])
+		if out != tt.out || err != tt.err {
+			t.Errorf("%d: was %+q (%v); want %+q (%v)", i, out, err, tt.out, tt.err)
+		}
+		if want := tt.f.String(tt.in)[:nDst]; want != out {
+			t.Errorf("%d: incorect normalization: was %+q; want %+q", i, out, want)
+		}
+	}
+}
+
+var transBufSizes = []int{
+	MaxTransformChunkSize,
+	3 * MaxTransformChunkSize / 2,
+	2 * MaxTransformChunkSize,
+	3 * MaxTransformChunkSize,
+	100 * MaxTransformChunkSize,
+}
+
+func doTransNorm(f Form, buf []byte, b []byte) []byte {
+	acc := []byte{}
+	for p := 0; p < len(b); {
+		nd, ns, _ := f.Transform(buf[:], b[p:], true)
+		p += ns
+		acc = append(acc, buf[:nd]...)
+	}
+	return acc
+}
+
+func TestTransformNorm(t *testing.T) {
+	for _, sz := range transBufSizes {
+		buf := make([]byte, sz)
+		runNormTests(t, fmt.Sprintf("Transform:%d", sz), func(f Form, out []byte, s string) []byte {
+			return doTransNorm(f, buf, append(out, s...))
+		})
+	}
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/trie.go b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/trie.go
new file mode 100644
index 0000000000000000000000000000000000000000..423386bf4369fde49e041a0b0a88ca9578664648
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/trie.go
@@ -0,0 +1,54 @@
+// 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 norm
+
+type valueRange struct {
+	value  uint16 // header: value:stride
+	lo, hi byte   // header: lo:n
+}
+
+type sparseBlocks struct {
+	values []valueRange
+	offset []uint16
+}
+
+var nfcSparse = sparseBlocks{
+	values: nfcSparseValues[:],
+	offset: nfcSparseOffset[:],
+}
+
+var nfkcSparse = sparseBlocks{
+	values: nfkcSparseValues[:],
+	offset: nfkcSparseOffset[:],
+}
+
+var (
+	nfcData  = newNfcTrie(0)
+	nfkcData = newNfkcTrie(0)
+)
+
+// lookupValue determines the type of block n and looks up the value for b.
+// For n < t.cutoff, the block is a simple lookup table. Otherwise, the block
+// is a list of ranges with an accompanying value. Given a matching range r,
+// the value for b is by r.value + (b - r.lo) * stride.
+func (t *sparseBlocks) lookup(n uint32, b byte) uint16 {
+	offset := t.offset[n]
+	header := t.values[offset]
+	lo := offset + 1
+	hi := lo + uint16(header.lo)
+	for lo < hi {
+		m := lo + (hi-lo)/2
+		r := t.values[m]
+		if r.lo <= b && b <= r.hi {
+			return r.value + uint16(b-r.lo)*header.value
+		}
+		if b < r.lo {
+			hi = m
+		} else {
+			lo = m + 1
+		}
+	}
+	return 0
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/triegen.go b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/triegen.go
new file mode 100644
index 0000000000000000000000000000000000000000..45d711900d144f5e66fb29941c1a8700049ab0c9
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/go.text/unicode/norm/triegen.go
@@ -0,0 +1,117 @@
+// 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 ignore
+
+// Trie table generator.
+// Used by make*tables tools to generate a go file with trie data structures
+// for mapping UTF-8 to a 16-bit value. All but the last byte in a UTF-8 byte
+// sequence are used to lookup offsets in the index table to be used for the
+// next byte. The last byte is used to index into a table with 16-bit values.
+
+package main
+
+import (
+	"fmt"
+	"io"
+)
+
+const maxSparseEntries = 16
+
+type normCompacter struct {
+	sparseBlocks [][]uint64
+	sparseOffset []uint16
+	sparseCount  int
+	name         string
+}
+
+func mostFrequentStride(a []uint64) int {
+	counts := make(map[int]int)
+	var v int
+	for _, x := range a {
+		if stride := int(x) - v; v != 0 && stride >= 0 {
+			counts[stride]++
+		}
+		v = int(x)
+	}
+	var maxs, maxc int
+	for stride, cnt := range counts {
+		if cnt > maxc || (cnt == maxc && stride < maxs) {
+			maxs, maxc = stride, cnt
+		}
+	}
+	return maxs
+}
+
+func countSparseEntries(a []uint64) int {
+	stride := mostFrequentStride(a)
+	var v, count int
+	for _, tv := range a {
+		if int(tv)-v != stride {
+			if tv != 0 {
+				count++
+			}
+		}
+		v = int(tv)
+	}
+	return count
+}
+
+func (c *normCompacter) Size(v []uint64) (sz int, ok bool) {
+	if n := countSparseEntries(v); n <= maxSparseEntries {
+		return (n+1)*4 + 2, true
+	}
+	return 0, false
+}
+
+func (c *normCompacter) Store(v []uint64) uint32 {
+	h := uint32(len(c.sparseOffset))
+	c.sparseBlocks = append(c.sparseBlocks, v)
+	c.sparseOffset = append(c.sparseOffset, uint16(c.sparseCount))
+	c.sparseCount += countSparseEntries(v) + 1
+	return h
+}
+
+func (c *normCompacter) Handler() string {
+	return c.name + "Sparse.lookup"
+}
+
+func (c *normCompacter) Print(w io.Writer) (retErr error) {
+	p := func(f string, x ...interface{}) {
+		if _, err := fmt.Fprintf(w, f, x...); retErr == nil && err != nil {
+			retErr = err
+		}
+	}
+
+	ls := len(c.sparseBlocks)
+	p("// %sSparseOffset: %d entries, %d bytes\n", c.name, ls, ls*2)
+	p("var %sSparseOffset = %#v\n\n", c.name, c.sparseOffset)
+
+	ns := c.sparseCount
+	p("// %sSparseValues: %d entries, %d bytes\n", c.name, ns, ns*4)
+	p("var %sSparseValues = [%d]valueRange {", c.name, ns)
+	for i, b := range c.sparseBlocks {
+		p("\n// Block %#x, offset %#x", i, c.sparseOffset[i])
+		var v int
+		stride := mostFrequentStride(b)
+		n := countSparseEntries(b)
+		p("\n{value:%#04x,lo:%#02x},", stride, uint8(n))
+		for i, nv := range b {
+			if int(nv)-v != stride {
+				if v != 0 {
+					p(",hi:%#02x},", 0x80+i-1)
+				}
+				if nv != 0 {
+					p("\n{value:%#04x,lo:%#02x", nv, 0x80+i)
+				}
+			}
+			v = int(nv)
+		}
+		if v != 0 {
+			p(",hi:%#02x},", 0x80+len(b)-1)
+		}
+	}
+	p("\n}\n\n")
+	return
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/README b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/README
new file mode 100644
index 0000000000000000000000000000000000000000..506dacea8ade3324daf5b35f14acd86f9ff54910
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/README
@@ -0,0 +1,7 @@
+This package provides an interface to the PortAudio audio I/O library (http://www.portaudio.com/).  See the package documentation for details.
+
+To build portaudio-go, you must first have the PortAudio development headers and libraries installed.  Some systems provide a package for this; e.g., on Ubuntu you would want to run `apt-get install portaudio19-dev`.  On other systems you might have to install from source.
+
+A previous version of OpenDefaultStream automatically called Initialize (and Stream.Close called Terminate).  This behavior no longer exists; clients must explicitly call Initialize before making any other calls (and finally Terminate).
+
+Thanks to sqweek for motivating and contributing to host API and device enumeration.
diff --git a/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/echo.go b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/echo.go
new file mode 100644
index 0000000000000000000000000000000000000000..2cfda02651f5072708d4c240ead39f7e1e31c108
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/echo.go
@@ -0,0 +1,48 @@
+package main
+
+import (
+	"code.google.com/p/portaudio-go/portaudio"
+	"time"
+)
+
+func main() {
+	portaudio.Initialize()
+	defer portaudio.Terminate()
+	e := newEcho(time.Second / 3)
+	defer e.Close()
+	chk(e.Start())
+	time.Sleep(4 * time.Second)
+	chk(e.Stop())
+}
+
+type echo struct {
+	*portaudio.Stream
+	buffer []float32
+	i      int
+}
+
+func newEcho(delay time.Duration) *echo {
+	h, err := portaudio.DefaultHostApi()
+	chk(err)
+	p := portaudio.LowLatencyParameters(h.DefaultInputDevice, h.DefaultOutputDevice)
+	p.Input.Channels = 1
+	p.Output.Channels = 1
+	e := &echo{buffer: make([]float32, int(p.SampleRate*delay.Seconds()))}
+	e.Stream, err = portaudio.OpenStream(p, e.processAudio)
+	chk(err)
+	return e
+}
+
+func (e *echo) processAudio(in, out []float32) {
+	for i := range out {
+		out[i] = .7 * e.buffer[e.i]
+		e.buffer[e.i] = in[i]
+		e.i = (e.i + 1) % len(e.buffer)
+	}
+}
+
+func chk(err error) {
+	if err != nil {
+		panic(err)
+	}
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/enumerate b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/enumerate
new file mode 100644
index 0000000000000000000000000000000000000000..5af5468c21cdd40c9f0c2e3fbb938edc60e2834b
Binary files /dev/null and b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/enumerate differ
diff --git a/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/enumerate.go b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/enumerate.go
new file mode 100644
index 0000000000000000000000000000000000000000..87d66223023c5e6702e4287bf4b95718185eaec5
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/enumerate.go
@@ -0,0 +1,40 @@
+package main
+
+import (
+	"code.google.com/p/portaudio-go/portaudio"
+	"os"
+	"text/template"
+)
+
+var tmpl = template.Must(template.New("").Parse(
+	`{{. | len}} host APIs: {{range .}}
+	Name:                   {{.Name}}
+	{{if .DefaultInputDevice}}Default input device:   {{.DefaultInputDevice.Name}}{{end}}
+	{{if .DefaultOutputDevice}}Default output device:  {{.DefaultOutputDevice.Name}}{{end}}
+	Devices: {{range .Devices}}
+		Name:                      {{.Name}}
+		MaxInputChannels:          {{.MaxInputChannels}}
+		MaxOutputChannels:         {{.MaxOutputChannels}}
+		DefaultLowInputLatency:    {{.DefaultLowInputLatency}}
+		DefaultLowOutputLatency:   {{.DefaultLowOutputLatency}}
+		DefaultHighInputLatency:   {{.DefaultHighInputLatency}}
+		DefaultHighOutputLatency:  {{.DefaultHighOutputLatency}}
+		DefaultSampleRate:         {{.DefaultSampleRate}}
+	{{end}}
+{{end}}`,
+))
+
+func main() {
+	portaudio.Initialize()
+	defer portaudio.Terminate()
+	hs, err := portaudio.HostApis()
+	chk(err)
+	err = tmpl.Execute(os.Stdout, hs)
+	chk(err)
+}
+
+func chk(err error) {
+	if err != nil {
+		panic(err)
+	}
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/fidelity.aiff b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/fidelity.aiff
new file mode 100644
index 0000000000000000000000000000000000000000..ab11adbe29da5c87a9346abf09540515628bd1d7
Binary files /dev/null and b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/fidelity.aiff differ
diff --git a/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/noise.go b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/noise.go
new file mode 100644
index 0000000000000000000000000000000000000000..efe3686da3e2c3d03baf62ad74ea67a11790b41e
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/noise.go
@@ -0,0 +1,30 @@
+package main
+
+import (
+	"code.google.com/p/portaudio-go/portaudio"
+	"math/rand"
+	"time"
+)
+
+func main() {
+	portaudio.Initialize()
+	defer portaudio.Terminate()
+	h, err := portaudio.DefaultHostApi()
+	chk(err)
+	stream, err := portaudio.OpenStream(portaudio.HighLatencyParameters(nil, h.DefaultOutputDevice), func(out []int32) {
+		for i := range out {
+			out[i] = int32(rand.Uint32())
+		}
+	})
+	chk(err)
+	defer stream.Close()
+	chk(stream.Start())
+	time.Sleep(time.Second)
+	chk(stream.Stop())
+}
+
+func chk(err error) {
+	if err != nil {
+		panic(err)
+	}
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/play b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/play
new file mode 100644
index 0000000000000000000000000000000000000000..422b154d5ed102cdd70918c5a2f28fbee40c3ae6
Binary files /dev/null and b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/play differ
diff --git a/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/play.go b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/play.go
new file mode 100644
index 0000000000000000000000000000000000000000..1997e95371ccecda96881e9adb53dc2a8d5eecce
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/play.go
@@ -0,0 +1,126 @@
+package main
+
+import (
+	"code.google.com/p/portaudio-go/portaudio"
+	"encoding/binary"
+	"fmt"
+	"io"
+	"os"
+	"os/signal"
+)
+
+func main() {
+	if len(os.Args) < 2 {
+		fmt.Println("missing required argument:  input file name")
+		return
+	}
+	fmt.Println("Playing.  Press Ctrl-C to stop.")
+
+	sig := make(chan os.Signal, 1)
+	signal.Notify(sig, os.Interrupt, os.Kill)
+
+	fileName := os.Args[1]
+	f, err := os.Open(fileName)
+	chk(err)
+	defer f.Close()
+
+	id, data, err := readChunk(f)
+	chk(err)
+	if id.String() != "FORM" {
+		fmt.Println("bad file format")
+		return
+	}
+	_, err = data.Read(id[:])
+	chk(err)
+	if id.String() != "AIFF" {
+		fmt.Println("bad file format")
+		return
+	}
+	var c commonChunk
+	var audio io.Reader
+	for {
+		id, chunk, err := readChunk(data)
+		if err == io.EOF {
+			break
+		}
+		chk(err)
+		switch id.String() {
+		case "COMM":
+			chk(binary.Read(chunk, binary.BigEndian, &c))
+		case "SSND":
+			chunk.Seek(8, 1) //ignore offset and block
+			audio = chunk
+		default:
+			fmt.Printf("ignoring unknown chunk '%s'\n", id)
+		}
+	}
+
+	//assume 44100 sample rate, mono, 32 bit
+
+	portaudio.Initialize()
+	defer portaudio.Terminate()
+	out := make([]int32, 8192)
+	stream, err := portaudio.OpenDefaultStream(0, 1, 44100, len(out), &out)
+	chk(err)
+	defer stream.Close()
+
+	chk(stream.Start())
+	defer stream.Stop()
+	for remaining := int(c.NumSamples); remaining > 0; remaining -= len(out) {
+		if len(out) > remaining {
+			out = out[:remaining]
+		}
+		err := binary.Read(audio, binary.BigEndian, out)
+		if err == io.EOF {
+			break
+		}
+		chk(err)
+		chk(stream.Write())
+		select {
+		case <-sig:
+			return
+		default:
+		}
+	}
+}
+
+func readChunk(r readerAtSeeker) (id ID, data *io.SectionReader, err error) {
+	_, err = r.Read(id[:])
+	if err != nil {
+		return
+	}
+	var n int32
+	err = binary.Read(r, binary.BigEndian, &n)
+	if err != nil {
+		return
+	}
+	off, _ := r.Seek(0, 1)
+	data = io.NewSectionReader(r, off, int64(n))
+	_, err = r.Seek(int64(n), 1)
+	return
+}
+
+type readerAtSeeker interface {
+	io.Reader
+	io.ReaderAt
+	io.Seeker
+}
+
+type ID [4]byte
+
+func (id ID) String() string {
+	return string(id[:])
+}
+
+type commonChunk struct {
+	NumChans      int16
+	NumSamples    int32
+	BitsPerSample int16
+	SampleRate    [10]byte
+}
+
+func chk(err error) {
+	if err != nil {
+		panic(err)
+	}
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/record.go b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/record.go
new file mode 100644
index 0000000000000000000000000000000000000000..52b850447fd7b5a34c2796cd5d67d96a6cad1e8b
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/record.go
@@ -0,0 +1,93 @@
+package main
+
+import (
+	"code.google.com/p/portaudio-go/portaudio"
+	"encoding/binary"
+	"fmt"
+	"os"
+	"os/signal"
+	"strings"
+)
+
+func main() {
+	if len(os.Args) < 2 {
+		fmt.Println("missing required argument:  output file name")
+		return
+	}
+	fmt.Println("Recording.  Press Ctrl-C to stop.")
+
+	sig := make(chan os.Signal, 1)
+	signal.Notify(sig, os.Interrupt, os.Kill)
+
+	fileName := os.Args[1]
+	if !strings.HasSuffix(fileName, ".aiff") {
+		fileName += ".aiff"
+	}
+	f, err := os.Create(fileName)
+	chk(err)
+
+	// form chunk
+	_, err = f.WriteString("FORM")
+	chk(err)
+	chk(binary.Write(f, binary.BigEndian, int32(0))) //total bytes
+	_, err = f.WriteString("AIFF")
+	chk(err)
+
+	// common chunk
+	_, err = f.WriteString("COMM")
+	chk(err)
+	chk(binary.Write(f, binary.BigEndian, int32(18)))                  //size
+	chk(binary.Write(f, binary.BigEndian, int16(1)))                   //channels
+	chk(binary.Write(f, binary.BigEndian, int32(0)))                   //number of samples
+	chk(binary.Write(f, binary.BigEndian, int16(32)))                  //bits per sample
+	_, err = f.Write([]byte{0x40, 0x0e, 0xac, 0x44, 0, 0, 0, 0, 0, 0}) //80-bit sample rate 44100
+	chk(err)
+
+	// sound chunk
+	_, err = f.WriteString("SSND")
+	chk(err)
+	chk(binary.Write(f, binary.BigEndian, int32(0))) //size
+	chk(binary.Write(f, binary.BigEndian, int32(0))) //offset
+	chk(binary.Write(f, binary.BigEndian, int32(0))) //block
+	nSamples := 0
+	defer func() {
+		// fill in missing sizes
+		totalBytes := 4 + 8 + 18 + 8 + 8 + 4*nSamples
+		_, err = f.Seek(4, 0)
+		chk(err)
+		chk(binary.Write(f, binary.BigEndian, int32(totalBytes)))
+		_, err = f.Seek(22, 0)
+		chk(err)
+		chk(binary.Write(f, binary.BigEndian, int32(nSamples)))
+		_, err = f.Seek(42, 0)
+		chk(err)
+		chk(binary.Write(f, binary.BigEndian, int32(4*nSamples+8)))
+		chk(f.Close())
+	}()
+
+	portaudio.Initialize()
+	defer portaudio.Terminate()
+	in := make([]int32, 64)
+	stream, err := portaudio.OpenDefaultStream(1, 0, 44100, len(in), in)
+	chk(err)
+	defer stream.Close()
+
+	chk(stream.Start())
+	for {
+		chk(stream.Read())
+		chk(binary.Write(f, binary.BigEndian, in))
+		nSamples += len(in)
+		select {
+		case <-sig:
+			return
+		default:
+		}
+	}
+	chk(stream.Stop())
+}
+
+func chk(err error) {
+	if err != nil {
+		panic(err)
+	}
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/stereoSine.go b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/stereoSine.go
new file mode 100644
index 0000000000000000000000000000000000000000..a672c014c53518cb51990c5cc0d9c95fb9c72d7f
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/examples/stereoSine.go
@@ -0,0 +1,48 @@
+package main
+
+import (
+	"code.google.com/p/portaudio-go/portaudio"
+	"math"
+	"time"
+)
+
+const sampleRate = 44100
+
+func main() {
+	portaudio.Initialize()
+	defer portaudio.Terminate()
+	s := newStereoSine(256, 320, sampleRate)
+	defer s.Close()
+	chk(s.Start())
+	time.Sleep(2 * time.Second)
+	chk(s.Stop())
+}
+
+type stereoSine struct {
+	*portaudio.Stream
+	stepL, phaseL float64
+	stepR, phaseR float64
+}
+
+func newStereoSine(freqL, freqR, sampleRate float64) *stereoSine {
+	s := &stereoSine{nil, freqL / sampleRate, 0, freqR / sampleRate, 0}
+	var err error
+	s.Stream, err = portaudio.OpenDefaultStream(0, 2, sampleRate, 0, s.processAudio)
+	chk(err)
+	return s
+}
+
+func (g *stereoSine) processAudio(out [][]float32) {
+	for i := range out[0] {
+		out[0][i] = float32(math.Sin(2 * math.Pi * g.phaseL))
+		_, g.phaseL = math.Modf(g.phaseL + g.stepL)
+		out[1][i] = float32(math.Sin(2 * math.Pi * g.phaseR))
+		_, g.phaseR = math.Modf(g.phaseR + g.stepR)
+	}
+}
+
+func chk(err error) {
+	if err != nil {
+		panic(err)
+	}
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/pa.c b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/pa.c
new file mode 100644
index 0000000000000000000000000000000000000000..d383504191741857b158a9cca6d98cbcb1bf5261
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/pa.c
@@ -0,0 +1,9 @@
+#include "_cgo_export.h"
+
+int cb(const void *inputBuffer, void *outputBuffer, unsigned long frames, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData) {
+	streamCallback((void*)inputBuffer, outputBuffer, frames, (PaStreamCallbackTimeInfo*)timeInfo, statusFlags, userData);
+	return paContinue;
+}
+
+//using a variable ensures that the callback signature is checked
+PaStreamCallback* paStreamCallback = cb;
diff --git a/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/portaudio.go b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/portaudio.go
new file mode 100644
index 0000000000000000000000000000000000000000..a5eb28420667794875c5bf355f46a30774525aa7
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/portaudio-go/portaudio/portaudio.go
@@ -0,0 +1,859 @@
+/*
+For the most part, these bindings parallel the underlying PortAudio API; please refer to http://www.portaudio.com/docs.html for details.  Differences introduced by the bindings are documented here:
+
+Instead of passing a flag to OpenStream, audio sample formats are inferred from the signature of the stream callback or, for a blocking stream, from the types of the buffers.  See the StreamCallback and Buffer types for details.
+
+Blocking I/O:  Read and Write do not accept buffer arguments; instead they use the buffers (or pointers to buffers) provided to OpenStream.  The number of samples to read or write is determined by the size of the buffers.
+
+The StreamParameters struct combines parameters for both the input and the output device as well as the sample rate, buffer size, and flags.
+*/
+package portaudio
+
+/*
+#cgo pkg-config: portaudio-2.0
+#include <portaudio.h>
+extern PaStreamCallback* paStreamCallback;
+*/
+import "C"
+
+import (
+	"fmt"
+	"reflect"
+	"time"
+	"unsafe"
+)
+
+func Version() int {
+	return int(C.Pa_GetVersion())
+}
+
+func VersionText() string {
+	return C.GoString(C.Pa_GetVersionText())
+}
+
+type Error C.PaError
+
+func (err Error) Error() string {
+	return C.GoString(C.Pa_GetErrorText(C.PaError(err)))
+}
+
+const (
+	NotInitialized                        Error = C.paNotInitialized
+	InvalidChannelCount                   Error = C.paInvalidChannelCount
+	InvalidSampleRate                     Error = C.paInvalidSampleRate
+	InvalidDevice                         Error = C.paInvalidDevice
+	InvalidFlag                           Error = C.paInvalidFlag
+	SampleFormatNotSupported              Error = C.paSampleFormatNotSupported
+	BadIODeviceCombination                Error = C.paBadIODeviceCombination
+	InsufficientMemory                    Error = C.paInsufficientMemory
+	BufferTooBig                          Error = C.paBufferTooBig
+	BufferTooSmall                        Error = C.paBufferTooSmall
+	NullCallback                          Error = C.paNullCallback
+	BadStreamPtr                          Error = C.paBadStreamPtr
+	TimedOut                              Error = C.paTimedOut
+	InternalError                         Error = C.paInternalError
+	DeviceUnavailable                     Error = C.paDeviceUnavailable
+	IncompatibleHostApiSpecificStreamInfo Error = C.paIncompatibleHostApiSpecificStreamInfo
+	StreamIsStopped                       Error = C.paStreamIsStopped
+	StreamIsNotStopped                    Error = C.paStreamIsNotStopped
+	InputOverflowed                       Error = C.paInputOverflowed
+	OutputUnderflowed                     Error = C.paOutputUnderflowed
+	HostApiNotFound                       Error = C.paHostApiNotFound
+	InvalidHostApi                        Error = C.paInvalidHostApi
+	CanNotReadFromACallbackStream         Error = C.paCanNotReadFromACallbackStream
+	CanNotWriteToACallbackStream          Error = C.paCanNotWriteToACallbackStream
+	CanNotReadFromAnOutputOnlyStream      Error = C.paCanNotReadFromAnOutputOnlyStream
+	CanNotWriteToAnInputOnlyStream        Error = C.paCanNotWriteToAnInputOnlyStream
+	IncompatibleStreamHostApi             Error = C.paIncompatibleStreamHostApi
+	BadBufferPtr                          Error = C.paBadBufferPtr
+)
+
+type UnanticipatedHostError struct {
+	HostApiType HostApiType
+	Code        int
+	Text        string
+}
+
+func (err UnanticipatedHostError) Error() string {
+	return err.Text
+}
+
+func newError(err C.PaError) error {
+	switch err {
+	case C.paUnanticipatedHostError:
+		hostErr := C.Pa_GetLastHostErrorInfo()
+		return UnanticipatedHostError{
+			HostApiType(hostErr.hostApiType),
+			int(hostErr.errorCode),
+			C.GoString(hostErr.errorText),
+		}
+	case C.paNoError:
+		return nil
+	}
+	return Error(err)
+}
+
+var initialized = 0
+
+func Initialize() error {
+	paErr := C.Pa_Initialize()
+	if paErr != C.paNoError {
+		return newError(paErr)
+	}
+	initialized++
+	return nil
+}
+
+func Terminate() error {
+	paErr := C.Pa_Terminate()
+	if paErr != C.paNoError {
+		return newError(paErr)
+	}
+	initialized--
+	if initialized <= 0 {
+		initialized = 0
+		cached = false
+	}
+	return nil
+}
+
+type HostApiType int
+
+func (t HostApiType) String() string {
+	return hostApiStrings[t]
+}
+
+var hostApiStrings = [...]string{
+	InDevelopment:   "InDevelopment",
+	DirectSound:     "DirectSound",
+	MME:             "MME",
+	ASIO:            "ASIO",
+	SoundManager:    "SoundManager",
+	CoreAudio:       "CoreAudio",
+	OSS:             "OSS",
+	ALSA:            "ALSA",
+	AL:              "AL",
+	BeOS:            "BeOS",
+	WDMkS:           "WDMKS",
+	JACK:            "JACK",
+	WASAPI:          "WASAPI",
+	AudioScienceHPI: "AudioScienceHPI",
+}
+
+const (
+	InDevelopment   HostApiType = C.paInDevelopment
+	DirectSound     HostApiType = C.paDirectSound
+	MME             HostApiType = C.paMME
+	ASIO            HostApiType = C.paASIO
+	SoundManager    HostApiType = C.paSoundManager
+	CoreAudio       HostApiType = C.paCoreAudio
+	OSS             HostApiType = C.paOSS
+	ALSA            HostApiType = C.paALSA
+	AL              HostApiType = C.paAL
+	BeOS            HostApiType = C.paBeOS
+	WDMkS           HostApiType = C.paWDMKS
+	JACK            HostApiType = C.paJACK
+	WASAPI          HostApiType = C.paWASAPI
+	AudioScienceHPI HostApiType = C.paAudioScienceHPI
+)
+
+type HostApiInfo struct {
+	Type                HostApiType
+	Name                string
+	DefaultInputDevice  *DeviceInfo
+	DefaultOutputDevice *DeviceInfo
+	Devices             []*DeviceInfo
+}
+
+type DeviceInfo struct {
+	index                    C.PaDeviceIndex
+	Name                     string
+	MaxInputChannels         int
+	MaxOutputChannels        int
+	DefaultLowInputLatency   time.Duration
+	DefaultLowOutputLatency  time.Duration
+	DefaultHighInputLatency  time.Duration
+	DefaultHighOutputLatency time.Duration
+	DefaultSampleRate        float64
+	HostApi                  *HostApiInfo
+}
+
+func HostApis() ([]*HostApiInfo, error) {
+	hosts, _, err := hostsAndDevices()
+	if err != nil {
+		return nil, err
+	}
+	return hosts, nil
+}
+
+func HostApi(apiType HostApiType) (*HostApiInfo, error) {
+	hosts, err := HostApis()
+	if err != nil {
+		return nil, err
+	}
+	i := C.Pa_HostApiTypeIdToHostApiIndex(C.PaHostApiTypeId(apiType))
+	if i < 0 {
+		return nil, newError(C.PaError(i))
+	}
+	return hosts[i], nil
+}
+
+func DefaultHostApi() (*HostApiInfo, error) {
+	hosts, err := HostApis()
+	if err != nil {
+		return nil, err
+	}
+	i := C.Pa_GetDefaultHostApi()
+	if i < 0 {
+		return nil, newError(C.PaError(i))
+	}
+	return hosts[i], nil
+}
+
+func Devices() ([]*DeviceInfo, error) {
+	_, devs, err := hostsAndDevices()
+	if err != nil {
+		return nil, err
+	}
+	return devs, nil
+}
+
+func DefaultInputDevice() (*DeviceInfo, error) {
+	devs, err := Devices()
+	if err != nil {
+		return nil, err
+	}
+	i := C.Pa_GetDefaultInputDevice()
+	if i < 0 {
+		return nil, newError(C.PaError(i))
+	}
+	return devs[i], nil
+}
+
+func DefaultOutputDevice() (*DeviceInfo, error) {
+	devs, err := Devices()
+	if err != nil {
+		return nil, err
+	}
+	i := C.Pa_GetDefaultOutputDevice()
+	if i < 0 {
+		return nil, newError(C.PaError(i))
+	}
+	return devs[i], nil
+}
+
+/* cache the HostApi/Device list to simplify the enumeration code.
+Note that portaudio itself caches the lists, so these won't go stale.
+
+However, there is talk of extending the portaudio API to allow clients
+to rescan available devices without calling Pa_Terminate() followed by
+Pa_Initialize() - our caching strategy will have to change if this
+goes ahead. See https://www.assembla.com/spaces/portaudio/tickets/11
+*/
+var (
+	cached   bool
+	hostApis []*HostApiInfo
+	devices  []*DeviceInfo
+)
+
+func hostsAndDevices() ([]*HostApiInfo, []*DeviceInfo, error) {
+	if !cached {
+		nhosts := C.Pa_GetHostApiCount()
+		ndevs := C.Pa_GetDeviceCount()
+		if nhosts < 0 {
+			return nil, nil, newError(C.PaError(nhosts))
+		}
+		if ndevs < 0 {
+			return nil, nil, newError(C.PaError(ndevs))
+		}
+		devices = make([]*DeviceInfo, ndevs)
+		hosti := make([]C.PaHostApiIndex, ndevs)
+		for i := range devices {
+			i := C.PaDeviceIndex(i)
+			paDev := C.Pa_GetDeviceInfo(i)
+			devices[i] = &DeviceInfo{
+				index:                    i,
+				Name:                     C.GoString(paDev.name),
+				MaxInputChannels:         int(paDev.maxInputChannels),
+				MaxOutputChannels:        int(paDev.maxOutputChannels),
+				DefaultLowInputLatency:   duration(paDev.defaultLowInputLatency),
+				DefaultLowOutputLatency:  duration(paDev.defaultLowOutputLatency),
+				DefaultHighInputLatency:  duration(paDev.defaultHighInputLatency),
+				DefaultHighOutputLatency: duration(paDev.defaultHighOutputLatency),
+				DefaultSampleRate:        float64(paDev.defaultSampleRate),
+			}
+			hosti[i] = paDev.hostApi
+		}
+		hostApis = make([]*HostApiInfo, nhosts)
+		for i := range hostApis {
+			i := C.PaHostApiIndex(i)
+			paHost := C.Pa_GetHostApiInfo(i)
+			devs := make([]*DeviceInfo, paHost.deviceCount)
+			for j := range devs {
+				devs[j] = devices[C.Pa_HostApiDeviceIndexToDeviceIndex(i, C.int(j))]
+			}
+			hostApis[i] = &HostApiInfo{
+				Type:                HostApiType(paHost._type),
+				Name:                C.GoString(paHost.name),
+				DefaultInputDevice:  lookupDevice(devices, paHost.defaultInputDevice),
+				DefaultOutputDevice: lookupDevice(devices, paHost.defaultOutputDevice),
+				Devices:             devs,
+			}
+		}
+		for i := range devices {
+			devices[i].HostApi = hostApis[hosti[i]]
+		}
+		cached = true
+	}
+	return hostApis, devices, nil
+}
+
+func duration(paTime C.PaTime) time.Duration {
+	return time.Duration(paTime * C.PaTime(time.Second))
+}
+
+func lookupDevice(d []*DeviceInfo, i C.PaDeviceIndex) *DeviceInfo {
+	if i >= 0 {
+		return d[i]
+	}
+	return nil
+}
+
+/*
+StreamParameters includes all parameters required to open a stream except for the callback or buffers.
+*/
+type StreamParameters struct {
+	Input, Output   StreamDeviceParameters
+	SampleRate      float64
+	FramesPerBuffer int
+	Flags           StreamFlags
+}
+
+/*
+StreamDeviceParameters specifies parameters for one device (either input or output) in a stream.  A nil Device indicates that no device is to be used -- i.e., for an input- or output-only stream.
+*/
+type StreamDeviceParameters struct {
+	Device   *DeviceInfo
+	Channels int
+	Latency  time.Duration
+}
+
+const FramesPerBufferUnspecified = C.paFramesPerBufferUnspecified
+
+type StreamFlags C.PaStreamFlags
+
+const (
+	NoFlag                                StreamFlags = C.paNoFlag
+	ClipOff                               StreamFlags = C.paClipOff
+	DitherOff                             StreamFlags = C.paDitherOff
+	NeverDropInput                        StreamFlags = C.paNeverDropInput
+	PrimeOutputBuffersUsingStreamCallback StreamFlags = C.paPrimeOutputBuffersUsingStreamCallback
+	PlatformSpecificFlags                 StreamFlags = C.paPlatformSpecificFlags
+)
+
+/*
+High latency parameters are mono in, stereo out (if supported), high latency, the smaller of the default sample rates of the two devices, andFramesPerBufferUnspecified.  One of the devices may be nil.
+*/
+func HighLatencyParameters(in, out *DeviceInfo) (p StreamParameters) {
+	sampleRate := 0.0
+	if in != nil {
+		p := &p.Input
+		p.Device = in
+		p.Channels = 1
+		if in.MaxInputChannels < 1 {
+			p.Channels = in.MaxInputChannels
+		}
+		p.Latency = in.DefaultHighInputLatency
+		sampleRate = in.DefaultSampleRate
+	}
+	if out != nil {
+		p := &p.Output
+		p.Device = out
+		p.Channels = 2
+		if out.MaxOutputChannels < 2 {
+			p.Channels = out.MaxOutputChannels
+		}
+		p.Latency = out.DefaultHighOutputLatency
+		if r := out.DefaultSampleRate; r < sampleRate || sampleRate == 0 {
+			sampleRate = r
+		}
+	}
+	p.SampleRate = sampleRate
+	p.FramesPerBuffer = FramesPerBufferUnspecified
+	return p
+}
+
+/*
+Low latency parameters are mono in, stereo out (if supported), low latency, the larger of the default sample rates of the two devices, and FramesPerBufferUnspecified.  One of the devices may be nil.
+*/
+func LowLatencyParameters(in, out *DeviceInfo) (p StreamParameters) {
+	sampleRate := 0.0
+	if in != nil {
+		p := &p.Input
+		p.Device = in
+		p.Channels = 1
+		if in.MaxInputChannels < 1 {
+			p.Channels = in.MaxInputChannels
+		}
+		p.Latency = in.DefaultLowInputLatency
+		sampleRate = in.DefaultSampleRate
+	}
+	if out != nil {
+		p := &p.Output
+		p.Device = out
+		p.Channels = 2
+		if out.MaxOutputChannels < 2 {
+			p.Channels = out.MaxOutputChannels
+		}
+		p.Latency = out.DefaultLowOutputLatency
+		if r := out.DefaultSampleRate; r > sampleRate {
+			sampleRate = r
+		}
+	}
+	p.SampleRate = sampleRate
+	p.FramesPerBuffer = FramesPerBufferUnspecified
+	return p
+}
+
+/*
+Returns nil if the format is supported, otherwise an error.
+The args parameter has the same meaning as in OpenStream.
+*/
+func IsFormatSupported(p StreamParameters, args ...interface{}) error {
+	s := &Stream{}
+	err := s.init(p, args...)
+	if err != nil {
+		return err
+	}
+	return newError(C.Pa_IsFormatSupported(s.inParams, s.outParams, C.double(p.SampleRate)))
+}
+
+type Int24 [3]byte
+
+type Stream struct {
+	paStream            unsafe.Pointer
+	inParams, outParams *C.PaStreamParameters
+	in, out             *reflect.SliceHeader
+	timeInfo            StreamCallbackTimeInfo
+	flags               StreamCallbackFlags
+	args                []reflect.Value
+	callback            reflect.Value
+	closed              bool
+}
+
+/*
+This type exists for documentation purposes only.
+
+A StreamCallback is a func whose signature resembles
+
+	func(in Buffer, out Buffer, timeInfo StreamCallbackTimeInfo, flags StreamCallbackFlags)
+
+where the final one or two parameters may be omitted.  For an input- or output-only stream, one of the Buffer parameters may also be omitted.  The two Buffer types may be different.
+*/
+type StreamCallback interface{}
+
+/*
+This type exists for documentation purposes only.
+
+A Buffer is of the form [][]SampleType or []SampleType
+where SampleType is float32, int32, Int24, int16, int8, or uint8.
+
+In the first form, channels are non-interleaved:
+len(buf) == numChannels and len(buf[i]) == framesPerBuffer
+
+In the second form, channels are interleaved:
+len(buf) == numChannels * framesPerBuffer
+*/
+type Buffer interface{}
+
+type StreamCallbackTimeInfo struct {
+	InputBufferAdcTime, CurrentTime, OutputBufferDacTime time.Duration
+}
+
+type StreamCallbackFlags C.PaStreamCallbackFlags
+
+const (
+	InputUnderflow  StreamCallbackFlags = C.paInputUnderflow
+	InputOverflow   StreamCallbackFlags = C.paInputOverflow
+	OutputUnderflow StreamCallbackFlags = C.paOutputUnderflow
+	OutputOverflow  StreamCallbackFlags = C.paOutputOverflow
+	PrimingOutput   StreamCallbackFlags = C.paPrimingOutput
+)
+
+/*
+For an input- or output-only stream, p.Output.Device or p.Input.Device must be nil, respectively.
+
+The args may consist of either a single StreamCallback or, for a blocking stream, two Buffers or pointers to Buffers.  For an input- or output-only stream, one of the Buffer args may be omitted.
+*/
+func OpenStream(p StreamParameters, args ...interface{}) (*Stream, error) {
+	if initialized <= 0 {
+		return nil, NotInitialized
+	}
+
+	s := &Stream{}
+	err := s.init(p, args...)
+	if err != nil {
+		return nil, err
+	}
+	cb := C.paStreamCallback
+	if !s.callback.IsValid() {
+		cb = nil
+	}
+	paErr := C.Pa_OpenStream(&s.paStream, s.inParams, s.outParams, C.double(p.SampleRate), C.ulong(p.FramesPerBuffer), C.PaStreamFlags(p.Flags), cb, unsafe.Pointer(s))
+	if paErr != C.paNoError {
+		return nil, newError(paErr)
+	}
+	return s, nil
+}
+
+/*
+The args parameter has the same meaning as in OpenStream.
+*/
+func OpenDefaultStream(numInputChannels, numOutputChannels int, sampleRate float64, framesPerBuffer int, args ...interface{}) (*Stream, error) {
+	if initialized <= 0 {
+		return nil, NotInitialized
+	}
+
+	var inDev, outDev *DeviceInfo
+	var err error
+	if numInputChannels > 0 {
+		inDev, err = DefaultInputDevice()
+		if err != nil {
+			return nil, err
+		}
+	}
+	if numOutputChannels > 0 {
+		outDev, err = DefaultOutputDevice()
+		if err != nil {
+			return nil, err
+		}
+	}
+	p := HighLatencyParameters(inDev, outDev)
+	p.Input.Channels = numInputChannels
+	p.Output.Channels = numOutputChannels
+	p.SampleRate = sampleRate
+	p.FramesPerBuffer = framesPerBuffer
+	return OpenStream(p, args...)
+}
+
+func (s *Stream) init(p StreamParameters, args ...interface{}) error {
+	switch len(args) {
+	case 0:
+		return fmt.Errorf("too few args")
+	case 1, 2:
+		if fun := reflect.ValueOf(args[0]); fun.Kind() == reflect.Func {
+			return s.initCallback(p, fun)
+		}
+		return s.initBuffers(p, args...)
+	default:
+		return fmt.Errorf("too many args")
+	}
+}
+
+func (s *Stream) initCallback(p StreamParameters, fun reflect.Value) error {
+	t := fun.Type()
+	if t.IsVariadic() {
+		return fmt.Errorf("StreamCallback must not be variadic")
+	}
+	nArgs := t.NumIn()
+	if nArgs == 0 {
+		return fmt.Errorf("too few parameters in StreamCallback")
+	}
+	args := make([]reflect.Value, nArgs)
+	i := 0
+	bothBufs := nArgs > 1 && t.In(1).Kind() == reflect.Slice
+	bufArg := func(p StreamDeviceParameters) (*C.PaStreamParameters, *reflect.SliceHeader, error) {
+		if p.Device != nil || bothBufs {
+			if i >= nArgs {
+				return nil, nil, fmt.Errorf("too few Buffer parameters in StreamCallback")
+			}
+			t := t.In(i)
+			sampleFmt := sampleFormat(t)
+			if sampleFmt == 0 {
+				return nil, nil, fmt.Errorf("expected Buffer type in StreamCallback, got %v", t)
+			}
+			buf := reflect.New(t)
+			args[i] = buf.Elem()
+			i++
+			if p.Device != nil {
+				pap := paStreamParameters(p, sampleFmt)
+				if pap.sampleFormat&C.paNonInterleaved != 0 {
+					n := int(pap.channelCount)
+					buf.Elem().Set(reflect.MakeSlice(t, n, n))
+				}
+				return pap, (*reflect.SliceHeader)(unsafe.Pointer(buf.Pointer())), nil
+			}
+		}
+		return nil, nil, nil
+	}
+	var err error
+	s.inParams, s.in, err = bufArg(p.Input)
+	if err != nil {
+		return err
+	}
+	s.outParams, s.out, err = bufArg(p.Output)
+	if err != nil {
+		return err
+	}
+	if i < nArgs {
+		t := t.In(i)
+		if t != reflect.TypeOf(StreamCallbackTimeInfo{}) {
+			return fmt.Errorf("invalid StreamCallback")
+		}
+		args[i] = reflect.ValueOf(&s.timeInfo).Elem()
+		i++
+	}
+	if i < nArgs {
+		t := t.In(i)
+		if t != reflect.TypeOf(StreamCallbackFlags(0)) {
+			return fmt.Errorf("invalid StreamCallback")
+		}
+		args[i] = reflect.ValueOf(&s.flags).Elem()
+		i++
+	}
+	if i < nArgs {
+		return fmt.Errorf("too many parameters in StreamCallback")
+	}
+	if t.NumOut() > 0 {
+		return fmt.Errorf("too many results in StreamCallback")
+	}
+	s.callback = fun
+	s.args = args
+	return nil
+}
+
+func (s *Stream) initBuffers(p StreamParameters, args ...interface{}) error {
+	bothBufs := len(args) == 2
+	bufArg := func(p StreamDeviceParameters) (*C.PaStreamParameters, *reflect.SliceHeader, error) {
+		if p.Device != nil || bothBufs {
+			if len(args) == 0 {
+				return nil, nil, fmt.Errorf("too few Buffer args")
+			}
+			arg := reflect.ValueOf(args[0])
+			args = args[1:]
+			t := arg.Type()
+			if t.Kind() == reflect.Ptr {
+				t = t.Elem()
+			} else {
+				argPtr := reflect.New(t)
+				argPtr.Elem().Set(arg)
+				arg = argPtr
+			}
+			sampleFmt := sampleFormat(t)
+			if sampleFmt == 0 {
+				return nil, nil, fmt.Errorf("invalid Buffer type %v", t)
+			}
+			if arg.IsNil() {
+				return nil, nil, fmt.Errorf("nil Buffer pointer")
+			}
+			if p.Device != nil {
+				return paStreamParameters(p, sampleFmt), (*reflect.SliceHeader)(unsafe.Pointer(arg.Pointer())), nil
+			}
+		}
+		return nil, nil, nil
+	}
+	var err error
+	s.inParams, s.in, err = bufArg(p.Input)
+	if err != nil {
+		return err
+	}
+	s.outParams, s.out, err = bufArg(p.Output)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func sampleFormat(b reflect.Type) (f C.PaSampleFormat) {
+	if b.Kind() != reflect.Slice {
+		return 0
+	}
+	b = b.Elem()
+	if b.Kind() == reflect.Slice {
+		f = C.paNonInterleaved
+		b = b.Elem()
+	}
+	switch b.Kind() {
+	case reflect.Float32:
+		f |= C.paFloat32
+	case reflect.Int32:
+		f |= C.paInt32
+	default:
+		if b == reflect.TypeOf(Int24{}) {
+			f |= C.paInt24
+		} else {
+			return 0
+		}
+	case reflect.Int16:
+		f |= C.paInt16
+	case reflect.Int8:
+		f |= C.paInt8
+	case reflect.Uint8:
+		f |= C.paUInt8
+	}
+	return f
+}
+
+func paStreamParameters(p StreamDeviceParameters, fmt C.PaSampleFormat) *C.PaStreamParameters {
+	return &C.PaStreamParameters{
+		device:           p.Device.index,
+		channelCount:     C.int(p.Channels),
+		sampleFormat:     fmt,
+		suggestedLatency: C.PaTime(p.Latency.Seconds()),
+	}
+}
+
+func (s *Stream) Close() error {
+	if !s.closed {
+		s.closed = true
+		return newError(C.Pa_CloseStream(s.paStream))
+	}
+	return nil
+}
+
+func (s *Stream) Start() error {
+	return newError(C.Pa_StartStream(s.paStream))
+}
+
+//export streamCallback
+func streamCallback(inputBuffer, outputBuffer unsafe.Pointer, frames C.ulong, timeInfo *C.PaStreamCallbackTimeInfo, statusFlags C.PaStreamCallbackFlags, userData unsafe.Pointer) {
+	s := (*Stream)(userData)
+	s.timeInfo = StreamCallbackTimeInfo{duration(timeInfo.inputBufferAdcTime), duration(timeInfo.currentTime), duration(timeInfo.outputBufferDacTime)}
+	s.flags = StreamCallbackFlags(statusFlags)
+	updateBuffer(s.in, uintptr(inputBuffer), s.inParams, int(frames))
+	updateBuffer(s.out, uintptr(outputBuffer), s.outParams, int(frames))
+	s.callback.Call(s.args)
+}
+
+func updateBuffer(buf *reflect.SliceHeader, p uintptr, params *C.PaStreamParameters, frames int) {
+	if p == 0 {
+		return
+	}
+	if params.sampleFormat&C.paNonInterleaved == 0 {
+		setSlice(buf, p, frames*int(params.channelCount))
+	} else {
+		setChannels(buf, p, frames)
+	}
+}
+
+func setChannels(s *reflect.SliceHeader, p uintptr, frames int) {
+	sp := s.Data
+	for i := 0; i < s.Len; i++ {
+		setSlice((*reflect.SliceHeader)(unsafe.Pointer(sp)), *(*uintptr)(unsafe.Pointer(p)), frames)
+		sp += unsafe.Sizeof(reflect.SliceHeader{})
+		p += unsafe.Sizeof(uintptr(0))
+	}
+}
+
+func setSlice(s *reflect.SliceHeader, data uintptr, n int) {
+	s.Data = data
+	s.Len = n
+	s.Cap = n
+}
+
+func (s *Stream) Stop() error {
+	return newError(C.Pa_StopStream(s.paStream))
+}
+
+func (s *Stream) Abort() error {
+	return newError(C.Pa_AbortStream(s.paStream))
+}
+
+func (s *Stream) Info() *StreamInfo {
+	i := C.Pa_GetStreamInfo(s.paStream)
+	if i == nil {
+		return nil
+	}
+	return &StreamInfo{duration(i.inputLatency), duration(i.outputLatency), float64(i.sampleRate)}
+}
+
+type StreamInfo struct {
+	InputLatency, OutputLatency time.Duration
+	SampleRate                  float64
+}
+
+func (s *Stream) Time() time.Duration {
+	return duration(C.Pa_GetStreamTime(s.paStream))
+}
+
+func (s *Stream) CpuLoad() float64 {
+	return float64(C.Pa_GetStreamCpuLoad(s.paStream))
+}
+
+func (s *Stream) AvailableToRead() (int, error) {
+	n := C.Pa_GetStreamReadAvailable(s.paStream)
+	if n < 0 {
+		return 0, newError(C.PaError(n))
+	}
+	return int(n), nil
+}
+
+func (s *Stream) AvailableToWrite() (int, error) {
+	n := C.Pa_GetStreamWriteAvailable(s.paStream)
+	if n < 0 {
+		return 0, newError(C.PaError(n))
+	}
+	return int(n), nil
+}
+
+/*
+Read uses the buffer provided to OpenStream.  The number of samples to read is determined by the size of the buffer.
+*/
+func (s *Stream) Read() error {
+	if s.callback.IsValid() {
+		return CanNotReadFromACallbackStream
+	}
+	if s.in == nil {
+		return CanNotReadFromAnOutputOnlyStream
+	}
+	buf, frames, err := getBuffer(s.in, s.inParams)
+	if err != nil {
+		return err
+	}
+	return newError(C.Pa_ReadStream(s.paStream, buf, C.ulong(frames)))
+}
+
+/*
+Write uses the buffer provided to OpenStream.  The number of samples to write is determined by the size of the buffer.
+*/
+func (s *Stream) Write() error {
+	if s.callback.IsValid() {
+		return CanNotWriteToACallbackStream
+	}
+	if s.out == nil {
+		return CanNotWriteToAnInputOnlyStream
+	}
+	buf, frames, err := getBuffer(s.out, s.outParams)
+	if err != nil {
+		return err
+	}
+	return newError(C.Pa_WriteStream(s.paStream, buf, C.ulong(frames)))
+}
+
+func getBuffer(s *reflect.SliceHeader, p *C.PaStreamParameters) (unsafe.Pointer, int, error) {
+	if p.sampleFormat&C.paNonInterleaved == 0 {
+		n := int(p.channelCount)
+		if s.Len%n != 0 {
+			return nil, 0, fmt.Errorf("length of interleaved buffer not divisible by number of channels")
+		}
+		return unsafe.Pointer(s.Data), s.Len / n, nil
+	} else {
+		if s.Len != int(p.channelCount) {
+			return nil, 0, fmt.Errorf("buffer has wrong number of channels")
+		}
+		buf := make([]uintptr, s.Len)
+		frames := -1
+		sp := s.Data
+		for i := range buf {
+			ch := (*reflect.SliceHeader)(unsafe.Pointer(sp))
+			if frames == -1 {
+				frames = ch.Len
+			} else if ch.Len != frames {
+				return nil, 0, fmt.Errorf("channels have different lengths")
+			}
+			buf[i] = ch.Data
+			sp += unsafe.Sizeof(reflect.SliceHeader{})
+		}
+		return unsafe.Pointer(&buf[0]), frames, nil
+	}
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/xsrftoken/COPYING b/Godeps/_workspace/src/code.google.com/p/xsrftoken/COPYING
new file mode 100644
index 0000000000000000000000000000000000000000..d645695673349e3947e8e5ae42332d0ac3164cd7
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/xsrftoken/COPYING
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor 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, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/Godeps/_workspace/src/code.google.com/p/xsrftoken/xsrf.go b/Godeps/_workspace/src/code.google.com/p/xsrftoken/xsrf.go
new file mode 100644
index 0000000000000000000000000000000000000000..c59828af2c135f6012bac9bef0675bc9941fbd8d
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/xsrftoken/xsrf.go
@@ -0,0 +1,94 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package xsrftoken provides methods for generating and validating secure XSRF tokens.
+package xsrftoken
+
+import (
+	"bytes"
+	"crypto/hmac"
+	"crypto/sha1"
+	"encoding/base64"
+	"fmt"
+	"strconv"
+	"strings"
+	"time"
+)
+
+// The duration that XSRF tokens are valid.
+// It is exported so clients may set cookie timeouts that match generated tokens.
+const Timeout = 24 * time.Hour
+
+// clean sanitizes a string for inclusion in a token by replacing all ":"s.
+func clean(s string) string {
+	return strings.Replace(s, ":", "_", -1)
+}
+
+// Generate returns a URL-safe secure XSRF token that expires in 24 hours.
+//
+// key is a secret key for your application.
+// userID is a unique identifier for the user.
+// actionID is the action the user is taking (e.g. POSTing to a particular path).
+func Generate(key, userID, actionID string) string {
+	return generateAtTime(key, userID, actionID, time.Now())
+}
+
+// generateAtTime is like Generate, but returns a token that expires 24 hours from now.
+func generateAtTime(key, userID, actionID string, now time.Time) string {
+	h := hmac.New(sha1.New, []byte(key))
+	fmt.Fprintf(h, "%s:%s:%d", clean(userID), clean(actionID), now.UnixNano())
+	tok := fmt.Sprintf("%s:%d", h.Sum(nil), now.UnixNano())
+	return base64.URLEncoding.EncodeToString([]byte(tok))
+}
+
+// Valid returns true if token is a valid, unexpired token returned by Generate.
+func Valid(token, key, userID, actionID string) bool {
+	return validAtTime(token, key, userID, actionID, time.Now())
+}
+
+// validAtTime is like Valid, but it uses now to check if the token is expired.
+func validAtTime(token, key, userID, actionID string, now time.Time) bool {
+	// Decode the token.
+	data, err := base64.URLEncoding.DecodeString(token)
+	if err != nil {
+		return false
+	}
+
+	// Extract the issue time of the token.
+	sep := bytes.LastIndex(data, []byte{':'})
+	if sep < 0 {
+		return false
+	}
+	nanos, err := strconv.ParseInt(string(data[sep+1:]), 10, 64)
+	if err != nil {
+		return false
+	}
+	issueTime := time.Unix(0, nanos)
+
+	// Check that the token is not expired.
+	if now.Sub(issueTime) >= Timeout {
+		return false
+	}
+
+	// Check that the token is not from the future.
+	// Allow 1 minute grace period in case the token is being verified on a
+	// machine whose clock is behind the machine that issued the token.
+	if issueTime.After(now.Add(1 * time.Minute)) {
+		return false
+	}
+
+	// Check that the token matches the expected value.
+	expected := generateAtTime(key, userID, actionID, issueTime)
+	return token == expected
+}
diff --git a/Godeps/_workspace/src/code.google.com/p/xsrftoken/xsrf_test.go b/Godeps/_workspace/src/code.google.com/p/xsrftoken/xsrf_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..40e1bd9895f6f827bc6a4fe78fb1542fc49ad38a
--- /dev/null
+++ b/Godeps/_workspace/src/code.google.com/p/xsrftoken/xsrf_test.go
@@ -0,0 +1,92 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+// 
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// 
+//     http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package xsrftoken
+
+import (
+	"encoding/base64"
+	"testing"
+	"time"
+)
+
+const (
+	key      = "quay"
+	userID   = "12345678"
+	actionID = "POST /form"
+)
+
+var (
+	now              = time.Now()
+	oneMinuteFromNow = now.Add(1 * time.Minute)
+)
+
+func TestValidToken(t *testing.T) {
+	tok := generateAtTime(key, userID, actionID, now)
+	if !validAtTime(tok, key, userID, actionID, oneMinuteFromNow) {
+		t.Error("One second later: Expected token to be valid")
+	}
+	if !validAtTime(tok, key, userID, actionID, now.Add(Timeout-1*time.Nanosecond)) {
+		t.Error("Just before timeout: Expected token to be valid")
+	}
+	if !validAtTime(tok, key, userID, actionID, now.Add(-1*time.Minute)) {
+		t.Error("One minute in the past: Expected token to be valid")
+	}
+}
+
+// TestSeparatorReplacement tests that separators are being correctly substituted
+func TestSeparatorReplacement(t *testing.T) {
+	tok := generateAtTime("foo:bar", "baz", "wah", now)
+	tok2 := generateAtTime("foo", "bar:baz", "wah", now)
+	if tok == tok2 {
+		t.Errorf("Expected generated tokens to be different")
+	}
+}
+
+func TestInvalidToken(t *testing.T) {
+	invalidTokenTests := []struct {
+		name, key, userID, actionID string
+		t                           time.Time
+	}{
+		{"Bad key", "foobar", userID, actionID, oneMinuteFromNow},
+		{"Bad userID", key, "foobar", actionID, oneMinuteFromNow},
+		{"Bad actionID", key, userID, "foobar", oneMinuteFromNow},
+		{"Expired", key, userID, actionID, now.Add(Timeout)},
+		{"More than 1 minute from the future", key, userID, actionID, now.Add(-1*time.Nanosecond - 1*time.Minute)},
+	}
+
+	tok := generateAtTime(key, userID, actionID, now)
+	for _, itt := range invalidTokenTests {
+		if validAtTime(tok, itt.key, itt.userID, itt.actionID, itt.t) {
+			t.Errorf("%v: Expected token to be invalid", itt.name)
+		}
+	}
+}
+
+// TestValidateBadData primarily tests that no unexpected panics are triggered
+// during parsing
+func TestValidateBadData(t *testing.T) {
+	badDataTests := []struct {
+		name, tok string
+	}{
+		{"Invalid Base64", "ASDab24(@)$*=="},
+		{"No delimiter", base64.URLEncoding.EncodeToString([]byte("foobar12345678"))},
+		{"Invalid time", base64.URLEncoding.EncodeToString([]byte("foobar:foobar"))},
+	}
+
+	for _, bdt := range badDataTests {
+		if validAtTime(bdt.tok, key, userID, actionID, oneMinuteFromNow) {
+			t.Errorf("%v: Expected token to be invalid", bdt.name)
+		}
+	}
+}
diff --git a/Godeps/_workspace/src/git.autistici.org/ale/gompd/COPYING b/Godeps/_workspace/src/git.autistici.org/ale/gompd/COPYING
new file mode 100644
index 0000000000000000000000000000000000000000..e963df8294069543e782fd72aa71832dca1571ca
--- /dev/null
+++ b/Godeps/_workspace/src/git.autistici.org/ale/gompd/COPYING
@@ -0,0 +1,622 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
diff --git a/Godeps/_workspace/src/git.autistici.org/ale/gompd/README.md b/Godeps/_workspace/src/git.autistici.org/ale/gompd/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..76b910d0b164ac00b607f3eeeda75be01dd9bf15
--- /dev/null
+++ b/Godeps/_workspace/src/git.autistici.org/ale/gompd/README.md
@@ -0,0 +1,4 @@
+
+A Go package to implement an MPD server (this is not a working server by
+itself).
+
diff --git a/Godeps/_workspace/src/git.autistici.org/ale/gompd/decode.go b/Godeps/_workspace/src/git.autistici.org/ale/gompd/decode.go
new file mode 100644
index 0000000000000000000000000000000000000000..06b59201834e091bbfbe528269ea58e51a184ab7
--- /dev/null
+++ b/Godeps/_workspace/src/git.autistici.org/ale/gompd/decode.go
@@ -0,0 +1,163 @@
+package mpd
+
+import (
+	"encoding/binary"
+	"io"
+	"log"
+	"os"
+	"os/exec"
+)
+
+var avconv = "avconv"
+
+func init() {
+	// Let the users override the location of the 'avconv' binary
+	// using an environment variable.
+	avconvEnv := os.Getenv("AVCONV")
+	if avconvEnv != "" {
+		avconv = avconvEnv
+	}
+
+	// If we can't find the avconv/ffmpeg executable, bail out and
+	// warn the user.
+	if _, err := exec.LookPath(avconv); err != nil {
+		log.Fatal("Can't find \"avconv\" in your PATH, please install it (\"sudo apt-get install libav-tools\" on Debian-based systems). You can also use \"ffmpeg\", and use the AVCONV environment variable to point this application at it.")
+	}
+}
+
+type decoder struct {
+	src    io.ReadCloser
+	cmd    *exec.Cmd
+	stdin  io.WriteCloser
+	stdout io.ReadCloser
+}
+
+func (d *decoder) Read(buf []byte) (int, error) {
+	return d.stdout.Read(buf)
+}
+
+func (d *decoder) Close() error {
+	d.src.Close()
+	d.cmd.Process.Kill()
+	err := d.cmd.Wait()
+	log.Printf("ffmpeg pid %d stopped (%v)", d.cmd.Process.Pid, err)
+	return err
+}
+
+// Decode an io.Reader using avconv/ffmpeg.
+func Decode(src io.ReadCloser, format string) (io.ReadCloser, error) {
+	cmd := exec.Command(avconv, "-i", "-", "-f", format, "-")
+	stdin, err := cmd.StdinPipe()
+	if err != nil {
+		return nil, err
+	}
+	stdout, err := cmd.StdoutPipe()
+	if err != nil {
+		stdin.Close()
+		return nil, err
+	}
+
+	if err := cmd.Start(); err != nil {
+		stdin.Close()
+		stdout.Close()
+		return nil, err
+	}
+
+	log.Printf("ffmpeg pid %d started", cmd.Process.Pid)
+
+	go func() {
+		// Copy 'src' to the standard input.
+		io.Copy(stdin, src)
+		// Close stdin to force avconv to exit.
+		stdin.Close()
+	}()
+
+	// Return the wrapped stdout.
+	return &decoder{src, cmd, stdin, stdout}, nil
+}
+
+// bufferedReader ensures no short reads.
+type bufferedReader struct {
+	io.Reader
+}
+
+func (r *bufferedReader) Read(buf []byte) (int, error) {
+	p := 0
+	for p < len(buf) {
+		n, err := r.Reader.Read(buf[p:len(buf)])
+		if err != nil {
+			return p, err
+		}
+		if n == 0 {
+			break
+		}
+		p += n
+	}
+	return p, nil
+}
+
+// Buffer pool to limit GC.
+type bufferPool struct {
+	bufsize int
+	ch      chan []int16
+}
+
+var audioBufferPool = &bufferPool{
+	bufsize: audioBufFrames * 2,
+	ch:      make(chan []int16, audioBufQueueSize),
+}
+
+func (p *bufferPool) New() []int16 {
+	var b []int16
+	select {
+	case b = <-p.ch:
+	default:
+		b = make([]int16, p.bufsize)
+	}
+	return b
+}
+
+func (p *bufferPool) Free(b []int16) {
+	select {
+	case p.ch <- b:
+	default:
+	}
+}
+
+// decodeSamples reads bytes and writes samples to a channel.
+func decodeSamples(src io.Reader) <-chan []int16 {
+	ch := make(chan []int16, audioBufQueueSize)
+
+	go func() {
+		// We use a local buffer and a sample decoding loop instead of
+		// a plain binary.Read because we want to handle gracefully
+		// the last (partial) buffer...
+		defer close(ch)
+		encoding := binary.LittleEndian
+		bbuf := make([]byte, audioBufFrames*2*2)
+		bufn := 0
+		for {
+			n, err := src.Read(bbuf)
+			if err != nil {
+				return
+			}
+			if n == 0 {
+				return
+			}
+
+			if bufn == 0 {
+				log.Println("received decoded data")
+			}
+			bufn++
+
+			// Decode the binary input buffer to samples.
+			abuf := audioBufferPool.New()
+			for i := 0; i < n/2; i++ {
+				abuf[i] = int16(encoding.Uint16(bbuf[i*2 : i*2+2]))
+			}
+			ch <- abuf
+		}
+	}()
+
+	return ch
+}
diff --git a/Godeps/_workspace/src/git.autistici.org/ale/gompd/mpd.go b/Godeps/_workspace/src/git.autistici.org/ale/gompd/mpd.go
new file mode 100644
index 0000000000000000000000000000000000000000..32951e018ecadc8b29971fa4a7dc7ef9e369e4d1
--- /dev/null
+++ b/Godeps/_workspace/src/git.autistici.org/ale/gompd/mpd.go
@@ -0,0 +1,527 @@
+package mpd
+
+import (
+	"fmt"
+	"io"
+	"log"
+	"net/url"
+	"strconv"
+	"time"
+)
+
+const (
+	StateStop = iota
+	StatePlay
+	StatePause
+)
+
+// FIXME: there are currently no stats.
+type stats struct {
+	artists int
+	albums  int
+	songs   int
+}
+
+// A song, with associated metadata and audio resource.
+type Song interface {
+	// URL returns a unique identifier for this song.
+	URL() string
+
+	// Info returns a string with the song metadata formatted
+	// according to the MPD protocol.
+	Info() string
+
+	// Open the audio file and return it (in the original format,
+	// which will be decoded by the player). The caller must call
+	// Close() on the result.
+	Open() (io.ReadCloser, error)
+
+	Channels() int
+	SampleRate() float64
+	Duration() int
+}
+
+// A song, with associated playlist information.
+type SongFromPlaylist interface {
+	Song
+
+	// ID returns the song id in the playlist.
+	ID() int
+
+	// Index of this song in the playlist.
+	Index() int
+
+	// Song returns the wrapped Song.
+	GetSong() Song
+}
+
+// Database is used to search for songs. Queries are encoded according
+// to the MPD protocol, consisting of paired tag/query fields, and
+// must be decoded by the implementation.
+type Database interface {
+	// Find an exact match for the query.
+	Find(args []string) ([]Song, error)
+
+	// Search the database with the given query.
+	Search(args []string) ([]Song, error)
+}
+
+// A function that returns the next song to be played.
+type SongCallbackFunc func() SongFromPlaylist
+
+// Callback called when a song has been successfully played in its
+// entirety.
+type SongPlayedCallbackFunc func(Song)
+
+// Audio device.
+type Output struct {
+	Name    string
+	ID      int
+	Enabled bool
+}
+
+type PlayerState int
+
+func (s PlayerState) String() string {
+	switch s {
+	case StateStop:
+		return "stop"
+	case StatePlay:
+		return "play"
+	case StatePause:
+		return "pause"
+	}
+	return ""
+}
+
+// A URLHandler is associated with a specific URL scheme, and it is
+// used to retrieve songs (possibly from a database).
+type URLHandler interface {
+	// GetSong returns the Song identified by the given url.
+	GetSong(songURL *url.URL) (Song, error)
+}
+
+// MPD server. Implements most of the commands of a real server, but
+// it is oriented towards searching rather than browsing (that is to
+// say, browsing is currently unimplemented).
+type MPD struct {
+	*Server
+
+	// Tag types. Currently not used.
+	TagTypes []string
+
+	lastError string
+
+	player   *portAudioPlayer
+	playlist *Playlist
+	database Database
+
+	stats     stats
+	startedAt time.Time
+
+	urlHandlers map[string]URLHandler
+}
+
+func (m *MPD) getSong(songURL string) (Song, error) {
+	url, err := url.Parse(songURL)
+	if err != nil {
+		return nil, err
+	}
+	h, ok := m.urlHandlers[url.Scheme]
+	if !ok {
+		return nil, ErrUnsupportedScheme
+	}
+	return h.GetSong(url)
+}
+
+// This and the following functions are just syntactical glue to make
+// it easy to express the large number of commands in the MPD
+// protocol, most of which do very similar things.
+//
+// RN in function names stands for 'returns nil' (in which case the
+// io.Writer argument is also omitted).
+func withArgs(f func(io.Writer, []string) error, minArgs, maxArgs int) Handler {
+	return CommandFunc(func(w io.Writer, args []string) error {
+		if len(args) < minArgs || len(args) > maxArgs {
+			return ErrBadArgs
+		}
+		return f(w, args)
+	})
+}
+
+func withOneArg(f func(io.Writer, string) error) Handler {
+	return withArgs(func(w io.Writer, args []string) error {
+		return f(w, args[0])
+	}, 1, 1)
+}
+
+func withTwoArgsRN(f func(io.Writer, string, string)) Handler {
+	return withArgs(func(w io.Writer, args []string) error {
+		f(w, args[0], args[1])
+		return nil
+	}, 2, 2)
+}
+
+func withInt(f func(io.Writer, int) error) Handler {
+	return withOneArg(func(w io.Writer, arg string) error {
+		value, err := strconv.Atoi(arg)
+		if err != nil {
+			return err
+		}
+		return f(w, value)
+	})
+}
+
+func withIntRN(f func(int)) Handler {
+	return withOneArg(func(w io.Writer, arg string) error {
+		value, err := strconv.Atoi(arg)
+		if err != nil {
+			return err
+		}
+		f(value)
+		return nil
+	})
+}
+
+func withTwoIntsRN(f func(int, int)) Handler {
+	return withArgs(func(w io.Writer, args []string) error {
+		value1, err := strconv.Atoi(args[0])
+		if err != nil {
+			return err
+		}
+		value2, err := strconv.Atoi(args[0])
+		if err != nil {
+			return err
+		}
+		f(value1, value2)
+		return nil
+	}, 2, 2)
+}
+
+func withNoOutput(f func()) Handler {
+	return withArgs(func(w io.Writer, args []string) error {
+		f()
+		return nil
+	}, 0, 0)
+}
+
+func NewMPD(db Database, notifier SongPlayNotifier) *MPD {
+	// Create and connect a player and a playlist.
+	playlist := NewPlaylist()
+	player := NewPortAudioPlayer(playlist, notifier)
+	m := &MPD{
+		Server:      NewServer(),
+		player:      player,
+		playlist:    playlist,
+		database:    db,
+		TagTypes:    []string{"Artist", "Album", "Title", "Genre"},
+		startedAt:   time.Now(),
+		urlHandlers: make(map[string]URLHandler),
+	}
+
+	// Exactly one output device can be enabled at any time, so
+	// most of these commands probably won't work as expected if
+	// used in non-obvious ways.
+	m.HandleFunc("outputs", m.cmdOutputs)
+	m.Handle("enableoutput", withIntRN(func(id int) {
+		m.player.SetOutput(id)
+	}))
+	m.HandleFunc("disableoutput", nopCmd)
+	m.HandleFunc("toggleoutput", nopCmd)
+
+	// Playback options.
+	m.Handle("setvol", withInt(m.cmdSetVol))
+	m.Handle("random", m.withNotify("options", withIntRN(func(state int) {
+		m.playlist.SetRandom(state == 1)
+	})))
+	m.Handle("repeat", m.withNotify("options", withIntRN(func(state int) {
+		m.playlist.SetRepeat(state == 1)
+	})))
+
+	// Status.
+	m.HandleFunc("status", m.cmdStatus)
+	m.HandleFunc("stats", m.cmdStats)
+	m.HandleFunc("currentsong", m.cmdCurrentSong)
+	m.Handle("clearerror", withNoOutput(func() {
+		m.lastError = ""
+	}))
+
+	// Reflection.
+	m.HandleFunc("urlhandlers", m.cmdURLHandlers)
+	m.HandleFunc("tagtypes", m.cmdTagTypes)
+
+	// Playlist commands.
+	m.Handle("add", m.withNotify("playlist", withOneArg(m.cmdAdd)))
+	m.Handle("addid", m.withNotify("playlist", withOneArg(m.cmdAddID)))
+	m.Handle("clear", m.withNotify("playlist", withNoOutput(m.playlist.Clear)))
+	m.Handle("delete", m.withNotify("playlist", withOneArg(func(w io.Writer, arg string) error {
+		r, err := ParseRange(arg)
+		if err != nil {
+			return err
+		}
+		m.playlist.Delete(r)
+		return nil
+	})))
+	m.Handle("deleteid", m.withNotify("playlist", withIntRN(m.playlist.DeleteID)))
+	m.Handle("move", m.withNotify("playlist", withTwoArgsRN(func(w io.Writer, from string, to string) {
+		fromRange, err := ParseRange(from)
+		if err != nil {
+			return
+		}
+		toInt, err := strconv.Atoi(to)
+		if err != nil {
+			return
+		}
+		m.playlist.Move(fromRange, toInt)
+	})))
+	m.Handle("moveid", m.withNotify("playlist", withTwoIntsRN(m.playlist.MoveID)))
+	m.Handle("swap", m.withNotify("playlist", withTwoIntsRN(m.playlist.Swap)))
+	m.Handle("swapid", m.withNotify("playlist", withTwoIntsRN(m.playlist.SwapID)))
+	m.HandleFunc("playlistinfo", m.cmdPlaylistInfo)
+	m.HandleFunc("playlistid", m.cmdPlaylistID)
+	m.Handle("plchanges", withInt(m.cmdPlaylistChanges))
+	m.Handle("plchangesposid", withInt(m.cmdPlaylistChangesPosID))
+	m.Handle("playlistfind", withTwoArgsRN(m.playlist.Find))
+	// m.HandleFunc("playlist", m.cmdPlaylistURLs)
+
+	// Play control.
+	m.Handle("next", m.withNotify("player", withNoOutput(func() {
+		m.player.Play(m.playlist.Next())
+	})))
+	m.Handle("previous", m.withNotify("player", withNoOutput(func() {
+		m.player.Play(m.playlist.Prev())
+	})))
+	m.Handle("stop", m.withNotify("player", withNoOutput(m.player.Stop)))
+	m.Handle("pause", m.withNotify("player", CommandFunc(func(w io.Writer, args []string) error {
+		// Ignore optional argument.
+		m.player.Pause()
+		return nil
+	})))
+	m.Handle("play", m.withNotify("player", CommandFunc(m.cmdPlay)))
+	m.Handle("playid", m.withNotify("player", CommandFunc(m.cmdPlayID)))
+
+	// Database management.
+	m.HandleFunc("search", m.cmdSearch)
+	m.HandleFunc("find", m.cmdFind)
+	m.HandleFunc("count", m.cmdCount)
+	m.HandleFunc("list", nopCmd)
+	m.HandleFunc("lsinfo", nopCmd)
+	m.HandleFunc("listplaylists", nopCmd)
+
+	return m
+}
+
+// Send a notification on the given channel only if the handler succeeds.
+func (m *MPD) withNotify(tag string, h Handler) Handler {
+	return CommandFunc(func(w io.Writer, args []string) error {
+		err := h.ServeMPD(w, args)
+		if err == nil {
+			m.Trigger(tag)
+		}
+		return err
+	})
+}
+
+// HandleURL installs a new URLHandler.
+func (m *MPD) HandleURL(schema string, h URLHandler) {
+	m.urlHandlers[schema] = h
+}
+
+func (m *MPD) cmdURLHandlers(w io.Writer, args []string) error {
+	for schema := range m.urlHandlers {
+		fmt.Fprintf(w, "handler: %s://\n", schema)
+	}
+	return nil
+}
+
+func (m *MPD) cmdTagTypes(w io.Writer, args []string) error {
+	for _, t := range m.TagTypes {
+		fmt.Fprintf(w, "tagtype: %s\n", t)
+	}
+	return nil
+}
+
+func (m *MPD) cmdOutputs(w io.Writer, args []string) error {
+	for _, o := range m.player.Outputs() {
+		fmt.Fprintf(w, "outputid: %d\noutputname: %s\noutputenabled: %d\n", o.ID, o.Name, bool2int(o.Enabled))
+	}
+	return nil
+}
+
+func (m *MPD) cmdEnableOutput(w io.Writer, args []string) error {
+	id, _ := strconv.Atoi(args[0])
+	m.player.SetOutput(id)
+	return nil
+}
+
+func (m *MPD) cmdCurrentSong(w io.Writer, args []string) error {
+	if m.player.State() == StatePlay {
+		if s := m.player.CurSong(); s != nil {
+			io.WriteString(w, s.Info())
+			fmt.Fprintf(w, "Id: %d\nPos: %d\n", s.ID(), s.Index())
+		}
+	}
+	return nil
+}
+
+func (m *MPD) cmdSetVol(w io.Writer, vol int) error {
+	if vol < 0 || vol > 100 {
+		return ErrBadArgs
+	}
+	m.player.SetVolume(vol)
+	return nil
+}
+
+func (m *MPD) cmdStats(w io.Writer, args []string) error {
+	uptime := int(time.Now().Sub(m.startedAt).Seconds())
+	fmt.Fprintf(w, "artists: %d\nalbums: %d\nsongs: %d\nuptime: %d\nplaytime: 0\n", m.stats.artists, m.stats.albums, m.stats.songs, uptime)
+	fmt.Fprintf(w, "db_playtime: 0\ndb_update: %d\n", time.Now().Unix())
+	return nil
+}
+
+func (m *MPD) cmdStatus(w io.Writer, args []string) error {
+	fmt.Fprintf(w, "volume: %d\n", m.player.Volume())
+	fmt.Fprintf(w, "repeat: %d\n", bool2int(m.playlist.Repeat()))
+	fmt.Fprintf(w, "random: %d\n", bool2int(m.playlist.Random()))
+	fmt.Fprintf(w, "state: %s\n", m.player.State())
+	fmt.Fprintf(w, "playlist: %d\nplaylistlength: %d\n", m.playlist.Version, m.playlist.Len())
+	if m.lastError != "" {
+		fmt.Fprintf(w, "error: %s\n", m.lastError)
+	}
+	if m.player.State() != StateStop {
+		if s := m.player.CurSong(); s != nil {
+			fmt.Fprintf(w, "song: %d\nsongid: %d\n", s.Index(), s.ID())
+			fmt.Fprintf(w, "audio: %d:16:%d\n", int(s.SampleRate()), s.Channels())
+			fmt.Fprintf(w, "time: %d:%d\n", m.player.SongTime(), s.Duration())
+		}
+	}
+	if s := m.playlist.PeekNext(); s != nil {
+		fmt.Fprintf(w, "nextsong: %d\nnextsongid: %d\n", s.Index(), s.ID())
+	}
+	return nil
+}
+
+func (m *MPD) cmdPlaylistID(w io.Writer, args []string) error {
+	if len(args) > 0 {
+		id, err := strconv.Atoi(args[0])
+		if err != nil {
+			return err
+		}
+		m.playlist.InfoID(w, id)
+	} else {
+		m.playlist.Info(w)
+	}
+	return nil
+}
+
+func (m *MPD) cmdPlaylistInfo(w io.Writer, args []string) error {
+	if len(args) > 0 {
+		r, err := ParseRange(args[0])
+		if err != nil {
+			return err
+		}
+		m.playlist.InfoRange(w, r)
+	} else {
+		m.playlist.Info(w)
+	}
+	return nil
+}
+
+func (m *MPD) cmdPlaylistChanges(w io.Writer, oldver int) error {
+	// Pretend all songs have changed.
+	m.playlist.Info(w)
+	return nil
+}
+
+func (m *MPD) cmdPlaylistChangesPosID(w io.Writer, oldver int) error {
+	// Pretend all songs have changed.
+	m.playlist.ChangesPosID(w, oldver)
+	return nil
+}
+
+func (m *MPD) cmdAdd(w io.Writer, songURL string) error {
+	song, err := m.getSong(songURL)
+	if err != nil {
+		return err
+	}
+	m.playlist.Add(song, -1)
+	return nil
+}
+
+func (m *MPD) cmdAddID(w io.Writer, songURL string) error {
+	song, err := m.getSong(songURL)
+	if err != nil {
+		return err
+	}
+	id := m.playlist.Add(song, -1)
+	fmt.Fprintf(w, "Id: %d\n", id)
+	return nil
+}
+
+func (m *MPD) cmdPlay(w io.Writer, args []string) error {
+	if len(args) > 0 {
+		pos, err := strconv.Atoi(args[0])
+		if err != nil {
+			return err
+		}
+		m.player.Play(m.playlist.SetCursor(pos))
+	} else {
+		m.player.Play(nil)
+	}
+	return nil
+}
+
+func (m *MPD) cmdPlayID(w io.Writer, args []string) error {
+	if len(args) > 0 {
+		id, _ := strconv.Atoi(args[0])
+		m.player.Play(m.playlist.SetCursorID(id))
+	} else {
+		m.player.Play(nil)
+	}
+	return nil
+}
+
+func (m *MPD) cmdSearch(w io.Writer, args []string) error {
+	if len(args) < 2 {
+		return ErrBadArgs
+	}
+	songs, err := m.database.Search(args)
+	if err != nil {
+		return err
+	}
+
+	log.Printf("search(%v) -> %+v", args, songs)
+	for _, s := range songs {
+		io.WriteString(w, s.Info())
+	}
+	return nil
+}
+
+func (m *MPD) cmdFind(w io.Writer, args []string) error {
+	if len(args) < 2 {
+		return ErrBadArgs
+	}
+	songs, err := m.database.Find(args)
+	if err != nil {
+		return err
+	}
+
+	log.Printf("find(%v) -> %+v", args, songs)
+	for _, s := range songs {
+		io.WriteString(w, s.Info())
+	}
+	return nil
+}
+
+func (m *MPD) cmdCount(w io.Writer, args []string) error {
+	// Currently just a stub.
+	io.WriteString(w, "songs: 0\nplaytime: 0\n")
+	return nil
+}
+
+func bool2int(b bool) int {
+	if b {
+		return 1
+	}
+	return 0
+}
diff --git a/Godeps/_workspace/src/git.autistici.org/ale/gompd/player.go b/Godeps/_workspace/src/git.autistici.org/ale/gompd/player.go
new file mode 100644
index 0000000000000000000000000000000000000000..adc1a19d102c6f92336bd67a267e1bb40a73d678
--- /dev/null
+++ b/Godeps/_workspace/src/git.autistici.org/ale/gompd/player.go
@@ -0,0 +1,436 @@
+package mpd
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"log"
+	"sync"
+
+	"code.google.com/p/portaudio-go/portaudio"
+)
+
+const (
+	// Audio buffer size (in frames).
+	audioBufFrames = 4096
+
+	// Size of the audio buffer queue.
+	audioBufQueueSize = 16
+)
+
+type audioParams struct {
+	channels   int
+	samplerate float64
+}
+
+// Keep an audio device always open, reconfigure it only when necessary.
+type audioDevice struct {
+	// Internal buffer. This limits the sample size to 16 bits, as
+	// portaudio has trouble with 24 bits per sample (result of a test
+	// with a high-end USB audio device: no output).
+	c       chan []int16
+	buf     []int16
+	params  audioParams
+	device  *portaudio.DeviceInfo
+	stream  *portaudio.Stream
+	started bool
+	lock    sync.Mutex
+}
+
+func newAudioDevice() (*audioDevice, error) {
+	defaultOutputDev, err := portaudio.DefaultOutputDevice()
+	if err != nil {
+		return nil, err
+	}
+	a := &audioDevice{
+		c:   make(chan []int16, 1),
+		buf: make([]int16, audioBufFrames*2),
+		params: audioParams{
+			channels:   2,
+			samplerate: 44100,
+		},
+		device: defaultOutputDev,
+	}
+	if err := a.open(); err != nil {
+		return nil, err
+	}
+	go a.audioLoop()
+	return a, nil
+}
+
+func (a *audioDevice) audioLoop() {
+	for buf := range a.c {
+		copy(a.buf, buf)
+		audioBufferPool.Free(buf)
+
+		// Write() will block, don't hold the lock.
+		if stream := a.stream; stream != nil {
+			if err := stream.Write(); err == portaudio.OutputUnderflowed {
+				log.Println("output underflowed")
+			} else if err != nil {
+				log.Printf("audio error: %v", err)
+			}
+		}
+	}
+}
+
+func (a *audioDevice) SetParameters(p audioParams) error {
+	if p == a.params {
+		return nil
+	}
+	// We may need to reallocate the buffer.
+	if p.channels != a.params.channels {
+		a.buf = make([]int16, audioBufFrames*p.channels)
+	}
+	a.params = p
+	return a.open()
+}
+
+func (a *audioDevice) SetDevice(device *portaudio.DeviceInfo) error {
+	if device == a.device {
+		return nil
+	}
+	a.device = device
+	return a.open()
+}
+
+func (a *audioDevice) Start() {
+	a.lock.Lock()
+	defer a.lock.Unlock()
+	if a.stream != nil {
+		a.stream.Start()
+		a.started = true
+	}
+}
+
+func (a *audioDevice) Stop() {
+	a.lock.Lock()
+	defer a.lock.Unlock()
+	if a.stream != nil {
+		a.stream.Stop()
+		a.started = false
+	}
+}
+
+func (a *audioDevice) open() error {
+	a.lock.Lock()
+	defer a.lock.Unlock()
+	if a.stream != nil {
+		a.stream.Stop()
+		a.stream.Close()
+	}
+
+	// Attempt to open the device. We rely on the return value
+	// being nil if err is set.
+	var err error
+	log.Printf("open audio device \"%s\" %+v", a.device.Name, a.params)
+	a.stream, err = portaudio.OpenStream(a.streamParameters(), &a.buf)
+
+	// For a seamless switch while a songPlayer goroutine is
+	// active, we need to restart the stream.
+	if err == nil && a.started {
+		a.stream.Start()
+	}
+
+	return err
+}
+
+func (a *audioDevice) streamParameters() portaudio.StreamParameters {
+	return portaudio.StreamParameters{
+		Output: portaudio.StreamDeviceParameters{
+			Device:   a.device,
+			Latency:  a.device.DefaultHighOutputLatency,
+			Channels: a.params.channels,
+		},
+		SampleRate:      a.params.samplerate,
+		FramesPerBuffer: audioBufFrames,
+	}
+}
+
+const (
+	opPlay = iota
+	opStop
+	opPause
+)
+
+type playerCommand struct {
+	op   int
+	song SongFromPlaylist
+}
+
+type songSource struct {
+	c       <-chan []int16
+	decoder io.ReadCloser
+	songfd  io.ReadCloser
+}
+
+func (s *songSource) Close() error {
+	//s.songfd.Close()
+	s.decoder.Close()
+	// Flush the buffered channel.
+	for _ = range s.c {
+	}
+	return nil
+}
+
+// Create a new song source. This is a chain of io.Readers ultimately
+// feeding constant-sized buffers into a channel. Since it is expected
+// that the source is remote, we read from it as fast as we can and
+// cache the results to disk.
+func newSongSource(song SongFromPlaylist) (*songSource, error) {
+	songfd, err := song.Open()
+	if err != nil {
+		return nil, err
+	}
+
+	// cr, err := newDiskBackedReader(songfd)
+	// if err != nil {
+	// 	songfd.Close()
+	// 	return nil, err
+	// }
+
+	decoder, err := Decode(songfd, "s16le")
+	if err != nil {
+		songfd.Close()
+		return nil, err
+	}
+
+	return &songSource{
+		c:       decodeSamples(&bufferedReader{decoder}),
+		decoder: decoder,
+		songfd:  songfd,
+	}, nil
+}
+
+type SongPlayNotifier interface {
+	Notify(Song)
+}
+
+type SongProvider interface {
+	Next() SongFromPlaylist
+}
+
+// Main audio player logic.
+type audioPlayer struct {
+	state         PlayerState
+	currentSong   SongFromPlaylist
+	currentSource *songSource
+	audioDev      *audioDevice
+	ctrl          chan playerCommand
+	songNotifier  SongPlayNotifier
+	songProvider  SongProvider
+	lock          sync.Mutex
+}
+
+func newAudioPlayer(dev *audioDevice, provider SongProvider, notifier SongPlayNotifier) *audioPlayer {
+	a := &audioPlayer{
+		audioDev:     dev,
+		state:        StateStop,
+		songProvider: provider,
+		songNotifier: notifier,
+		ctrl:         make(chan playerCommand),
+	}
+	go a.loop()
+	return a
+}
+
+func (p *audioPlayer) loop() {
+	for {
+		switch p.state {
+		case StatePlay:
+			select {
+			case buf, ok := <-p.currentSource.c:
+				if !ok {
+					// The current song has ended. Notify
+					// the caller in a separate goroutine,
+					// and play the next song (if any).
+					go p.songNotifier.Notify(p.currentSong.GetSong())
+					song := p.songProvider.Next()
+					if song == nil {
+						p.handleCmd(playerCommand{op: opStop})
+					} else {
+						p.handleCmd(playerCommand{op: opPlay, song: song})
+					}
+				} else {
+					p.audioDev.c <- buf
+				}
+			case cmd := <-p.ctrl:
+				p.handleCmd(cmd)
+			}
+		default:
+			cmd := <-p.ctrl
+			p.handleCmd(cmd)
+		}
+	}
+}
+
+func (p *audioPlayer) handleCmd(cmd playerCommand) {
+	p.lock.Lock()
+	defer p.lock.Unlock()
+	switch {
+	case cmd.op == opPlay:
+		if p.state != StateStop {
+			p.stopSource()
+		}
+		if err := p.startSource(cmd.song); err != nil {
+			log.Printf("error playing song %s: %v", cmd.song.URL(), err)
+			p.state = StateStop
+		} else {
+			p.state = StatePlay
+		}
+	case cmd.op == opStop && p.state != StateStop:
+		p.stopSource()
+		p.audioDev.Stop()
+		p.state = StateStop
+	case cmd.op == opPause:
+		switch p.state {
+		case StatePlay:
+			p.audioDev.Stop()
+			p.state = StatePause
+		case StatePause:
+			p.audioDev.Start()
+			p.state = StatePlay
+		}
+	}
+}
+
+func (p *audioPlayer) startSource(song SongFromPlaylist) error {
+	params := audioParams{
+		channels:   song.Channels(),
+		samplerate: song.SampleRate(),
+	}
+	if err := p.audioDev.SetParameters(params); err != nil {
+		return fmt.Errorf("error setting parameters for audio device (%v): %v", params, err)
+	}
+
+	src, err := newSongSource(song)
+	if err != nil {
+		return err
+	}
+	p.currentSong = song
+	p.currentSource = src
+
+	p.audioDev.Start()
+	return nil
+}
+
+func (p *audioPlayer) stopSource() {
+	// Cleanup the current source in a separate goroutine.
+	if p.currentSource != nil {
+		go p.currentSource.Close()
+	}
+	p.currentSong = nil
+	p.currentSource = nil
+}
+
+func (p *audioPlayer) Play(song SongFromPlaylist) {
+	if song == nil {
+		song = p.songProvider.Next()
+	}
+	if song == nil {
+		return
+	}
+
+	p.ctrl <- playerCommand{op: opPlay, song: song}
+}
+
+func (p *audioPlayer) Pause() {
+	p.ctrl <- playerCommand{op: opPause}
+}
+
+func (p *audioPlayer) Stop() {
+	p.ctrl <- playerCommand{op: opStop}
+}
+
+func (p *audioPlayer) State() PlayerState {
+	p.lock.Lock()
+	defer p.lock.Unlock()
+	return p.state
+}
+
+func (p *audioPlayer) CurSong() SongFromPlaylist {
+	p.lock.Lock()
+	defer p.lock.Unlock()
+	return p.currentSong
+}
+
+// An audioPlayer that knows about PortAudio hw devices.
+type portAudioPlayer struct {
+	*audioPlayer
+
+	outputDevs   []*portaudio.DeviceInfo
+	curOutputDev *portaudio.DeviceInfo
+
+	volume int
+}
+
+func NewPortAudioPlayer(provider SongProvider, notifier SongPlayNotifier) *portAudioPlayer {
+	portaudio.Initialize()
+	audiodev, err := newAudioDevice()
+	if err != nil {
+		log.Fatal(err)
+	}
+	p := &portAudioPlayer{
+		audioPlayer:  newAudioPlayer(audiodev, provider, notifier),
+		curOutputDev: audiodev.device,
+		volume:       100,
+	}
+	p.updateDevices()
+	return p
+}
+
+// Close the audio player and release all resources.
+func (p *portAudioPlayer) Close() {
+	portaudio.Terminate()
+}
+
+// Update the list of available output devices (according to PortAudio).
+func (p *portAudioPlayer) updateDevices() {
+	// Ignore errors here for the moment.
+	var out []*portaudio.DeviceInfo
+	devs, _ := portaudio.Devices()
+	for _, d := range devs {
+		if d.MaxOutputChannels > 0 {
+			out = append(out, d)
+		}
+	}
+	p.outputDevs = out
+}
+
+func (p *portAudioPlayer) Outputs() []Output {
+	var out []Output
+	for idx, d := range p.outputDevs {
+		out = append(out, Output{
+			ID:      idx,
+			Name:    d.Name,
+			Enabled: d == p.curOutputDev,
+		})
+	}
+	return out
+}
+
+func (p *portAudioPlayer) SetOutput(idx int) error {
+	if idx < 0 || idx >= len(p.outputDevs) {
+		return errors.New("no such device")
+	}
+	if err := p.audioDev.SetDevice(p.outputDevs[idx]); err != nil {
+		p.audioDev.SetDevice(p.curOutputDev)
+		return err
+	}
+	p.curOutputDev = p.outputDevs[idx]
+	return nil
+}
+
+func (p *portAudioPlayer) Volume() int {
+	return p.volume
+}
+
+func (p *portAudioPlayer) SetVolume(vol int) {
+	// This doesn't do anything right now.
+	p.volume = vol
+}
+
+func (p *portAudioPlayer) SongTime() int {
+	// TODO: implement this again.
+	return 0
+}
diff --git a/Godeps/_workspace/src/git.autistici.org/ale/gompd/playlist.go b/Godeps/_workspace/src/git.autistici.org/ale/gompd/playlist.go
new file mode 100644
index 0000000000000000000000000000000000000000..8993b524ae2e3a12e205bc5538df78f229173d85
--- /dev/null
+++ b/Godeps/_workspace/src/git.autistici.org/ale/gompd/playlist.go
@@ -0,0 +1,554 @@
+package mpd
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"log"
+	"math/rand"
+	"strconv"
+	"strings"
+	"sync"
+)
+
+// Range represents a range of song indexes. The END item is not
+// included in the range.
+type Range struct {
+	Start, End int
+}
+
+// Len returns the total size of the range.
+func (r Range) Len() int {
+	return r.End - r.Start
+}
+
+func (r Range) Contains(i int) bool {
+	return (i >= r.Start && i < r.End)
+}
+
+// Bound the range to match a given slice (if it extends beyond it, it
+// will be limited).
+func (r *Range) Bound(slicelen int) {
+	if r.Start < 0 {
+		r.Start = 0
+	}
+	if r.Start >= slicelen {
+		r.Start = slicelen - 1
+	}
+	if r.End < 0 {
+		r.End = 0
+	}
+	if r.End > slicelen {
+		r.End = slicelen
+	}
+}
+
+func singleIndexRange(i int) Range {
+	return Range{Start: i, End: i + 1}
+}
+
+// ParseRange parses a START:END integer range according to the MPD
+// protocol spec. Note that in the MPD specification, the END element
+// is included in the range.
+func ParseRange(s string) (Range, error) {
+	var r Range
+	if strings.Contains(s, ":") {
+		parts := strings.Split(s, ":")
+		if len(parts) != 2 {
+			return r, errors.New("bad range format")
+		}
+		var err error
+		r.Start, err = strconv.Atoi(parts[0])
+		if err != nil {
+			return r, err
+		}
+		end, err := strconv.Atoi(parts[1])
+		if err != nil {
+			return r, err
+		}
+		r.End = end + 1
+		if r.Start > r.End {
+			return r, errors.New("malformed range")
+		}
+	} else {
+		i, err := strconv.Atoi(s)
+		if err != nil {
+			return r, err
+		}
+		r.Start = i
+		r.End = i + 1
+	}
+	return r, nil
+}
+
+type orderedSongList struct {
+	// Store separately a list of songs (identified by their index
+	// in the array), and an ordered list of indices, representing
+	// the order in which the songs should be visited.
+	songs     []Song
+	songOrder []int
+}
+
+func (l *orderedSongList) Len() int { return len(l.songs) }
+
+func (l *orderedSongList) Empty() bool { return len(l.songs) == 0 }
+
+func (l *orderedSongList) SongAtIndex(idx int) Song {
+	if idx < 0 || idx >= len(l.songs) {
+		return nil
+	}
+	return l.songs[idx]
+}
+
+func (l *orderedSongList) SongAtPos(pos int) Song {
+	if pos < 0 || pos >= len(l.songs) {
+		return nil
+	}
+	idx := l.songOrder[pos]
+	return l.songs[idx]
+}
+
+func (l *orderedSongList) PositionOf(song Song) int {
+	for i, j := range l.songOrder {
+		if l.songs[j] == song {
+			return i
+		}
+	}
+	return -1
+}
+
+func (l *orderedSongList) IndexAtPos(idx int) int {
+	if idx < 0 || idx >= len(l.songOrder) {
+		return -1
+	}
+	return l.songOrder[idx]
+}
+
+// Add a song. The specified index is actually ignored. Returns the
+// new index of the added song.
+func (l *orderedSongList) Add(song Song, idx int) int {
+	idx = len(l.songs)
+	l.songs = append(l.songs, song)
+	l.songOrder = append(l.songOrder, idx)
+	return idx
+}
+
+func (l *orderedSongList) Delete(r Range) {
+	r.Bound(len(l.songs))
+
+	// Remove from songs.
+	out := make([]Song, len(l.songs)-r.Len())
+	copy(out[:r.Start], l.songs[:r.Start])
+	copy(out[r.Start:len(out)], l.songs[r.End:len(l.songs)])
+	l.songs = out
+
+	// Remove from song index.
+	var tmp []int
+	for _, j := range l.songOrder {
+		if j < r.Start || j > r.End {
+			tmp = append(tmp, j)
+		}
+	}
+	l.songOrder = tmp
+}
+
+func (l *orderedSongList) Swap(from, to int) {
+	l.songs[from], l.songs[to] = l.songs[to], l.songs[from]
+	for i, j := range l.songOrder {
+		if j == from {
+			l.songOrder[i] = to
+		} else if j == to {
+			l.songOrder[i] = from
+		}
+	}
+}
+
+func (l *orderedSongList) Move(from Range, pos int) {
+	from.Bound(len(l.songs))
+	to := Range{Start: pos, End: pos + from.Len()}
+
+	getpos := func(pos int) int {
+		if (pos < from.Start && pos < to.Start) || (pos >= from.End && pos >= to.End) {
+			return pos
+		}
+		if to.Contains(pos) {
+			return pos + from.Start - to.Start
+		}
+		if from.Start > to.Start {
+			return pos - from.Len()
+		}
+		return pos + from.Len()
+	}
+
+	newsongs := make([]Song, len(l.songs))
+	for i := 0; i < len(l.songs); i++ {
+		newsongs[i] = l.songs[getpos(i)]
+	}
+	l.songs = newsongs
+}
+
+// Shuffle the song ordering starting at position minPos.
+func (l *orderedSongList) Shuffle(minPos int) {
+	var tmp []int
+	if minPos < 0 || minPos >= len(l.songOrder)-1 {
+		// Just do a full shuffle.
+		minPos = 0
+	}
+	if minPos > 0 {
+		copy(tmp[:minPos-1], l.songOrder[:minPos-1])
+	}
+	for oidx, nidx := range rand.Perm(len(l.songOrder) - minPos) {
+		tmp[minPos+nidx] = l.songOrder[minPos+oidx]
+	}
+	l.songOrder = tmp
+}
+
+type playlistSong struct {
+	Song
+	idx int
+}
+
+func (s *playlistSong) ID() int {
+	return s.idx + 1
+}
+
+func (s *playlistSong) Index() int {
+	return s.idx
+}
+
+func (s *playlistSong) GetSong() Song {
+	return s.Song
+}
+
+// A Playlist contains an ordered list of songs, and a cursor.
+type Playlist struct {
+	Version int
+	songs   *orderedSongList
+
+	// Offset of the current song in the ordered list.
+	curPos int
+
+	doRandom bool
+	doRepeat bool
+
+	lock sync.Mutex
+}
+
+func NewPlaylist() *Playlist {
+	return &Playlist{
+		Version: 1,
+		songs:   new(orderedSongList),
+		curPos:  -1,
+	}
+}
+
+// Len returns the number of songs currently in the playlist.
+func (p *Playlist) Len() int {
+	p.lock.Lock()
+	defer p.lock.Unlock()
+	return p.songs.Len()
+}
+
+// Makes sure that no matter what alterations are performed on the
+// song list, the current cursor points at the same song if possible.
+// This isn't fast, but reasonably effective.
+func (p *Playlist) cursorInvariant(f func()) {
+	curSong := p.songs.SongAtPos(p.curPos)
+	f()
+	if curSong != nil {
+		if newpos := p.songs.PositionOf(curSong); newpos >= 0 {
+			p.curPos = newpos
+		} else {
+			p.curPos = -1
+		}
+	}
+}
+
+// Clear the playlist.
+func (p *Playlist) Clear() {
+	p.lock.Lock()
+	defer p.lock.Unlock()
+	p.songs = new(orderedSongList)
+	p.curPos = -1
+	p.Version++
+}
+
+// SetRandom sets the playlist random mode on or off.
+func (p *Playlist) SetRandom(state bool) {
+	if state && p.doRandom != state {
+		p.lock.Lock()
+		defer p.lock.Unlock()
+		p.cursorInvariant(func() {
+			p.songs.Shuffle(0)
+		})
+	}
+	p.doRandom = state
+}
+
+// SetRepeat toggles the playlist repeat mode.
+func (p *Playlist) SetRepeat(state bool) {
+	p.doRepeat = state
+}
+
+// Random returns the current state of the playlist random mode.
+func (p *Playlist) Random() bool { return p.doRandom }
+
+// Repeat returns the current state of the playlist repeat mode.
+func (p *Playlist) Repeat() bool { return p.doRepeat }
+
+// Next advances the cursor to the next song and returns it.
+func (p *Playlist) Next() SongFromPlaylist {
+	p.lock.Lock()
+	defer p.lock.Unlock()
+
+	if p.songs.Empty() {
+		return nil
+	}
+
+	p.curPos++
+	if p.curPos >= p.songs.Len() {
+		if p.doRepeat {
+			if p.doRandom {
+				p.songs.Shuffle(0)
+			}
+			p.curPos = 0
+		} else {
+			log.Printf("Next() reached end of playlist")
+			p.curPos = -1
+			return nil
+		}
+	}
+	return &playlistSong{p.songs.SongAtPos(p.curPos), p.songs.IndexAtPos(p.curPos)}
+}
+
+// PeekNext looks at the next iteration of the cursor, but does not
+// advance it.
+func (p *Playlist) PeekNext() SongFromPlaylist {
+	p.lock.Lock()
+	defer p.lock.Unlock()
+
+	if p.songs.Empty() {
+		return nil
+	}
+
+	pos := p.curPos + 1
+	if pos >= p.songs.Len() {
+		if p.doRepeat {
+			// Uhh, we are actually lying here.
+			pos = 0
+		} else {
+			return nil
+		}
+	}
+	return &playlistSong{p.songs.SongAtPos(pos), p.songs.IndexAtPos(pos)}
+}
+
+// Prev moves the cursor back to the previous song and returns it.
+func (p *Playlist) Prev() SongFromPlaylist {
+	p.lock.Lock()
+	defer p.lock.Unlock()
+
+	if p.songs.Empty() {
+		return nil
+	}
+
+	p.curPos--
+	if p.curPos < 0 {
+		if p.doRepeat {
+			if p.doRandom {
+				p.songs.Shuffle(0)
+			}
+			p.curPos = p.songs.Len() - 1
+		} else {
+			log.Printf("Prev() reached beginning of playlist")
+			// Just in case someone calls Prev multiple times.
+			p.curPos = -1
+			return nil
+		}
+	}
+	return &playlistSong{p.songs.SongAtPos(p.curPos), p.songs.IndexAtPos(p.curPos)}
+}
+
+// SetCursor moves the cursor to point at the specified song, and
+// returns it.
+func (p *Playlist) SetCursor(idx int) SongFromPlaylist {
+	p.lock.Lock()
+	defer p.lock.Unlock()
+
+	song := p.songs.SongAtIndex(idx)
+	p.curPos = p.songs.PositionOf(song)
+	return &playlistSong{song, idx}
+}
+
+// SetCursorID moves the cursor to point at the specified song (using
+// its ID), and returns it.
+func (p *Playlist) SetCursorID(id int) SongFromPlaylist {
+	p.lock.Lock()
+	defer p.lock.Unlock()
+
+	// -1 means stop.
+	if id == -1 {
+		p.curPos = -1
+		return nil
+	}
+
+	idx := p.idToIndex(id)
+	song := p.songs.SongAtIndex(idx)
+	p.curPos = p.songs.PositionOf(song)
+	return &playlistSong{song, idx}
+}
+
+// Add adds a new song to the playlist, returns the song ID.
+func (p *Playlist) Add(s Song, before int) int {
+	p.lock.Lock()
+	defer p.lock.Unlock()
+
+	var idx int
+	p.cursorInvariant(func() {
+		idx = p.songs.Add(s, before)
+		if p.doRandom {
+			p.songs.Shuffle(p.curPos)
+		}
+	})
+	p.Version++
+	return p.indexToID(idx)
+}
+
+// Convert between song index and song ID. Song IDs in reality are
+// just str(index + 1).
+func (p *Playlist) indexToID(idx int) int {
+	return idx + 1
+}
+
+// Convert between song ID and song index.
+func (p *Playlist) idToIndex(id int) int {
+	return id - 1
+}
+
+func (p *Playlist) dumpSongInfoWithID(w io.Writer, song Song, idx int) {
+	io.WriteString(w, song.Info())
+	fmt.Fprintf(w, "Id: %d\nPos: %d\n", p.indexToID(idx), idx)
+}
+
+// Info dumps information about all the songs in the playlist to w.
+func (p *Playlist) Info(w io.Writer) {
+	p.lock.Lock()
+	defer p.lock.Unlock()
+	for idx, song := range p.songs.songs {
+		p.dumpSongInfoWithID(w, song, idx)
+	}
+}
+
+// Info dumps information about the songs in the specified range.
+func (p *Playlist) InfoRange(w io.Writer, r Range) {
+	p.lock.Lock()
+	defer p.lock.Unlock()
+	if p.songs.Len() == 0 {
+		return
+	}
+	r.Bound(len(p.songs.songs))
+	for idx, song := range p.songs.songs[r.Start:r.End] {
+		p.dumpSongInfoWithID(w, song, r.Start+idx)
+	}
+}
+
+// InfoID dumps information about a song to w.
+func (p *Playlist) InfoID(w io.Writer, id int) {
+	p.lock.Lock()
+	defer p.lock.Unlock()
+	idx := p.idToIndex(id)
+	song := p.songs.SongAtIndex(idx)
+	if song != nil {
+		p.dumpSongInfoWithID(w, song, idx)
+	} else {
+		// Return first song, if available.
+		log.Printf("warning: playlistid %d matches no songs", id)
+		// song := p.songs.SongAtIndex(0)
+		// if song != nil {
+		// 	p.dumpSongInfoWithID(w, song, 0)
+		// }
+	}
+}
+
+func findMatch(song Song, tag, needle string) bool {
+	switch tag {
+	case "file":
+		return song.URL() == needle
+	}
+	return false
+}
+
+// Find runs a literal query on the current playlist.
+func (p *Playlist) Find(w io.Writer, tag, needle string) {
+	p.lock.Lock()
+	defer p.lock.Unlock()
+
+	for idx, song := range p.songs.songs {
+		if findMatch(song, tag, needle) {
+			p.dumpSongInfoWithID(w, song, idx)
+		}
+	}
+}
+
+// ChangesPosID prints to w the difference between the specified
+// playlist version and the current one, encoded in the differential
+// format specified by the MPD protocol. At the moment, since playlist
+// history is not supported, this function pretends that the playlist
+// changed completely.
+func (p *Playlist) ChangesPosID(w io.Writer, oldver int) {
+	for idx := range p.songs.songs {
+		fmt.Fprintf(w, "cpos: %d\nId: %d\n", idx, idx+1)
+	}
+}
+
+// Delete a range of songs from the playlist.
+func (p *Playlist) Delete(r Range) {
+	p.lock.Lock()
+	defer p.lock.Unlock()
+
+	p.cursorInvariant(func() {
+		p.songs.Delete(r)
+	})
+	p.Version++
+}
+
+// DeleteID removes a specific song from the playlist.
+func (p *Playlist) DeleteID(id int) {
+	idx := p.idToIndex(id)
+	p.Delete(singleIndexRange(idx))
+}
+
+// Swap the position of two songs.
+func (p *Playlist) Swap(from, to int) {
+	p.lock.Lock()
+	defer p.lock.Unlock()
+	p.cursorInvariant(func() {
+		p.songs.Swap(from, to)
+	})
+	p.Version++
+}
+
+// SwapID changes the position of two songs (the first song is
+// specified with its ID).
+func (p *Playlist) SwapID(id, to int) {
+	from := p.idToIndex(id)
+	if from > 0 {
+		p.Swap(from, to)
+	}
+}
+
+// Move the song at position from to position to.
+func (p *Playlist) Move(from Range, to int) {
+	p.lock.Lock()
+	defer p.lock.Unlock()
+	p.songs.Move(from, to)
+	p.Version++
+}
+
+// Move the specified song to position to.
+func (p *Playlist) MoveID(id, to int) {
+	from := p.idToIndex(id)
+	if from > 0 {
+		p.Move(singleIndexRange(from), to)
+	}
+}
diff --git a/Godeps/_workspace/src/git.autistici.org/ale/gompd/playlist_test.go b/Godeps/_workspace/src/git.autistici.org/ale/gompd/playlist_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..c8782312811a4a204e3ad498eac64ae37c27c7be
--- /dev/null
+++ b/Godeps/_workspace/src/git.autistici.org/ale/gompd/playlist_test.go
@@ -0,0 +1,197 @@
+package mpd
+
+import (
+	"io"
+	"reflect"
+	"strconv"
+	"testing"
+)
+
+func TestRange_ParseRange(t *testing.T) {
+	p, err := ParseRange("0:3")
+	if err != nil {
+		t.Fatalf("[0:3]: %v", err)
+	}
+	if p.Start != 0 || p.End != 4 {
+		t.Fatalf("[0:3]: expected {0, 4} got %v", p)
+	}
+
+	p, err = ParseRange("2")
+	if err != nil {
+		t.Fatalf("[2]: %v", err)
+	}
+	if p.Start != 2 || p.End != 3 {
+		t.Fatalf("[2]: expected {2, 3} got %v", p)
+	}
+}
+
+type testSong struct {
+	id string
+}
+
+func (s testSong) URL() string         { return "url" }
+func (s testSong) Info() string        { return "info" }
+func (s testSong) Channels() int       { return 2 }
+func (s testSong) SampleRate() float64 { return 44100 }
+func (s testSong) Duration() int       { return 100 }
+
+type testReadCloser struct{}
+
+func (r testReadCloser) Read(buf []byte) (int, error) {
+	return 0, io.EOF
+}
+
+func (r testReadCloser) Close() error { return nil }
+
+func (s testSong) Open() (io.ReadCloser, error) {
+	return &testReadCloser{}, nil
+}
+
+func checkList(t *testing.T, sl *orderedSongList, expected []string) {
+	if sl.Len() != len(expected) {
+		t.Fatalf("Len() is %d, expected %d", sl.Len(), len(expected))
+	}
+
+	var got []string
+	for i := 0; i < sl.Len(); i++ {
+		s := sl.SongAtPos(i)
+		got = append(got, s.(*testSong).id)
+	}
+
+	if !reflect.DeepEqual(got, expected) {
+		t.Fatalf("Error in song list: got=%v, expected=%v", got, expected)
+	}
+}
+
+func TestOrderedSongList_IndexPositionCoherence(t *testing.T) {
+	var sl orderedSongList
+	song1 := &testSong{"1"}
+	song2 := &testSong{"2"}
+	sl.Add(song1, 0)
+	sl.Add(song2, 0)
+
+	if sl.Len() != 2 {
+		t.Fatalf("Len() is %d, expected 2", sl.Len())
+	}
+
+	if s := sl.SongAtPos(0); s != song1 {
+		t.Error("SongAtPos(0) is not song1")
+	}
+	if s := sl.SongAtPos(1); s != song2 {
+		t.Error("SongAtPos(1) is not song2")
+	}
+	if sl.SongAtPos(2) != nil {
+		t.Error("SongAtPos(2) is not nil")
+	}
+
+	if s := sl.SongAtIndex(0); s != song1 {
+		t.Error("SongAtIndex(0) is not song1")
+	}
+	if s := sl.SongAtIndex(1); s != song2 {
+		t.Error("SongAtIndex(1) is not song2")
+	}
+	if sl.SongAtIndex(2) != nil {
+		t.Error("SongAtIndex(2) is not nil")
+	}
+
+	if pos := sl.PositionOf(song1); pos != 0 {
+		t.Errorf("PositionOf(song1) is %d, expected 0", pos)
+	}
+	if pos := sl.PositionOf(song2); pos != 1 {
+		t.Errorf("PositionOf(song2) is %d, expected 1", pos)
+	}
+	if pos := sl.PositionOf(&testSong{"3"}); pos != -1 {
+		t.Errorf("PositionOf(new song) is %d, expected -1", pos)
+	}
+
+	// Without a shuffle, order is known.
+	for pos := 0; pos < 2; pos++ {
+		if idx := sl.IndexAtPos(pos); idx != pos {
+			t.Errorf("IndexAtPos(%d) is %d, expected %d", pos, idx, pos)
+		}
+	}
+}
+
+func createOrderedSongList(size int) *orderedSongList {
+	var sl orderedSongList
+	for i := 0; i < size; i++ {
+		sl.Add(&testSong{strconv.Itoa(i + 1)}, 0)
+	}
+	return &sl
+}
+
+func TestOrderedSongList_Delete(t *testing.T) {
+	sl := createOrderedSongList(3)
+	sl.Delete(Range{Start: 1, End: 3})
+	checkList(t, sl, []string{"1"})
+}
+
+func TestOrderedSongList_Move(t *testing.T) {
+	testdata := []struct {
+		from Range
+		to   int
+		exp  []string
+	}{
+		{Range{3, 6}, 1, []string{"1", "4", "5", "6", "2", "3"}},
+		{Range{0, 2}, 3, []string{"3", "4", "5", "1", "2", "6"}},
+		{Range{0, 1}, 5, []string{"2", "3", "4", "5", "6", "1"}},
+		{Range{5, 6}, 0, []string{"6", "1", "2", "3", "4", "5"}},
+	}
+	for _, tt := range testdata {
+		t.Logf("Move(from=%v, to=%v)", tt.from, tt.to)
+		sl := createOrderedSongList(6)
+		sl.Move(tt.from, tt.to)
+		checkList(t, sl, tt.exp)
+	}
+}
+
+func testPlaylist(size int) *Playlist {
+	pl := NewPlaylist()
+	for i := 0; i < size; i++ {
+		pl.Add(&testSong{strconv.Itoa(i + 1)}, 0)
+	}
+	return pl
+}
+
+func TestPlaylist_Delete(t *testing.T) {
+	pl := testPlaylist(3)
+	pl.Delete(Range{Start: 1, End: 3})
+	checkList(t, pl.songs, []string{"1"})
+}
+
+func TestPlaylist_DeleteID(t *testing.T) {
+	pl := testPlaylist(3)
+	pl.DeleteID(3)
+	checkList(t, pl.songs, []string{"1", "2"})
+}
+
+func TestPlaylist_Next(t *testing.T) {
+	pl := testPlaylist(3)
+	for i := 0; i < 3; i++ {
+		song := pl.Next()
+		if song.Index() != i {
+			t.Errorf("Next(@%d) returned song %v", i, song)
+		}
+	}
+	if song := pl.Next(); song != nil {
+		t.Errorf("Next(end) returned non-nil: %v", song)
+	}
+}
+
+func TestPlaylist_Prev(t *testing.T) {
+	pl := testPlaylist(3)
+	if song := pl.Prev(); song != nil {
+		t.Fatalf("Prev(beg) returned non-nil: %v", song)
+	}
+
+	pl.Next()
+	if song := pl.Prev(); song != nil {
+		t.Fatalf("Prev(0) returned non-nil: %v", song)
+	}
+
+	pl.Next()
+	pl.Next()
+	if song := pl.Prev(); song == nil {
+		t.Error("Prev(1) returned nil")
+	}
+}
diff --git a/Godeps/_workspace/src/git.autistici.org/ale/gompd/protocol.go b/Godeps/_workspace/src/git.autistici.org/ale/gompd/protocol.go
new file mode 100644
index 0000000000000000000000000000000000000000..7962b4cec172c5f04e96d91a961834bcc611b48c
--- /dev/null
+++ b/Godeps/_workspace/src/git.autistici.org/ale/gompd/protocol.go
@@ -0,0 +1,366 @@
+package mpd
+
+import (
+	"bufio"
+	"errors"
+	"fmt"
+	"io"
+	"log"
+	"net"
+	"strings"
+	"sync"
+	"unicode"
+)
+
+const helloString = "OK MPD 0.16.0\n"
+
+// States for the connection state machine.
+const (
+	connStateDefault = iota
+	connStateList
+	connStateIdle
+)
+
+// Standard MPD error codes.
+const (
+	MpdNotListErrorCode        = 1
+	MpdArgErrorCode            = 2
+	MpdPasswordErrorCode       = 3
+	MpdPermissionErrorCode     = 4
+	MpdUnknownCommandErrorCode = 5
+	MpdNoExistErrorCode        = 50
+	MpdPlaylistMaxErrorCode    = 51
+	MpdSystemErrorCode         = 52
+	MpdPlaylistLoadErrorCode   = 53
+	MpdUpdateAlreadyErrorCode  = 54
+	MpdPlayerSyncErrorCode     = 55
+	MpdExistErrorCode          = 56
+)
+
+// An MPD error, with command details. Its Error method will return
+// the error formatted according to the MPD protocol (an ACK reply).
+type MpdError struct {
+	Code    int
+	CmdNum  int
+	Cmd     string
+	Message string
+}
+
+func (e *MpdError) Error() string {
+	return fmt.Sprintf("ACK [%d@%d] {%s} %s\n", e.Code, e.CmdNum, e.Cmd, e.Message)
+}
+
+var (
+	// Special internal errors.
+	errNoOutput = errors.New("no output")
+	errClose    = errors.New("close")
+
+	// Common errors.
+	ErrBadArgs           = &MpdError{Code: MpdArgErrorCode, Message: "bad arguments"}
+	ErrNoCommandGiven    = &MpdError{Code: MpdUnknownCommandErrorCode, Message: "No command given"}
+	ErrUnsupportedScheme = &MpdError{Code: MpdNoExistErrorCode, Message: "unsupported URL scheme"}
+)
+
+// Create a new "unknown command" error.
+func unknownCommandError(cmd string) error {
+	return &MpdError{
+		Code:    MpdUnknownCommandErrorCode,
+		Message: fmt.Sprintf("unknown command \"%s\"", cmd),
+	}
+}
+
+// No-op handler.
+func nopCmd(w io.Writer, args []string) error {
+	return nil
+}
+
+// Objects implementing the Handler interface can be registered with a
+// Mux to handle a particular MPD command. The command should do its
+// own argument parsing (returning ErrBadArgs in case of errors), and
+// write its output to the specified io.Writer.
+type Handler interface {
+	ServeMPD(w io.Writer, args []string) error
+}
+
+// CommandFunc turns a function into a Handler.
+type CommandFunc func(w io.Writer, args []string) error
+
+func (f CommandFunc) ServeMPD(w io.Writer, args []string) error {
+	return f(w, args)
+}
+
+// Mux is a multiplexer for MPD commands. Handlers can be registered
+// to deal with specific commands.
+type Mux struct {
+	commands map[string]Handler
+}
+
+func NewMux() *Mux {
+	return &Mux{
+		commands: make(map[string]Handler),
+	}
+}
+
+// Handle installs a new command handler.
+func (m *Mux) Handle(name string, c Handler) {
+	m.commands[name] = c
+}
+
+// HandleFunc installs a new command handler (saving a cast to CommandFunc).
+func (m *Mux) HandleFunc(name string, f func(io.Writer, []string) error) {
+	m.Handle(name, CommandFunc(f))
+}
+
+func (m *Mux) ServeMPD(w io.Writer, args []string) error {
+	if len(args) < 1 {
+		return ErrNoCommandGiven
+	}
+	cmd := args[0]
+	args = args[1:]
+	h, ok := m.commands[cmd]
+	if !ok {
+		log.Printf("unknown command: %s %v", cmd, args)
+		return unknownCommandError(cmd)
+	}
+
+	log.Printf("command: %s %v", cmd, args)
+	return h.ServeMPD(w, args)
+}
+
+// A server that speaks the MPD protocol.
+type Server struct {
+	*Mux
+
+	subscribers []net.Conn
+	subLock     sync.Mutex
+	notifyCh    chan string
+}
+
+func NewServer() *Server {
+	s := &Server{
+		Mux:      NewMux(),
+		notifyCh: make(chan string, 50),
+	}
+
+	// Set up some fundamental commands.
+	s.HandleFunc("ping", nopCmd)
+	s.HandleFunc("close", func(w io.Writer, args []string) error {
+		return errClose
+	})
+	s.HandleFunc("commands", func(w io.Writer, args []string) error {
+		// 'command_list_begin' and related commands should
+		// not appear in this list as they are not really
+		// commands.
+		for cmd := range s.commands {
+			fmt.Fprintf(w, "command: %s\n", cmd)
+		}
+		// 'idle' and 'noidle' are treated as proper commands.
+		io.WriteString(w, "command: idle\n")
+		io.WriteString(w, "command: noidle\n")
+		return nil
+	})
+	s.HandleFunc("notcommands", nopCmd)
+
+	return s
+}
+
+// Handles a new connection, receiving commands and handling them. The
+// MPD protocol is a relatively simple line-based text protocol, with
+// a couple of interesting features (idle polling and command lists)
+// which are handled transparently by this function.
+func (s *Server) handleConnection(c net.Conn) {
+	defer s.removeSubscriber(c)
+	defer c.Close()
+
+	// Send our greeting.
+	log.Printf("connection from %v", c.RemoteAddr())
+	io.WriteString(c, helloString)
+
+	state := connStateDefault
+	var commandList []string
+	listDumpStatus := false
+
+	scanner := bufio.NewScanner(c)
+	for scanner.Scan() {
+		line := scanner.Text()
+		err := errNoOutput
+
+		// Handle the possible connection states using a
+		// simple state machine. No output will be sent to the
+		// client unless 'err' is set.
+		switch {
+		case state == connStateIdle && line == "noidle":
+			state = connStateDefault
+			s.removeSubscriber(c)
+			// Send 'OK' to the client.
+			err = nil
+		case state == connStateDefault && (line == "idle" || strings.HasPrefix(line, "idle ")):
+			// Ignore the actual arguments to the "idle" command.
+			state = connStateIdle
+			s.registerSubscriber(c)
+		case state == connStateDefault && line == "command_list_begin":
+			state = connStateList
+			commandList = nil
+			listDumpStatus = false
+		case state == connStateDefault && line == "command_list_ok_begin":
+			state = connStateList
+			commandList = nil
+			listDumpStatus = true
+		case state == connStateList && line == "command_list_end":
+			state = connStateDefault
+			err = s.execCommandList(c, commandList, listDumpStatus)
+		case state == connStateList:
+			commandList = append(commandList, line)
+		case state == connStateDefault:
+			err = s.execCommandList(c, []string{line}, false)
+		}
+
+		if err == errNoOutput {
+			continue
+		}
+		if err == errClose {
+			break
+		}
+
+		// Detect errors sending data back to the client,
+		// which should cause us to close the connection.
+		var oerr error
+		if err != nil {
+			if merr, ok := err.(*MpdError); ok {
+				_, oerr = io.WriteString(c, merr.Error())
+			} else {
+				merr = &MpdError{Message: err.Error()}
+				_, oerr = io.WriteString(c, merr.Error())
+				log.Printf("Internal error: %v", err)
+			}
+		} else {
+			_, oerr = io.WriteString(c, "OK\n")
+		}
+		if oerr != nil {
+			log.Printf("write error: %v: %s", c.RemoteAddr(), oerr)
+			break
+		}
+	}
+
+	if err := scanner.Err(); err != nil {
+		log.Printf("read error: %v: %s", c.RemoteAddr(), err)
+	}
+}
+
+// Execute all commands in a command list (which may consist of a
+// single command).
+func (s *Server) execCommandList(w io.Writer, commands []string, dumpStatus bool) error {
+	for i, cmd := range commands {
+		args := splitArgs(cmd)
+		if err := s.ServeMPD(w, args); err != nil {
+			return errorForCommand(err, i, args[0])
+		}
+		if dumpStatus {
+			io.WriteString(w, "list_OK\n")
+		}
+	}
+	return nil
+}
+
+func (s *Server) removeSubscriber(c net.Conn) {
+	s.subLock.Lock()
+	defer s.subLock.Unlock()
+	if len(s.subscribers) == 0 {
+		return
+	}
+	out := make([]net.Conn, 0, len(s.subscribers)-1)
+	for _, sc := range s.subscribers {
+		if c != sc {
+			out = append(out, sc)
+		}
+	}
+	s.subscribers = out
+}
+
+func (s *Server) registerSubscriber(c net.Conn) {
+	s.subLock.Lock()
+	defer s.subLock.Unlock()
+	s.subscribers = append(s.subscribers, c)
+}
+
+func (s *Server) pubsubLoop() {
+	// Trivial loop, let's hope we don't have slow clients.
+	for tag := range s.notifyCh {
+		tag = fmt.Sprintf("changed: %s\n", tag)
+		s.subLock.Lock()
+		for _, c := range s.subscribers {
+			io.WriteString(c, tag)
+		}
+		s.subLock.Unlock()
+	}
+}
+
+// Trigger sends a notification about 'tag' to all available
+// subscribers (clients in idle mode).
+func (s *Server) Trigger(tag string) {
+	select {
+	case s.notifyCh <- tag:
+	default:
+	}
+}
+
+// ListenAndServe starts the MPD server on the specified TCP address
+// and runs our Mux to handle incoming commands.
+func (s *Server) ListenAndServe(addr string) error {
+	ln, err := net.Listen("tcp", addr)
+	if err != nil {
+		return err
+	}
+	go s.pubsubLoop()
+	for {
+		c, err := ln.Accept()
+		if err != nil {
+			return err
+		}
+		go s.handleConnection(c)
+	}
+}
+
+// Split a command into space-separated fields (allowing quoting for
+// fields containing spaces).
+func splitArgs(s string) []string {
+	var lastQuote rune
+	f := func(c rune) bool {
+		switch {
+		case c == lastQuote:
+			lastQuote = rune(0)
+			return false
+		case lastQuote != rune(0):
+			return false
+		case c == '"':
+			lastQuote = c
+			return false
+		default:
+			return unicode.IsSpace(c)
+		}
+	}
+	var out []string
+	for _, field := range strings.FieldsFunc(s, f) {
+		out = append(out, strings.Trim(field, "\""))
+	}
+	return out
+}
+
+// Augment error information with command-specific data (but leave our
+// special state-handling errors untouched).
+func errorForCommand(err error, cmdNum int, cmd string) error {
+	if err == errClose || err == errNoOutput {
+		return err
+	}
+	if err, ok := err.(*MpdError); ok {
+		err.CmdNum = cmdNum
+		err.Cmd = cmd
+		return err
+	}
+	return &MpdError{
+		Code:    MpdSystemErrorCode,
+		CmdNum:  cmdNum,
+		Cmd:     cmd,
+		Message: err.Error(),
+	}
+}
diff --git a/Godeps/_workspace/src/git.autistici.org/ale/gompd/spill.go b/Godeps/_workspace/src/git.autistici.org/ale/gompd/spill.go
new file mode 100644
index 0000000000000000000000000000000000000000..d2565c2c76bdd3da9edef6edc8e991fa0b007118
--- /dev/null
+++ b/Godeps/_workspace/src/git.autistici.org/ale/gompd/spill.go
@@ -0,0 +1,78 @@
+package mpd
+
+import (
+	"io"
+	"io/ioutil"
+	"log"
+	"os"
+	"sync"
+)
+
+func newDiskBackedReader(src io.ReadCloser) (*diskBackedReader, error) {
+	tmpf, err := ioutil.TempFile("", "djmpd_data_")
+	if err != nil {
+		return nil, err
+	}
+	os.Remove(tmpf.Name())
+	c := &diskBackedReader{
+		f:   tmpf,
+		c:   make(chan bool, 1),
+		src: src,
+	}
+	go c.sourceloop()
+	return c, nil
+}
+
+type diskBackedReader struct {
+	f          *os.File
+	c          chan bool
+	wpos, rpos int64
+	finalized  bool
+	src        io.ReadCloser
+	lock       sync.Mutex
+}
+
+func (r *diskBackedReader) Close() error {
+	r.f.Close()
+	return r.src.Close()
+}
+
+func (r *diskBackedReader) sourceloop() {
+	buf := make([]byte, 16384)
+	for {
+		n, err := r.src.Read(buf)
+		r.lock.Lock()
+		if err != nil || n == 0 {
+			r.finalized = true
+			if err != nil {
+				log.Printf("read error: %v", err)
+			}
+			break
+		}
+
+		r.f.Seek(r.wpos, 0)
+		r.f.Write(buf[:n])
+		r.wpos += int64(n)
+		r.lock.Unlock()
+		select {
+		case r.c <- true:
+		default:
+		}
+	}
+
+}
+
+func (r *diskBackedReader) Read(buf []byte) (int, error) {
+	// Wait until there is something to read.
+	r.lock.Lock()
+	for !r.finalized && r.rpos+int64(len(buf)) > r.wpos {
+		r.lock.Unlock()
+		<-r.c
+		r.lock.Lock()
+	}
+	r.f.Seek(r.rpos, 0)
+	n, err := r.f.Read(buf)
+	r.rpos += int64(n)
+	r.lock.Unlock()
+	return n, err
+}
diff --git a/Godeps/_workspace/src/git.autistici.org/ale/imms/imms-go/imms.go b/Godeps/_workspace/src/git.autistici.org/ale/imms/imms-go/imms.go
new file mode 100644
index 0000000000000000000000000000000000000000..bd2841c02d19f9d23e987ff26cb0ed5188b84cf0
--- /dev/null
+++ b/Godeps/_workspace/src/git.autistici.org/ale/imms/imms-go/imms.go
@@ -0,0 +1,66 @@
+package imms
+
+// #cgo CFLAGS: -I/usr/local/include
+// #cgo LDFLAGS: -L/usr/local/lib -limms-c
+// #include <imms-c.h>
+import "C"
+import "unsafe"
+
+type StreamAnalyzer struct {
+	ptr C.imms_analyzer_t
+}
+
+func NewStreamAnalyzer() *StreamAnalyzer {
+	return &StreamAnalyzer{C.imms_stream_analyzer_new()}
+}
+
+func (s *StreamAnalyzer) Process(data []byte) {
+	dataPtr := (*C.char)(unsafe.Pointer(&data[0]))
+	C.imms_stream_analyzer_process(s.ptr, dataPtr, C.int(len(data)))
+}
+
+func (s *StreamAnalyzer) GetResult() *Features {
+	return &Features{C.imms_stream_analyzer_get_result(s.ptr)}
+}
+
+func (s *StreamAnalyzer) Close() {
+	C.imms_stream_analyzer_free(s.ptr)
+}
+
+type Features struct {
+	ptr C.imms_features_t
+}
+
+func NewFeaturesFromData(data []byte) *Features {
+	bufPtr := (*C.char)(unsafe.Pointer(&data[0]))
+	return &Features{C.imms_features_from_data(bufPtr, C.int(len(data)))}
+}
+
+func (f *Features) Data() []byte {
+	n := C.imms_features_data_size()
+	buf := make([]byte, n)
+	bufPtr := (*C.char)(unsafe.Pointer(&buf[0]))
+	C.imms_features_data(f.ptr, bufPtr, n)
+	return buf
+}
+
+func (f *Features) Close() {
+	C.imms_features_free(f.ptr)
+}
+
+type SimilarityModel struct {
+	ptr C.imms_similarity_model_t
+}
+
+func NewSimilarityModel() *SimilarityModel {
+	return &SimilarityModel{C.imms_similarity_model_new()}
+}
+
+func (m *SimilarityModel) Eval(a, b *Features) float32 {
+	score := C.imms_similarity_model_evaluate(m.ptr, a.ptr, b.ptr)
+	return float32(score)
+}
+
+func (m *SimilarityModel) Close() {
+	C.imms_similarity_model_free(m.ptr)
+}
diff --git a/Godeps/_workspace/src/git.autistici.org/ale/rrpc/README b/Godeps/_workspace/src/git.autistici.org/ale/rrpc/README
new file mode 100644
index 0000000000000000000000000000000000000000..b7e777088831e4ad17dfeba09fa690008bfbaeef
--- /dev/null
+++ b/Godeps/_workspace/src/git.autistici.org/ale/rrpc/README
@@ -0,0 +1,10 @@
+
+rrpc - some useful additions to the net/rpc package
+
+
+What we're trying to provide:
+
+* reconnections in case of network errors
+* retries with exponential backoff
+* connection timeouts
+
diff --git a/Godeps/_workspace/src/git.autistici.org/ale/rrpc/backoff.go b/Godeps/_workspace/src/git.autistici.org/ale/rrpc/backoff.go
new file mode 100644
index 0000000000000000000000000000000000000000..29b84281dbb27a4d3266e83210b88a3a981836ef
--- /dev/null
+++ b/Godeps/_workspace/src/git.autistici.org/ale/rrpc/backoff.go
@@ -0,0 +1,100 @@
+package rrpc
+
+import (
+	"math/rand"
+	"time"
+)
+
+// Inspired by github.com/cenkalti/backoff.
+type backoff struct {
+	InitialInterval     time.Duration
+	MaxInterval         time.Duration
+	RandomizationFactor float64
+	Multiplier          float64
+
+	currentInterval time.Duration
+}
+
+const (
+	defaultInitialInterval     = 100 * time.Millisecond
+	defaultRandomizationFactor = 0.3
+	defaultMultiplier          = 1.4
+	defaultMaxInterval         = 60 * time.Second
+)
+
+func newBackoff() *backoff {
+	return &backoff{
+		InitialInterval:     defaultInitialInterval,
+		RandomizationFactor: defaultRandomizationFactor,
+		Multiplier:          defaultMultiplier,
+		MaxInterval:         defaultMaxInterval,
+		currentInterval:     defaultInitialInterval,
+	}
+}
+
+func (b *backoff) nextBackoff() time.Duration {
+	defer b.incrementCurrentInterval()
+	return getRandomValueFromInterval(b.RandomizationFactor, rand.Float64(), b.currentInterval)
+}
+
+func (b *backoff) incrementCurrentInterval() {
+	if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier {
+		b.currentInterval = b.MaxInterval
+	} else {
+		b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier)
+	}
+}
+
+// Returns a random value from the interval:
+// 	[randomizationFactor * currentInterval, randomizationFactor * currentInterval].
+func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration {
+	var delta = randomizationFactor * float64(currentInterval)
+	var minInterval = float64(currentInterval) - delta
+	var maxInterval = float64(currentInterval) + delta
+	// Get a random value from the range [minInterval, maxInterval].
+	// The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then
+	// we want a 33% chance for selecting either 1, 2 or 3.
+	return time.Duration(minInterval + (random * (maxInterval - minInterval + 1)))
+}
+
+type backoffTicker struct {
+	C    chan time.Time
+	b    *backoff
+	stop chan bool
+}
+
+func newBackoffTicker(b *backoff) *backoffTicker {
+	t := &backoffTicker{
+		C:    make(chan time.Time),
+		stop: make(chan bool),
+		b:    b,
+	}
+	go t.run()
+	return t
+}
+
+func (t *backoffTicker) Stop() {
+	close(t.stop)
+}
+
+func (t *backoffTicker) run() {
+	defer close(t.C)
+	var c <-chan time.Time
+	for {
+		delay := t.b.nextBackoff()
+		c = time.After(delay)
+		select {
+		case tick := <-c:
+			sendTick(tick, t.C)
+		case <-t.stop:
+			return
+		}
+	}
+}
+
+func sendTick(tick time.Time, c chan time.Time) {
+	select {
+	case c <- tick:
+	default:
+	}
+}
diff --git a/Godeps/_workspace/src/git.autistici.org/ale/rrpc/codec/snappy.go b/Godeps/_workspace/src/git.autistici.org/ale/rrpc/codec/snappy.go
new file mode 100644
index 0000000000000000000000000000000000000000..d04ef6af5ef9a0fc19bfea38f5160adb5dea03b6
--- /dev/null
+++ b/Godeps/_workspace/src/git.autistici.org/ale/rrpc/codec/snappy.go
@@ -0,0 +1,33 @@
+package codec
+
+import (
+	"bufio"
+	"io"
+
+	"code.google.com/p/snappy-go/snappy"
+)
+
+type snappyBufferedWriter struct {
+	w io.Writer
+}
+
+func (sw *snappyBufferedWriter) Write(b []byte) (int, error) {
+	log.Printf("snappyBuf: write(%d)", len(b))
+
+	zdata, err := snappy.Encode(nil, b)
+	if err != nil {
+		return 0, err
+	}
+
+	return sw.w.Write(zdata)
+}
+
+type snappyBufferedReader struct {
+	r io.Reader
+}
+
+func (sr *snappyBufferedReader) Read(b []byte) (int, error) {
+	log.Printf("snappyBuf: read(%d)", len(b))
+
+
+}
diff --git a/Godeps/_workspace/src/git.autistici.org/ale/rrpc/resolver.go b/Godeps/_workspace/src/git.autistici.org/ale/rrpc/resolver.go
new file mode 100644
index 0000000000000000000000000000000000000000..bc112086ab76b152d7cd03b63099fe6dbd8ca4f7
--- /dev/null
+++ b/Godeps/_workspace/src/git.autistici.org/ale/rrpc/resolver.go
@@ -0,0 +1,119 @@
+package rrpc
+
+import (
+	"errors"
+	"math/rand"
+	"net"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+)
+
+// A Resolver finds one multiple endpoints for a service, given an
+// address string. The address string take the form of a path, where
+// the prefix specifies which method to use for name resolution.
+//
+// A few resolvers are provided by default for simple DNS-based name
+// resolution.
+//
+type Resolver interface {
+	Resolve(addr string) ([]string, error)
+}
+
+// A Policy selects one specific address out of all the possible ones
+// returned by a Resolver.
+type Policy interface {
+	Select(addrs []string) string
+}
+
+// RandomPolicy picks a random address among those available.
+type RandomPolicy struct{}
+
+func (rr *RandomPolicy) Select(addrs []string) string {
+	return addrs[rand.Intn(len(addrs))]
+}
+
+// Plan A/AAAA DNS resolver.
+type DnsResolver struct{}
+
+func (r *DnsResolver) Resolve(addr string) ([]string, error) {
+	host, port, err := net.SplitHostPort(addr)
+	if err != nil {
+		return nil, err
+	}
+
+	addrs, err := net.LookupIP(host)
+	if err != nil {
+		return nil, err
+	}
+	out := make([]string, 0, len(addrs))
+	for _, ip := range addrs {
+		out = append(out, net.JoinHostPort(ip.String(), port))
+	}
+	return out, nil
+}
+
+// SRV-based DNS resolution, retrieving port information as well.
+// It expects addresses in the "NAME/SERVICE" format, which translates
+// to an SRV query for "_SERVICE._tcp.NAME".
+type DnsSrvResolver struct{}
+
+func (r DnsSrvResolver) Resolve(addr string) ([]string, error) {
+	parts := strings.Split(addr, "/")
+	if len(parts) != 2 {
+		return nil, errors.New("bad address format")
+	}
+
+	_, results, err := net.LookupSRV(parts[1], "tcp", parts[0])
+	if err != nil {
+		return nil, err
+	}
+
+	resolved := make([]string, 0, len(results))
+	for _, result := range results {
+		resolved = append(resolved, net.JoinHostPort(result.Target, strconv.Itoa(int(result.Port))))
+	}
+	return resolved, nil
+}
+
+type cacheEntry struct {
+	addrs []string
+	err   error
+	stamp time.Time
+}
+
+// A caching resolver that wraps an upstream Resolver. Note that the
+// cache locking serializes all name resolution, so you shouldn't use
+// this object if you expect to independently resolve a large number
+// of different addresses.
+type SimpleCachingResolver struct {
+	TTL time.Duration
+
+	parent Resolver
+	cache  map[string]cacheEntry
+	lock   sync.Mutex
+}
+
+func NewSimpleCachingResolver(r Resolver) *SimpleCachingResolver {
+	return &SimpleCachingResolver{
+		TTL:    60 * time.Second,
+		parent: r,
+		cache:  make(map[string]cacheEntry),
+	}
+}
+
+func (r *SimpleCachingResolver) Resolve(addr string) ([]string, error) {
+	r.lock.Lock()
+	defer r.lock.Unlock()
+
+	now := time.Now()
+	entry, ok := r.cache[addr]
+	if !ok || now.Sub(entry.stamp) > r.TTL {
+		addrs, err := r.parent.Resolve(addr)
+		entry = cacheEntry{addrs, err, now}
+		r.cache[addr] = entry
+	}
+
+	return entry.addrs, entry.err
+}
diff --git a/Godeps/_workspace/src/git.autistici.org/ale/rrpc/rrpc.go b/Godeps/_workspace/src/git.autistici.org/ale/rrpc/rrpc.go
new file mode 100644
index 0000000000000000000000000000000000000000..7f92e25033cbcc494e3386cc8a063c08edbc496d
--- /dev/null
+++ b/Godeps/_workspace/src/git.autistici.org/ale/rrpc/rrpc.go
@@ -0,0 +1,235 @@
+package rrpc
+
+import (
+	"bufio"
+	"errors"
+	"io"
+	"log"
+	"net"
+	"net/http"
+	"net/rpc"
+	"strings"
+	"sync"
+	"time"
+)
+
+var (
+	ErrDeadline    = errors.New("deadline exceeded")
+	ErrNoAddresses = errors.New("no addresses could be resolved")
+)
+
+type Options struct {
+	// Connection timeout.
+	ConnectTimeout time.Duration
+
+	// Maximum time the whole call can take (including retries).
+	Deadline time.Duration
+
+	// Maximum number of retries (or -1 for unlimited).
+	MaxRetries int
+
+	// Support application-specific retriable errors. This
+	// function will be called whenever the remote rpc.Call
+	// returns an error, if it returns true the error is
+	// considered temporary and the call will be retried.
+	IsRetriableError func(error) bool
+}
+
+func (o Options) merge(other *Options) Options {
+	if other.ConnectTimeout > 0 {
+		o.ConnectTimeout = other.ConnectTimeout
+	}
+	if other.Deadline > 0 {
+		o.Deadline = other.Deadline
+	}
+	if other.MaxRetries > 0 {
+		o.MaxRetries = other.MaxRetries
+	}
+	if other.IsRetriableError != nil {
+		o.IsRetriableError = other.IsRetriableError
+	}
+	return o
+}
+
+var defaultOptions = Options{
+	ConnectTimeout: 5 * time.Second,
+	Deadline:       900 * time.Second,
+	MaxRetries:     -1,
+}
+
+// Client represents a specific abstract endpoint.
+type Client struct {
+	Addrs    []string
+	Resolver Resolver
+	Policy   Policy
+
+	DefaultOptions Options
+
+	rpcClient *rpc.Client
+	lock      sync.Mutex
+}
+
+// New returns a client with default options.
+func New(addr string, options *Options) *Client {
+	c := Client{
+		Addrs:          strings.Split(addr, ","),
+		Resolver:       NewSimpleCachingResolver(&DnsResolver{}),
+		Policy:         &RandomPolicy{},
+		DefaultOptions: defaultOptions,
+	}
+	if options != nil {
+		c.DefaultOptions = c.DefaultOptions.merge(options)
+	}
+	return &c
+}
+
+func (c *Client) dial(oldClient *rpc.Client, timeout time.Duration) (*rpc.Client, error) {
+	c.lock.Lock()
+	defer c.lock.Unlock()
+
+	// Optimize the case where multiple clients get an error and
+	// try to reconnect: only the first one wins, so we avoid a
+	// connection storm.
+	if c.rpcClient != nil && c.rpcClient != oldClient {
+		return c.rpcClient, nil
+	}
+
+	if c.rpcClient != nil {
+		go c.rpcClient.Close()
+	}
+
+	addr, err := c.pickAddress()
+	if err != nil {
+		return nil, err
+	}
+
+	client, err := dialHTTPTimeout("tcp", addr, timeout)
+	if err == nil {
+		c.rpcClient = client
+		log.Printf("rpc: connected to %s", addr)
+	}
+	return client, err
+}
+
+func (c *Client) pickAddress() (string, error) {
+	var candidates []string
+	for _, addr := range c.Addrs {
+		if addrs, err := c.Resolver.Resolve(addr); err == nil {
+			candidates = append(candidates, addrs...)
+		}
+	}
+	if len(candidates) == 0 {
+		return "", ErrNoAddresses
+	}
+	return c.Policy.Select(candidates), nil
+}
+
+func withDeadline(f func() error, deadline time.Duration) error {
+	resultCh := make(chan error, 1)
+	go func() {
+		resultCh <- f()
+	}()
+
+	deadlineCh := time.After(deadline)
+	var err error
+	select {
+	case err = <-resultCh:
+	case <-deadlineCh:
+		err = ErrDeadline
+	}
+	return err
+}
+
+// Retry 'f' with exponential backoff until 'deadline' expires, or until 'quit' is triggered.
+func retry(f func() error, shouldRetry func(error) bool, deadline time.Duration, maxRetries int, quit chan bool) error {
+	nconn := 0
+	b := newBackoff()
+	ticker := newBackoffTicker(b)
+	defer ticker.Stop()
+
+	var err error
+
+	for {
+		err = f()
+		if err == nil || !shouldRetry(err) {
+			break
+		}
+
+		// Reconnect.
+		nconn++
+		if maxRetries > 0 && nconn >= maxRetries {
+			break
+		}
+		select {
+		case <-ticker.C:
+		case <-quit:
+			return nil
+		}
+	}
+
+	return err
+}
+
+// Call invokes the named function, waits for it to complete, and returns
+// its error status.
+func (c *Client) Call(method string, req, resp interface{}, options *Options) error {
+	o := c.DefaultOptions
+	if options != nil {
+		o = o.merge(options)
+	}
+
+	quit := make(chan bool)
+	defer close(quit)
+
+	var client *rpc.Client
+
+	return withDeadline(func() error {
+		return retry(func() error {
+			var err error
+			client, err = c.dial(client, o.ConnectTimeout)
+			if err != nil {
+				return err
+			}
+			return client.Call(method, req, resp)
+		}, func(err error) bool {
+			result := isRpcTransportError(err) || (o.IsRetriableError != nil && o.IsRetriableError(err))
+			// log.Printf("is error retriable? %v -> %v", err, result)
+			return result
+		}, o.Deadline, o.MaxRetries, quit)
+	}, o.Deadline)
+}
+
+func (c *Client) Close() {
+}
+
+// Create a RPC client from an HTTP connection, with a timeout.
+// Basically just a clone of rpc.DialHTTP with added timeouts.  We
+// wouldn't really need this but it helps clients if unreachable hosts
+// are detected quickly.
+func dialHTTPTimeout(network, address string, timeout time.Duration) (*rpc.Client, error) {
+	var err error
+	conn, err := net.DialTimeout(network, address, timeout)
+	if err != nil {
+		return nil, err
+	}
+	io.WriteString(conn, "CONNECT "+rpc.DefaultRPCPath+" HTTP/1.0\n\n")
+
+	resp, err := http.ReadResponse(bufio.NewReader(conn), &http.Request{Method: "CONNECT"})
+	if err == nil && resp.StatusCode == 200 {
+		return rpc.NewClient(conn), nil
+	}
+	if err == nil {
+		err = errors.New("unexpected HTTP response: " + resp.Status)
+	}
+	conn.Close()
+	return nil, &net.OpError{
+		Op:   "dial-http",
+		Net:  network + " " + address,
+		Addr: nil,
+		Err:  err,
+	}
+}
+
+func isRpcTransportError(err error) bool {
+	return (err == io.EOF || err == io.ErrUnexpectedEOF || err == rpc.ErrShutdown)
+}
diff --git a/Godeps/_workspace/src/git.autistici.org/ale/rrpc/rrpc_test.go b/Godeps/_workspace/src/git.autistici.org/ale/rrpc/rrpc_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..c5f082d470e6ef71a177a6a226fd0e76aea02f22
--- /dev/null
+++ b/Godeps/_workspace/src/git.autistici.org/ale/rrpc/rrpc_test.go
@@ -0,0 +1,129 @@
+package rrpc
+
+import (
+	"errors"
+	"fmt"
+	"net/http"
+	"net/rpc"
+	"testing"
+	"time"
+)
+
+type TestRequest struct {
+	A, B int
+}
+
+type TestResponse struct {
+	Sum int
+}
+
+type goodServer struct{}
+
+func (s *goodServer) Add(req *TestRequest, resp *TestResponse) error {
+	resp.Sum = req.A + req.B
+	return nil
+}
+
+var errTestError = errors.New("remote test error")
+
+type badServer struct{}
+
+func (b *badServer) Add(req *TestRequest, resp *TestResponse) error {
+	return errTestError
+}
+
+var testPort = 23456
+
+type testServer struct {
+	addr string
+}
+
+func newTestServer() *testServer {
+	addr := fmt.Sprintf("127.0.0.1:%d", testPort)
+	testPort++
+	return &testServer{addr: addr}
+}
+
+func (f *testServer) Serve(obj interface{}) {
+	s := rpc.NewServer()
+	s.RegisterName("Test", obj)
+
+	mux := http.NewServeMux()
+	mux.Handle("/", s)
+
+	hs := &http.Server{
+		Addr:    f.addr,
+		Handler: mux,
+	}
+	go hs.ListenAndServe()
+}
+
+func TestRpc_SingleCall(t *testing.T) {
+	srv := newTestServer()
+	srv.Serve(&goodServer{})
+
+	c := New(srv.addr, nil)
+	req := TestRequest{1, 2}
+	var resp TestResponse
+	err := c.Call("Test.Add", &req, &resp, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestRpc_Fallback(t *testing.T) {
+	srv := newTestServer()
+	srv.Serve(&goodServer{})
+
+	// Inject a bad server before the good one. Run a bunch of
+	// times to sort out randomness and try to ensure that the bad
+	// server is chosen at least once by pickAddress().
+	c := New("127.0.1.2:23,"+srv.addr, nil)
+	req := TestRequest{1, 2}
+	for i := 0; i < 10; i++ {
+		var resp TestResponse
+		err := c.Call("Test.Add", &req, &resp, nil)
+		if err != nil {
+			t.Fatal(err)
+		}
+	}
+}
+
+func TestRpc_BadServer(t *testing.T) {
+	srv := newTestServer()
+	srv.Serve(&badServer{})
+
+	c := New(srv.addr, nil)
+	req := TestRequest{1, 2}
+	var resp TestResponse
+	err := c.Call("Test.Add", &req, &resp, nil)
+	if err == nil {
+		t.Fatal("no error from badServer.Add")
+	}
+}
+
+func TestRpc_RetriableErrorAndDeadline(t *testing.T) {
+	srv := newTestServer()
+	srv.Serve(&badServer{})
+
+	// IsRetriableError will treat the (known) remote error as a
+	// temporary one, so the call should ultimately timeout.
+	c := New(srv.addr, &Options{
+		Deadline: 600 * time.Millisecond,
+		IsRetriableError: func(err error) bool {
+			if _, ok := err.(rpc.ServerError); ok {
+				// We need to compare strings, the
+				// original error message is not
+				// preserved.
+				return err.Error() == errTestError.Error()
+			}
+			return false
+		},
+	})
+	req := TestRequest{1, 2}
+	var resp TestResponse
+	err := c.Call("Test.Add", &req, &resp, nil)
+	if err != ErrDeadline {
+		t.Fatalf("bad error: %v", err)
+	}
+}
diff --git a/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd/doc.go b/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd/doc.go
new file mode 100644
index 0000000000000000000000000000000000000000..722e98046f3bf07bb0bd37e8b4b71977840e10d3
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd/doc.go
@@ -0,0 +1,25 @@
+/*
+Package statsd provides a StatsD client implementation that is safe for
+concurrent use by multiple goroutines and for efficiency can be created and
+reused.
+
+Example usage:
+
+	// first create a client
+	client, err := statsd.New("127.0.0.1:8125", "test-client")
+	// handle any errors
+	if err != nil {
+		log.Fatal(err)
+	}
+	// make sure to clean up
+	defer client.Close()
+
+	// Send a stat
+	err = client.Inc("stat1", 42, 1.0)
+	// handle any errors
+	if err != nil {
+		log.Printf("Error sending metric: %+v", err)
+	}
+
+*/
+package statsd
diff --git a/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd/main.go b/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd/main.go
new file mode 100644
index 0000000000000000000000000000000000000000..8ab09e2787dfe7cdee90833de5356be2dd6e49f2
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd/main.go
@@ -0,0 +1,159 @@
+package statsd
+
+import (
+	"errors"
+	"fmt"
+	"math/rand"
+	"net"
+)
+
+type Statter interface {
+	Inc(stat string, value int64, rate float32) error
+	Dec(stat string, value int64, rate float32) error
+	Gauge(stat string, value int64, rate float32) error
+	GaugeDelta(stat string, value int64, rate float32) error
+	Timing(stat string, delta int64, rate float32) error
+	Raw(stat string, value string, rate float32) error
+	SetPrefix(prefix string)
+	Close() error
+}
+
+type Client struct {
+	// underlying connection
+	c net.PacketConn
+	// resolved udp address
+	ra *net.UDPAddr
+	// prefix for statsd name
+	prefix string
+}
+
+// Close closes the connection and cleans up.
+func (s *Client) Close() error {
+	if s == nil {
+		return nil
+	}
+	err := s.c.Close()
+	return err
+}
+
+// Increments a statsd count type.
+// stat is a string name for the metric.
+// value is the integer value
+// rate is the sample rate (0.0 to 1.0)
+func (s *Client) Inc(stat string, value int64, rate float32) error {
+	dap := fmt.Sprintf("%d|c", value)
+	return s.Raw(stat, dap, rate)
+}
+
+// Decrements a statsd count type.
+// stat is a string name for the metric.
+// value is the integer value.
+// rate is the sample rate (0.0 to 1.0).
+func (s *Client) Dec(stat string, value int64, rate float32) error {
+	return s.Inc(stat, -value, rate)
+}
+
+// Submits/Updates a statsd gauge type.
+// stat is a string name for the metric.
+// value is the integer value.
+// rate is the sample rate (0.0 to 1.0).
+func (s *Client) Gauge(stat string, value int64, rate float32) error {
+	dap := fmt.Sprintf("%d|g", value)
+	return s.Raw(stat, dap, rate)
+}
+
+// Submits a delta to a statsd gauge.
+// stat is the string name for the metric.
+// value is the (positive or negative) change.
+// rate is the sample rate (0.0 to 1.0).
+func (s *Client) GaugeDelta(stat string, value int64, rate float32) error {
+	dap := fmt.Sprintf("%+d|g", value)
+	return s.Raw(stat, dap, rate)
+}
+
+// Submits a statsd timing type.
+// stat is a string name for the metric.
+// value is the integer value.
+// rate is the sample rate (0.0 to 1.0).
+func (s *Client) Timing(stat string, delta int64, rate float32) error {
+	dap := fmt.Sprintf("%d|ms", delta)
+	return s.Raw(stat, dap, rate)
+}
+
+// Raw formats the statsd event data, handles sampling, prepares it,
+// and sends it to the server.
+// stat is the string name for the metric.
+// value is a preformatted "raw" value string.
+// rate is the sample rate (0.0 to 1.0).
+func (s *Client) Raw(stat string, value string, rate float32) error {
+	if s == nil {
+		return nil
+	}
+	if rate < 1 {
+		if rand.Float32() < rate {
+			value = fmt.Sprintf("%s|@%f", value, rate)
+		} else {
+			return nil
+		}
+	}
+
+	if s.prefix != "" {
+		stat = fmt.Sprintf("%s.%s", s.prefix, stat)
+	}
+
+	data := fmt.Sprintf("%s:%s", stat, value)
+
+	_, err := s.send([]byte(data))
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// Sets/Updates the statsd client prefix
+func (s *Client) SetPrefix(prefix string) {
+	if s == nil {
+		return
+	}
+	s.prefix = prefix
+}
+
+// sends the data to the server endpoint
+func (s *Client) send(data []byte) (int, error) {
+	// no need for locking here, as the underlying fdNet
+	// already serialized writes
+	n, err := s.c.(*net.UDPConn).WriteToUDP([]byte(data), s.ra)
+	if err != nil {
+		return 0, err
+	}
+	if n == 0 {
+		return n, errors.New("Wrote no bytes")
+	}
+	return n, nil
+}
+
+// Returns a pointer to a new Client, and an error.
+// addr is a string of the format "hostname:port", and must be parsable by
+// net.ResolveUDPAddr.
+// prefix is the statsd client prefix. Can be "" if no prefix is desired.
+func New(addr, prefix string) (*Client, error) {
+	c, err := net.ListenPacket("udp", ":0")
+	if err != nil {
+		return nil, err
+	}
+
+	ra, err := net.ResolveUDPAddr("udp", addr)
+	if err != nil {
+		return nil, err
+	}
+
+	client := &Client{
+		c:      c,
+		ra:     ra,
+		prefix: prefix}
+
+	return client, nil
+}
+
+// Compatibility alias
+var Dial = New
diff --git a/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd/main_test.go b/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd/main_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..586f03bb6403d5661d2df23b370f7932df8d40aa
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd/main_test.go
@@ -0,0 +1,196 @@
+package statsd
+
+import (
+	"bytes"
+	"log"
+	"net"
+	"reflect"
+	"testing"
+	"time"
+)
+
+var statsdPacketTests = []struct {
+	Prefix   string
+	Method   string
+	Stat     string
+	Value    int64
+	Rate     float32
+	Expected string
+}{
+	{"test", "Gauge", "gauge", 1, 1.0, "test.gauge:1|g"},
+	{"test", "Inc", "count", 1, 0.999999, "test.count:1|c|@0.999999"},
+	{"test", "Inc", "count", 1, 1.0, "test.count:1|c"},
+	{"test", "Dec", "count", 1, 1.0, "test.count:-1|c"},
+	{"test", "Timing", "timing", 1, 1.0, "test.timing:1|ms"},
+	{"", "Inc", "count", 1, 1.0, "count:1|c"},
+	{"", "GaugeDelta", "gauge", 1, 1.0, "gauge:+1|g"},
+	{"", "GaugeDelta", "gauge", -1, 1.0, "gauge:-1|g"},
+}
+
+func TestClient(t *testing.T) {
+	l, err := newUDPListener("127.0.0.1:0")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer l.Close()
+	for _, tt := range statsdPacketTests {
+		c, err := New(l.LocalAddr().String(), tt.Prefix)
+		if err != nil {
+			t.Fatal(err)
+		}
+		method := reflect.ValueOf(c).MethodByName(tt.Method)
+		e := method.Call([]reflect.Value{
+			reflect.ValueOf(tt.Stat),
+			reflect.ValueOf(tt.Value),
+			reflect.ValueOf(tt.Rate)})[0]
+		errInter := e.Interface()
+		if errInter != nil {
+			t.Fatal(errInter.(error))
+		}
+
+		data := make([]byte, 128)
+		_, _, err = l.ReadFrom(data)
+		if err != nil {
+			c.Close()
+			t.Fatal(err)
+		}
+
+		data = bytes.TrimRight(data, "\x00")
+		if bytes.Equal(data, []byte(tt.Expected)) != true {
+			c.Close()
+			t.Fatalf("%s got '%s' expected '%s'", tt.Method, data, tt.Expected)
+		}
+		c.Close()
+	}
+}
+
+func TestNilClient(t *testing.T) {
+	l, err := newUDPListener("127.0.0.1:0")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer l.Close()
+	for _, tt := range statsdPacketTests {
+		var c *Client
+
+		method := reflect.ValueOf(c).MethodByName(tt.Method)
+		e := method.Call([]reflect.Value{
+			reflect.ValueOf(tt.Stat),
+			reflect.ValueOf(tt.Value),
+			reflect.ValueOf(tt.Rate)})[0]
+		errInter := e.Interface()
+		if errInter != nil {
+			t.Fatal(errInter.(error))
+		}
+
+		data := make([]byte, 128)
+		n, _, err := l.ReadFrom(data)
+		// this is expected to error, since there should
+		// be no udp data sent, so the read will time out
+		if err == nil || n != 0 {
+			c.Close()
+			t.Fatal(err)
+		}
+		c.Close()
+	}
+}
+
+func TestNoopClient(t *testing.T) {
+	l, err := newUDPListener("127.0.0.1:0")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer l.Close()
+	for _, tt := range statsdPacketTests {
+		c, err := NewNoop(l.LocalAddr().String(), tt.Prefix)
+		if err != nil {
+			t.Fatal(err)
+		}
+		method := reflect.ValueOf(c).MethodByName(tt.Method)
+		e := method.Call([]reflect.Value{
+			reflect.ValueOf(tt.Stat),
+			reflect.ValueOf(tt.Value),
+			reflect.ValueOf(tt.Rate)})[0]
+		errInter := e.Interface()
+		if errInter != nil {
+			t.Fatal(errInter.(error))
+		}
+
+		data := make([]byte, 128)
+		n, _, err := l.ReadFrom(data)
+		// this is expected to error, since there should
+		// be no udp data sent, so the read will time out
+		if err == nil || n != 0 {
+			c.Close()
+			t.Fatal(err)
+		}
+		c.Close()
+	}
+}
+
+func newUDPListener(addr string) (*net.UDPConn, error) {
+	l, err := net.ListenPacket("udp", addr)
+	if err != nil {
+		return nil, err
+	}
+	l.SetDeadline(time.Now().Add(100 * time.Millisecond))
+	l.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
+	l.SetWriteDeadline(time.Now().Add(100 * time.Millisecond))
+	return l.(*net.UDPConn), nil
+}
+
+func ExampleClient() {
+	// first create a client
+	client, err := Dial("127.0.0.1:8125", "test-client")
+	// handle any errors
+	if err != nil {
+		log.Fatal(err)
+	}
+	// make sure to clean up
+	defer client.Close()
+
+	// Send a stat
+	err = client.Inc("stat1", 42, 1.0)
+	// handle any errors
+	if err != nil {
+		log.Printf("Error sending metric: %+v", err)
+	}
+}
+
+func ExampleNilClient() {
+	// use interface so we can sub noop client if needed
+	var client *Client
+	var err error
+
+	// Send a stat
+	err = client.Inc("stat1", 42, 1.0)
+	// handle any errors
+	if err != nil {
+		log.Printf("Error sending metric: %+v", err)
+	}
+}
+
+func ExampleNoopClient() {
+	// use interface so we can sub noop client if needed
+	var client Statter
+	var err error
+
+	// first try to create a real client
+	client, err = Dial("not-resolvable:8125", "test-client")
+	// Lets say real client creation fails, but you don't care enough about
+	// stats that you don't want your program to run. Just log an error and
+	// make a NoopClient instead
+	if err != nil {
+		log.Println("Remote endpoint did not resolve. Disabling stats", err)
+		client, err = NewNoop()
+	}
+	// make sure to clean up
+	defer client.Close()
+
+	// Send a stat
+	err = client.Inc("stat1", 42, 1.0)
+	// handle any errors
+	if err != nil {
+		log.Printf("Error sending metric: %+v", err)
+	}
+}
diff --git a/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd/noop.go b/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd/noop.go
new file mode 100644
index 0000000000000000000000000000000000000000..ee11e74a9791847846aa6ba2745ed47bdb0309f5
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd/noop.go
@@ -0,0 +1,74 @@
+package statsd
+
+type NoopClient struct {
+	// prefix for statsd name
+	prefix string
+}
+
+// Close closes the connection and cleans up.
+func (s *NoopClient) Close() error {
+	return nil
+}
+
+// Increments a statsd count type.
+// stat is a string name for the metric.
+// value is the integer value
+// rate is the sample rate (0.0 to 1.0)
+func (s *NoopClient) Inc(stat string, value int64, rate float32) error {
+	return nil
+}
+
+// Decrements a statsd count type.
+// stat is a string name for the metric.
+// value is the integer value.
+// rate is the sample rate (0.0 to 1.0).
+func (s *NoopClient) Dec(stat string, value int64, rate float32) error {
+	return nil
+}
+
+// Submits/Updates a statsd gauge type.
+// stat is a string name for the metric.
+// value is the integer value.
+// rate is the sample rate (0.0 to 1.0).
+func (s *NoopClient) Gauge(stat string, value int64, rate float32) error {
+	return nil
+}
+
+// Submits a delta to a statsd gauge.
+// stat is the string name for the metric.
+// value is the (positive or negative) change.
+// rate is the sample rate (0.0 to 1.0).
+func (s *NoopClient) GaugeDelta(stat string, value int64, rate float32) error {
+	return nil
+}
+
+// Submits a statsd timing type.
+// stat is a string name for the metric.
+// value is the integer value.
+// rate is the sample rate (0.0 to 1.0).
+func (s *NoopClient) Timing(stat string, delta int64, rate float32) error {
+	return nil
+}
+
+// Raw formats the statsd event data, handles sampling, prepares it,
+// and sends it to the server.
+// stat is the string name for the metric.
+// value is the preformatted "raw" value string.
+// rate is the sample rate (0.0 to 1.0).
+func (s *NoopClient) Raw(stat string, value string, rate float32) error {
+	return nil
+}
+
+// Sets/Updates the statsd client prefix
+func (s *NoopClient) SetPrefix(prefix string) {
+	s.prefix = prefix
+}
+
+// Returns a pointer to a new NoopClient, and an error (always nil, just
+// supplied to support api convention).
+// Use variadic arguments to support identical format as New, or a more
+// conventional no argument form.
+func NewNoop(a ...interface{}) (*NoopClient, error) {
+	noopClient := &NoopClient{}
+	return noopClient, nil
+}
diff --git a/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd/test-client/main.go b/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd/test-client/main.go
new file mode 100644
index 0000000000000000000000000000000000000000..7a7786e19ca6affa9db5220b6fec6f52b622aace
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd/test-client/main.go
@@ -0,0 +1,88 @@
+package main
+
+import (
+	"fmt"
+	"github.com/cactus/go-statsd-client/statsd"
+	flags "github.com/jessevdk/go-flags"
+	"log"
+	"os"
+	"time"
+)
+
+func main() {
+
+	// command line flags
+	var opts struct {
+		HostPort  string        `long:"host" default:"127.0.0.1:8125" description:"host:port of statsd server"`
+		Prefix    string        `long:"prefix" default:"test-client" description:"Statsd prefix"`
+		StatType  string        `long:"type" default:"count" description:"stat type to send. Can be timing, count, guage"`
+		StatValue int64         `long:"value" default:"1" description:"Value to send"`
+		Name      string        `short:"n" long:"name" default:"counter" description:"stat name"`
+		Rate      float32       `short:"r" long:"rate" default:"1.0" description:"sample rate"`
+		Volume    int           `short:"c" long:"count" default:"1000" description:"Number of stats to send. Volume."`
+		Nil       bool          `long:"nil" default:"false" description:"Use nil client"`
+		Duration  time.Duration `short:"d" long:"duration" default:"10s" description:"How long to spread the volume across. Each second of duration volume/seconds events will be sent."`
+	}
+
+	// parse said flags
+	_, err := flags.Parse(&opts)
+	if err != nil {
+		if e, ok := err.(*flags.Error); ok {
+			if e.Type == flags.ErrHelp {
+				os.Exit(0)
+			}
+		}
+		fmt.Printf("Error: %+v\n", err)
+		os.Exit(1)
+	}
+
+	var client *statsd.Client
+	if !opts.Nil {
+		client, err = statsd.New(opts.HostPort, opts.Prefix)
+		if err != nil {
+			log.Fatal(err)
+		}
+		defer client.Close()
+	}
+
+	var stat func(stat string, value int64, rate float32) error
+	switch opts.StatType {
+	case "count":
+		stat = func(stat string, value int64, rate float32) error {
+			return client.Inc(stat, value, rate)
+		}
+	case "gauge":
+		stat = func(stat string, value int64, rate float32) error {
+			return client.Gauge(stat, value, rate)
+		}
+	case "timing":
+		stat = func(stat string, value int64, rate float32) error {
+			return client.Timing(stat, value, rate)
+		}
+	default:
+		log.Fatal("Unsupported state type")
+	}
+
+	pertick := opts.Volume / int(opts.Duration.Seconds()) / 10
+	// add some extra tiem, because the first tick takes a while
+	ender := time.After(opts.Duration + 100*time.Millisecond)
+	c := time.Tick(time.Second / 10)
+	count := 0
+	for {
+		select {
+		case <-c:
+			for x := 0; x < pertick; x++ {
+				err := stat(opts.Name, opts.StatValue, opts.Rate)
+				if err != nil {
+					log.Printf("Got Error: %+v", err)
+					break
+				}
+				count += 1
+			}
+		case <-ender:
+			log.Printf("%d events called", count)
+			os.Exit(0)
+			return
+		}
+	}
+}
diff --git a/Godeps/_workspace/src/github.com/dgryski/dmrgo/README b/Godeps/_workspace/src/github.com/dgryski/dmrgo/README
new file mode 100644
index 0000000000000000000000000000000000000000..972215dc87172734d55c353c5f5e58f07ce59120
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dgryski/dmrgo/README
@@ -0,0 +1,24 @@
+dmrgo is a Go library for writing map/reduce jobs.
+
+It can be used with Hadoop's streaming protocol, but also includes a standalone
+map/reduce implementation (including partitioner) for 'small' jobs (~5G-10G).
+
+It is partially based on ideas from Yelp's MrJob package for Python, but since
+the Go is statically typed I've tried to make the API match more closely with
+Hadoop's Java API.
+
+The traditional "word count" example is in the examples directory.
+
+This code is licensed under the GPLv3, or at your option any later version.
+
+Further reading:
+
+MrJob:
+   http://packages.python.org/mrjob/
+   https://github.com/Yelp/mrjob
+
+Hadoop map/reduce tutorial:
+   http://hadoop.apache.org/common/docs/current/mapred_tutorial.html
+
+Hadoop streaming protocol:
+   http://hadoop.apache.org/common/docs/current/streaming.html
diff --git a/Godeps/_workspace/src/github.com/dgryski/dmrgo/TODO b/Godeps/_workspace/src/github.com/dgryski/dmrgo/TODO
new file mode 100644
index 0000000000000000000000000000000000000000..591efbce2657b6374727182eb467cee5b081027f
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dgryski/dmrgo/TODO
@@ -0,0 +1,6 @@
+Add multi-step jobs (map/reduce1/reduce2/...)
+Fix names: s/M(ap)?R(educe)?// ?
+Expose doMap/doReduce so callers can know what stage they need to prepare for?
+Add ReduceFinal() ?
+Add more status logging for full map/reduce code (behind -v ?)
+Client mappers and reducers now need to be thread-safe.  How to make this easy?
diff --git a/Godeps/_workspace/src/github.com/dgryski/dmrgo/doc.go b/Godeps/_workspace/src/github.com/dgryski/dmrgo/doc.go
new file mode 100644
index 0000000000000000000000000000000000000000..832bf39c2f8ca7115e0f2829225927d19c990708
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dgryski/dmrgo/doc.go
@@ -0,0 +1,27 @@
+/*
+dmrgo is a Go library for writing map/reduce jobs.
+
+It can be used with Hadoop's streaming protocol, but also includes a standalone
+map/reduce implementation (including partitioner) for 'small' jobs (~5G-10G).
+
+It is partially based on ideas from Yelp's MrJob package for Python, but since
+the Go is statically typed I've tried to make the API match more closely with
+Hadoop's Java API.
+
+The traditional "word count" example is in the examples directory.
+
+This code is licensed under the GPLv3, or at your option any later version.
+
+Further reading:
+
+MrJob:
+   http://packages.python.org/mrjob/
+   https://github.com/Yelp/mrjob
+
+Hadoop map/reduce tutorial:
+   http://hadoop.apache.org/common/docs/current/mapred_tutorial.html
+
+Hadoop streaming protocol:
+   http://hadoop.apache.org/common/docs/current/streaming.html
+*/
+package dmrgo
diff --git a/Godeps/_workspace/src/github.com/dgryski/dmrgo/emitter.go b/Godeps/_workspace/src/github.com/dgryski/dmrgo/emitter.go
new file mode 100644
index 0000000000000000000000000000000000000000..c612f81f630e1c2dce4f700c31f0eceaa9248096
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dgryski/dmrgo/emitter.go
@@ -0,0 +1,99 @@
+// Logic for handling mapper and reducer output
+// Copyright (c) 2011 Damian Gryski <damian@gryski.com>
+// License: GPLv3 or, at your option, any later version
+
+package dmrgo
+
+import (
+	"bufio"
+	"fmt"
+	"hash/adler32"
+	"os"
+)
+
+type Emitter interface {
+	Emit(key string, value string)
+	Flush()
+}
+
+type printEmitter struct {
+	w *bufio.Writer
+}
+
+func newPrintEmitter(w *bufio.Writer) *printEmitter {
+	e := new(printEmitter)
+	e.w = w
+	return e
+}
+
+func (e *printEmitter) Emit(key string, value string) {
+	e.w.WriteString(key)
+	e.w.WriteByte('\t')
+	e.w.WriteString(value)
+	e.w.WriteByte('\n')
+}
+
+func (e *printEmitter) Flush() {
+	e.w.Flush()
+}
+
+type partitionEmitter struct {
+	partitions       uint32
+	FileNames        []string
+	fds              []*os.File
+	emitters         []Emitter
+	fileNameTemplate string
+}
+
+// data sink -- useful for benchmarking
+type nullEmitter struct{}
+
+func (*nullEmitter) Emit(key string, value string) { /* nothing */
+}
+func (*nullEmitter) Flush() { /* nothing */
+}
+
+func newPartitionEmitter(partitions uint, template string) *partitionEmitter {
+	pe := new(partitionEmitter)
+	pe.partitions = uint32(partitions)
+	pe.fileNameTemplate = template
+	pe.FileNames = make([]string, partitions)
+	pe.fds = make([]*os.File, partitions)
+	pe.emitters = make([]Emitter, partitions)
+	return pe
+}
+
+func (e *partitionEmitter) Emit(key string, value string) {
+
+	partition := uint32(0)
+
+	if e.partitions > 1 {
+		partition = adler32.Checksum([]byte(key)) % uint32(e.partitions)
+	}
+
+	if e.emitters[partition] == nil {
+		e.FileNames[partition] = fmt.Sprintf("%s.%04d", e.fileNameTemplate, partition)
+		fd, _ := os.Create(e.FileNames[partition])
+		e.fds[partition] = fd
+		w := bufio.NewWriter(fd)
+		e.emitters[partition] = newPrintEmitter(w)
+	}
+
+	e.emitters[partition].Emit(key, value)
+}
+
+func (e *partitionEmitter) Flush() {
+	for _, w := range e.emitters {
+		if w != nil {
+			w.Flush()
+		}
+	}
+}
+
+func (e *partitionEmitter) Close() {
+	for _, w := range e.fds {
+		if w != nil {
+			w.Close()
+		}
+	}
+}
diff --git a/Godeps/_workspace/src/github.com/dgryski/dmrgo/examples/Makefile b/Godeps/_workspace/src/github.com/dgryski/dmrgo/examples/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..3d19a36ab4182bb1e1ed54e806bcb29e3f5c0747
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dgryski/dmrgo/examples/Makefile
@@ -0,0 +1,25 @@
+PWD=$(shell pwd)
+INFILE=/usr/share/common-licenses/GPL-3
+
+wordcount:	wordcount.go
+	go build -o $@
+
+wordcount_test:	wordcount data.in wordcount_test_tr
+		cat data.in | ./wordcount --mapper |sort |./wordcount --reducer >data.out
+		./wordcount --mapreduce data.in
+		md5sum `ls -rt red-out-p*.0000 |tail -1` data.out wordcount-tr.txt
+		
+wordcount_test_hadoop:	wordcount data.in
+	${HADOOP_HOME}/bin/hadoop fs -ls data.in && ${HADOOP_HOME}/bin/hadoop fs -rm data.in
+	${HADOOP_HOME}/bin/hadoop fs -put data.in data.in
+	${HADOOP_HOME}/bin/hadoop fs -test -d data.out && ${HADOOP_HOME}/bin/hadoop fs -rmr data.out
+	${HADOOP_HOME}/bin/hadoop jar ${HADOOP_HOME}/contrib/streaming/hadoop-*streaming*.jar -verbose -mapper "${PWD}/wordcount --mapper" -reducer "${PWD}/wordcount --reducer" -input "data.in" -output "data.out"
+	rm -rf data.out
+	${HADOOP_HOME}/bin/hadoop fs -get data.out data.out
+	md5sum data.out/part-00000
+
+wordcount_test_tr:
+	cat $(INFILE) |tr 'A-Z' 'a-z' |tr -c 'a-z\n' ' ' |tr ' ' '\n' |grep -v '^$$' |sort |uniq -c |awk '{print $$2 "\t" $$1;}' >wordcount-tr.txt
+
+data.in:
+	cp $(INFILE) data.in
diff --git a/Godeps/_workspace/src/github.com/dgryski/dmrgo/examples/wordcount.go b/Godeps/_workspace/src/github.com/dgryski/dmrgo/examples/wordcount.go
new file mode 100644
index 0000000000000000000000000000000000000000..1f3e9b4b6a5a9a80d02fb7c627fdbc0a2cc07340
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dgryski/dmrgo/examples/wordcount.go
@@ -0,0 +1,141 @@
+// The standard map/reduce example: counting words
+// Copyright (c) 2011 Damian Gryski <damian@gryski.com>
+// License: GPLv3 or, at your option, any later version
+package main
+
+import (
+	"flag"
+	"fmt"
+	"github.com/dgryski/dmrgo"
+	"log"
+	"os"
+	"runtime/pprof"
+	"strconv"
+	"strings"
+	"sync/atomic"
+)
+
+// As example, just to show we can write our own custom protocols
+type WordCountProto struct{}
+
+func (p *WordCountProto) UnmarshalKVs(key string, values []string, k interface{}, vs interface{}) {
+
+	kptr := k.(*string)
+	*kptr = key
+
+	vsptr := vs.(*[]int)
+
+	v := make([]int, len(values))
+
+	for i, s := range values {
+		v[i], _ = strconv.Atoi(s)
+	}
+
+	*vsptr = v
+}
+
+func (p *WordCountProto) MarshalKV(key interface{}, value interface{}) *dmrgo.KeyValue {
+	ks := key.(string)
+	vi := value.(int)
+
+	if vi == 1 {
+		return &dmrgo.KeyValue{ks, "1"}
+	}
+
+	return &dmrgo.KeyValue{ks, strconv.Itoa(vi)}
+}
+
+type MRWordCount struct {
+	protocol dmrgo.StreamProtocol // overkill -- we would normally just inline the un/marshal calls
+
+	// mapper variables
+	mappedWords uint32
+}
+
+func NewWordCount(proto dmrgo.StreamProtocol) dmrgo.MapReduceJob {
+
+	mr := new(MRWordCount)
+	mr.protocol = proto
+
+	return mr
+}
+
+func (mr *MRWordCount) Map(key string, value string, emitter dmrgo.Emitter) {
+
+	lower := strings.ToLower(string(value))
+
+	letters := strings.Map(func(r rune) rune {
+		if r >= 'a' && r <= 'z' {
+			return r
+		}
+
+		return ' '
+	},
+		lower)
+
+	trimmed := strings.TrimSpace(letters)
+	words := strings.Fields(trimmed)
+
+	w := uint32(0)
+	for _, word := range words {
+		w++
+		kv := mr.protocol.MarshalKV(word, 1)
+		emitter.Emit(kv.Key, kv.Value)
+	}
+	atomic.AddUint32(&mr.mappedWords, w)
+
+}
+
+func (mr *MRWordCount) MapFinal(emitter dmrgo.Emitter) {
+	dmrgo.Statusln("finished -- mapped ", mr.mappedWords)
+	dmrgo.IncrCounter("Program", "mapped words", int(mr.mappedWords))
+}
+
+func (mr *MRWordCount) Reduce(key string, values []string, emitter dmrgo.Emitter) {
+
+	counts := []int{}
+	mr.protocol.UnmarshalKVs(key, values, &key, &counts)
+
+	count := 0
+	for _, c := range counts {
+		count += c
+	}
+
+	kv := mr.protocol.MarshalKV(key, count)
+	emitter.Emit(kv.Key, kv.Value)
+}
+
+var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
+
+func main() {
+
+	var use_proto = flag.String("proto", "wc", "use protocol (json/wc/tsv)")
+
+	flag.Parse()
+
+	if *cpuprofile != "" {
+		f, err := os.Create(*cpuprofile)
+		if err != nil {
+			log.Fatal(err)
+		}
+		pprof.StartCPUProfile(f)
+		defer pprof.StopCPUProfile()
+	}
+
+	var proto dmrgo.StreamProtocol
+
+	if *use_proto == "json" {
+		proto = new(dmrgo.JSONProtocol)
+	} else if *use_proto == "wc" {
+		proto = new(WordCountProto)
+	} else if *use_proto == "tsv" {
+		proto = new(dmrgo.TSVProtocol)
+	} else {
+		fmt.Println("unknown proto=", *use_proto)
+		os.Exit(1)
+	}
+
+	wordCounter := NewWordCount(proto)
+
+	dmrgo.Main(wordCounter)
+}
diff --git a/Godeps/_workspace/src/github.com/dgryski/dmrgo/proto.go b/Godeps/_workspace/src/github.com/dgryski/dmrgo/proto.go
new file mode 100644
index 0000000000000000000000000000000000000000..a22ac9463c70ea507cfad49d75cefabacdbeb76a
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dgryski/dmrgo/proto.go
@@ -0,0 +1,211 @@
+// Protocols for un/marshaling stream values
+// Copyright (c) 2011 Damian Gryski <damian@gryski.com>
+// License: GPLv3 or, at your option, any later version
+
+package dmrgo
+
+import (
+	"encoding/json"
+	"fmt"
+	"reflect"
+	"strconv"
+	"strings"
+)
+
+// StreamProtocol is a set of routines for marshaling and unmarshaling key/value pairs from the input stream.
+// Map Reduce jobs can define their own protocols.
+type StreamProtocol interface {
+
+	// UnmarshalKV turns strings into their associated values.
+	// k should be a pointer to the destination value for the unmarshalled "key"
+	// vs should be a pointer to an array for the unmarshalled "values"
+	UnmarshalKVs(key string, values []string, k interface{}, vs interface{})
+
+	// MarshalKV turns a key/value pair into a KeyValue
+	MarshalKV(key interface{}, value interface{}) *KeyValue
+}
+
+// JSONProtocol parse input/output values as JSON strings
+type JSONProtocol struct {
+	// empty -- just a type
+}
+
+func (p *JSONProtocol) UnmarshalKVs(key string, values []string, k interface{}, vs interface{}) {
+
+	json.Unmarshal([]byte(key), &k)
+
+	vsPtrValue := reflect.ValueOf(vs)
+	vsType := reflect.TypeOf(vs).Elem()
+
+	v := reflect.MakeSlice(vsType, len(values), len(values))
+
+	for i, js := range values {
+		e := v.Index(i)
+		err := json.Unmarshal([]byte(js), e.Addr().Interface())
+		if err != nil {
+			// skip, for now
+			continue
+		}
+	}
+
+	vsPtrValue.Elem().Set(v)
+}
+
+func (p *JSONProtocol) MarshalKV(key interface{}, value interface{}) *KeyValue {
+	k, _ := json.Marshal(key)
+	v, _ := json.Marshal(value)
+	return &KeyValue{string(k), string(v)}
+}
+
+type TSVProtocol struct {
+	// empty -- just a type
+}
+
+func (p *TSVProtocol) MarshalKV(key interface{}, value interface{}) *KeyValue {
+
+	kVal := reflect.ValueOf(key)
+	k := primitiveToString(kVal)
+
+	var vs []string
+
+	vType := reflect.TypeOf(value)
+	vVal := reflect.ValueOf(value)
+
+	if vType.Kind() == reflect.Struct {
+		vs = make([]string, vType.NumField())
+		for i := 0; i < vType.NumField(); i++ {
+			field := vVal.Field(i)
+			vs[i] = primitiveToString(field)
+		}
+	} else if isPrimitive(vType.Kind()) {
+		vs = append(vs, primitiveToString(vVal))
+	} else if vType.Kind() == reflect.Array || vType.Kind() == reflect.Slice {
+		vs = make([]string, vVal.Len())
+		for i := 0; i < vVal.Len(); i++ {
+			field := vVal.Index(i)
+			// arrays/slices must be of primitives
+			vs[i] = primitiveToString(field)
+		}
+	}
+
+	vals := strings.Join(vs, "\t")
+
+	return &KeyValue{k, vals}
+}
+
+func (p *TSVProtocol) UnmarshalKVs(key string, values []string, k interface{}, vs interface{}) {
+
+	fmt.Sscan(key, &k)
+
+	vsPtrValue := reflect.ValueOf(vs)
+	vsType := reflect.TypeOf(vs).Elem()
+	vType := vsType.Elem()
+
+	v := reflect.MakeSlice(vsType, len(values), len(values))
+
+	for vi, s := range values {
+		vs := strings.Split(s, "\t")
+
+		// create our new element
+		e := v.Index(vi)
+
+		// figure out what kind we need to unpack our data into
+		if vType.Kind() == reflect.Struct {
+			for i := 0; i < vType.NumField(); i++ {
+				_, err := fmt.Sscan(vs[i], e.Field(i).Addr().Interface())
+				if err != nil {
+					continue // skip
+				}
+			}
+		} else if vType.Kind() == reflect.Array {
+			for i := 0; i < vType.Len(); i++ {
+				_, err := fmt.Sscan(vs[i], e.Index(i).Addr().Interface())
+				if err != nil {
+					continue // skip
+				}
+			}
+		} else if isPrimitive(vType.Kind()) {
+			fmt.Sscan(vs[0], e.Addr().Interface())
+		}
+	}
+
+	vsPtrValue.Elem().Set(v)
+}
+
+func isPrimitive(k reflect.Kind) bool {
+
+	switch k {
+	case reflect.Bool:
+		fallthrough
+	case reflect.Int:
+		fallthrough
+	case reflect.Int8:
+		fallthrough
+	case reflect.Int16:
+		fallthrough
+	case reflect.Int32:
+		fallthrough
+	case reflect.Int64:
+		fallthrough
+	case reflect.Uint:
+		fallthrough
+	case reflect.Uint8:
+		fallthrough
+	case reflect.Uint16:
+		fallthrough
+	case reflect.Uint32:
+		fallthrough
+	case reflect.Uint64:
+		fallthrough
+	case reflect.Float32:
+		fallthrough
+	case reflect.Float64:
+		fallthrough
+	case reflect.String:
+		return true
+	}
+
+	return false
+}
+
+func primitiveToString(v reflect.Value) string {
+
+	switch v.Kind() {
+
+	case reflect.Bool:
+		if v.Bool() {
+			return "1"
+		}
+		return "0"
+	case reflect.Int:
+		fallthrough
+	case reflect.Int8:
+		fallthrough
+	case reflect.Int16:
+		fallthrough
+	case reflect.Int32:
+		fallthrough
+	case reflect.Int64:
+		return strconv.FormatInt(v.Int(), 10)
+
+	case reflect.Uint:
+		fallthrough
+	case reflect.Uint8:
+		fallthrough
+	case reflect.Uint16:
+		fallthrough
+	case reflect.Uint32:
+		fallthrough
+	case reflect.Uint64:
+		return strconv.FormatUint(v.Uint(), 10)
+
+	case reflect.Float32:
+		fallthrough
+	case reflect.Float64:
+		return strconv.FormatFloat(v.Float(), 'g', 5, 64)
+	case reflect.String:
+		return v.String()
+	}
+
+	return "(unknown type " + string(v.Kind()) + ")"
+}
diff --git a/Godeps/_workspace/src/github.com/dgryski/dmrgo/reporter.go b/Godeps/_workspace/src/github.com/dgryski/dmrgo/reporter.go
new file mode 100644
index 0000000000000000000000000000000000000000..f340ddeb9623eb362da30b01b38d649515286169
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dgryski/dmrgo/reporter.go
@@ -0,0 +1,27 @@
+// Update status and counters to the Hadoop framework
+// Copyright (c) 2011 Damian Gryski <damian@gryski.com>
+// License: GPLv3 or, at your option, any later versiono
+
+package dmrgo
+
+import (
+	"fmt"
+	"os"
+)
+
+// Statusln updates the Hadoop job status.  The arguments are passed to fmt.Sprintln
+func Statusln(a ...interface{}) {
+	s := fmt.Sprintln(a...)
+	fmt.Fprintf(os.Stderr, "reporter:status:%s", s) // \n is in s
+}
+
+// Statusf updates the Hadoop job status.  The arguments are passed to fmt.Sprintf
+func Statusf(format string, a ...interface{}) {
+	s := fmt.Sprintf(format, a...) // we should check if s contains \n
+	fmt.Fprintf(os.Stderr, "reporter:status:%s\n", s)
+}
+
+// IncrCounter updates the given group/counter by 'amount'
+func IncrCounter(group, counter string, amount int) {
+	fmt.Fprintf(os.Stderr, "reporter:counter:%s,%s,%d\n", group, counter, amount)
+}
diff --git a/Godeps/_workspace/src/github.com/dgryski/dmrgo/runners.go b/Godeps/_workspace/src/github.com/dgryski/dmrgo/runners.go
new file mode 100644
index 0000000000000000000000000000000000000000..ce98e77d68453134fe64989d600d9ed607f5d20f
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dgryski/dmrgo/runners.go
@@ -0,0 +1,294 @@
+// Logic for running our map/reduce jobs
+// Copyright (c) 2011 Damian Gryski <damian@gryski.com>
+// License: GPLv3 or, at your option, any later version
+
+package dmrgo
+
+import (
+	"bufio"
+	"flag"
+	"fmt"
+	"io"
+	"os"
+	"path/filepath"
+	"strings"
+	"sync"
+)
+
+// KeyValue is the primary type for interacting with Hadoop.
+type KeyValue struct {
+	Key   string
+	Value string
+}
+
+func readLineValue(br *bufio.Reader) (*KeyValue, error) {
+	s, err := br.ReadString('\n')
+	s = strings.TrimRight(s, "\n")
+	if err != nil {
+		return nil, err
+	}
+	return &KeyValue{"", s}, err
+}
+
+func readLineKeyValue(br *bufio.Reader) (*KeyValue, error) {
+
+	k, err := br.ReadString('\t')
+	if err != nil {
+		return nil, err
+	}
+
+	v, err := br.ReadString('\n')
+	if err != nil {
+		return nil, err
+	}
+
+	k = strings.TrimRight(k, "\t")
+	v = strings.TrimRight(v, "\n")
+
+	return &KeyValue{k, v}, nil
+}
+
+// MapReduceJob is the interface expected by the job runner
+type MapReduceJob interface {
+	Map(key string, value string, emitter Emitter)
+
+	// Called at the end of the Map phase
+	MapFinal(emitter Emitter)
+
+	Reduce(key string, values []string, emitter Emitter)
+}
+
+// are in we in the map or reduce phase?
+var optDoMap bool
+var optDoReduce bool
+
+// or the full map/reduce code
+var optDoMapReduce bool
+
+// how many output partitions should we use
+var optNumPartitions int
+
+// how many concurrent mappers should we try to use
+var optNumMappers int
+
+// how many concurrent reducers should we try to use
+var optNumReducers int
+
+func init() {
+	flag.BoolVar(&optDoMap, "mapper", false, "run mapper code on stdin")
+	flag.BoolVar(&optDoReduce, "reducer", false, "run reducer on stdin")
+	flag.IntVar(&optNumPartitions, "partitions", 1, "parition data into sets")
+	flag.BoolVar(&optDoMapReduce, "mapreduce", false, "run full map/reduce")
+	flag.IntVar(&optNumMappers, "mappers", 4, "number of map processes")
+	flag.IntVar(&optNumReducers, "reducers", 4, "number of reducer processes")
+}
+
+func mapreduce(mrjob MapReduceJob) {
+
+	attr := new(os.ProcAttr)
+	attr.Files = []*os.File{nil, nil, nil}
+
+	pid := os.Getpid()
+
+	wg := new(sync.WaitGroup)
+
+	mapperInputFiles := flag.Args()
+
+	// no input files -- read from stdin
+	if len(mapperInputFiles) == 0 {
+		mEmit := newPartitionEmitter(uint(optNumPartitions), fmt.Sprintf("tmp-map-out-p%d-f0", pid))
+		mapper(mrjob, os.Stdin, mEmit)
+		mapper_final(mrjob, mEmit)
+		mEmit.Flush()
+		mEmit.Close()
+		mapperInputFiles = []string{"(stdin)"}
+	} else {
+		// we have multiple input files -- run up to 'mappers' of them in parallel
+
+		// the type of our channel -- limit scope 'cause we don't need it anywhere else
+		type mapperFile struct {
+			index int
+			fname string
+		}
+
+		mapperWork := make(chan *mapperFile)
+
+		// launch the goroutines
+		for i := 0; i < optNumMappers; i++ {
+			wg.Add(1)
+			go func(inputs chan *mapperFile) {
+
+				for input := range inputs {
+
+					f, err := os.Open(input.fname)
+					if err != nil {
+						fmt.Fprintln(os.Stderr, "err opening ", f, ": ", err)
+						return
+					}
+
+					mEmit := newPartitionEmitter(uint(optNumPartitions), fmt.Sprintf("tmp-map-out-p%d-f%d", pid, input.index))
+					mapper(mrjob, f, mEmit)
+					mEmit.Flush()
+					mEmit.Close()
+					f.Close()
+				}
+				wg.Done()
+			}(mapperWork)
+		}
+
+		// and send the work
+		for i, fname := range mapperInputFiles {
+			mapperWork <- &mapperFile{i, fname}
+		}
+		close(mapperWork)
+
+		wg.Wait()
+
+		// then launch mapper_final
+		mEmit := newPartitionEmitter(uint(optNumPartitions), fmt.Sprintf("tmp-map-out-p%d-f%d", pid, len(mapperInputFiles)))
+		mapper_final(mrjob, mEmit)
+		mEmit.Flush()
+		mEmit.Close()
+	}
+
+	partitions := make(chan int)
+
+	for i := 0; i < optNumReducers; i++ {
+
+		wg.Add(1)
+
+		go func(work chan int) {
+
+			for partition := range work {
+
+				fns, _ := filepath.Glob(fmt.Sprintf("tmp-map-out-p%d-f*.%04d", pid, partition))
+
+				redin := fmt.Sprintf("tmp-red-in-p%d.%04d", pid, partition)
+
+				cmdline := []string{"sort", "-o", redin}
+				cmdline = append(cmdline, fns...)
+
+				// sort
+				p, err := os.StartProcess("/usr/bin/sort", cmdline, attr)
+				if err != nil {
+					fmt.Fprintln(os.Stderr, "err running sort: ", err)
+				}
+				p.Wait()
+
+				// reduce
+				f, _ := os.Open(redin)
+				rout, _ := os.Create(fmt.Sprintf("red-out-p%d.%04d", pid, partition))
+				rEmit := newPrintEmitter(bufio.NewWriter(rout))
+				reducer(mrjob, f, rEmit)
+				for _, fn := range fns {
+					os.Remove(fn)
+				}
+				os.Remove(redin)
+				rEmit.Flush()
+				rout.Close()
+			}
+			wg.Done()
+		}(partitions)
+	}
+
+	for i := 0; i < optNumPartitions; i++ {
+		partitions <- i
+	}
+	close(partitions)
+
+	wg.Wait()
+
+	if optNumPartitions == 1 {
+		fmt.Printf("output is in: red-out-p%d.0000\n", pid)
+	} else {
+		fmt.Printf("output is in: red-out-p%d.0000 - red-out-p%d.%04d\n", pid, pid, optNumPartitions-1)
+	}
+}
+
+// Main runs the map reduce job passed in
+func Main(mrjob MapReduceJob) {
+
+	if optDoMapReduce {
+		mapreduce(mrjob)
+		return
+	}
+
+	if optDoMap && optDoReduce {
+		fmt.Println("can either map or reduce, not both. (Did  you mean --mapreduce ?)")
+		os.Exit(1)
+	}
+
+	if !optDoMap && !optDoReduce {
+		fmt.Println("neither map nor reduce called")
+		os.Exit(1)
+	}
+
+	stdout := bufio.NewWriter(os.Stdout)
+
+	emitter := newPrintEmitter(stdout)
+
+	if optDoMap {
+		mapper(mrjob, os.Stdin, emitter)
+		// handle any finalization from the mapper
+		mapper_final(mrjob, emitter)
+	}
+
+	if optDoReduce {
+		reducer(mrjob, os.Stdin, emitter)
+	}
+
+	emitter.Flush()
+}
+
+// run the mapping phase, calling the map routine on key/value pairs from the Reader
+// The users' Map routine will write any key/value pairs generated to the Emitter
+func mapper(mrjob MapReduceJob, r io.Reader, emitter Emitter) {
+
+	br := bufio.NewReader(r)
+
+	for {
+		kv, err := readLineValue(br)
+		if err != nil {
+			break
+		}
+
+		mrjob.Map("", kv.Value, emitter)
+	}
+}
+
+// run the cleanup phase for the mapper
+func mapper_final(mrjob MapReduceJob, emitter Emitter) {
+	mrjob.MapFinal(emitter)
+}
+
+// run the reduce phase, calling the reduce routine on key/[]value read the Reader.
+// We aggregate the values that have been mapped with the same key, then call the users' Reduce function.
+// The users' Reduce routine will output any key/value pairs via the Emitter.
+func reducer(mrjob MapReduceJob, r io.Reader, emitter Emitter) {
+
+	br := bufio.NewReader(r)
+
+	var currentKey string
+	values := []string{}
+
+	for {
+		mkv, err := readLineKeyValue(br)
+		if err != nil {
+			break
+		}
+
+		if currentKey == mkv.Key {
+			values = append(values, mkv.Value)
+		} else {
+			if currentKey != "" {
+				mrjob.Reduce(currentKey, values, emitter)
+				values = []string{}
+			}
+			currentKey = mkv.Key
+			values = append(values, mkv.Value)
+		}
+	}
+
+	// final reducer call with pending 'values'
+	mrjob.Reduce(currentKey, values, emitter)
+}
diff --git a/Godeps/_workspace/src/github.com/dustin/go-id3/.gitignore b/Godeps/_workspace/src/github.com/dustin/go-id3/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..ff4fe8d639ba27a91ff4a698472465a8b55626b6
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dustin/go-id3/.gitignore
@@ -0,0 +1,3 @@
+*.swp
+bin
+pkg
diff --git a/Godeps/_workspace/src/github.com/dustin/go-id3/LICENSE b/Godeps/_workspace/src/github.com/dustin/go-id3/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..d645695673349e3947e8e5ae42332d0ac3164cd7
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dustin/go-id3/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor 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, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/Godeps/_workspace/src/github.com/dustin/go-id3/README.md b/Godeps/_workspace/src/github.com/dustin/go-id3/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..dae424d67cdc5ffa9a7d685283cc60e18d33ab9d
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dustin/go-id3/README.md
@@ -0,0 +1,34 @@
+ID3 Parsing For Go
+==================
+
+Andrew Scherkus
+May 21, 2012
+
+
+Introduction
+------------
+
+Simple ID3 parsing library for go based on the specs at www.id3.org.
+
+It doesn't handle everything but at least gets the imporant bits like artist,
+album, track, etc...
+
+
+Usage
+-----
+Pass in a suitable io.Reader and away you go!
+
+    fd, _ := os.Open("foo.mp3")
+    defer fd.Close()
+    file := id3.Read(fd)
+    if file != nil {
+            fmt.Println(file)
+    }
+
+
+Examples
+--------
+An example tag reading program can be found under id3/tagreader.
+
+    go install github.com/dustin/id3/tagreader
+    $GOPATH/bin/tagreader path/to/file.mp3 [...]
diff --git a/Godeps/_workspace/src/github.com/dustin/go-id3/TODO b/Godeps/_workspace/src/github.com/dustin/go-id3/TODO
new file mode 100644
index 0000000000000000000000000000000000000000..8687b957bc4aa0b4c6216a7e4c3d1cf00ac9ceba
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dustin/go-id3/TODO
@@ -0,0 +1,13 @@
+General
+-------
+  - ID3 v1 support
+  - ID3 v2.x code can be deduplicated
+  - ID3 (un)synchronization handling
+  - ID3 v2.4 timestamp parsing
+  - Pictures!
+
+Unicode support
+---------------
+  - UTF-16BE needs to be tested
+  - Variable length UTF-16 strings are probably handled incorrectly
+  - UTF-16 w/o BOM needs to be tested
diff --git a/Godeps/_workspace/src/github.com/dustin/go-id3/examples/Makefile b/Godeps/_workspace/src/github.com/dustin/go-id3/examples/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..5e7b40101dc46bb355c93c2df9df9d6c63927bf0
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dustin/go-id3/examples/Makefile
@@ -0,0 +1,7 @@
+include $(GOROOT)/src/Make.inc
+
+TARG=tagreader
+GOFILES=\
+  tagreader.go\
+
+include $(GOROOT)/src/Make.cmd
diff --git a/Godeps/_workspace/src/github.com/dustin/go-id3/genres.go b/Godeps/_workspace/src/github.com/dustin/go-id3/genres.go
new file mode 100644
index 0000000000000000000000000000000000000000..5cb1083a073c921a9e474b9987cdb5ee5413adac
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dustin/go-id3/genres.go
@@ -0,0 +1,145 @@
+// Copyright 2011 Andrew Scherkus
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package id3
+
+import (
+	"fmt"
+	"strconv"
+	"strings"
+)
+
+var id3v1Genres = []string{
+	"Blues",
+	"Classic Rock",
+	"Country",
+	"Dance",
+	"Disco",
+	"Funk",
+	"Grunge",
+	"Hip-Hop",
+	"Jazz",
+	"Metal",
+	"New Age",
+	"Oldies",
+	"Other",
+	"Pop",
+	"R&B",
+	"Rap",
+	"Reggae",
+	"Rock",
+	"Techno",
+	"Industrial",
+	"Alternative",
+	"Ska",
+	"Death Metal",
+	"Pranks",
+	"Soundtrack",
+	"Euro-Techno",
+	"Ambient",
+	"Trip-Hop",
+	"Vocal",
+	"Jazz+Funk",
+	"Fusion",
+	"Trance",
+	"Classical",
+	"Instrumental",
+	"Acid",
+	"House",
+	"Game",
+	"Sound Clip",
+	"Gospel",
+	"Noise",
+	"AlternRock",
+	"Bass",
+	"Soul",
+	"Punk",
+	"Space",
+	"Meditative",
+	"Instrumental Pop",
+	"Instrumental Rock",
+	"Ethnic",
+	"Gothic",
+	"Darkwave",
+	"Techno-Industrial",
+	"Electronic",
+	"Pop-Folk",
+	"Eurodance",
+	"Dream",
+	"Southern Rock",
+	"Comedy",
+	"Cult",
+	"Gangsta",
+	"Top 40",
+	"Christian Rap",
+	"Pop/Funk",
+	"Jungle",
+	"Native American",
+	"Cabaret",
+	"New Wave",
+	"Psychadelic",
+	"Rave",
+	"Showtunes",
+	"Trailer",
+	"Lo-Fi",
+	"Tribal",
+	"Acid Punk",
+	"Acid Jazz",
+	"Polka",
+	"Retro",
+	"Musical",
+	"Rock & Roll",
+	"Hard Rock",
+}
+
+// ID3v2.2 and ID3v2.3 use "(NN)" where as ID3v2.4 simply uses "NN" when
+// referring to ID3v1 genres. The "(NN)" format is allowed to have trailing
+// information.
+//
+// RX and CR are shorthand for Remix and Cover, respectively.
+//
+// Refer to the following documentation:
+//   http://id3.org/id3v2-00          TCO frame
+//   http://id3.org/id3v2.3.0         TCON frame
+//   http://id3.org/id3v2.4.0-frames  TCON frame
+func convertID3v1Genre(genre string) string {
+	if genre == "RX" || strings.HasPrefix(genre, "(RX)") {
+		return "Remix"
+	}
+	if genre == "CR" || strings.HasPrefix(genre, "(CR)") {
+		return "Cover"
+	}
+
+	// Try to parse "NN" format.
+	index, err := strconv.Atoi(genre)
+	if err == nil {
+		if index >= 0 && index < len(id3v1Genres) {
+			return id3v1Genres[index]
+		}
+		return "Unknown"
+	}
+
+	// Try to parse "(NN)" format.
+	index = 0
+	_, err = fmt.Sscanf(genre, "(%d)", &index)
+	if err == nil {
+		if index >= 0 && index < len(id3v1Genres) {
+			return id3v1Genres[index]
+		}
+		return "Unknown"
+	}
+
+	// Couldn't parse so it's likely not an ID3v1 genre.
+	return genre
+}
diff --git a/Godeps/_workspace/src/github.com/dustin/go-id3/id3.go b/Godeps/_workspace/src/github.com/dustin/go-id3/id3.go
new file mode 100644
index 0000000000000000000000000000000000000000..557d8ec1b18dbf9491a9e84137ce0d53dd4e6760
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dustin/go-id3/id3.go
@@ -0,0 +1,101 @@
+// Copyright 2011 Andrew Scherkus
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package id3 implements basic ID3 parsing for MP3 files.
+//
+// Instead of providing access to every single ID3 frame this package
+// exposes only the ID3v2 header and a few basic fields such as the
+// artist, album, year, etc...
+package id3
+
+import (
+	"bufio"
+	"fmt"
+	"io"
+)
+
+// A parsed ID3v2 header as defined in Section 3 of
+// http://id3.org/id3v2.4.0-structure
+type ID3v2Header struct {
+	Version           int
+	MinorVersion      int
+	Unsynchronization bool
+	Extended          bool
+	Experimental      bool
+	Footer            bool
+	Size              int32
+}
+
+// A parsed ID3 file with common fields exposed.
+type File struct {
+	Header ID3v2Header
+
+	Name   string
+	Artist string
+	Album  string
+	Year   string
+	Track  string
+	Disc   string
+	Genre  string
+	Length string
+}
+
+// Parse the input for ID3 information. Returns nil if parsing failed or the
+// input didn't contain ID3 information.
+func Read(reader io.Reader) (file *File) {
+	defer func() {
+		if r := recover(); r != nil {
+			file = nil
+		}
+
+	}()
+	file = new(File)
+	bufReader := bufio.NewReader(reader)
+	if !isID3Tag(bufReader) {
+		return
+	}
+
+	parseID3v2Header(bufReader, file)
+	limitReader := bufio.NewReader(io.LimitReader(bufReader, int64(file.Header.Size)))
+	if file.Header.Version == 2 {
+		parseID3v22File(limitReader, file)
+	} else if file.Header.Version == 3 {
+		parseID3v23File(limitReader, file)
+	} else if file.Header.Version == 4 {
+		parseID3v24File(limitReader, file)
+	} else {
+		panic(fmt.Sprintf("Unrecognized ID3v2 version: %d", file.Header.Version))
+	}
+
+	return
+}
+
+func isID3Tag(reader *bufio.Reader) bool {
+	data, err := reader.Peek(3)
+	if len(data) < 3 || err != nil {
+		return false
+	}
+	return data[0] == 'I' && data[1] == 'D' && data[2] == '3'
+}
+
+func parseID3v2Header(reader *bufio.Reader, file *File) {
+	data := readBytes(reader, 10)
+	file.Header.Version = int(data[3])
+	file.Header.MinorVersion = int(data[4])
+	file.Header.Unsynchronization = data[5]&1<<7 != 0
+	file.Header.Extended = data[5]&1<<6 != 0
+	file.Header.Experimental = data[5]&1<<5 != 0
+	file.Header.Footer = data[5]&1<<4 != 0
+	file.Header.Size = parseSize(data[6:])
+}
diff --git a/Godeps/_workspace/src/github.com/dustin/go-id3/id3_test.go b/Godeps/_workspace/src/github.com/dustin/go-id3/id3_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..83a3b0822cee7994d8dd2bf954fae561b8827bc0
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dustin/go-id3/id3_test.go
@@ -0,0 +1,123 @@
+// Copyright 2011 Andrew Scherkus
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package id3
+
+import (
+	"bytes"
+	"os"
+	"path"
+	"testing"
+)
+
+type fileTest struct {
+	path string
+	file File
+}
+
+func testFile(t *testing.T, expected fileTest) {
+	p := path.Join("test", expected.path)
+	t.Logf("With file %s", p)
+
+	fd, err := os.Open(p)
+	if fd == nil || err != nil {
+		t.Error(err)
+		return
+	}
+	defer fd.Close()
+
+	actual := Read(fd)
+	if actual == nil {
+		t.Error("Could not parse ID3 information")
+		return
+	}
+
+	// ID3v2Header fields.
+	header := expected.file.Header
+	if actual.Header.Version != header.Version {
+		t.Errorf("Header.Version: expected %d got %d", header.Version, actual.Header.Version)
+	}
+	if actual.Header.MinorVersion != header.MinorVersion {
+		t.Errorf("Header.MinorVersion: expected %d got %d", header.MinorVersion, actual.Header.MinorVersion)
+	}
+	if actual.Header.Unsynchronization != header.Unsynchronization {
+		t.Errorf("Header.Unsynchronization: expected %t got %t", header.Unsynchronization, actual.Header.Unsynchronization)
+	}
+	if actual.Header.Extended != header.Extended {
+		t.Errorf("Header.Extended: expected %t got %t", header.Extended, actual.Header.Extended)
+	}
+	if actual.Header.Experimental != header.Experimental {
+		t.Errorf("Header.Experimental: expected %t got %t", header.Experimental, actual.Header.Experimental)
+	}
+	if actual.Header.Footer != header.Footer {
+		t.Errorf("Header.Footer: expected %t got %t", header.Footer, actual.Header.Footer)
+	}
+	if actual.Header.Size != header.Size {
+		t.Errorf("Header.Size: expected %d got %d", header.Size, actual.Header.Size)
+	}
+
+	// Name, Artist, etc...
+	file := expected.file
+	if actual.Name != file.Name {
+		t.Errorf("Name: expected '%s' got '%s'", file.Name, actual.Name)
+	}
+	if actual.Artist != file.Artist {
+		t.Errorf("Artist: expected '%s' got '%s'", file.Artist, actual.Artist)
+	}
+	if actual.Album != file.Album {
+		t.Errorf("Album: expected '%s' got '%s'", file.Album, actual.Album)
+	}
+	if actual.Year != file.Year {
+		t.Errorf("Year: expected '%s' got '%s'", file.Year, actual.Year)
+	}
+	if actual.Track != file.Track {
+		t.Errorf("Track: expected '%s' got '%s'", file.Track, actual.Track)
+	}
+	if actual.Disc != file.Disc {
+		t.Errorf("Disc: expected '%s' got '%s'", file.Disc, actual.Disc)
+	}
+	if actual.Genre != file.Genre {
+		t.Errorf("Genre: expected '%s' got '%s'", file.Genre, actual.Genre)
+	}
+	if actual.Length != file.Length {
+		t.Errorf("Length: expected '%s' got '%s'", file.Length, actual.Length)
+	}
+}
+
+func TestEmpty(t *testing.T) {
+	file := Read(new(bytes.Buffer))
+	if file != nil {
+		t.Fail()
+	}
+}
+
+func TestID3v220(t *testing.T) {
+	testFile(t, fileTest{"test_220.mp3", File{ID3v2Header{2, 0, false, false, false, false, 226741},
+		"There There", "Radiohead", "Hail To The Thief", "2003", "9", "", "Alternative", ""}})
+}
+
+func TestID3v230(t *testing.T) {
+	testFile(t, fileTest{"test_230.mp3", File{ID3v2Header{3, 0, false, false, false, false, 150717},
+		"Everything In Its Right Place", "Radiohead", "Kid A", "2000", "1", "", "Alternative", ""}})
+}
+
+func TestID3v240(t *testing.T) {
+	testFile(t, fileTest{"test_240.mp3", File{ID3v2Header{4, 0, false, false, false, false, 165126},
+		"Give Up The Ghost", "Radiohead", "The King Of Limbs", "2011", "07/08", "1/1", "Alternative", ""}})
+}
+
+func TestISO8859_1(t *testing.T) {
+	testFile(t, fileTest{"test_iso8859_1.mp3", File{ID3v2Header{3, 0, false, false, false, false, 273649},
+		"Pompeii Am Götterdämmerung", "The Flaming Lips", "At War With The Mystics", "2006", "11", "1/1", "Unknown", ""}})
+}
diff --git a/Godeps/_workspace/src/github.com/dustin/go-id3/id3v22.go b/Godeps/_workspace/src/github.com/dustin/go-id3/id3v22.go
new file mode 100644
index 0000000000000000000000000000000000000000..21052f5a6913432dd076627c1549d0b693afb985
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dustin/go-id3/id3v22.go
@@ -0,0 +1,51 @@
+// Copyright 2011 Andrew Scherkus
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package id3
+
+import (
+	"bufio"
+)
+
+// ID3 v2.2 uses 24-bit big endian frame sizes.
+func parseID3v22FrameSize(reader *bufio.Reader) int {
+	size := readBytes(reader, 3)
+	return int(size[0])<<16 | int(size[1])<<8 | int(size[2])
+}
+
+func parseID3v22File(reader *bufio.Reader, file *File) {
+	for hasFrame(reader, 3) {
+		id := string(readBytes(reader, 3))
+		size := parseID3v22FrameSize(reader)
+
+		switch id {
+		case "TAL":
+			file.Album = readString(reader, size)
+		case "TRK":
+			file.Track = readString(reader, size)
+		case "TP1":
+			file.Artist = readString(reader, size)
+		case "TT2":
+			file.Name = readString(reader, size)
+		case "TYE":
+			file.Year = readString(reader, size)
+		case "TPA":
+			file.Disc = readString(reader, size)
+		case "TCO":
+			file.Genre = readGenre(reader, size)
+		default:
+			skipBytes(reader, size)
+		}
+	}
+}
diff --git a/Godeps/_workspace/src/github.com/dustin/go-id3/id3v23.go b/Godeps/_workspace/src/github.com/dustin/go-id3/id3v23.go
new file mode 100644
index 0000000000000000000000000000000000000000..9ec9ba1053d8d3fa6b1ed734791f6cf1596c2182
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dustin/go-id3/id3v23.go
@@ -0,0 +1,58 @@
+// Copyright 2011 Andrew Scherkus
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package id3
+
+import (
+	"bufio"
+	"encoding/binary"
+)
+
+// ID3 v2.3 doesn't use sync-safe frame sizes: read in as a regular big endian number.
+func parseID3v23Size(reader *bufio.Reader) int {
+	var size int32
+	binary.Read(reader, binary.BigEndian, &size)
+	return int(size)
+}
+
+func parseID3v23File(reader *bufio.Reader, file *File) {
+	for hasFrame(reader, 4) {
+		id := string(readBytes(reader, 4))
+		size := parseID3v23Size(reader)
+
+		// Skip over frame flags.
+		skipBytes(reader, 2)
+
+		switch id {
+		case "TALB":
+			file.Album = readString(reader, size)
+		case "TRCK":
+			file.Track = readString(reader, size)
+		case "TPE1":
+			file.Artist = readString(reader, size)
+		case "TCON":
+			file.Genre = readGenre(reader, size)
+		case "TIT2":
+			file.Name = readString(reader, size)
+		case "TYER":
+			file.Year = readString(reader, size)
+		case "TPOS":
+			file.Disc = readString(reader, size)
+		case "TLEN":
+			file.Length = readString(reader, size)
+		default:
+			skipBytes(reader, size)
+		}
+	}
+}
diff --git a/Godeps/_workspace/src/github.com/dustin/go-id3/id3v24.go b/Godeps/_workspace/src/github.com/dustin/go-id3/id3v24.go
new file mode 100644
index 0000000000000000000000000000000000000000..a54cb154a111f4224a7cfd78b1f539a2b5c80d8e
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dustin/go-id3/id3v24.go
@@ -0,0 +1,56 @@
+// Copyright 2011 Andrew Scherkus
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package id3
+
+import (
+	"bufio"
+)
+
+// ID3 v2.4 uses sync-safe frame sizes similar to those found in the header.
+func parseID3v24Size(reader *bufio.Reader) int {
+	return int(parseSize(readBytes(reader, 4)))
+}
+
+func parseID3v24File(reader *bufio.Reader, file *File) {
+	for hasFrame(reader, 4) {
+		id := string(readBytes(reader, 4))
+		size := parseID3v24Size(reader)
+
+		// Skip over frame flags.
+		skipBytes(reader, 2)
+
+		switch id {
+		case "TALB":
+			file.Album = readString(reader, size)
+		case "TRCK":
+			file.Track = readString(reader, size)
+		case "TPE1":
+			file.Artist = readString(reader, size)
+		case "TCON":
+			file.Genre = readGenre(reader, size)
+		case "TIT2":
+			file.Name = readString(reader, size)
+		case "TDRC":
+			// TODO: implement timestamp parsing
+			file.Year = readString(reader, size)
+		case "TPOS":
+			file.Disc = readString(reader, size)
+		case "TLEN":
+			file.Length = readString(reader, size)
+		default:
+			skipBytes(reader, size)
+		}
+	}
+}
diff --git a/Godeps/_workspace/src/github.com/dustin/go-id3/tagreader/tagreader.go b/Godeps/_workspace/src/github.com/dustin/go-id3/tagreader/tagreader.go
new file mode 100644
index 0000000000000000000000000000000000000000..a6e6f97ed9342b9a0b4ee78c8a06efc43115004e
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dustin/go-id3/tagreader/tagreader.go
@@ -0,0 +1,54 @@
+// Copyright 2011 Andrew Scherkus
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+	"fmt"
+	"os"
+
+	"github.com/dustin/go-id3"
+)
+
+func main() {
+	if len(os.Args) == 1 {
+		fmt.Printf("Usage: %s [path to mp3s]\n", os.Args[0])
+		return
+	}
+
+	for _, s := range os.Args[1:] {
+		var fd, err = os.Open(s)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "Could not open %s: %s\n", s, err)
+			return
+		}
+		file := id3.Read(fd)
+		if file == nil {
+			fmt.Fprintf(os.Stderr, "Could not read ID3 information from %s\n", s)
+		} else {
+			fmt.Println(s)
+			fmt.Printf("Header\t%#v\n", file.Header)
+			fmt.Printf("Name\t%s\n", file.Name)
+			fmt.Printf("Artist\t%s\n", file.Artist)
+			fmt.Printf("Album\t%s\n", file.Album)
+			fmt.Printf("Year\t%s\n", file.Year)
+			fmt.Printf("Track\t%s\n", file.Track)
+			fmt.Printf("Disc\t%s\n", file.Disc)
+			fmt.Printf("Genre\t%s\n", file.Genre)
+			fmt.Printf("Length\t%s\n", file.Length)
+			fmt.Println()
+		}
+		fd.Close()
+	}
+}
diff --git a/Godeps/_workspace/src/github.com/dustin/go-id3/test/test_220.mp3 b/Godeps/_workspace/src/github.com/dustin/go-id3/test/test_220.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..e495f8c4fb91573d7ba1fbcaee84740512d747f4
Binary files /dev/null and b/Godeps/_workspace/src/github.com/dustin/go-id3/test/test_220.mp3 differ
diff --git a/Godeps/_workspace/src/github.com/dustin/go-id3/test/test_230.mp3 b/Godeps/_workspace/src/github.com/dustin/go-id3/test/test_230.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..d8196a23f9b1b3032e9ff5eaae767631f1788793
Binary files /dev/null and b/Godeps/_workspace/src/github.com/dustin/go-id3/test/test_230.mp3 differ
diff --git a/Godeps/_workspace/src/github.com/dustin/go-id3/test/test_240.mp3 b/Godeps/_workspace/src/github.com/dustin/go-id3/test/test_240.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..a2d291a0db46464655243b71d54287734bd73dd3
Binary files /dev/null and b/Godeps/_workspace/src/github.com/dustin/go-id3/test/test_240.mp3 differ
diff --git a/Godeps/_workspace/src/github.com/dustin/go-id3/test/test_iso8859_1.mp3 b/Godeps/_workspace/src/github.com/dustin/go-id3/test/test_iso8859_1.mp3
new file mode 100644
index 0000000000000000000000000000000000000000..f18adfc37e70c9d088c1d192248c29d08c73d039
Binary files /dev/null and b/Godeps/_workspace/src/github.com/dustin/go-id3/test/test_iso8859_1.mp3 differ
diff --git a/Godeps/_workspace/src/github.com/dustin/go-id3/util.go b/Godeps/_workspace/src/github.com/dustin/go-id3/util.go
new file mode 100644
index 0000000000000000000000000000000000000000..11ede3ce168856f1df24366055f14e1fe7232b67
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/dustin/go-id3/util.go
@@ -0,0 +1,159 @@
+// Copyright 2011 Andrew Scherkus
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package id3
+
+import (
+	"bufio"
+	"fmt"
+	"strings"
+	"unicode/utf16"
+)
+
+var skipBuffer []byte = make([]byte, 1024*4)
+
+func ISO8859_1ToUTF8(data []byte) string {
+	p := make([]rune, len(data))
+	for i, b := range data {
+		p[i] = rune(b)
+	}
+	return string(p)
+}
+
+func toUTF16(data []byte) []uint16 {
+	if len(data) < 2 {
+		panic("Sequence is too short too contain a UTF-16 BOM")
+	}
+	if len(data)%2 > 0 {
+		// TODO: if this is UTF-16 BE then this is likely encoded wrong
+		data = append(data, 0)
+	}
+
+	var shift0, shift1 uint
+	if data[0] == 0xFF && data[1] == 0xFE {
+		// UTF-16 LE
+		shift0 = 0
+		shift1 = 8
+	} else if data[0] == 0xFE && data[1] == 0xFF {
+		// UTF-16 BE
+		shift0 = 8
+		shift1 = 0
+		panic("UTF-16 BE found!")
+	} else {
+		panic(fmt.Sprintf("Unrecognized UTF-16 BOM: 0x%02X%02X", data[0], data[1]))
+	}
+
+	s := make([]uint16, 0, len(data)/2)
+	for i := 2; i < len(data); i += 2 {
+		s = append(s, uint16(data[i])<<shift0|uint16(data[i+1])<<shift1)
+	}
+	return s
+}
+
+// Peeks at the buffer to see if there is a valid frame.
+func hasFrame(reader *bufio.Reader, frameSize int) bool {
+	data, err := reader.Peek(frameSize)
+	if err != nil {
+		return false
+	}
+
+	for _, c := range data {
+		if (c < 'A' || c > 'Z') && (c < '0' || c > '9') {
+			return false
+		}
+	}
+	return true
+}
+
+// Sizes are stored big endian but with the first bit set to 0 and always ignored.
+//
+// Refer to section 3.1 of http://id3.org/id3v2.4.0-structure
+func parseSize(data []byte) int32 {
+	size := int32(0)
+	for i, b := range data {
+		if b&0x80 > 0 {
+			fmt.Println("Size byte had non-zero first bit")
+		}
+
+		shift := uint32(len(data)-i-1) * 7
+		size |= int32(b&0x7f) << shift
+	}
+	return size
+}
+
+// Parses a string from frame data. The first byte represents the encoding:
+//   0x01  ISO-8859-1
+//   0x02  UTF-16 w/ BOM
+//   0x03  UTF-16BE w/o BOM
+//   0x04  UTF-8
+//
+// Refer to section 4 of http://id3.org/id3v2.4.0-structure
+func parseString(data []byte) string {
+	var s string
+	switch data[0] {
+	case 0: // ISO-8859-1 text.
+		s = ISO8859_1ToUTF8(data[1:])
+		break
+	case 1: // UTF-16 with BOM.
+		s = string(utf16.Decode(toUTF16(data[1:])))
+		break
+	case 2: // UTF-16BE without BOM.
+		panic("Unsupported text encoding UTF-16BE.")
+	case 3: // UTF-8 text.
+		s = string(data[1:])
+		break
+	default:
+		// No encoding, assume ISO-8859-1 text.
+		s = ISO8859_1ToUTF8(data)
+	}
+	return strings.TrimRight(s, "\u0000")
+}
+
+func readBytes(reader *bufio.Reader, c int) []byte {
+	b := make([]byte, c)
+	pos := 0
+	for pos < c {
+		i, err := reader.Read(b[pos:])
+		pos += i
+		if err != nil {
+			panic(err)
+		}
+	}
+	return b
+}
+
+func readString(reader *bufio.Reader, c int) string {
+	return parseString(readBytes(reader, c))
+}
+
+func readGenre(reader *bufio.Reader, c int) string {
+	genre := parseString(readBytes(reader, c))
+	return convertID3v1Genre(genre)
+}
+
+func skipBytes(reader *bufio.Reader, c int) {
+	pos := 0
+	for pos < c {
+		end := c - pos
+		if end > len(skipBuffer) {
+			end = len(skipBuffer)
+		}
+
+		i, err := reader.Read(skipBuffer[0:end])
+		pos += i
+		if err != nil {
+			panic(err)
+		}
+	}
+}
diff --git a/Godeps/_workspace/src/github.com/gorilla/context/LICENSE b/Godeps/_workspace/src/github.com/gorilla/context/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..0e5fb872800da9557f75a5650bb9d80c1c2cf715
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/context/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2012 Rodrigo Moraes. 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/Godeps/_workspace/src/github.com/gorilla/context/README.md b/Godeps/_workspace/src/github.com/gorilla/context/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..8ee62b42634e47e651612ec69f65efe6bf7b8df8
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/context/README.md
@@ -0,0 +1,6 @@
+context
+=======
+
+gorilla/context is a general purpose registry for global request variables.
+
+Read the full documentation here: http://www.gorillatoolkit.org/pkg/context
diff --git a/Godeps/_workspace/src/github.com/gorilla/context/context.go b/Godeps/_workspace/src/github.com/gorilla/context/context.go
new file mode 100644
index 0000000000000000000000000000000000000000..35d65561f3c6376da1723843efec165b7b376026
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/context/context.go
@@ -0,0 +1,112 @@
+// Copyright 2012 The Gorilla 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 context
+
+import (
+	"net/http"
+	"sync"
+	"time"
+)
+
+var (
+	mutex sync.Mutex
+	data  = make(map[*http.Request]map[interface{}]interface{})
+	datat = make(map[*http.Request]int64)
+)
+
+// Set stores a value for a given key in a given request.
+func Set(r *http.Request, key, val interface{}) {
+	mutex.Lock()
+	defer mutex.Unlock()
+	if data[r] == nil {
+		data[r] = make(map[interface{}]interface{})
+		datat[r] = time.Now().Unix()
+	}
+	data[r][key] = val
+}
+
+// Get returns a value stored for a given key in a given request.
+func Get(r *http.Request, key interface{}) interface{} {
+	mutex.Lock()
+	defer mutex.Unlock()
+	if data[r] != nil {
+		return data[r][key]
+	}
+	return nil
+}
+
+// GetOk returns stored value and presence state like multi-value return of map access.
+func GetOk(r *http.Request, key interface{}) (interface{}, bool) {
+	mutex.Lock()
+	defer mutex.Unlock()
+	if _, ok := data[r]; ok {
+		value, ok := data[r][key]
+		return value, ok
+	}
+	return nil, false
+}
+
+// Delete removes a value stored for a given key in a given request.
+func Delete(r *http.Request, key interface{}) {
+	mutex.Lock()
+	defer mutex.Unlock()
+	if data[r] != nil {
+		delete(data[r], key)
+	}
+}
+
+// Clear removes all values stored for a given request.
+//
+// This is usually called by a handler wrapper to clean up request
+// variables at the end of a request lifetime. See ClearHandler().
+func Clear(r *http.Request) {
+	mutex.Lock()
+	defer mutex.Unlock()
+	clear(r)
+}
+
+// clear is Clear without the lock.
+func clear(r *http.Request) {
+	delete(data, r)
+	delete(datat, r)
+}
+
+// Purge removes request data stored for longer than maxAge, in seconds.
+// It returns the amount of requests removed.
+//
+// If maxAge <= 0, all request data is removed.
+//
+// This is only used for sanity check: in case context cleaning was not
+// properly set some request data can be kept forever, consuming an increasing
+// amount of memory. In case this is detected, Purge() must be called
+// periodically until the problem is fixed.
+func Purge(maxAge int) int {
+	mutex.Lock()
+	defer mutex.Unlock()
+	count := 0
+	if maxAge <= 0 {
+		count = len(data)
+		data = make(map[*http.Request]map[interface{}]interface{})
+		datat = make(map[*http.Request]int64)
+	} else {
+		min := time.Now().Unix() - int64(maxAge)
+		for r, _ := range data {
+			if datat[r] < min {
+				clear(r)
+				count++
+			}
+		}
+	}
+	return count
+}
+
+// ClearHandler wraps an http.Handler and clears request values at the end
+// of a request lifetime.
+func ClearHandler(h http.Handler) http.Handler {
+	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		defer Clear(r)
+		h.ServeHTTP(w, r)
+	})
+}
diff --git a/Godeps/_workspace/src/github.com/gorilla/context/context_test.go b/Godeps/_workspace/src/github.com/gorilla/context/context_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..ff9e2ad5fc3ed462a360380e1289b772b04a05b5
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/context/context_test.go
@@ -0,0 +1,66 @@
+// Copyright 2012 The Gorilla 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 context
+
+import (
+	"net/http"
+	"testing"
+)
+
+type keyType int
+
+const (
+	key1 keyType = iota
+	key2
+)
+
+func TestContext(t *testing.T) {
+	assertEqual := func(val interface{}, exp interface{}) {
+		if val != exp {
+			t.Errorf("Expected %v, got %v.", exp, val)
+		}
+	}
+
+	r, _ := http.NewRequest("GET", "http://localhost:8080/", nil)
+
+	// Get()
+	assertEqual(Get(r, key1), nil)
+
+	// Set()
+	Set(r, key1, "1")
+	assertEqual(Get(r, key1), "1")
+	assertEqual(len(data[r]), 1)
+
+	Set(r, key2, "2")
+	assertEqual(Get(r, key2), "2")
+	assertEqual(len(data[r]), 2)
+
+	//GetOk
+	value, ok := GetOk(r, key1)
+	assertEqual(value, "1")
+	assertEqual(ok, true)
+
+	value, ok = GetOk(r, "not exists")
+	assertEqual(value, nil)
+	assertEqual(ok, false)
+
+	Set(r, "nil value", nil)
+	value, ok = GetOk(r, "nil value")
+	assertEqual(value, nil)
+	assertEqual(ok, true)
+
+	// Delete()
+	Delete(r, key1)
+	assertEqual(Get(r, key1), nil)
+	assertEqual(len(data[r]), 2)
+
+	Delete(r, key2)
+	assertEqual(Get(r, key2), nil)
+	assertEqual(len(data[r]), 1)
+
+	// Clear()
+	Clear(r)
+	assertEqual(len(data), 0)
+}
diff --git a/Godeps/_workspace/src/github.com/gorilla/context/doc.go b/Godeps/_workspace/src/github.com/gorilla/context/doc.go
new file mode 100644
index 0000000000000000000000000000000000000000..297606455ce2dd2112784be88defe1e682e83b72
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/context/doc.go
@@ -0,0 +1,82 @@
+// Copyright 2012 The Gorilla 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 gorilla/context stores values shared during a request lifetime.
+
+For example, a router can set variables extracted from the URL and later
+application handlers can access those values, or it can be used to store
+sessions values to be saved at the end of a request. There are several
+others common uses.
+
+The idea was posted by Brad Fitzpatrick to the go-nuts mailing list:
+
+	http://groups.google.com/group/golang-nuts/msg/e2d679d303aa5d53
+
+Here's the basic usage: first define the keys that you will need. The key
+type is interface{} so a key can be of any type that supports equality.
+Here we define a key using a custom int type to avoid name collisions:
+
+	package foo
+
+	import (
+		"github.com/gorilla/context"
+	)
+
+	type key int
+
+	const MyKey key = 0
+
+Then set a variable. Variables are bound to an http.Request object, so you
+need a request instance to set a value:
+
+	context.Set(r, MyKey, "bar")
+
+The application can later access the variable using the same key you provided:
+
+	func MyHandler(w http.ResponseWriter, r *http.Request) {
+		// val is "bar".
+		val := context.Get(r, foo.MyKey)
+
+		// returns ("bar", true)
+		val, ok := context.GetOk(r, foo.MyKey)
+		// ...
+	}
+
+And that's all about the basic usage. We discuss some other ideas below.
+
+Any type can be stored in the context. To enforce a given type, make the key
+private and wrap Get() and Set() to accept and return values of a specific
+type:
+
+	type key int
+
+	const mykey key = 0
+
+	// GetMyKey returns a value for this package from the request values.
+	func GetMyKey(r *http.Request) SomeType {
+		if rv := context.Get(r, mykey); rv != nil {
+			return rv.(SomeType)
+		}
+		return nil
+	}
+
+	// SetMyKey sets a value for this package in the request values.
+	func SetMyKey(r *http.Request, val SomeType) {
+		context.Set(r, mykey, val)
+	}
+
+Variables must be cleared at the end of a request, to remove all values
+that were stored. This can be done in an http.Handler, after a request was
+served. Just call Clear() passing the request:
+
+	context.Clear(r)
+
+...or use ClearHandler(), which conveniently wraps an http.Handler to clear
+variables at the end of a request lifetime.
+
+The Routers from the packages gorilla/mux and gorilla/pat call Clear()
+so if you are using either of them you don't need to clear the context manually.
+*/
+package context
diff --git a/Godeps/_workspace/src/github.com/gorilla/mux/LICENSE b/Godeps/_workspace/src/github.com/gorilla/mux/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..0e5fb872800da9557f75a5650bb9d80c1c2cf715
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/mux/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2012 Rodrigo Moraes. 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/Godeps/_workspace/src/github.com/gorilla/mux/README.md b/Godeps/_workspace/src/github.com/gorilla/mux/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..f6db41ad81d920e88183eea58e7d3619954d4ded
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/mux/README.md
@@ -0,0 +1,6 @@
+mux
+===
+
+gorilla/mux is a powerful URL router and dispatcher.
+
+Read the full documentation here: http://www.gorillatoolkit.org/pkg/mux
diff --git a/Godeps/_workspace/src/github.com/gorilla/mux/bench_test.go b/Godeps/_workspace/src/github.com/gorilla/mux/bench_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..c5f97b2b2a80b42d6cd21f2b3de9f9a0d3f5e788
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/mux/bench_test.go
@@ -0,0 +1,21 @@
+// Copyright 2012 The Gorilla 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 mux
+
+import (
+	"net/http"
+	"testing"
+)
+
+func BenchmarkMux(b *testing.B) {
+	router := new(Router)
+	handler := func(w http.ResponseWriter, r *http.Request) {}
+	router.HandleFunc("/v1/{v1}", handler)
+
+	request, _ := http.NewRequest("GET", "/v1/anything", nil)
+	for i := 0; i < b.N; i++ {
+		router.ServeHTTP(nil, request)
+	}
+}
diff --git a/Godeps/_workspace/src/github.com/gorilla/mux/doc.go b/Godeps/_workspace/src/github.com/gorilla/mux/doc.go
new file mode 100644
index 0000000000000000000000000000000000000000..8ee5540a4f900615272897ced1b07d6b35d5d685
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/mux/doc.go
@@ -0,0 +1,199 @@
+// Copyright 2012 The Gorilla 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 gorilla/mux implements a request router and dispatcher.
+
+The name mux stands for "HTTP request multiplexer". Like the standard
+http.ServeMux, mux.Router matches incoming requests against a list of
+registered routes and calls a handler for the route that matches the URL
+or other conditions. The main features are:
+
+	* Requests can be matched based on URL host, path, path prefix, schemes,
+	  header and query values, HTTP methods or using custom matchers.
+	* URL hosts and paths can have variables with an optional regular
+	  expression.
+	* Registered URLs can be built, or "reversed", which helps maintaining
+	  references to resources.
+	* Routes can be used as subrouters: nested routes are only tested if the
+	  parent route matches. This is useful to define groups of routes that
+	  share common conditions like a host, a path prefix or other repeated
+	  attributes. As a bonus, this optimizes request matching.
+	* It implements the http.Handler interface so it is compatible with the
+	  standard http.ServeMux.
+
+Let's start registering a couple of URL paths and handlers:
+
+	func main() {
+		r := mux.NewRouter()
+		r.HandleFunc("/", HomeHandler)
+		r.HandleFunc("/products", ProductsHandler)
+		r.HandleFunc("/articles", ArticlesHandler)
+		http.Handle("/", r)
+	}
+
+Here we register three routes mapping URL paths to handlers. This is
+equivalent to how http.HandleFunc() works: if an incoming request URL matches
+one of the paths, the corresponding handler is called passing
+(http.ResponseWriter, *http.Request) as parameters.
+
+Paths can have variables. They are defined using the format {name} or
+{name:pattern}. If a regular expression pattern is not defined, the matched
+variable will be anything until the next slash. For example:
+
+	r := mux.NewRouter()
+	r.HandleFunc("/products/{key}", ProductHandler)
+	r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler)
+	r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler)
+
+The names are used to create a map of route variables which can be retrieved
+calling mux.Vars():
+
+	vars := mux.Vars(request)
+	category := vars["category"]
+
+And this is all you need to know about the basic usage. More advanced options
+are explained below.
+
+Routes can also be restricted to a domain or subdomain. Just define a host
+pattern to be matched. They can also have variables:
+
+	r := mux.NewRouter()
+	// Only matches if domain is "www.domain.com".
+	r.Host("www.domain.com")
+	// Matches a dynamic subdomain.
+	r.Host("{subdomain:[a-z]+}.domain.com")
+
+There are several other matchers that can be added. To match path prefixes:
+
+	r.PathPrefix("/products/")
+
+...or HTTP methods:
+
+	r.Methods("GET", "POST")
+
+...or URL schemes:
+
+	r.Schemes("https")
+
+...or header values:
+
+	r.Headers("X-Requested-With", "XMLHttpRequest")
+
+...or query values:
+
+	r.Queries("key", "value")
+
+...or to use a custom matcher function:
+
+	r.MatcherFunc(func(r *http.Request, rm *RouteMatch) bool {
+		return r.ProtoMajor == 0
+    })
+
+...and finally, it is possible to combine several matchers in a single route:
+
+	r.HandleFunc("/products", ProductsHandler).
+	  Host("www.domain.com").
+	  Methods("GET").
+	  Schemes("http")
+
+Setting the same matching conditions again and again can be boring, so we have
+a way to group several routes that share the same requirements.
+We call it "subrouting".
+
+For example, let's say we have several URLs that should only match when the
+host is "www.domain.com". Create a route for that host and get a "subrouter"
+from it:
+
+	r := mux.NewRouter()
+	s := r.Host("www.domain.com").Subrouter()
+
+Then register routes in the subrouter:
+
+	s.HandleFunc("/products/", ProductsHandler)
+	s.HandleFunc("/products/{key}", ProductHandler)
+	s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler)
+
+The three URL paths we registered above will only be tested if the domain is
+"www.domain.com", because the subrouter is tested first. This is not
+only convenient, but also optimizes request matching. You can create
+subrouters combining any attribute matchers accepted by a route.
+
+Subrouters can be used to create domain or path "namespaces": you define
+subrouters in a central place and then parts of the app can register its
+paths relatively to a given subrouter.
+
+There's one more thing about subroutes. When a subrouter has a path prefix,
+the inner routes use it as base for their paths:
+
+	r := mux.NewRouter()
+	s := r.PathPrefix("/products").Subrouter()
+	// "/products/"
+	s.HandleFunc("/", ProductsHandler)
+	// "/products/{key}/"
+	s.HandleFunc("/{key}/", ProductHandler)
+	// "/products/{key}/details"
+	s.HandleFunc("/{key}/details"), ProductDetailsHandler)
+
+Now let's see how to build registered URLs.
+
+Routes can be named. All routes that define a name can have their URLs built,
+or "reversed". We define a name calling Name() on a route. For example:
+
+	r := mux.NewRouter()
+	r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).
+	  Name("article")
+
+To build a URL, get the route and call the URL() method, passing a sequence of
+key/value pairs for the route variables. For the previous route, we would do:
+
+	url, err := r.Get("article").URL("category", "technology", "id", "42")
+
+...and the result will be a url.URL with the following path:
+
+	"/articles/technology/42"
+
+This also works for host variables:
+
+	r := mux.NewRouter()
+	r.Host("{subdomain}.domain.com").
+	  Path("/articles/{category}/{id:[0-9]+}").
+	  HandlerFunc(ArticleHandler).
+	  Name("article")
+
+	// url.String() will be "http://news.domain.com/articles/technology/42"
+	url, err := r.Get("article").URL("subdomain", "news",
+									 "category", "technology",
+									 "id", "42")
+
+All variables defined in the route are required, and their values must
+conform to the corresponding patterns. These requirements guarantee that a
+generated URL will always match a registered route -- the only exception is
+for explicitly defined "build-only" routes which never match.
+
+There's also a way to build only the URL host or path for a route:
+use the methods URLHost() or URLPath() instead. For the previous route,
+we would do:
+
+	// "http://news.domain.com/"
+	host, err := r.Get("article").URLHost("subdomain", "news")
+
+	// "/articles/technology/42"
+	path, err := r.Get("article").URLPath("category", "technology", "id", "42")
+
+And if you use subrouters, host and path defined separately can be built
+as well:
+
+	r := mux.NewRouter()
+	s := r.Host("{subdomain}.domain.com").Subrouter()
+	s.Path("/articles/{category}/{id:[0-9]+}").
+	  HandlerFunc(ArticleHandler).
+	  Name("article")
+
+	// "http://news.domain.com/articles/technology/42"
+	url, err := r.Get("article").URL("subdomain", "news",
+									 "category", "technology",
+									 "id", "42")
+*/
+package mux
diff --git a/Godeps/_workspace/src/github.com/gorilla/mux/mux.go b/Godeps/_workspace/src/github.com/gorilla/mux/mux.go
new file mode 100644
index 0000000000000000000000000000000000000000..385717394c90acd7ddcf897fa9199345d59b06d7
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/mux/mux.go
@@ -0,0 +1,335 @@
+// Copyright 2012 The Gorilla 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 mux
+
+import (
+	"fmt"
+	"net/http"
+	"path"
+
+	"github.com/gorilla/context"
+)
+
+// NewRouter returns a new router instance.
+func NewRouter() *Router {
+	return &Router{namedRoutes: make(map[string]*Route)}
+}
+
+// Router registers routes to be matched and dispatches a handler.
+//
+// It implements the http.Handler interface, so it can be registered to serve
+// requests:
+//
+//     var router = mux.NewRouter()
+//
+//     func main() {
+//         http.Handle("/", router)
+//     }
+//
+// Or, for Google App Engine, register it in a init() function:
+//
+//     func init() {
+//         http.Handle("/", router)
+//     }
+//
+// This will send all incoming requests to the router.
+type Router struct {
+	// Configurable Handler to be used when no route matches.
+	NotFoundHandler http.Handler
+	// Parent route, if this is a subrouter.
+	parent parentRoute
+	// Routes to be matched, in order.
+	routes []*Route
+	// Routes by name for URL building.
+	namedRoutes map[string]*Route
+	// See Router.StrictSlash(). This defines the flag for new routes.
+	strictSlash bool
+}
+
+// Match matches registered routes against the request.
+func (r *Router) Match(req *http.Request, match *RouteMatch) bool {
+	for _, route := range r.routes {
+		if route.Match(req, match) {
+			return true
+		}
+	}
+	return false
+}
+
+// ServeHTTP dispatches the handler registered in the matched route.
+//
+// When there is a match, the route variables can be retrieved calling
+// mux.Vars(request).
+func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+	// Clean path to canonical form and redirect.
+	if p := cleanPath(req.URL.Path); p != req.URL.Path {
+		w.Header().Set("Location", p)
+		w.WriteHeader(http.StatusMovedPermanently)
+		return
+	}
+	var match RouteMatch
+	var handler http.Handler
+	if r.Match(req, &match) {
+		handler = match.Handler
+		setVars(req, match.Vars)
+		setCurrentRoute(req, match.Route)
+	}
+	if handler == nil {
+		if r.NotFoundHandler == nil {
+			r.NotFoundHandler = http.NotFoundHandler()
+		}
+		handler = r.NotFoundHandler
+	}
+	defer context.Clear(req)
+	handler.ServeHTTP(w, req)
+}
+
+// Get returns a route registered with the given name.
+func (r *Router) Get(name string) *Route {
+	return r.getNamedRoutes()[name]
+}
+
+// GetRoute returns a route registered with the given name. This method
+// was renamed to Get() and remains here for backwards compatibility.
+func (r *Router) GetRoute(name string) *Route {
+	return r.getNamedRoutes()[name]
+}
+
+// StrictSlash defines the slash behavior for new routes.
+//
+// When true, if the route path is "/path/", accessing "/path" will redirect
+// to the former and vice versa.
+//
+// Special case: when a route sets a path prefix, strict slash is
+// automatically set to false for that route because the redirect behavior
+// can't be determined for prefixes.
+func (r *Router) StrictSlash(value bool) *Router {
+	r.strictSlash = value
+	return r
+}
+
+// ----------------------------------------------------------------------------
+// parentRoute
+// ----------------------------------------------------------------------------
+
+// getNamedRoutes returns the map where named routes are registered.
+func (r *Router) getNamedRoutes() map[string]*Route {
+	if r.namedRoutes == nil {
+		if r.parent != nil {
+			r.namedRoutes = r.parent.getNamedRoutes()
+		} else {
+			r.namedRoutes = make(map[string]*Route)
+		}
+	}
+	return r.namedRoutes
+}
+
+// getRegexpGroup returns regexp definitions from the parent route, if any.
+func (r *Router) getRegexpGroup() *routeRegexpGroup {
+	if r.parent != nil {
+		return r.parent.getRegexpGroup()
+	}
+	return nil
+}
+
+// ----------------------------------------------------------------------------
+// Route factories
+// ----------------------------------------------------------------------------
+
+// NewRoute registers an empty route.
+func (r *Router) NewRoute() *Route {
+	route := &Route{parent: r, strictSlash: r.strictSlash}
+	r.routes = append(r.routes, route)
+	return route
+}
+
+// Handle registers a new route with a matcher for the URL path.
+// See Route.Path() and Route.Handler().
+func (r *Router) Handle(path string, handler http.Handler) *Route {
+	return r.NewRoute().Path(path).Handler(handler)
+}
+
+// HandleFunc registers a new route with a matcher for the URL path.
+// See Route.Path() and Route.HandlerFunc().
+func (r *Router) HandleFunc(path string, f func(http.ResponseWriter,
+	*http.Request)) *Route {
+	return r.NewRoute().Path(path).HandlerFunc(f)
+}
+
+// Headers registers a new route with a matcher for request header values.
+// See Route.Headers().
+func (r *Router) Headers(pairs ...string) *Route {
+	return r.NewRoute().Headers(pairs...)
+}
+
+// Host registers a new route with a matcher for the URL host.
+// See Route.Host().
+func (r *Router) Host(tpl string) *Route {
+	return r.NewRoute().Host(tpl)
+}
+
+// MatcherFunc registers a new route with a custom matcher function.
+// See Route.MatcherFunc().
+func (r *Router) MatcherFunc(f MatcherFunc) *Route {
+	return r.NewRoute().MatcherFunc(f)
+}
+
+// Methods registers a new route with a matcher for HTTP methods.
+// See Route.Methods().
+func (r *Router) Methods(methods ...string) *Route {
+	return r.NewRoute().Methods(methods...)
+}
+
+// Path registers a new route with a matcher for the URL path.
+// See Route.Path().
+func (r *Router) Path(tpl string) *Route {
+	return r.NewRoute().Path(tpl)
+}
+
+// PathPrefix registers a new route with a matcher for the URL path prefix.
+// See Route.PathPrefix().
+func (r *Router) PathPrefix(tpl string) *Route {
+	return r.NewRoute().PathPrefix(tpl)
+}
+
+// Queries registers a new route with a matcher for URL query values.
+// See Route.Queries().
+func (r *Router) Queries(pairs ...string) *Route {
+	return r.NewRoute().Queries(pairs...)
+}
+
+// Schemes registers a new route with a matcher for URL schemes.
+// See Route.Schemes().
+func (r *Router) Schemes(schemes ...string) *Route {
+	return r.NewRoute().Schemes(schemes...)
+}
+
+// ----------------------------------------------------------------------------
+// Context
+// ----------------------------------------------------------------------------
+
+// RouteMatch stores information about a matched route.
+type RouteMatch struct {
+	Route   *Route
+	Handler http.Handler
+	Vars    map[string]string
+}
+
+type contextKey int
+
+const (
+	varsKey contextKey = iota
+	routeKey
+)
+
+// Vars returns the route variables for the current request, if any.
+func Vars(r *http.Request) map[string]string {
+	if rv := context.Get(r, varsKey); rv != nil {
+		return rv.(map[string]string)
+	}
+	return nil
+}
+
+// CurrentRoute returns the matched route for the current request, if any.
+func CurrentRoute(r *http.Request) *Route {
+	if rv := context.Get(r, routeKey); rv != nil {
+		return rv.(*Route)
+	}
+	return nil
+}
+
+func setVars(r *http.Request, val interface{}) {
+	context.Set(r, varsKey, val)
+}
+
+func setCurrentRoute(r *http.Request, val interface{}) {
+	context.Set(r, routeKey, val)
+}
+
+// ----------------------------------------------------------------------------
+// Helpers
+// ----------------------------------------------------------------------------
+
+// cleanPath returns the canonical path for p, eliminating . and .. elements.
+// Borrowed from the net/http package.
+func cleanPath(p string) string {
+	if p == "" {
+		return "/"
+	}
+	if p[0] != '/' {
+		p = "/" + p
+	}
+	np := path.Clean(p)
+	// path.Clean removes trailing slash except for root;
+	// put the trailing slash back if necessary.
+	if p[len(p)-1] == '/' && np != "/" {
+		np += "/"
+	}
+	return np
+}
+
+// uniqueVars returns an error if two slices contain duplicated strings.
+func uniqueVars(s1, s2 []string) error {
+	for _, v1 := range s1 {
+		for _, v2 := range s2 {
+			if v1 == v2 {
+				return fmt.Errorf("mux: duplicated route variable %q", v2)
+			}
+		}
+	}
+	return nil
+}
+
+// mapFromPairs converts variadic string parameters to a string map.
+func mapFromPairs(pairs ...string) (map[string]string, error) {
+	length := len(pairs)
+	if length%2 != 0 {
+		return nil, fmt.Errorf(
+			"mux: number of parameters must be multiple of 2, got %v", pairs)
+	}
+	m := make(map[string]string, length/2)
+	for i := 0; i < length; i += 2 {
+		m[pairs[i]] = pairs[i+1]
+	}
+	return m, nil
+}
+
+// matchInArray returns true if the given string value is in the array.
+func matchInArray(arr []string, value string) bool {
+	for _, v := range arr {
+		if v == value {
+			return true
+		}
+	}
+	return false
+}
+
+// matchMap returns true if the given key/value pairs exist in a given map.
+func matchMap(toCheck map[string]string, toMatch map[string][]string,
+	canonicalKey bool) bool {
+	for k, v := range toCheck {
+		// Check if key exists.
+		if canonicalKey {
+			k = http.CanonicalHeaderKey(k)
+		}
+		if values := toMatch[k]; values == nil {
+			return false
+		} else if v != "" {
+			// If value was defined as an empty string we only check that the
+			// key exists. Otherwise we also check for equality.
+			valueExists := false
+			for _, value := range values {
+				if v == value {
+					valueExists = true
+					break
+				}
+			}
+			if !valueExists {
+				return false
+			}
+		}
+	}
+	return true
+}
diff --git a/Godeps/_workspace/src/github.com/gorilla/mux/mux_test.go b/Godeps/_workspace/src/github.com/gorilla/mux/mux_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..55159bd10d35ef3bd3ebf7a60560ac72819871b0
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/mux/mux_test.go
@@ -0,0 +1,723 @@
+// Copyright 2012 The Gorilla 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 mux
+
+import (
+	"fmt"
+	"net/http"
+	"testing"
+)
+
+type routeTest struct {
+	title       string            // title of the test
+	route       *Route            // the route being tested
+	request     *http.Request     // a request to test the route
+	vars        map[string]string // the expected vars of the match
+	host        string            // the expected host of the match
+	path        string            // the expected path of the match
+	shouldMatch bool              // whether the request is expected to match the route at all
+}
+
+func TestHost(t *testing.T) {
+	// newRequestHost a new request with a method, url, and host header
+	newRequestHost := func(method, url, host string) *http.Request {
+		req, err := http.NewRequest(method, url, nil)
+		if err != nil {
+			panic(err)
+		}
+		req.Host = host
+		return req
+	}
+
+	tests := []routeTest{
+		{
+			title:       "Host route match",
+			route:       new(Route).Host("aaa.bbb.ccc"),
+			request:     newRequest("GET", "http://aaa.bbb.ccc/111/222/333"),
+			vars:        map[string]string{},
+			host:        "aaa.bbb.ccc",
+			path:        "",
+			shouldMatch: true,
+		},
+		{
+			title:       "Host route, wrong host in request URL",
+			route:       new(Route).Host("aaa.bbb.ccc"),
+			request:     newRequest("GET", "http://aaa.222.ccc/111/222/333"),
+			vars:        map[string]string{},
+			host:        "aaa.bbb.ccc",
+			path:        "",
+			shouldMatch: false,
+		},
+		{
+			title:       "Host route with port, match",
+			route:       new(Route).Host("aaa.bbb.ccc:1234"),
+			request:     newRequest("GET", "http://aaa.bbb.ccc:1234/111/222/333"),
+			vars:        map[string]string{},
+			host:        "aaa.bbb.ccc:1234",
+			path:        "",
+			shouldMatch: true,
+		},
+		{
+			title:       "Host route with port, wrong port in request URL",
+			route:       new(Route).Host("aaa.bbb.ccc:1234"),
+			request:     newRequest("GET", "http://aaa.bbb.ccc:9999/111/222/333"),
+			vars:        map[string]string{},
+			host:        "aaa.bbb.ccc:1234",
+			path:        "",
+			shouldMatch: false,
+		},
+		{
+			title:       "Host route, match with host in request header",
+			route:       new(Route).Host("aaa.bbb.ccc"),
+			request:     newRequestHost("GET", "/111/222/333", "aaa.bbb.ccc"),
+			vars:        map[string]string{},
+			host:        "aaa.bbb.ccc",
+			path:        "",
+			shouldMatch: true,
+		},
+		{
+			title:       "Host route, wrong host in request header",
+			route:       new(Route).Host("aaa.bbb.ccc"),
+			request:     newRequestHost("GET", "/111/222/333", "aaa.222.ccc"),
+			vars:        map[string]string{},
+			host:        "aaa.bbb.ccc",
+			path:        "",
+			shouldMatch: false,
+		},
+		// BUG {new(Route).Host("aaa.bbb.ccc:1234"), newRequestHost("GET", "/111/222/333", "aaa.bbb.ccc:1234"), map[string]string{}, "aaa.bbb.ccc:1234", "", true},
+		{
+			title:       "Host route with port, wrong host in request header",
+			route:       new(Route).Host("aaa.bbb.ccc:1234"),
+			request:     newRequestHost("GET", "/111/222/333", "aaa.bbb.ccc:9999"),
+			vars:        map[string]string{},
+			host:        "aaa.bbb.ccc:1234",
+			path:        "",
+			shouldMatch: false,
+		},
+		{
+			title:       "Host route with pattern, match",
+			route:       new(Route).Host("aaa.{v1:[a-z]{3}}.ccc"),
+			request:     newRequest("GET", "http://aaa.bbb.ccc/111/222/333"),
+			vars:        map[string]string{"v1": "bbb"},
+			host:        "aaa.bbb.ccc",
+			path:        "",
+			shouldMatch: true,
+		},
+		{
+			title:       "Host route with pattern, wrong host in request URL",
+			route:       new(Route).Host("aaa.{v1:[a-z]{3}}.ccc"),
+			request:     newRequest("GET", "http://aaa.222.ccc/111/222/333"),
+			vars:        map[string]string{"v1": "bbb"},
+			host:        "aaa.bbb.ccc",
+			path:        "",
+			shouldMatch: false,
+		},
+		{
+			title:       "Host route with multiple patterns, match",
+			route:       new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}"),
+			request:     newRequest("GET", "http://aaa.bbb.ccc/111/222/333"),
+			vars:        map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc"},
+			host:        "aaa.bbb.ccc",
+			path:        "",
+			shouldMatch: true,
+		},
+		{
+			title:       "Host route with multiple patterns, wrong host in request URL",
+			route:       new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}"),
+			request:     newRequest("GET", "http://aaa.222.ccc/111/222/333"),
+			vars:        map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc"},
+			host:        "aaa.bbb.ccc",
+			path:        "",
+			shouldMatch: false,
+		},
+	}
+	for _, test := range tests {
+		testRoute(t, test)
+	}
+}
+
+func TestPath(t *testing.T) {
+	tests := []routeTest{
+		{
+			title:       "Path route, match",
+			route:       new(Route).Path("/111/222/333"),
+			request:     newRequest("GET", "http://localhost/111/222/333"),
+			vars:        map[string]string{},
+			host:        "",
+			path:        "/111/222/333",
+			shouldMatch: true,
+		},
+		{
+			title:       "Path route, wrong path in request in request URL",
+			route:       new(Route).Path("/111/222/333"),
+			request:     newRequest("GET", "http://localhost/1/2/3"),
+			vars:        map[string]string{},
+			host:        "",
+			path:        "/111/222/333",
+			shouldMatch: false,
+		},
+		{
+			title:       "Path route with pattern, match",
+			route:       new(Route).Path("/111/{v1:[0-9]{3}}/333"),
+			request:     newRequest("GET", "http://localhost/111/222/333"),
+			vars:        map[string]string{"v1": "222"},
+			host:        "",
+			path:        "/111/222/333",
+			shouldMatch: true,
+		},
+		{
+			title:       "Path route with pattern, URL in request does not match",
+			route:       new(Route).Path("/111/{v1:[0-9]{3}}/333"),
+			request:     newRequest("GET", "http://localhost/111/aaa/333"),
+			vars:        map[string]string{"v1": "222"},
+			host:        "",
+			path:        "/111/222/333",
+			shouldMatch: false,
+		},
+		{
+			title:       "Path route with multiple patterns, match",
+			route:       new(Route).Path("/{v1:[0-9]{3}}/{v2:[0-9]{3}}/{v3:[0-9]{3}}"),
+			request:     newRequest("GET", "http://localhost/111/222/333"),
+			vars:        map[string]string{"v1": "111", "v2": "222", "v3": "333"},
+			host:        "",
+			path:        "/111/222/333",
+			shouldMatch: true,
+		},
+		{
+			title:       "Path route with multiple patterns, URL in request does not match",
+			route:       new(Route).Path("/{v1:[0-9]{3}}/{v2:[0-9]{3}}/{v3:[0-9]{3}}"),
+			request:     newRequest("GET", "http://localhost/111/aaa/333"),
+			vars:        map[string]string{"v1": "111", "v2": "222", "v3": "333"},
+			host:        "",
+			path:        "/111/222/333",
+			shouldMatch: false,
+		},
+	}
+
+	for _, test := range tests {
+		testRoute(t, test)
+	}
+}
+
+func TestPathPrefix(t *testing.T) {
+	tests := []routeTest{
+		{
+			title:       "PathPrefix route, match",
+			route:       new(Route).PathPrefix("/111"),
+			request:     newRequest("GET", "http://localhost/111/222/333"),
+			vars:        map[string]string{},
+			host:        "",
+			path:        "/111",
+			shouldMatch: true,
+		},
+		{
+			title:       "PathPrefix route, URL prefix in request does not match",
+			route:       new(Route).PathPrefix("/111"),
+			request:     newRequest("GET", "http://localhost/1/2/3"),
+			vars:        map[string]string{},
+			host:        "",
+			path:        "/111",
+			shouldMatch: false,
+		},
+		{
+			title:       "PathPrefix route with pattern, match",
+			route:       new(Route).PathPrefix("/111/{v1:[0-9]{3}}"),
+			request:     newRequest("GET", "http://localhost/111/222/333"),
+			vars:        map[string]string{"v1": "222"},
+			host:        "",
+			path:        "/111/222",
+			shouldMatch: true,
+		},
+		{
+			title:       "PathPrefix route with pattern, URL prefix in request does not match",
+			route:       new(Route).PathPrefix("/111/{v1:[0-9]{3}}"),
+			request:     newRequest("GET", "http://localhost/111/aaa/333"),
+			vars:        map[string]string{"v1": "222"},
+			host:        "",
+			path:        "/111/222",
+			shouldMatch: false,
+		},
+		{
+			title:       "PathPrefix route with multiple patterns, match",
+			route:       new(Route).PathPrefix("/{v1:[0-9]{3}}/{v2:[0-9]{3}}"),
+			request:     newRequest("GET", "http://localhost/111/222/333"),
+			vars:        map[string]string{"v1": "111", "v2": "222"},
+			host:        "",
+			path:        "/111/222",
+			shouldMatch: true,
+		},
+		{
+			title:       "PathPrefix route with multiple patterns, URL prefix in request does not match",
+			route:       new(Route).PathPrefix("/{v1:[0-9]{3}}/{v2:[0-9]{3}}"),
+			request:     newRequest("GET", "http://localhost/111/aaa/333"),
+			vars:        map[string]string{"v1": "111", "v2": "222"},
+			host:        "",
+			path:        "/111/222",
+			shouldMatch: false,
+		},
+	}
+
+	for _, test := range tests {
+		testRoute(t, test)
+	}
+}
+
+func TestHostPath(t *testing.T) {
+	tests := []routeTest{
+		{
+			title:       "Host and Path route, match",
+			route:       new(Route).Host("aaa.bbb.ccc").Path("/111/222/333"),
+			request:     newRequest("GET", "http://aaa.bbb.ccc/111/222/333"),
+			vars:        map[string]string{},
+			host:        "",
+			path:        "",
+			shouldMatch: true,
+		},
+		{
+			title:       "Host and Path route, wrong host in request URL",
+			route:       new(Route).Host("aaa.bbb.ccc").Path("/111/222/333"),
+			request:     newRequest("GET", "http://aaa.222.ccc/111/222/333"),
+			vars:        map[string]string{},
+			host:        "",
+			path:        "",
+			shouldMatch: false,
+		},
+		{
+			title:       "Host and Path route with pattern, match",
+			route:       new(Route).Host("aaa.{v1:[a-z]{3}}.ccc").Path("/111/{v2:[0-9]{3}}/333"),
+			request:     newRequest("GET", "http://aaa.bbb.ccc/111/222/333"),
+			vars:        map[string]string{"v1": "bbb", "v2": "222"},
+			host:        "aaa.bbb.ccc",
+			path:        "/111/222/333",
+			shouldMatch: true,
+		},
+		{
+			title:       "Host and Path route with pattern, URL in request does not match",
+			route:       new(Route).Host("aaa.{v1:[a-z]{3}}.ccc").Path("/111/{v2:[0-9]{3}}/333"),
+			request:     newRequest("GET", "http://aaa.222.ccc/111/222/333"),
+			vars:        map[string]string{"v1": "bbb", "v2": "222"},
+			host:        "aaa.bbb.ccc",
+			path:        "/111/222/333",
+			shouldMatch: false,
+		},
+		{
+			title:       "Host and Path route with multiple patterns, match",
+			route:       new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}").Path("/{v4:[0-9]{3}}/{v5:[0-9]{3}}/{v6:[0-9]{3}}"),
+			request:     newRequest("GET", "http://aaa.bbb.ccc/111/222/333"),
+			vars:        map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc", "v4": "111", "v5": "222", "v6": "333"},
+			host:        "aaa.bbb.ccc",
+			path:        "/111/222/333",
+			shouldMatch: true,
+		},
+		{
+			title:       "Host and Path route with multiple patterns, URL in request does not match",
+			route:       new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}").Path("/{v4:[0-9]{3}}/{v5:[0-9]{3}}/{v6:[0-9]{3}}"),
+			request:     newRequest("GET", "http://aaa.222.ccc/111/222/333"),
+			vars:        map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc", "v4": "111", "v5": "222", "v6": "333"},
+			host:        "aaa.bbb.ccc",
+			path:        "/111/222/333",
+			shouldMatch: false,
+		},
+	}
+
+	for _, test := range tests {
+		testRoute(t, test)
+	}
+}
+
+func TestHeaders(t *testing.T) {
+	// newRequestHeaders creates a new request with a method, url, and headers
+	newRequestHeaders := func(method, url string, headers map[string]string) *http.Request {
+		req, err := http.NewRequest(method, url, nil)
+		if err != nil {
+			panic(err)
+		}
+		for k, v := range headers {
+			req.Header.Add(k, v)
+		}
+		return req
+	}
+
+	tests := []routeTest{
+		{
+			title:       "Headers route, match",
+			route:       new(Route).Headers("foo", "bar", "baz", "ding"),
+			request:     newRequestHeaders("GET", "http://localhost", map[string]string{"foo": "bar", "baz": "ding"}),
+			vars:        map[string]string{},
+			host:        "",
+			path:        "",
+			shouldMatch: true,
+		},
+		{
+			title:       "Headers route, bad header values",
+			route:       new(Route).Headers("foo", "bar", "baz", "ding"),
+			request:     newRequestHeaders("GET", "http://localhost", map[string]string{"foo": "bar", "baz": "dong"}),
+			vars:        map[string]string{},
+			host:        "",
+			path:        "",
+			shouldMatch: false,
+		},
+	}
+
+	for _, test := range tests {
+		testRoute(t, test)
+	}
+
+}
+
+func TestMethods(t *testing.T) {
+	tests := []routeTest{
+		{
+			title:       "Methods route, match GET",
+			route:       new(Route).Methods("GET", "POST"),
+			request:     newRequest("GET", "http://localhost"),
+			vars:        map[string]string{},
+			host:        "",
+			path:        "",
+			shouldMatch: true,
+		},
+		{
+			title:       "Methods route, match POST",
+			route:       new(Route).Methods("GET", "POST"),
+			request:     newRequest("POST", "http://localhost"),
+			vars:        map[string]string{},
+			host:        "",
+			path:        "",
+			shouldMatch: true,
+		},
+		{
+			title:       "Methods route, bad method",
+			route:       new(Route).Methods("GET", "POST"),
+			request:     newRequest("PUT", "http://localhost"),
+			vars:        map[string]string{},
+			host:        "",
+			path:        "",
+			shouldMatch: false,
+		},
+	}
+
+	for _, test := range tests {
+		testRoute(t, test)
+	}
+}
+
+func TestQueries(t *testing.T) {
+	tests := []routeTest{
+		{
+			title:       "Queries route, match",
+			route:       new(Route).Queries("foo", "bar", "baz", "ding"),
+			request:     newRequest("GET", "http://localhost?foo=bar&baz=ding"),
+			vars:        map[string]string{},
+			host:        "",
+			path:        "",
+			shouldMatch: true,
+		},
+		{
+			title:       "Queries route, bad query",
+			route:       new(Route).Queries("foo", "bar", "baz", "ding"),
+			request:     newRequest("GET", "http://localhost?foo=bar&baz=dong"),
+			vars:        map[string]string{},
+			host:        "",
+			path:        "",
+			shouldMatch: false,
+		},
+	}
+
+	for _, test := range tests {
+		testRoute(t, test)
+	}
+}
+
+func TestSchemes(t *testing.T) {
+	tests := []routeTest{
+		// Schemes
+		{
+			title:       "Schemes route, match https",
+			route:       new(Route).Schemes("https", "ftp"),
+			request:     newRequest("GET", "https://localhost"),
+			vars:        map[string]string{},
+			host:        "",
+			path:        "",
+			shouldMatch: true,
+		},
+		{
+			title:       "Schemes route, match ftp",
+			route:       new(Route).Schemes("https", "ftp"),
+			request:     newRequest("GET", "ftp://localhost"),
+			vars:        map[string]string{},
+			host:        "",
+			path:        "",
+			shouldMatch: true,
+		},
+		{
+			title:       "Schemes route, bad scheme",
+			route:       new(Route).Schemes("https", "ftp"),
+			request:     newRequest("GET", "http://localhost"),
+			vars:        map[string]string{},
+			host:        "",
+			path:        "",
+			shouldMatch: false,
+		},
+	}
+	for _, test := range tests {
+		testRoute(t, test)
+	}
+}
+
+func TestMatcherFunc(t *testing.T) {
+	m := func(r *http.Request, m *RouteMatch) bool {
+		if r.URL.Host == "aaa.bbb.ccc" {
+			return true
+		}
+		return false
+	}
+
+	tests := []routeTest{
+		{
+			title:       "MatchFunc route, match",
+			route:       new(Route).MatcherFunc(m),
+			request:     newRequest("GET", "http://aaa.bbb.ccc"),
+			vars:        map[string]string{},
+			host:        "",
+			path:        "",
+			shouldMatch: true,
+		},
+		{
+			title:       "MatchFunc route, non-match",
+			route:       new(Route).MatcherFunc(m),
+			request:     newRequest("GET", "http://aaa.222.ccc"),
+			vars:        map[string]string{},
+			host:        "",
+			path:        "",
+			shouldMatch: false,
+		},
+	}
+
+	for _, test := range tests {
+		testRoute(t, test)
+	}
+}
+
+func TestSubRouter(t *testing.T) {
+	subrouter1 := new(Route).Host("{v1:[a-z]+}.google.com").Subrouter()
+	subrouter2 := new(Route).PathPrefix("/foo/{v1}").Subrouter()
+
+	tests := []routeTest{
+		{
+			route:       subrouter1.Path("/{v2:[a-z]+}"),
+			request:     newRequest("GET", "http://aaa.google.com/bbb"),
+			vars:        map[string]string{"v1": "aaa", "v2": "bbb"},
+			host:        "aaa.google.com",
+			path:        "/bbb",
+			shouldMatch: true,
+		},
+		{
+			route:       subrouter1.Path("/{v2:[a-z]+}"),
+			request:     newRequest("GET", "http://111.google.com/111"),
+			vars:        map[string]string{"v1": "aaa", "v2": "bbb"},
+			host:        "aaa.google.com",
+			path:        "/bbb",
+			shouldMatch: false,
+		},
+		{
+			route:       subrouter2.Path("/baz/{v2}"),
+			request:     newRequest("GET", "http://localhost/foo/bar/baz/ding"),
+			vars:        map[string]string{"v1": "bar", "v2": "ding"},
+			host:        "",
+			path:        "/foo/bar/baz/ding",
+			shouldMatch: true,
+		},
+		{
+			route:       subrouter2.Path("/baz/{v2}"),
+			request:     newRequest("GET", "http://localhost/foo/bar"),
+			vars:        map[string]string{"v1": "bar", "v2": "ding"},
+			host:        "",
+			path:        "/foo/bar/baz/ding",
+			shouldMatch: false,
+		},
+	}
+
+	for _, test := range tests {
+		testRoute(t, test)
+	}
+}
+
+func TestNamedRoutes(t *testing.T) {
+	r1 := NewRouter()
+	r1.NewRoute().Name("a")
+	r1.NewRoute().Name("b")
+	r1.NewRoute().Name("c")
+
+	r2 := r1.NewRoute().Subrouter()
+	r2.NewRoute().Name("d")
+	r2.NewRoute().Name("e")
+	r2.NewRoute().Name("f")
+
+	r3 := r2.NewRoute().Subrouter()
+	r3.NewRoute().Name("g")
+	r3.NewRoute().Name("h")
+	r3.NewRoute().Name("i")
+
+	if r1.namedRoutes == nil || len(r1.namedRoutes) != 9 {
+		t.Errorf("Expected 9 named routes, got %v", r1.namedRoutes)
+	} else if r1.Get("i") == nil {
+		t.Errorf("Subroute name not registered")
+	}
+}
+
+func TestStrictSlash(t *testing.T) {
+	var r *Router
+	var req *http.Request
+	var route *Route
+	var match *RouteMatch
+	var matched bool
+
+	// StrictSlash should be ignored for path prefix.
+	// So we register a route ending in slash but it doesn't attempt to add
+	// the slash for a path not ending in slash.
+	r = NewRouter()
+	r.StrictSlash(true)
+	route = r.NewRoute().PathPrefix("/static/")
+	req, _ = http.NewRequest("GET", "http://localhost/static/logo.png", nil)
+	match = new(RouteMatch)
+	matched = r.Match(req, match)
+	if !matched {
+		t.Errorf("Should match request %q -- %v", req.URL.Path, getRouteTemplate(route))
+	}
+	if match.Handler != nil {
+		t.Errorf("Should not redirect")
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Helpers
+// ----------------------------------------------------------------------------
+
+func getRouteTemplate(route *Route) string {
+	host, path := "none", "none"
+	if route.regexp != nil {
+		if route.regexp.host != nil {
+			host = route.regexp.host.template
+		}
+		if route.regexp.path != nil {
+			path = route.regexp.path.template
+		}
+	}
+	return fmt.Sprintf("Host: %v, Path: %v", host, path)
+}
+
+func testRoute(t *testing.T, test routeTest) {
+	request := test.request
+	route := test.route
+	vars := test.vars
+	shouldMatch := test.shouldMatch
+	host := test.host
+	path := test.path
+	url := test.host + test.path
+
+	var match RouteMatch
+	ok := route.Match(request, &match)
+	if ok != shouldMatch {
+		msg := "Should match"
+		if !shouldMatch {
+			msg = "Should not match"
+		}
+		t.Errorf("(%v) %v:\nRoute: %#v\nRequest: %#v\nVars: %v\n", test.title, msg, route, request, vars)
+		return
+	}
+	if shouldMatch {
+		if test.vars != nil && !stringMapEqual(test.vars, match.Vars) {
+			t.Errorf("(%v) Vars not equal: expected %v, got %v", test.title, vars, match.Vars)
+			return
+		}
+		if host != "" {
+			u, _ := test.route.URLHost(mapToPairs(match.Vars)...)
+			if host != u.Host {
+				t.Errorf("(%v) URLHost not equal: expected %v, got %v -- %v", test.title, host, u.Host, getRouteTemplate(route))
+				return
+			}
+		}
+		if path != "" {
+			u, _ := route.URLPath(mapToPairs(match.Vars)...)
+			if path != u.Path {
+				t.Errorf("(%v) URLPath not equal: expected %v, got %v -- %v", test.title, path, u.Path, getRouteTemplate(route))
+				return
+			}
+		}
+		if url != "" {
+			u, _ := route.URL(mapToPairs(match.Vars)...)
+			if url != u.Host+u.Path {
+				t.Errorf("(%v) URL not equal: expected %v, got %v -- %v", test.title, url, u.Host+u.Path, getRouteTemplate(route))
+				return
+			}
+		}
+	}
+}
+
+// https://plus.google.com/101022900381697718949/posts/eWy6DjFJ6uW
+func TestSubrouterHeader(t *testing.T) {
+	expected := "func1 response"
+	func1 := func(w http.ResponseWriter, r *http.Request) {
+		fmt.Fprint(w, expected)
+	}
+	func2 := func(http.ResponseWriter, *http.Request) {}
+
+	r := NewRouter()
+	s := r.Headers("SomeSpecialHeader", "").Subrouter()
+	s.HandleFunc("/", func1).Name("func1")
+	r.HandleFunc("/", func2).Name("func2")
+
+	req, _ := http.NewRequest("GET", "http://localhost/", nil)
+	req.Header.Add("SomeSpecialHeader", "foo")
+	match := new(RouteMatch)
+	matched := r.Match(req, match)
+	if !matched {
+		t.Errorf("Should match request")
+	}
+	if match.Route.GetName() != "func1" {
+		t.Errorf("Expecting func1 handler, got %s", match.Route.GetName())
+	}
+	resp := NewRecorder()
+	match.Handler.ServeHTTP(resp, req)
+	if resp.Body.String() != expected {
+		t.Errorf("Expecting %q", expected)
+	}
+}
+
+// mapToPairs converts a string map to a slice of string pairs
+func mapToPairs(m map[string]string) []string {
+	var i int
+	p := make([]string, len(m)*2)
+	for k, v := range m {
+		p[i] = k
+		p[i+1] = v
+		i += 2
+	}
+	return p
+}
+
+// stringMapEqual checks the equality of two string maps
+func stringMapEqual(m1, m2 map[string]string) bool {
+	nil1 := m1 == nil
+	nil2 := m2 == nil
+	if nil1 != nil2 || len(m1) != len(m2) {
+		return false
+	}
+	for k, v := range m1 {
+		if v != m2[k] {
+			return false
+		}
+	}
+	return true
+}
+
+// newRequest is a helper function to create a new request with a method and url
+func newRequest(method, url string) *http.Request {
+	req, err := http.NewRequest(method, url, nil)
+	if err != nil {
+		panic(err)
+	}
+	return req
+}
diff --git a/Godeps/_workspace/src/github.com/gorilla/mux/old_test.go b/Godeps/_workspace/src/github.com/gorilla/mux/old_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..7e266bb6954e641f75f1ad5e73f3e7c8dcec9f9d
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/mux/old_test.go
@@ -0,0 +1,758 @@
+// Old tests ported to Go1. This is a mess. Want to drop it one day.
+
+// Copyright 2011 Gorilla 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 mux
+
+import (
+	"bytes"
+	"net/http"
+	"testing"
+)
+
+// ----------------------------------------------------------------------------
+// ResponseRecorder
+// ----------------------------------------------------------------------------
+// Copyright 2009 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.
+
+// ResponseRecorder is an implementation of http.ResponseWriter that
+// records its mutations for later inspection in tests.
+type ResponseRecorder struct {
+	Code      int           // the HTTP response code from WriteHeader
+	HeaderMap http.Header   // the HTTP response headers
+	Body      *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to
+	Flushed   bool
+}
+
+// NewRecorder returns an initialized ResponseRecorder.
+func NewRecorder() *ResponseRecorder {
+	return &ResponseRecorder{
+		HeaderMap: make(http.Header),
+		Body:      new(bytes.Buffer),
+	}
+}
+
+// DefaultRemoteAddr is the default remote address to return in RemoteAddr if
+// an explicit DefaultRemoteAddr isn't set on ResponseRecorder.
+const DefaultRemoteAddr = "1.2.3.4"
+
+// Header returns the response headers.
+func (rw *ResponseRecorder) Header() http.Header {
+	return rw.HeaderMap
+}
+
+// Write always succeeds and writes to rw.Body, if not nil.
+func (rw *ResponseRecorder) Write(buf []byte) (int, error) {
+	if rw.Body != nil {
+		rw.Body.Write(buf)
+	}
+	if rw.Code == 0 {
+		rw.Code = http.StatusOK
+	}
+	return len(buf), nil
+}
+
+// WriteHeader sets rw.Code.
+func (rw *ResponseRecorder) WriteHeader(code int) {
+	rw.Code = code
+}
+
+// Flush sets rw.Flushed to true.
+func (rw *ResponseRecorder) Flush() {
+	rw.Flushed = true
+}
+
+// ----------------------------------------------------------------------------
+
+func TestRouteMatchers(t *testing.T) {
+	var scheme, host, path, query, method string
+	var headers map[string]string
+	var resultVars map[bool]map[string]string
+
+	router := NewRouter()
+	router.NewRoute().Host("{var1}.google.com").
+		Path("/{var2:[a-z]+}/{var3:[0-9]+}").
+		Queries("foo", "bar").
+		Methods("GET").
+		Schemes("https").
+		Headers("x-requested-with", "XMLHttpRequest")
+	router.NewRoute().Host("www.{var4}.com").
+		PathPrefix("/foo/{var5:[a-z]+}/{var6:[0-9]+}").
+		Queries("baz", "ding").
+		Methods("POST").
+		Schemes("http").
+		Headers("Content-Type", "application/json")
+
+	reset := func() {
+		// Everything match.
+		scheme = "https"
+		host = "www.google.com"
+		path = "/product/42"
+		query = "?foo=bar"
+		method = "GET"
+		headers = map[string]string{"X-Requested-With": "XMLHttpRequest"}
+		resultVars = map[bool]map[string]string{
+			true:  map[string]string{"var1": "www", "var2": "product", "var3": "42"},
+			false: map[string]string{},
+		}
+	}
+
+	reset2 := func() {
+		// Everything match.
+		scheme = "http"
+		host = "www.google.com"
+		path = "/foo/product/42/path/that/is/ignored"
+		query = "?baz=ding"
+		method = "POST"
+		headers = map[string]string{"Content-Type": "application/json"}
+		resultVars = map[bool]map[string]string{
+			true:  map[string]string{"var4": "google", "var5": "product", "var6": "42"},
+			false: map[string]string{},
+		}
+	}
+
+	match := func(shouldMatch bool) {
+		url := scheme + "://" + host + path + query
+		request, _ := http.NewRequest(method, url, nil)
+		for key, value := range headers {
+			request.Header.Add(key, value)
+		}
+
+		var routeMatch RouteMatch
+		matched := router.Match(request, &routeMatch)
+		if matched != shouldMatch {
+			// Need better messages. :)
+			if matched {
+				t.Errorf("Should match.")
+			} else {
+				t.Errorf("Should not match.")
+			}
+		}
+
+		if matched {
+			currentRoute := routeMatch.Route
+			if currentRoute == nil {
+				t.Errorf("Expected a current route.")
+			}
+			vars := routeMatch.Vars
+			expectedVars := resultVars[shouldMatch]
+			if len(vars) != len(expectedVars) {
+				t.Errorf("Expected vars: %v Got: %v.", expectedVars, vars)
+			}
+			for name, value := range vars {
+				if expectedVars[name] != value {
+					t.Errorf("Expected vars: %v Got: %v.", expectedVars, vars)
+				}
+			}
+		}
+	}
+
+	// 1st route --------------------------------------------------------------
+
+	// Everything match.
+	reset()
+	match(true)
+
+	// Scheme doesn't match.
+	reset()
+	scheme = "http"
+	match(false)
+
+	// Host doesn't match.
+	reset()
+	host = "www.mygoogle.com"
+	match(false)
+
+	// Path doesn't match.
+	reset()
+	path = "/product/notdigits"
+	match(false)
+
+	// Query doesn't match.
+	reset()
+	query = "?foo=baz"
+	match(false)
+
+	// Method doesn't match.
+	reset()
+	method = "POST"
+	match(false)
+
+	// Header doesn't match.
+	reset()
+	headers = map[string]string{}
+	match(false)
+
+	// Everything match, again.
+	reset()
+	match(true)
+
+	// 2nd route --------------------------------------------------------------
+
+	// Everything match.
+	reset2()
+	match(true)
+
+	// Scheme doesn't match.
+	reset2()
+	scheme = "https"
+	match(false)
+
+	// Host doesn't match.
+	reset2()
+	host = "sub.google.com"
+	match(false)
+
+	// Path doesn't match.
+	reset2()
+	path = "/bar/product/42"
+	match(false)
+
+	// Query doesn't match.
+	reset2()
+	query = "?foo=baz"
+	match(false)
+
+	// Method doesn't match.
+	reset2()
+	method = "GET"
+	match(false)
+
+	// Header doesn't match.
+	reset2()
+	headers = map[string]string{}
+	match(false)
+
+	// Everything match, again.
+	reset2()
+	match(true)
+}
+
+type headerMatcherTest struct {
+	matcher headerMatcher
+	headers map[string]string
+	result  bool
+}
+
+var headerMatcherTests = []headerMatcherTest{
+	{
+		matcher: headerMatcher(map[string]string{"x-requested-with": "XMLHttpRequest"}),
+		headers: map[string]string{"X-Requested-With": "XMLHttpRequest"},
+		result:  true,
+	},
+	{
+		matcher: headerMatcher(map[string]string{"x-requested-with": ""}),
+		headers: map[string]string{"X-Requested-With": "anything"},
+		result:  true,
+	},
+	{
+		matcher: headerMatcher(map[string]string{"x-requested-with": "XMLHttpRequest"}),
+		headers: map[string]string{},
+		result:  false,
+	},
+}
+
+type hostMatcherTest struct {
+	matcher *Route
+	url     string
+	vars    map[string]string
+	result  bool
+}
+
+var hostMatcherTests = []hostMatcherTest{
+	{
+		matcher: NewRouter().NewRoute().Host("{foo:[a-z][a-z][a-z]}.{bar:[a-z][a-z][a-z]}.{baz:[a-z][a-z][a-z]}"),
+		url:     "http://abc.def.ghi/",
+		vars:    map[string]string{"foo": "abc", "bar": "def", "baz": "ghi"},
+		result:  true,
+	},
+	{
+		matcher: NewRouter().NewRoute().Host("{foo:[a-z][a-z][a-z]}.{bar:[a-z][a-z][a-z]}.{baz:[a-z][a-z][a-z]}"),
+		url:     "http://a.b.c/",
+		vars:    map[string]string{"foo": "abc", "bar": "def", "baz": "ghi"},
+		result:  false,
+	},
+}
+
+type methodMatcherTest struct {
+	matcher methodMatcher
+	method  string
+	result  bool
+}
+
+var methodMatcherTests = []methodMatcherTest{
+	{
+		matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
+		method:  "GET",
+		result:  true,
+	},
+	{
+		matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
+		method:  "POST",
+		result:  true,
+	},
+	{
+		matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
+		method:  "PUT",
+		result:  true,
+	},
+	{
+		matcher: methodMatcher([]string{"GET", "POST", "PUT"}),
+		method:  "DELETE",
+		result:  false,
+	},
+}
+
+type pathMatcherTest struct {
+	matcher *Route
+	url     string
+	vars    map[string]string
+	result  bool
+}
+
+var pathMatcherTests = []pathMatcherTest{
+	{
+		matcher: NewRouter().NewRoute().Path("/{foo:[0-9][0-9][0-9]}/{bar:[0-9][0-9][0-9]}/{baz:[0-9][0-9][0-9]}"),
+		url:     "http://localhost:8080/123/456/789",
+		vars:    map[string]string{"foo": "123", "bar": "456", "baz": "789"},
+		result:  true,
+	},
+	{
+		matcher: NewRouter().NewRoute().Path("/{foo:[0-9][0-9][0-9]}/{bar:[0-9][0-9][0-9]}/{baz:[0-9][0-9][0-9]}"),
+		url:     "http://localhost:8080/1/2/3",
+		vars:    map[string]string{"foo": "123", "bar": "456", "baz": "789"},
+		result:  false,
+	},
+}
+
+type queryMatcherTest struct {
+	matcher queryMatcher
+	url     string
+	result  bool
+}
+
+var queryMatcherTests = []queryMatcherTest{
+	{
+		matcher: queryMatcher(map[string]string{"foo": "bar", "baz": "ding"}),
+		url:     "http://localhost:8080/?foo=bar&baz=ding",
+		result:  true,
+	},
+	{
+		matcher: queryMatcher(map[string]string{"foo": "", "baz": ""}),
+		url:     "http://localhost:8080/?foo=anything&baz=anything",
+		result:  true,
+	},
+	{
+		matcher: queryMatcher(map[string]string{"foo": "ding", "baz": "bar"}),
+		url:     "http://localhost:8080/?foo=bar&baz=ding",
+		result:  false,
+	},
+	{
+		matcher: queryMatcher(map[string]string{"bar": "foo", "ding": "baz"}),
+		url:     "http://localhost:8080/?foo=bar&baz=ding",
+		result:  false,
+	},
+}
+
+type schemeMatcherTest struct {
+	matcher schemeMatcher
+	url     string
+	result  bool
+}
+
+var schemeMatcherTests = []schemeMatcherTest{
+	{
+		matcher: schemeMatcher([]string{"http", "https"}),
+		url:     "http://localhost:8080/",
+		result:  true,
+	},
+	{
+		matcher: schemeMatcher([]string{"http", "https"}),
+		url:     "https://localhost:8080/",
+		result:  true,
+	},
+	{
+		matcher: schemeMatcher([]string{"https"}),
+		url:     "http://localhost:8080/",
+		result:  false,
+	},
+	{
+		matcher: schemeMatcher([]string{"http"}),
+		url:     "https://localhost:8080/",
+		result:  false,
+	},
+}
+
+type urlBuildingTest struct {
+	route *Route
+	vars  []string
+	url   string
+}
+
+var urlBuildingTests = []urlBuildingTest{
+	{
+		route: new(Route).Host("foo.domain.com"),
+		vars:  []string{},
+		url:   "http://foo.domain.com",
+	},
+	{
+		route: new(Route).Host("{subdomain}.domain.com"),
+		vars:  []string{"subdomain", "bar"},
+		url:   "http://bar.domain.com",
+	},
+	{
+		route: new(Route).Host("foo.domain.com").Path("/articles"),
+		vars:  []string{},
+		url:   "http://foo.domain.com/articles",
+	},
+	{
+		route: new(Route).Path("/articles"),
+		vars:  []string{},
+		url:   "/articles",
+	},
+	{
+		route: new(Route).Path("/articles/{category}/{id:[0-9]+}"),
+		vars:  []string{"category", "technology", "id", "42"},
+		url:   "/articles/technology/42",
+	},
+	{
+		route: new(Route).Host("{subdomain}.domain.com").Path("/articles/{category}/{id:[0-9]+}"),
+		vars:  []string{"subdomain", "foo", "category", "technology", "id", "42"},
+		url:   "http://foo.domain.com/articles/technology/42",
+	},
+}
+
+func TestHeaderMatcher(t *testing.T) {
+	for _, v := range headerMatcherTests {
+		request, _ := http.NewRequest("GET", "http://localhost:8080/", nil)
+		for key, value := range v.headers {
+			request.Header.Add(key, value)
+		}
+		var routeMatch RouteMatch
+		result := v.matcher.Match(request, &routeMatch)
+		if result != v.result {
+			if v.result {
+				t.Errorf("%#v: should match %v.", v.matcher, request.Header)
+			} else {
+				t.Errorf("%#v: should not match %v.", v.matcher, request.Header)
+			}
+		}
+	}
+}
+
+func TestHostMatcher(t *testing.T) {
+	for _, v := range hostMatcherTests {
+		request, _ := http.NewRequest("GET", v.url, nil)
+		var routeMatch RouteMatch
+		result := v.matcher.Match(request, &routeMatch)
+		vars := routeMatch.Vars
+		if result != v.result {
+			if v.result {
+				t.Errorf("%#v: should match %v.", v.matcher, v.url)
+			} else {
+				t.Errorf("%#v: should not match %v.", v.matcher, v.url)
+			}
+		}
+		if result {
+			if len(vars) != len(v.vars) {
+				t.Errorf("%#v: vars length should be %v, got %v.", v.matcher, len(v.vars), len(vars))
+			}
+			for name, value := range vars {
+				if v.vars[name] != value {
+					t.Errorf("%#v: expected value %v for key %v, got %v.", v.matcher, v.vars[name], name, value)
+				}
+			}
+		} else {
+			if len(vars) != 0 {
+				t.Errorf("%#v: vars length should be 0, got %v.", v.matcher, len(vars))
+			}
+		}
+	}
+}
+
+func TestMethodMatcher(t *testing.T) {
+	for _, v := range methodMatcherTests {
+		request, _ := http.NewRequest(v.method, "http://localhost:8080/", nil)
+		var routeMatch RouteMatch
+		result := v.matcher.Match(request, &routeMatch)
+		if result != v.result {
+			if v.result {
+				t.Errorf("%#v: should match %v.", v.matcher, v.method)
+			} else {
+				t.Errorf("%#v: should not match %v.", v.matcher, v.method)
+			}
+		}
+	}
+}
+
+func TestPathMatcher(t *testing.T) {
+	for _, v := range pathMatcherTests {
+		request, _ := http.NewRequest("GET", v.url, nil)
+		var routeMatch RouteMatch
+		result := v.matcher.Match(request, &routeMatch)
+		vars := routeMatch.Vars
+		if result != v.result {
+			if v.result {
+				t.Errorf("%#v: should match %v.", v.matcher, v.url)
+			} else {
+				t.Errorf("%#v: should not match %v.", v.matcher, v.url)
+			}
+		}
+		if result {
+			if len(vars) != len(v.vars) {
+				t.Errorf("%#v: vars length should be %v, got %v.", v.matcher, len(v.vars), len(vars))
+			}
+			for name, value := range vars {
+				if v.vars[name] != value {
+					t.Errorf("%#v: expected value %v for key %v, got %v.", v.matcher, v.vars[name], name, value)
+				}
+			}
+		} else {
+			if len(vars) != 0 {
+				t.Errorf("%#v: vars length should be 0, got %v.", v.matcher, len(vars))
+			}
+		}
+	}
+}
+
+func TestQueryMatcher(t *testing.T) {
+	for _, v := range queryMatcherTests {
+		request, _ := http.NewRequest("GET", v.url, nil)
+		var routeMatch RouteMatch
+		result := v.matcher.Match(request, &routeMatch)
+		if result != v.result {
+			if v.result {
+				t.Errorf("%#v: should match %v.", v.matcher, v.url)
+			} else {
+				t.Errorf("%#v: should not match %v.", v.matcher, v.url)
+			}
+		}
+	}
+}
+
+func TestSchemeMatcher(t *testing.T) {
+	for _, v := range queryMatcherTests {
+		request, _ := http.NewRequest("GET", v.url, nil)
+		var routeMatch RouteMatch
+		result := v.matcher.Match(request, &routeMatch)
+		if result != v.result {
+			if v.result {
+				t.Errorf("%#v: should match %v.", v.matcher, v.url)
+			} else {
+				t.Errorf("%#v: should not match %v.", v.matcher, v.url)
+			}
+		}
+	}
+}
+
+func TestUrlBuilding(t *testing.T) {
+
+	for _, v := range urlBuildingTests {
+		u, _ := v.route.URL(v.vars...)
+		url := u.String()
+		if url != v.url {
+			t.Errorf("expected %v, got %v", v.url, url)
+			/*
+				reversePath := ""
+				reverseHost := ""
+				if v.route.pathTemplate != nil {
+						reversePath = v.route.pathTemplate.Reverse
+				}
+				if v.route.hostTemplate != nil {
+						reverseHost = v.route.hostTemplate.Reverse
+				}
+
+				t.Errorf("%#v:\nexpected: %q\ngot: %q\nreverse path: %q\nreverse host: %q", v.route, v.url, url, reversePath, reverseHost)
+			*/
+		}
+	}
+
+	ArticleHandler := func(w http.ResponseWriter, r *http.Request) {
+	}
+
+	router := NewRouter()
+	router.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).Name("article")
+
+	url, _ := router.Get("article").URL("category", "technology", "id", "42")
+	expected := "/articles/technology/42"
+	if url.String() != expected {
+		t.Errorf("Expected %v, got %v", expected, url.String())
+	}
+}
+
+func TestMatchedRouteName(t *testing.T) {
+	routeName := "stock"
+	router := NewRouter()
+	route := router.NewRoute().Path("/products/").Name(routeName)
+
+	url := "http://www.domain.com/products/"
+	request, _ := http.NewRequest("GET", url, nil)
+	var rv RouteMatch
+	ok := router.Match(request, &rv)
+
+	if !ok || rv.Route != route {
+		t.Errorf("Expected same route, got %+v.", rv.Route)
+	}
+
+	retName := rv.Route.GetName()
+	if retName != routeName {
+		t.Errorf("Expected %q, got %q.", routeName, retName)
+	}
+}
+
+func TestSubRouting(t *testing.T) {
+	// Example from docs.
+	router := NewRouter()
+	subrouter := router.NewRoute().Host("www.domain.com").Subrouter()
+	route := subrouter.NewRoute().Path("/products/").Name("products")
+
+	url := "http://www.domain.com/products/"
+	request, _ := http.NewRequest("GET", url, nil)
+	var rv RouteMatch
+	ok := router.Match(request, &rv)
+
+	if !ok || rv.Route != route {
+		t.Errorf("Expected same route, got %+v.", rv.Route)
+	}
+
+	u, _ := router.Get("products").URL()
+	builtUrl := u.String()
+	// Yay, subroute aware of the domain when building!
+	if builtUrl != url {
+		t.Errorf("Expected %q, got %q.", url, builtUrl)
+	}
+}
+
+func TestVariableNames(t *testing.T) {
+	route := new(Route).Host("{arg1}.domain.com").Path("/{arg1}/{arg2:[0-9]+}")
+	if route.err == nil {
+		t.Errorf("Expected error for duplicated variable names")
+	}
+}
+
+func TestRedirectSlash(t *testing.T) {
+	var route *Route
+	var routeMatch RouteMatch
+	r := NewRouter()
+
+	r.StrictSlash(false)
+	route = r.NewRoute()
+	if route.strictSlash != false {
+		t.Errorf("Expected false redirectSlash.")
+	}
+
+	r.StrictSlash(true)
+	route = r.NewRoute()
+	if route.strictSlash != true {
+		t.Errorf("Expected true redirectSlash.")
+	}
+
+	route = new(Route)
+	route.strictSlash = true
+	route.Path("/{arg1}/{arg2:[0-9]+}/")
+	request, _ := http.NewRequest("GET", "http://localhost/foo/123", nil)
+	routeMatch = RouteMatch{}
+	_ = route.Match(request, &routeMatch)
+	vars := routeMatch.Vars
+	if vars["arg1"] != "foo" {
+		t.Errorf("Expected foo.")
+	}
+	if vars["arg2"] != "123" {
+		t.Errorf("Expected 123.")
+	}
+	rsp := NewRecorder()
+	routeMatch.Handler.ServeHTTP(rsp, request)
+	if rsp.HeaderMap.Get("Location") != "http://localhost/foo/123/" {
+		t.Errorf("Expected redirect header.")
+	}
+
+	route = new(Route)
+	route.strictSlash = true
+	route.Path("/{arg1}/{arg2:[0-9]+}")
+	request, _ = http.NewRequest("GET", "http://localhost/foo/123/", nil)
+	routeMatch = RouteMatch{}
+	_ = route.Match(request, &routeMatch)
+	vars = routeMatch.Vars
+	if vars["arg1"] != "foo" {
+		t.Errorf("Expected foo.")
+	}
+	if vars["arg2"] != "123" {
+		t.Errorf("Expected 123.")
+	}
+	rsp = NewRecorder()
+	routeMatch.Handler.ServeHTTP(rsp, request)
+	if rsp.HeaderMap.Get("Location") != "http://localhost/foo/123" {
+		t.Errorf("Expected redirect header.")
+	}
+}
+
+// Test for the new regexp library, still not available in stable Go.
+func TestNewRegexp(t *testing.T) {
+	var p *routeRegexp
+	var matches []string
+
+	tests := map[string]map[string][]string{
+		"/{foo:a{2}}": {
+			"/a":    nil,
+			"/aa":   {"aa"},
+			"/aaa":  nil,
+			"/aaaa": nil,
+		},
+		"/{foo:a{2,}}": {
+			"/a":    nil,
+			"/aa":   {"aa"},
+			"/aaa":  {"aaa"},
+			"/aaaa": {"aaaa"},
+		},
+		"/{foo:a{2,3}}": {
+			"/a":    nil,
+			"/aa":   {"aa"},
+			"/aaa":  {"aaa"},
+			"/aaaa": nil,
+		},
+		"/{foo:[a-z]{3}}/{bar:[a-z]{2}}": {
+			"/a":       nil,
+			"/ab":      nil,
+			"/abc":     nil,
+			"/abcd":    nil,
+			"/abc/ab":  {"abc", "ab"},
+			"/abc/abc": nil,
+			"/abcd/ab": nil,
+		},
+		`/{foo:\w{3,}}/{bar:\d{2,}}`: {
+			"/a":        nil,
+			"/ab":       nil,
+			"/abc":      nil,
+			"/abc/1":    nil,
+			"/abc/12":   {"abc", "12"},
+			"/abcd/12":  {"abcd", "12"},
+			"/abcd/123": {"abcd", "123"},
+		},
+	}
+
+	for pattern, paths := range tests {
+		p, _ = newRouteRegexp(pattern, false, false, false)
+		for path, result := range paths {
+			matches = p.regexp.FindStringSubmatch(path)
+			if result == nil {
+				if matches != nil {
+					t.Errorf("%v should not match %v.", pattern, path)
+				}
+			} else {
+				if len(matches) != len(result)+1 {
+					t.Errorf("Expected %v matches, got %v.", len(result)+1, len(matches))
+				} else {
+					for k, v := range result {
+						if matches[k+1] != v {
+							t.Errorf("Expected %v, got %v.", v, matches[k+1])
+						}
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/Godeps/_workspace/src/github.com/gorilla/mux/regexp.go b/Godeps/_workspace/src/github.com/gorilla/mux/regexp.go
new file mode 100644
index 0000000000000000000000000000000000000000..4c3482bfbdd9701ae377aae1716c24ac1fd30b54
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/mux/regexp.go
@@ -0,0 +1,247 @@
+// Copyright 2012 The Gorilla 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 mux
+
+import (
+	"bytes"
+	"fmt"
+	"net/http"
+	"net/url"
+	"regexp"
+	"strings"
+)
+
+// newRouteRegexp parses a route template and returns a routeRegexp,
+// used to match a host or path.
+//
+// It will extract named variables, assemble a regexp to be matched, create
+// a "reverse" template to build URLs and compile regexps to validate variable
+// values used in URL building.
+//
+// Previously we accepted only Python-like identifiers for variable
+// names ([a-zA-Z_][a-zA-Z0-9_]*), but currently the only restriction is that
+// name and pattern can't be empty, and names can't contain a colon.
+func newRouteRegexp(tpl string, matchHost, matchPrefix, strictSlash bool) (*routeRegexp, error) {
+	// Check if it is well-formed.
+	idxs, errBraces := braceIndices(tpl)
+	if errBraces != nil {
+		return nil, errBraces
+	}
+	// Backup the original.
+	template := tpl
+	// Now let's parse it.
+	defaultPattern := "[^/]+"
+	if matchHost {
+		defaultPattern = "[^.]+"
+		matchPrefix, strictSlash = false, false
+	}
+	if matchPrefix {
+		strictSlash = false
+	}
+	// Set a flag for strictSlash.
+	endSlash := false
+	if strictSlash && strings.HasSuffix(tpl, "/") {
+		tpl = tpl[:len(tpl)-1]
+		endSlash = true
+	}
+	varsN := make([]string, len(idxs)/2)
+	varsR := make([]*regexp.Regexp, len(idxs)/2)
+	pattern := bytes.NewBufferString("^")
+	reverse := bytes.NewBufferString("")
+	var end int
+	var err error
+	for i := 0; i < len(idxs); i += 2 {
+		// Set all values we are interested in.
+		raw := tpl[end:idxs[i]]
+		end = idxs[i+1]
+		parts := strings.SplitN(tpl[idxs[i]+1:end-1], ":", 2)
+		name := parts[0]
+		patt := defaultPattern
+		if len(parts) == 2 {
+			patt = parts[1]
+		}
+		// Name or pattern can't be empty.
+		if name == "" || patt == "" {
+			return nil, fmt.Errorf("mux: missing name or pattern in %q",
+				tpl[idxs[i]:end])
+		}
+		// Build the regexp pattern.
+		fmt.Fprintf(pattern, "%s(%s)", regexp.QuoteMeta(raw), patt)
+		// Build the reverse template.
+		fmt.Fprintf(reverse, "%s%%s", raw)
+		// Append variable name and compiled pattern.
+		varsN[i/2] = name
+		varsR[i/2], err = regexp.Compile(fmt.Sprintf("^%s$", patt))
+		if err != nil {
+			return nil, err
+		}
+	}
+	// Add the remaining.
+	raw := tpl[end:]
+	pattern.WriteString(regexp.QuoteMeta(raw))
+	if strictSlash {
+		pattern.WriteString("[/]?")
+	}
+	if !matchPrefix {
+		pattern.WriteByte('$')
+	}
+	reverse.WriteString(raw)
+	if endSlash {
+		reverse.WriteByte('/')
+	}
+	// Compile full regexp.
+	reg, errCompile := regexp.Compile(pattern.String())
+	if errCompile != nil {
+		return nil, errCompile
+	}
+	// Done!
+	return &routeRegexp{
+		template:  template,
+		matchHost: matchHost,
+		regexp:    reg,
+		reverse:   reverse.String(),
+		varsN:     varsN,
+		varsR:     varsR,
+	}, nil
+}
+
+// routeRegexp stores a regexp to match a host or path and information to
+// collect and validate route variables.
+type routeRegexp struct {
+	// The unmodified template.
+	template string
+	// True for host match, false for path match.
+	matchHost bool
+	// Expanded regexp.
+	regexp *regexp.Regexp
+	// Reverse template.
+	reverse string
+	// Variable names.
+	varsN []string
+	// Variable regexps (validators).
+	varsR []*regexp.Regexp
+}
+
+// Match matches the regexp against the URL host or path.
+func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool {
+	if !r.matchHost {
+		return r.regexp.MatchString(req.URL.Path)
+	}
+	return r.regexp.MatchString(getHost(req))
+}
+
+// url builds a URL part using the given values.
+func (r *routeRegexp) url(pairs ...string) (string, error) {
+	values, err := mapFromPairs(pairs...)
+	if err != nil {
+		return "", err
+	}
+	urlValues := make([]interface{}, len(r.varsN))
+	for k, v := range r.varsN {
+		value, ok := values[v]
+		if !ok {
+			return "", fmt.Errorf("mux: missing route variable %q", v)
+		}
+		urlValues[k] = value
+	}
+	rv := fmt.Sprintf(r.reverse, urlValues...)
+	if !r.regexp.MatchString(rv) {
+		// The URL is checked against the full regexp, instead of checking
+		// individual variables. This is faster but to provide a good error
+		// message, we check individual regexps if the URL doesn't match.
+		for k, v := range r.varsN {
+			if !r.varsR[k].MatchString(values[v]) {
+				return "", fmt.Errorf(
+					"mux: variable %q doesn't match, expected %q", values[v],
+					r.varsR[k].String())
+			}
+		}
+	}
+	return rv, nil
+}
+
+// braceIndices returns the first level curly brace indices from a string.
+// It returns an error in case of unbalanced braces.
+func braceIndices(s string) ([]int, error) {
+	var level, idx int
+	idxs := make([]int, 0)
+	for i := 0; i < len(s); i++ {
+		switch s[i] {
+		case '{':
+			if level++; level == 1 {
+				idx = i
+			}
+		case '}':
+			if level--; level == 0 {
+				idxs = append(idxs, idx, i+1)
+			} else if level < 0 {
+				return nil, fmt.Errorf("mux: unbalanced braces in %q", s)
+			}
+		}
+	}
+	if level != 0 {
+		return nil, fmt.Errorf("mux: unbalanced braces in %q", s)
+	}
+	return idxs, nil
+}
+
+// ----------------------------------------------------------------------------
+// routeRegexpGroup
+// ----------------------------------------------------------------------------
+
+// routeRegexpGroup groups the route matchers that carry variables.
+type routeRegexpGroup struct {
+	host *routeRegexp
+	path *routeRegexp
+}
+
+// setMatch extracts the variables from the URL once a route matches.
+func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) {
+	// Store host variables.
+	if v.host != nil {
+		hostVars := v.host.regexp.FindStringSubmatch(getHost(req))
+		if hostVars != nil {
+			for k, v := range v.host.varsN {
+				m.Vars[v] = hostVars[k+1]
+			}
+		}
+	}
+	// Store path variables.
+	if v.path != nil {
+		pathVars := v.path.regexp.FindStringSubmatch(req.URL.Path)
+		if pathVars != nil {
+			for k, v := range v.path.varsN {
+				m.Vars[v] = pathVars[k+1]
+			}
+			// Check if we should redirect.
+			if r.strictSlash {
+				p1 := strings.HasSuffix(req.URL.Path, "/")
+				p2 := strings.HasSuffix(v.path.template, "/")
+				if p1 != p2 {
+					u, _ := url.Parse(req.URL.String())
+					if p1 {
+						u.Path = u.Path[:len(u.Path)-1]
+					} else {
+						u.Path += "/"
+					}
+					m.Handler = http.RedirectHandler(u.String(), 301)
+				}
+			}
+		}
+	}
+}
+
+// getHost tries its best to return the request host.
+func getHost(r *http.Request) string {
+	if !r.URL.IsAbs() {
+		host := r.Host
+		// Slice off any port information.
+		if i := strings.Index(host, ":"); i != -1 {
+			host = host[:i]
+		}
+		return host
+	}
+	return r.URL.Host
+}
diff --git a/Godeps/_workspace/src/github.com/gorilla/mux/route.go b/Godeps/_workspace/src/github.com/gorilla/mux/route.go
new file mode 100644
index 0000000000000000000000000000000000000000..cb538ea4ec2744b0b8efd75010d5a92dd40d1fea
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/mux/route.go
@@ -0,0 +1,499 @@
+// Copyright 2012 The Gorilla 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 mux
+
+import (
+	"errors"
+	"fmt"
+	"net/http"
+	"net/url"
+	"strings"
+)
+
+// Route stores information to match a request and build URLs.
+type Route struct {
+	// Parent where the route was registered (a Router).
+	parent parentRoute
+	// Request handler for the route.
+	handler http.Handler
+	// List of matchers.
+	matchers []matcher
+	// Manager for the variables from host and path.
+	regexp *routeRegexpGroup
+	// If true, when the path pattern is "/path/", accessing "/path" will
+	// redirect to the former and vice versa.
+	strictSlash bool
+	// If true, this route never matches: it is only used to build URLs.
+	buildOnly bool
+	// The name used to build URLs.
+	name string
+	// Error resulted from building a route.
+	err error
+}
+
+// Match matches the route against the request.
+func (r *Route) Match(req *http.Request, match *RouteMatch) bool {
+	if r.buildOnly || r.err != nil {
+		return false
+	}
+	// Match everything.
+	for _, m := range r.matchers {
+		if matched := m.Match(req, match); !matched {
+			return false
+		}
+	}
+	// Yay, we have a match. Let's collect some info about it.
+	if match.Route == nil {
+		match.Route = r
+	}
+	if match.Handler == nil {
+		match.Handler = r.handler
+	}
+	if match.Vars == nil {
+		match.Vars = make(map[string]string)
+	}
+	// Set variables.
+	if r.regexp != nil {
+		r.regexp.setMatch(req, match, r)
+	}
+	return true
+}
+
+// ----------------------------------------------------------------------------
+// Route attributes
+// ----------------------------------------------------------------------------
+
+// GetError returns an error resulted from building the route, if any.
+func (r *Route) GetError() error {
+	return r.err
+}
+
+// BuildOnly sets the route to never match: it is only used to build URLs.
+func (r *Route) BuildOnly() *Route {
+	r.buildOnly = true
+	return r
+}
+
+// Handler --------------------------------------------------------------------
+
+// Handler sets a handler for the route.
+func (r *Route) Handler(handler http.Handler) *Route {
+	if r.err == nil {
+		r.handler = handler
+	}
+	return r
+}
+
+// HandlerFunc sets a handler function for the route.
+func (r *Route) HandlerFunc(f func(http.ResponseWriter, *http.Request)) *Route {
+	return r.Handler(http.HandlerFunc(f))
+}
+
+// GetHandler returns the handler for the route, if any.
+func (r *Route) GetHandler() http.Handler {
+	return r.handler
+}
+
+// Name -----------------------------------------------------------------------
+
+// Name sets the name for the route, used to build URLs.
+// If the name was registered already it will be overwritten.
+func (r *Route) Name(name string) *Route {
+	if r.name != "" {
+		r.err = fmt.Errorf("mux: route already has name %q, can't set %q",
+			r.name, name)
+	}
+	if r.err == nil {
+		r.name = name
+		r.getNamedRoutes()[name] = r
+	}
+	return r
+}
+
+// GetName returns the name for the route, if any.
+func (r *Route) GetName() string {
+	return r.name
+}
+
+// ----------------------------------------------------------------------------
+// Matchers
+// ----------------------------------------------------------------------------
+
+// matcher types try to match a request.
+type matcher interface {
+	Match(*http.Request, *RouteMatch) bool
+}
+
+// addMatcher adds a matcher to the route.
+func (r *Route) addMatcher(m matcher) *Route {
+	if r.err == nil {
+		r.matchers = append(r.matchers, m)
+	}
+	return r
+}
+
+// addRegexpMatcher adds a host or path matcher and builder to a route.
+func (r *Route) addRegexpMatcher(tpl string, matchHost, matchPrefix bool) error {
+	if r.err != nil {
+		return r.err
+	}
+	r.regexp = r.getRegexpGroup()
+	if !matchHost {
+		if len(tpl) == 0 || tpl[0] != '/' {
+			return fmt.Errorf("mux: path must start with a slash, got %q", tpl)
+		}
+		if r.regexp.path != nil {
+			tpl = strings.TrimRight(r.regexp.path.template, "/") + tpl
+		}
+	}
+	rr, err := newRouteRegexp(tpl, matchHost, matchPrefix, r.strictSlash)
+	if err != nil {
+		return err
+	}
+	if matchHost {
+		if r.regexp.path != nil {
+			if err = uniqueVars(rr.varsN, r.regexp.path.varsN); err != nil {
+				return err
+			}
+		}
+		r.regexp.host = rr
+	} else {
+		if r.regexp.host != nil {
+			if err = uniqueVars(rr.varsN, r.regexp.host.varsN); err != nil {
+				return err
+			}
+		}
+		r.regexp.path = rr
+	}
+	r.addMatcher(rr)
+	return nil
+}
+
+// Headers --------------------------------------------------------------------
+
+// headerMatcher matches the request against header values.
+type headerMatcher map[string]string
+
+func (m headerMatcher) Match(r *http.Request, match *RouteMatch) bool {
+	return matchMap(m, r.Header, true)
+}
+
+// Headers adds a matcher for request header values.
+// It accepts a sequence of key/value pairs to be matched. For example:
+//
+//     r := mux.NewRouter()
+//     r.Headers("Content-Type", "application/json",
+//               "X-Requested-With", "XMLHttpRequest")
+//
+// The above route will only match if both request header values match.
+//
+// It the value is an empty string, it will match any value if the key is set.
+func (r *Route) Headers(pairs ...string) *Route {
+	if r.err == nil {
+		var headers map[string]string
+		headers, r.err = mapFromPairs(pairs...)
+		return r.addMatcher(headerMatcher(headers))
+	}
+	return r
+}
+
+// Host -----------------------------------------------------------------------
+
+// Host adds a matcher for the URL host.
+// It accepts a template with zero or more URL variables enclosed by {}.
+// Variables can define an optional regexp pattern to me matched:
+//
+// - {name} matches anything until the next dot.
+//
+// - {name:pattern} matches the given regexp pattern.
+//
+// For example:
+//
+//     r := mux.NewRouter()
+//     r.Host("www.domain.com")
+//     r.Host("{subdomain}.domain.com")
+//     r.Host("{subdomain:[a-z]+}.domain.com")
+//
+// Variable names must be unique in a given route. They can be retrieved
+// calling mux.Vars(request).
+func (r *Route) Host(tpl string) *Route {
+	r.err = r.addRegexpMatcher(tpl, true, false)
+	return r
+}
+
+// MatcherFunc ----------------------------------------------------------------
+
+// MatcherFunc is the function signature used by custom matchers.
+type MatcherFunc func(*http.Request, *RouteMatch) bool
+
+func (m MatcherFunc) Match(r *http.Request, match *RouteMatch) bool {
+	return m(r, match)
+}
+
+// MatcherFunc adds a custom function to be used as request matcher.
+func (r *Route) MatcherFunc(f MatcherFunc) *Route {
+	return r.addMatcher(f)
+}
+
+// Methods --------------------------------------------------------------------
+
+// methodMatcher matches the request against HTTP methods.
+type methodMatcher []string
+
+func (m methodMatcher) Match(r *http.Request, match *RouteMatch) bool {
+	return matchInArray(m, r.Method)
+}
+
+// Methods adds a matcher for HTTP methods.
+// It accepts a sequence of one or more methods to be matched, e.g.:
+// "GET", "POST", "PUT".
+func (r *Route) Methods(methods ...string) *Route {
+	for k, v := range methods {
+		methods[k] = strings.ToUpper(v)
+	}
+	return r.addMatcher(methodMatcher(methods))
+}
+
+// Path -----------------------------------------------------------------------
+
+// Path adds a matcher for the URL path.
+// It accepts a template with zero or more URL variables enclosed by {}.
+// Variables can define an optional regexp pattern to me matched:
+//
+// - {name} matches anything until the next slash.
+//
+// - {name:pattern} matches the given regexp pattern.
+//
+// For example:
+//
+//     r := mux.NewRouter()
+//     r.Path("/products/").Handler(ProductsHandler)
+//     r.Path("/products/{key}").Handler(ProductsHandler)
+//     r.Path("/articles/{category}/{id:[0-9]+}").
+//       Handler(ArticleHandler)
+//
+// Variable names must be unique in a given route. They can be retrieved
+// calling mux.Vars(request).
+func (r *Route) Path(tpl string) *Route {
+	r.err = r.addRegexpMatcher(tpl, false, false)
+	return r
+}
+
+// PathPrefix -----------------------------------------------------------------
+
+// PathPrefix adds a matcher for the URL path prefix.
+func (r *Route) PathPrefix(tpl string) *Route {
+	r.strictSlash = false
+	r.err = r.addRegexpMatcher(tpl, false, true)
+	return r
+}
+
+// Query ----------------------------------------------------------------------
+
+// queryMatcher matches the request against URL queries.
+type queryMatcher map[string]string
+
+func (m queryMatcher) Match(r *http.Request, match *RouteMatch) bool {
+	return matchMap(m, r.URL.Query(), false)
+}
+
+// Queries adds a matcher for URL query values.
+// It accepts a sequence of key/value pairs. For example:
+//
+//     r := mux.NewRouter()
+//     r.Queries("foo", "bar", "baz", "ding")
+//
+// The above route will only match if the URL contains the defined queries
+// values, e.g.: ?foo=bar&baz=ding.
+//
+// It the value is an empty string, it will match any value if the key is set.
+func (r *Route) Queries(pairs ...string) *Route {
+	if r.err == nil {
+		var queries map[string]string
+		queries, r.err = mapFromPairs(pairs...)
+		return r.addMatcher(queryMatcher(queries))
+	}
+	return r
+}
+
+// Schemes --------------------------------------------------------------------
+
+// schemeMatcher matches the request against URL schemes.
+type schemeMatcher []string
+
+func (m schemeMatcher) Match(r *http.Request, match *RouteMatch) bool {
+	return matchInArray(m, r.URL.Scheme)
+}
+
+// Schemes adds a matcher for URL schemes.
+// It accepts a sequence schemes to be matched, e.g.: "http", "https".
+func (r *Route) Schemes(schemes ...string) *Route {
+	for k, v := range schemes {
+		schemes[k] = strings.ToLower(v)
+	}
+	return r.addMatcher(schemeMatcher(schemes))
+}
+
+// Subrouter ------------------------------------------------------------------
+
+// Subrouter creates a subrouter for the route.
+//
+// It will test the inner routes only if the parent route matched. For example:
+//
+//     r := mux.NewRouter()
+//     s := r.Host("www.domain.com").Subrouter()
+//     s.HandleFunc("/products/", ProductsHandler)
+//     s.HandleFunc("/products/{key}", ProductHandler)
+//     s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler)
+//
+// Here, the routes registered in the subrouter won't be tested if the host
+// doesn't match.
+func (r *Route) Subrouter() *Router {
+	router := &Router{parent: r, strictSlash: r.strictSlash}
+	r.addMatcher(router)
+	return router
+}
+
+// ----------------------------------------------------------------------------
+// URL building
+// ----------------------------------------------------------------------------
+
+// URL builds a URL for the route.
+//
+// It accepts a sequence of key/value pairs for the route variables. For
+// example, given this route:
+//
+//     r := mux.NewRouter()
+//     r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).
+//       Name("article")
+//
+// ...a URL for it can be built using:
+//
+//     url, err := r.Get("article").URL("category", "technology", "id", "42")
+//
+// ...which will return an url.URL with the following path:
+//
+//     "/articles/technology/42"
+//
+// This also works for host variables:
+//
+//     r := mux.NewRouter()
+//     r.Host("{subdomain}.domain.com").
+//       HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).
+//       Name("article")
+//
+//     // url.String() will be "http://news.domain.com/articles/technology/42"
+//     url, err := r.Get("article").URL("subdomain", "news",
+//                                      "category", "technology",
+//                                      "id", "42")
+//
+// All variables defined in the route are required, and their values must
+// conform to the corresponding patterns.
+func (r *Route) URL(pairs ...string) (*url.URL, error) {
+	if r.err != nil {
+		return nil, r.err
+	}
+	if r.regexp == nil {
+		return nil, errors.New("mux: route doesn't have a host or path")
+	}
+	var scheme, host, path string
+	var err error
+	if r.regexp.host != nil {
+		// Set a default scheme.
+		scheme = "http"
+		if host, err = r.regexp.host.url(pairs...); err != nil {
+			return nil, err
+		}
+	}
+	if r.regexp.path != nil {
+		if path, err = r.regexp.path.url(pairs...); err != nil {
+			return nil, err
+		}
+	}
+	return &url.URL{
+		Scheme: scheme,
+		Host:   host,
+		Path:   path,
+	}, nil
+}
+
+// URLHost builds the host part of the URL for a route. See Route.URL().
+//
+// The route must have a host defined.
+func (r *Route) URLHost(pairs ...string) (*url.URL, error) {
+	if r.err != nil {
+		return nil, r.err
+	}
+	if r.regexp == nil || r.regexp.host == nil {
+		return nil, errors.New("mux: route doesn't have a host")
+	}
+	host, err := r.regexp.host.url(pairs...)
+	if err != nil {
+		return nil, err
+	}
+	return &url.URL{
+		Scheme: "http",
+		Host:   host,
+	}, nil
+}
+
+// URLPath builds the path part of the URL for a route. See Route.URL().
+//
+// The route must have a path defined.
+func (r *Route) URLPath(pairs ...string) (*url.URL, error) {
+	if r.err != nil {
+		return nil, r.err
+	}
+	if r.regexp == nil || r.regexp.path == nil {
+		return nil, errors.New("mux: route doesn't have a path")
+	}
+	path, err := r.regexp.path.url(pairs...)
+	if err != nil {
+		return nil, err
+	}
+	return &url.URL{
+		Path: path,
+	}, nil
+}
+
+// ----------------------------------------------------------------------------
+// parentRoute
+// ----------------------------------------------------------------------------
+
+// parentRoute allows routes to know about parent host and path definitions.
+type parentRoute interface {
+	getNamedRoutes() map[string]*Route
+	getRegexpGroup() *routeRegexpGroup
+}
+
+// getNamedRoutes returns the map where named routes are registered.
+func (r *Route) getNamedRoutes() map[string]*Route {
+	if r.parent == nil {
+		// During tests router is not always set.
+		r.parent = NewRouter()
+	}
+	return r.parent.getNamedRoutes()
+}
+
+// getRegexpGroup returns regexp definitions from this route.
+func (r *Route) getRegexpGroup() *routeRegexpGroup {
+	if r.regexp == nil {
+		if r.parent == nil {
+			// During tests router is not always set.
+			r.parent = NewRouter()
+		}
+		regexp := r.parent.getRegexpGroup()
+		if regexp == nil {
+			r.regexp = new(routeRegexpGroup)
+		} else {
+			// Copy.
+			r.regexp = &routeRegexpGroup{
+				host: regexp.host,
+				path: regexp.path,
+			}
+		}
+	}
+	return r.regexp
+}
diff --git a/Godeps/_workspace/src/github.com/gorilla/securecookie/.travis.yml b/Godeps/_workspace/src/github.com/gorilla/securecookie/.travis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d87d4657686743eff53951131c0831d9aaac0ab3
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/securecookie/.travis.yml
@@ -0,0 +1,7 @@
+language: go
+
+go:
+  - 1.0
+  - 1.1
+  - 1.2
+  - tip
diff --git a/Godeps/_workspace/src/github.com/gorilla/securecookie/LICENSE b/Godeps/_workspace/src/github.com/gorilla/securecookie/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..0e5fb872800da9557f75a5650bb9d80c1c2cf715
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/securecookie/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2012 Rodrigo Moraes. 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/Godeps/_workspace/src/github.com/gorilla/securecookie/README.md b/Godeps/_workspace/src/github.com/gorilla/securecookie/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..2f0d5d48c25fee562cff4e9aca96b8412635da36
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/securecookie/README.md
@@ -0,0 +1,3 @@
+securecookie
+============
+[![Build Status](https://travis-ci.org/gorilla/securecookie.png?branch=master)](https://travis-ci.org/gorilla/securecookie)
diff --git a/Godeps/_workspace/src/github.com/gorilla/securecookie/doc.go b/Godeps/_workspace/src/github.com/gorilla/securecookie/doc.go
new file mode 100644
index 0000000000000000000000000000000000000000..e80e3aed2e2e2a9a68be16c22976dce837b0edc2
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/securecookie/doc.go
@@ -0,0 +1,61 @@
+// Copyright 2012 The Gorilla 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 gorilla/securecookie encodes and decodes authenticated and optionally
+encrypted cookie values.
+
+Secure cookies can't be forged, because their values are validated using HMAC.
+When encrypted, the content is also inaccessible to malicious eyes.
+
+To use it, first create a new SecureCookie instance:
+
+	var hashKey = []byte("very-secret")
+	var blockKey = []byte("a-lot-secret")
+	var s = securecookie.New(hashKey, blockKey)
+
+The hashKey is required, used to authenticate the cookie value using HMAC.
+It is recommended to use a key with 32 or 64 bytes.
+
+The blockKey is optional, used to encrypt the cookie value -- set it to nil
+to not use encryption. If set, the length must correspond to the block size
+of the encryption algorithm. For AES, used by default, valid lengths are
+16, 24, or 32 bytes to select AES-128, AES-192, or AES-256.
+
+Strong keys can be created using the convenience function GenerateRandomKey().
+
+Once a SecureCookie instance is set, use it to encode a cookie value:
+
+	func SetCookieHandler(w http.ResponseWriter, r *http.Request) {
+		value := map[string]string{
+			"foo": "bar",
+		}
+		if encoded, err := s.Encode("cookie-name", value); err == nil {
+			cookie := &http.Cookie{
+				Name:  "cookie-name",
+				Value: encoded,
+				Path:  "/",
+			}
+			http.SetCookie(w, cookie)
+		}
+	}
+
+Later, use the same SecureCookie instance to decode and validate a cookie
+value:
+
+	func ReadCookieHandler(w http.ResponseWriter, r *http.Request) {
+		if cookie, err := r.Cookie("cookie-name"); err == nil {
+			value := make(map[string]string)
+			if err = s2.Decode("cookie-name", cookie.Value, &value); err == nil {
+				fmt.Fprintf(w, "The value of foo is %q", value["foo"])
+			}
+		}
+	}
+
+We stored a map[string]string, but secure cookies can hold any value that
+can be encoded using encoding/gob. To store custom types, they must be
+registered first using gob.Register(). For basic types this is not needed;
+it works out of the box.
+*/
+package securecookie
diff --git a/Godeps/_workspace/src/github.com/gorilla/securecookie/securecookie.go b/Godeps/_workspace/src/github.com/gorilla/securecookie/securecookie.go
new file mode 100644
index 0000000000000000000000000000000000000000..74b8acc5c43cf95a6ba23590598872bd7b3360ab
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/securecookie/securecookie.go
@@ -0,0 +1,429 @@
+// Copyright 2012 The Gorilla 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 securecookie
+
+import (
+	"bytes"
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/hmac"
+	"crypto/rand"
+	"crypto/sha256"
+	"crypto/subtle"
+	"encoding/base64"
+	"encoding/gob"
+	"errors"
+	"fmt"
+	"hash"
+	"io"
+	"strconv"
+	"time"
+)
+
+var (
+	errNoCodecs      = errors.New("securecookie: no codecs provided")
+	errHashKeyNotSet = errors.New("securecookie: hash key is not set")
+
+	ErrMacInvalid = errors.New("securecookie: the value is not valid")
+)
+
+// Codec defines an interface to encode and decode cookie values.
+type Codec interface {
+	Encode(name string, value interface{}) (string, error)
+	Decode(name, value string, dst interface{}) error
+}
+
+// New returns a new SecureCookie.
+//
+// hashKey is required, used to authenticate values using HMAC. Create it using
+// GenerateRandomKey(). It is recommended to use a key with 32 or 64 bytes.
+//
+// blockKey is optional, used to encrypt values. Create it using
+// GenerateRandomKey(). The key length must correspond to the block size
+// of the encryption algorithm. For AES, used by default, valid lengths are
+// 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256.
+func New(hashKey, blockKey []byte) *SecureCookie {
+	s := &SecureCookie{
+		hashKey:   hashKey,
+		blockKey:  blockKey,
+		hashFunc:  sha256.New,
+		maxAge:    86400 * 30,
+		maxLength: 4096,
+	}
+	if hashKey == nil {
+		s.err = errHashKeyNotSet
+	}
+	if blockKey != nil {
+		s.BlockFunc(aes.NewCipher)
+	}
+	return s
+}
+
+// SecureCookie encodes and decodes authenticated and optionally encrypted
+// cookie values.
+type SecureCookie struct {
+	hashKey   []byte
+	hashFunc  func() hash.Hash
+	blockKey  []byte
+	block     cipher.Block
+	maxLength int
+	maxAge    int64
+	minAge    int64
+	err       error
+	// For testing purposes, the function that returns the current timestamp.
+	// If not set, it will use time.Now().UTC().Unix().
+	timeFunc func() int64
+}
+
+// MaxLength restricts the maximum length, in bytes, for the cookie value.
+//
+// Default is 4096, which is the maximum value accepted by Internet Explorer.
+func (s *SecureCookie) MaxLength(value int) *SecureCookie {
+	s.maxLength = value
+	return s
+}
+
+// MaxAge restricts the maximum age, in seconds, for the cookie value.
+//
+// Default is 86400 * 30. Set it to 0 for no restriction.
+func (s *SecureCookie) MaxAge(value int) *SecureCookie {
+	s.maxAge = int64(value)
+	return s
+}
+
+// MinAge restricts the minimum age, in seconds, for the cookie value.
+//
+// Default is 0 (no restriction).
+func (s *SecureCookie) MinAge(value int) *SecureCookie {
+	s.minAge = int64(value)
+	return s
+}
+
+// HashFunc sets the hash function used to create HMAC.
+//
+// Default is crypto/sha256.New.
+func (s *SecureCookie) HashFunc(f func() hash.Hash) *SecureCookie {
+	s.hashFunc = f
+	return s
+}
+
+// BlockFunc sets the encryption function used to create a cipher.Block.
+//
+// Default is crypto/aes.New.
+func (s *SecureCookie) BlockFunc(f func([]byte) (cipher.Block, error)) *SecureCookie {
+	if s.blockKey == nil {
+		s.err = errors.New("securecookie: block key is not set")
+	} else if block, err := f(s.blockKey); err == nil {
+		s.block = block
+	} else {
+		s.err = err
+	}
+	return s
+}
+
+// Encode encodes a cookie value.
+//
+// It serializes, optionally encrypts, signs with a message authentication code, and
+// finally encodes the value.
+//
+// The name argument is the cookie name. It is stored with the encoded value.
+// The value argument is the value to be encoded. It can be any value that can
+// be encoded using encoding/gob. To store special structures, they must be
+// registered first using gob.Register().
+func (s *SecureCookie) Encode(name string, value interface{}) (string, error) {
+	if s.err != nil {
+		return "", s.err
+	}
+	if s.hashKey == nil {
+		s.err = errHashKeyNotSet
+		return "", s.err
+	}
+	var err error
+	var b []byte
+	// 1. Serialize.
+	if b, err = serialize(value); err != nil {
+		return "", err
+	}
+	// 2. Encrypt (optional).
+	if s.block != nil {
+		if b, err = encrypt(s.block, b); err != nil {
+			return "", err
+		}
+	}
+	b = encode(b)
+	// 3. Create MAC for "name|date|value". Extra pipe to be used later.
+	b = []byte(fmt.Sprintf("%s|%d|%s|", name, s.timestamp(), b))
+	mac := createMac(hmac.New(s.hashFunc, s.hashKey), b[:len(b)-1])
+	// Append mac, remove name.
+	b = append(b, mac...)[len(name)+1:]
+	// 4. Encode to base64.
+	b = encode(b)
+	// 5. Check length.
+	if s.maxLength != 0 && len(b) > s.maxLength {
+		return "", errors.New("securecookie: the value is too long")
+	}
+	// Done.
+	return string(b), nil
+}
+
+// Decode decodes a cookie value.
+//
+// It decodes, verifies a message authentication code, optionally decrypts and
+// finally deserializes the value.
+//
+// The name argument is the cookie name. It must be the same name used when
+// it was stored. The value argument is the encoded cookie value. The dst
+// argument is where the cookie will be decoded. It must be a pointer.
+func (s *SecureCookie) Decode(name, value string, dst interface{}) error {
+	if s.err != nil {
+		return s.err
+	}
+	if s.hashKey == nil {
+		s.err = errHashKeyNotSet
+		return s.err
+	}
+	// 1. Check length.
+	if s.maxLength != 0 && len(value) > s.maxLength {
+		return errors.New("securecookie: the value is too long")
+	}
+	// 2. Decode from base64.
+	b, err := decode([]byte(value))
+	if err != nil {
+		return err
+	}
+	// 3. Verify MAC. Value is "date|value|mac".
+	parts := bytes.SplitN(b, []byte("|"), 3)
+	if len(parts) != 3 {
+		return errors.New("securecookie: invalid value %v")
+	}
+	h := hmac.New(s.hashFunc, s.hashKey)
+	b = append([]byte(name+"|"), b[:len(b)-len(parts[2])-1]...)
+	if err = verifyMac(h, b, parts[2]); err != nil {
+		return err
+	}
+	// 4. Verify date ranges.
+	var t1 int64
+	if t1, err = strconv.ParseInt(string(parts[0]), 10, 64); err != nil {
+		return errors.New("securecookie: invalid timestamp")
+	}
+	t2 := s.timestamp()
+	if s.minAge != 0 && t1 > t2-s.minAge {
+		return errors.New("securecookie: timestamp is too new")
+	}
+	if s.maxAge != 0 && t1 < t2-s.maxAge {
+		return errors.New("securecookie: expired timestamp")
+	}
+	// 5. Decrypt (optional).
+	b, err = decode(parts[1])
+	if err != nil {
+		return err
+	}
+	if s.block != nil {
+		if b, err = decrypt(s.block, b); err != nil {
+			return err
+		}
+	}
+	// 6. Deserialize.
+	if err = deserialize(b, dst); err != nil {
+		return err
+	}
+	// Done.
+	return nil
+}
+
+// timestamp returns the current timestamp, in seconds.
+//
+// For testing purposes, the function that generates the timestamp can be
+// overridden. If not set, it will return time.Now().UTC().Unix().
+func (s *SecureCookie) timestamp() int64 {
+	if s.timeFunc == nil {
+		return time.Now().UTC().Unix()
+	}
+	return s.timeFunc()
+}
+
+// Authentication -------------------------------------------------------------
+
+// createMac creates a message authentication code (MAC).
+func createMac(h hash.Hash, value []byte) []byte {
+	h.Write(value)
+	return h.Sum(nil)
+}
+
+// verifyMac verifies that a message authentication code (MAC) is valid.
+func verifyMac(h hash.Hash, value []byte, mac []byte) error {
+	mac2 := createMac(h, value)
+	if len(mac) == len(mac2) && subtle.ConstantTimeCompare(mac, mac2) == 1 {
+		return nil
+	}
+	return ErrMacInvalid
+}
+
+// Encryption -----------------------------------------------------------------
+
+// encrypt encrypts a value using the given block in counter mode.
+//
+// A random initialization vector (http://goo.gl/zF67k) with the length of the
+// block size is prepended to the resulting ciphertext.
+func encrypt(block cipher.Block, value []byte) ([]byte, error) {
+	iv := GenerateRandomKey(block.BlockSize())
+	if iv == nil {
+		return nil, errors.New("securecookie: failed to generate random iv")
+	}
+	// Encrypt it.
+	stream := cipher.NewCTR(block, iv)
+	stream.XORKeyStream(value, value)
+	// Return iv + ciphertext.
+	return append(iv, value...), nil
+}
+
+// decrypt decrypts a value using the given block in counter mode.
+//
+// The value to be decrypted must be prepended by a initialization vector
+// (http://goo.gl/zF67k) with the length of the block size.
+func decrypt(block cipher.Block, value []byte) ([]byte, error) {
+	size := block.BlockSize()
+	if len(value) > size {
+		// Extract iv.
+		iv := value[:size]
+		// Extract ciphertext.
+		value = value[size:]
+		// Decrypt it.
+		stream := cipher.NewCTR(block, iv)
+		stream.XORKeyStream(value, value)
+		return value, nil
+	}
+	return nil, errors.New("securecookie: the value could not be decrypted")
+}
+
+// Serialization --------------------------------------------------------------
+
+// serialize encodes a value using gob.
+func serialize(src interface{}) ([]byte, error) {
+	buf := new(bytes.Buffer)
+	enc := gob.NewEncoder(buf)
+	if err := enc.Encode(src); err != nil {
+		return nil, err
+	}
+	return buf.Bytes(), nil
+}
+
+// deserialize decodes a value using gob.
+func deserialize(src []byte, dst interface{}) error {
+	dec := gob.NewDecoder(bytes.NewBuffer(src))
+	if err := dec.Decode(dst); err != nil {
+		return err
+	}
+	return nil
+}
+
+// Encoding -------------------------------------------------------------------
+
+// encode encodes a value using base64.
+func encode(value []byte) []byte {
+	encoded := make([]byte, base64.URLEncoding.EncodedLen(len(value)))
+	base64.URLEncoding.Encode(encoded, value)
+	return encoded
+}
+
+// decode decodes a cookie using base64.
+func decode(value []byte) ([]byte, error) {
+	decoded := make([]byte, base64.URLEncoding.DecodedLen(len(value)))
+	b, err := base64.URLEncoding.Decode(decoded, value)
+	if err != nil {
+		return nil, err
+	}
+	return decoded[:b], nil
+}
+
+// Helpers --------------------------------------------------------------------
+
+// GenerateRandomKey creates a random key with the given strength.
+func GenerateRandomKey(strength int) []byte {
+	k := make([]byte, strength)
+	if _, err := io.ReadFull(rand.Reader, k); err != nil {
+		return nil
+	}
+	return k
+}
+
+// CodecsFromPairs returns a slice of SecureCookie instances.
+//
+// It is a convenience function to create a list of codecs for key rotation.
+func CodecsFromPairs(keyPairs ...[]byte) []Codec {
+	codecs := make([]Codec, len(keyPairs)/2+len(keyPairs)%2)
+	for i := 0; i < len(keyPairs); i += 2 {
+		var blockKey []byte
+		if i+1 < len(keyPairs) {
+			blockKey = keyPairs[i+1]
+		}
+		codecs[i/2] = New(keyPairs[i], blockKey)
+	}
+	return codecs
+}
+
+// EncodeMulti encodes a cookie value using a group of codecs.
+//
+// The codecs are tried in order. Multiple codecs are accepted to allow
+// key rotation.
+func EncodeMulti(name string, value interface{}, codecs ...Codec) (string, error) {
+	if len(codecs) == 0 {
+		return "", errNoCodecs
+	}
+
+	var errors MultiError
+	for _, codec := range codecs {
+		if encoded, err := codec.Encode(name, value); err == nil {
+			return encoded, nil
+		} else {
+			errors = append(errors, err)
+		}
+	}
+	return "", errors
+}
+
+// DecodeMulti decodes a cookie value using a group of codecs.
+//
+// The codecs are tried in order. Multiple codecs are accepted to allow
+// key rotation.
+func DecodeMulti(name string, value string, dst interface{}, codecs ...Codec) error {
+	if len(codecs) == 0 {
+		return errNoCodecs
+	}
+
+	var errors MultiError
+	for _, codec := range codecs {
+		if err := codec.Decode(name, value, dst); err == nil {
+			return nil
+		} else {
+			errors = append(errors, err)
+		}
+	}
+	return errors
+}
+
+// MultiError groups multiple errors.
+type MultiError []error
+
+func (m MultiError) Error() string {
+	s, n := "", 0
+	for _, e := range m {
+		if e != nil {
+			if n == 0 {
+				s = e.Error()
+			}
+			n++
+		}
+	}
+	switch n {
+	case 0:
+		return "(0 errors)"
+	case 1:
+		return s
+	case 2:
+		return s + " (and 1 other error)"
+	}
+	return fmt.Sprintf("%s (and %d other errors)", s, n-1)
+}
diff --git a/Godeps/_workspace/src/github.com/gorilla/securecookie/securecookie_test.go b/Godeps/_workspace/src/github.com/gorilla/securecookie/securecookie_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..fe0cdb109858cbdca39f36baf249d65afa22ed38
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/securecookie/securecookie_test.go
@@ -0,0 +1,178 @@
+// Copyright 2012 The Gorilla 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 securecookie
+
+import (
+	"crypto/aes"
+	"crypto/hmac"
+	"crypto/sha256"
+	"errors"
+	"fmt"
+	"strings"
+	"testing"
+)
+
+var testCookies = []interface{}{
+	map[string]string{"foo": "bar"},
+	map[string]string{"baz": "ding"},
+}
+
+var testStrings = []string{"foo", "bar", "baz"}
+
+func TestSecureCookie(t *testing.T) {
+	// TODO test too old / too new timestamps
+	compareMaps := func(m1, m2 map[string]interface{}) error {
+		if len(m1) != len(m2) {
+			return errors.New("different maps")
+		}
+		for k, v := range m1 {
+			if m2[k] != v {
+				return fmt.Errorf("Different value for key %v: expected %v, got %v", k, m2[k], v)
+			}
+		}
+		return nil
+	}
+
+	s1 := New([]byte("12345"), []byte("1234567890123456"))
+	s2 := New([]byte("54321"), []byte("6543210987654321"))
+	value := map[string]interface{}{
+		"foo": "bar",
+		"baz": 128,
+	}
+
+	for i := 0; i < 50; i++ {
+		// Running this multiple times to check if any special character
+		// breaks encoding/decoding.
+		encoded, err1 := s1.Encode("sid", value)
+		if err1 != nil {
+			t.Error(err1)
+			continue
+		}
+		dst := make(map[string]interface{})
+		err2 := s1.Decode("sid", encoded, &dst)
+		if err2 != nil {
+			t.Fatalf("%v: %v", err2, encoded)
+		}
+		if err := compareMaps(dst, value); err != nil {
+			t.Fatalf("Expected %v, got %v.", value, dst)
+		}
+		dst2 := make(map[string]interface{})
+		err3 := s2.Decode("sid", encoded, &dst2)
+		if err3 == nil {
+			t.Fatalf("Expected failure decoding.")
+		}
+	}
+}
+
+func TestAuthentication(t *testing.T) {
+	hash := hmac.New(sha256.New, []byte("secret-key"))
+	for _, value := range testStrings {
+		hash.Reset()
+		signed := createMac(hash, []byte(value))
+		hash.Reset()
+		err := verifyMac(hash, []byte(value), signed)
+		if err != nil {
+			t.Error(err)
+		}
+	}
+}
+
+func TestEncription(t *testing.T) {
+	block, err := aes.NewCipher([]byte("1234567890123456"))
+	if err != nil {
+		t.Fatalf("Block could not be created")
+	}
+	var encrypted, decrypted []byte
+	for _, value := range testStrings {
+		if encrypted, err = encrypt(block, []byte(value)); err != nil {
+			t.Error(err)
+		} else {
+			if decrypted, err = decrypt(block, encrypted); err != nil {
+				t.Error(err)
+			}
+			if string(decrypted) != value {
+				t.Errorf("Expected %v, got %v.", value, string(decrypted))
+			}
+		}
+	}
+}
+
+func TestSerialization(t *testing.T) {
+	var (
+		serialized   []byte
+		deserialized map[string]string
+		err          error
+	)
+	for _, value := range testCookies {
+		if serialized, err = serialize(value); err != nil {
+			t.Error(err)
+		} else {
+			deserialized = make(map[string]string)
+			if err = deserialize(serialized, &deserialized); err != nil {
+				t.Error(err)
+			}
+			if fmt.Sprintf("%v", deserialized) != fmt.Sprintf("%v", value) {
+				t.Errorf("Expected %v, got %v.", value, deserialized)
+			}
+		}
+	}
+}
+
+func TestEncoding(t *testing.T) {
+	for _, value := range testStrings {
+		encoded := encode([]byte(value))
+		decoded, err := decode(encoded)
+		if err != nil {
+			t.Error(err)
+		} else if string(decoded) != value {
+			t.Errorf("Expected %v, got %s.", value, string(decoded))
+		}
+	}
+}
+
+func TestMultiError(t *testing.T) {
+	s1, s2 := New(nil, nil), New(nil, nil)
+	_, err := EncodeMulti("sid", "value", s1, s2)
+	if len(err.(MultiError)) != 2 {
+		t.Errorf("Expected 2 errors, got %s.", err)
+	} else {
+		if strings.Index(err.Error(), "hash key is not set") == -1 {
+			t.Errorf("Expected missing hash key error, got %s.", err.Error())
+		}
+	}
+}
+
+func TestMultiNoCodecs(t *testing.T) {
+	_, err := EncodeMulti("foo", "bar")
+	if err != errNoCodecs {
+		t.Errorf("EncodeMulti: bad value for error, got: %v", err)
+	}
+
+	var dst []byte
+	err = DecodeMulti("foo", "bar", &dst)
+	if err != errNoCodecs {
+		t.Errorf("DecodeMulti: bad value for error, got: %v", err)
+	}
+}
+
+// ----------------------------------------------------------------------------
+
+type FooBar struct {
+	Foo int
+	Bar string
+}
+
+func TestCustomType(t *testing.T) {
+	s1 := New([]byte("12345"), []byte("1234567890123456"))
+	// Type is not registered in gob. (!!!)
+	src := &FooBar{42, "bar"}
+	encoded, _ := s1.Encode("sid", src)
+
+	dst := &FooBar{}
+	_ = s1.Decode("sid", encoded, dst)
+	if dst.Foo != 42 || dst.Bar != "bar" {
+		t.Fatalf("Expected %#v, got %#v", src, dst)
+	}
+}
diff --git a/Godeps/_workspace/src/github.com/gorilla/sessions/LICENSE b/Godeps/_workspace/src/github.com/gorilla/sessions/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..0e5fb872800da9557f75a5650bb9d80c1c2cf715
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/sessions/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2012 Rodrigo Moraes. 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/Godeps/_workspace/src/github.com/gorilla/sessions/README.md b/Godeps/_workspace/src/github.com/gorilla/sessions/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..cd92e082922273e27eeccfd72c873a8d68107116
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/sessions/README.md
@@ -0,0 +1,8 @@
+sessions
+========
+
+Store Implementations
+---------------------
+Other implementations of the sessions.Store interface:
+
+ * [redistore](https://github.com/boj/redistore) - store sessions in Redis
diff --git a/Godeps/_workspace/src/github.com/gorilla/sessions/doc.go b/Godeps/_workspace/src/github.com/gorilla/sessions/doc.go
new file mode 100644
index 0000000000000000000000000000000000000000..1bf3b3c2cf9a3125b7d78f713660f7c72c1e52cd
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/sessions/doc.go
@@ -0,0 +1,126 @@
+// Copyright 2012 The Gorilla 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 gorilla/sessions provides cookie and filesystem sessions and
+infrastructure for custom session backends.
+
+The key features are:
+
+	* Simple API: use it as an easy way to set signed (and optionally
+	  encrypted) cookies.
+	* Built-in backends to store sessions in cookies or the filesystem.
+	* Flash messages: session values that last until read.
+	* Convenient way to switch session persistency (aka "remember me") and set
+	  other attributes.
+	* Mechanism to rotate authentication and encryption keys.
+	* Multiple sessions per request, even using different backends.
+	* Interfaces and infrastructure for custom session backends: sessions from
+	  different stores can be retrieved and batch-saved using a common API.
+
+Let's start with an example that shows the sessions API in a nutshell:
+
+	import (
+		"net/http"
+		"github.com/gorilla/sessions"
+	)
+
+	var store = sessions.NewCookieStore([]byte("something-very-secret"))
+
+	func MyHandler(w http.ResponseWriter, r *http.Request) {
+		// Get a session. We're ignoring the error resulted from decoding an
+		// existing session: Get() always returns a session, even if empty.
+		session, _ := store.Get(r, "session-name")
+		// Set some session values.
+		session.Values["foo"] = "bar"
+		session.Values[42] = 43
+		// Save it.
+		session.Save(r, w)
+	}
+
+First we initialize a session store calling NewCookieStore() and passing a
+secret key used to authenticate the session. Inside the handler, we call
+store.Get() to retrieve an existing session or a new one. Then we set some
+session values in session.Values, which is a map[interface{}]interface{}.
+And finally we call session.Save() to save the session in the response.
+
+That's all you need to know for the basic usage. Let's take a look at other
+options, starting with flash messages.
+
+Flash messages are session values that last until read. The term appeared with
+Ruby On Rails a few years back. When we request a flash message, it is removed
+from the session. To add a flash, call session.AddFlash(), and to get all
+flashes, call session.Flashes(). Here is an example:
+
+	func MyHandler(w http.ResponseWriter, r *http.Request) {
+		// Get a session.
+		session, _ := store.Get(r, "session-name")
+		// Get the previously flashes, if any.
+		if flashes := session.Flashes(); len(flashes) > 0 {
+			// Just print the flash values.
+			fmt.Fprint(w, "%v", flashes)
+		} else {
+			// Set a new flash.
+			session.AddFlash("Hello, flash messages world!")
+			fmt.Fprint(w, "No flashes found.")
+		}
+		session.Save(r, w)
+	}
+
+Flash messages are useful to set information to be read after a redirection,
+like after form submissions.
+
+By default, session cookies last for a month. This is probably too long for
+some cases, but it is easy to change this and other attributes during
+runtime. Sessions can be configured individually or the store can be
+configured and then all sessions saved using it will use that configuration.
+We access session.Options or store.Options to set a new configuration. The
+fields are basically a subset of http.Cookie fields. Let's change the
+maximum age of a session to one week:
+
+	session.Options = &sessions.Options{
+		Path:   "/",
+		MaxAge: 86400 * 7,
+	}
+
+Sometimes we may want to change authentication and/or encryption keys without
+breaking existing sessions. The CookieStore supports key rotation, and to use
+it you just need to set multiple authentication and encryption keys, in pairs,
+to be tested in order:
+
+	var store = sessions.NewCookieStore(
+		[]byte("new-authentication-key"),
+		[]byte("new-encryption-key"),
+		[]byte("old-authentication-key"),
+		[]byte("old-encryption-key"),
+	)
+
+New sessions will be saved using the first pair. Old sessions can still be
+read because the first pair will fail, and the second will be tested. This
+makes it easy to "rotate" secret keys and still be able to validate existing
+sessions. Note: for all pairs the encryption key is optional; set it to nil
+or omit it and and encryption won't be used.
+
+Multiple sessions can be used in the same request, even with different
+session backends. When this happens, calling Save() on each session
+individually would be cumbersome, so we have a way to save all sessions
+at once: it's sessions.Save(). Here's an example:
+
+	var store = sessions.NewCookieStore([]byte("something-very-secret"))
+
+	func MyHandler(w http.ResponseWriter, r *http.Request) {
+		// Get a session and set a value.
+		session1, _ := store.Get(r, "session-one")
+		session1.Values["foo"] = "bar"
+		// Get another session and set another value.
+		session2, _ := store.Get(r, "session-two")
+		session2.Values[42] = 43
+		// Save all sessions.
+		sessions.Save(r, w)
+	}
+
+This is possible because when we call Get() from a session store, it adds the
+session to a common registry. Save() uses it to save all registered sessions.
+*/
+package sessions
diff --git a/Godeps/_workspace/src/github.com/gorilla/sessions/sessions.go b/Godeps/_workspace/src/github.com/gorilla/sessions/sessions.go
new file mode 100644
index 0000000000000000000000000000000000000000..53111b3aca1684a040d0ca97e0cd1de88088ae9a
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/sessions/sessions.go
@@ -0,0 +1,234 @@
+// Copyright 2012 The Gorilla 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 sessions
+
+import (
+	"encoding/gob"
+	"fmt"
+	"net/http"
+	"time"
+
+	"github.com/gorilla/context"
+)
+
+// Default flashes key.
+const flashesKey = "_flash"
+
+// Options --------------------------------------------------------------------
+
+// Options stores configuration for a session or session store.
+//
+// Fields are a subset of http.Cookie fields.
+type Options struct {
+	Path   string
+	Domain string
+	// MaxAge=0 means no 'Max-Age' attribute specified.
+	// MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'.
+	// MaxAge>0 means Max-Age attribute present and given in seconds.
+	MaxAge   int
+	Secure   bool
+	HttpOnly bool
+}
+
+// Session --------------------------------------------------------------------
+
+// NewSession is called by session stores to create a new session instance.
+func NewSession(store Store, name string) *Session {
+	return &Session{
+		Values: make(map[interface{}]interface{}),
+		store:  store,
+		name:   name,
+	}
+}
+
+// Session stores the values and optional configuration for a session.
+type Session struct {
+	ID      string
+	Values  map[interface{}]interface{}
+	Options *Options
+	IsNew   bool
+	store   Store
+	name    string
+}
+
+// Flashes returns a slice of flash messages from the session.
+//
+// A single variadic argument is accepted, and it is optional: it defines
+// the flash key. If not defined "_flash" is used by default.
+func (s *Session) Flashes(vars ...string) []interface{} {
+	var flashes []interface{}
+	key := flashesKey
+	if len(vars) > 0 {
+		key = vars[0]
+	}
+	if v, ok := s.Values[key]; ok {
+		// Drop the flashes and return it.
+		delete(s.Values, key)
+		flashes = v.([]interface{})
+	}
+	return flashes
+}
+
+// AddFlash adds a flash message to the session.
+//
+// A single variadic argument is accepted, and it is optional: it defines
+// the flash key. If not defined "_flash" is used by default.
+func (s *Session) AddFlash(value interface{}, vars ...string) {
+	key := flashesKey
+	if len(vars) > 0 {
+		key = vars[0]
+	}
+	var flashes []interface{}
+	if v, ok := s.Values[key]; ok {
+		flashes = v.([]interface{})
+	}
+	s.Values[key] = append(flashes, value)
+}
+
+// Save is a convenience method to save this session. It is the same as calling
+// store.Save(request, response, session)
+func (s *Session) Save(r *http.Request, w http.ResponseWriter) error {
+	return s.store.Save(r, w, s)
+}
+
+// Name returns the name used to register the session.
+func (s *Session) Name() string {
+	return s.name
+}
+
+// Store returns the session store used to register the session.
+func (s *Session) Store() Store {
+	return s.store
+}
+
+// Registry -------------------------------------------------------------------
+
+// sessionInfo stores a session tracked by the registry.
+type sessionInfo struct {
+	s *Session
+	e error
+}
+
+// contextKey is the type used to store the registry in the context.
+type contextKey int
+
+// registryKey is the key used to store the registry in the context.
+const registryKey contextKey = 0
+
+// GetRegistry returns a registry instance for the current request.
+func GetRegistry(r *http.Request) *Registry {
+	registry := context.Get(r, registryKey)
+	if registry != nil {
+		return registry.(*Registry)
+	}
+	newRegistry := &Registry{
+		request:  r,
+		sessions: make(map[string]sessionInfo),
+	}
+	context.Set(r, registryKey, newRegistry)
+	return newRegistry
+}
+
+// Registry stores sessions used during a request.
+type Registry struct {
+	request  *http.Request
+	sessions map[string]sessionInfo
+}
+
+// Get registers and returns a session for the given name and session store.
+//
+// It returns a new session if there are no sessions registered for the name.
+func (s *Registry) Get(store Store, name string) (session *Session, err error) {
+	if info, ok := s.sessions[name]; ok {
+		session, err = info.s, info.e
+	} else {
+		session, err = store.New(s.request, name)
+		session.name = name
+		s.sessions[name] = sessionInfo{s: session, e: err}
+	}
+	session.store = store
+	return
+}
+
+// Save saves all sessions registered for the current request.
+func (s *Registry) Save(w http.ResponseWriter) error {
+	var errMulti MultiError
+	for name, info := range s.sessions {
+		session := info.s
+		if session.store == nil {
+			errMulti = append(errMulti, fmt.Errorf(
+				"sessions: missing store for session %q", name))
+		} else if err := session.store.Save(s.request, w, session); err != nil {
+			errMulti = append(errMulti, fmt.Errorf(
+				"sessions: error saving session %q -- %v", name, err))
+		}
+	}
+	if errMulti != nil {
+		return errMulti
+	}
+	return nil
+}
+
+// Helpers --------------------------------------------------------------------
+
+func init() {
+	gob.Register([]interface{}{})
+}
+
+// Save saves all sessions used during the current request.
+func Save(r *http.Request, w http.ResponseWriter) error {
+	return GetRegistry(r).Save(w)
+}
+
+// NewCookie returns an http.Cookie with the options set. It also sets
+// the Expires field calculated based on the MaxAge value, for Internet
+// Explorer compatibility.
+func NewCookie(name, value string, options *Options) *http.Cookie {
+	cookie := &http.Cookie{
+		Name:     name,
+		Value:    value,
+		Path:     options.Path,
+		Domain:   options.Domain,
+		MaxAge:   options.MaxAge,
+		Secure:   options.Secure,
+		HttpOnly: options.HttpOnly,
+	}
+	if options.MaxAge > 0 {
+		d := time.Duration(options.MaxAge) * time.Second
+		cookie.Expires = time.Now().Add(d)
+	} else if options.MaxAge < 0 {
+		// Set it to the past to expire now.
+		cookie.Expires = time.Unix(1, 0)
+	}
+	return cookie
+}
+
+// Error ----------------------------------------------------------------------
+
+// MultiError stores multiple errors.
+//
+// Borrowed from the App Engine SDK.
+type MultiError []error
+
+func (m MultiError) Error() string {
+	s, n := "", 0
+	for _, e := range m {
+		if e != nil {
+			if n == 0 {
+				s = e.Error()
+			}
+			n++
+		}
+	}
+	switch n {
+	case 0:
+		return "(0 errors)"
+	case 1:
+		return s
+	case 2:
+		return s + " (and 1 other error)"
+	}
+	return fmt.Sprintf("%s (and %d other errors)", s, n-1)
+}
diff --git a/Godeps/_workspace/src/github.com/gorilla/sessions/sessions_test.go b/Godeps/_workspace/src/github.com/gorilla/sessions/sessions_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..3667d6312b58596c9399721d075bd15138495582
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/sessions/sessions_test.go
@@ -0,0 +1,197 @@
+// Copyright 2012 The Gorilla 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 sessions
+
+import (
+	"bytes"
+	"encoding/gob"
+	"net/http"
+	"testing"
+)
+
+// ----------------------------------------------------------------------------
+// ResponseRecorder
+// ----------------------------------------------------------------------------
+// Copyright 2009 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.
+
+// ResponseRecorder is an implementation of http.ResponseWriter that
+// records its mutations for later inspection in tests.
+type ResponseRecorder struct {
+	Code      int           // the HTTP response code from WriteHeader
+	HeaderMap http.Header   // the HTTP response headers
+	Body      *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to
+	Flushed   bool
+}
+
+// NewRecorder returns an initialized ResponseRecorder.
+func NewRecorder() *ResponseRecorder {
+	return &ResponseRecorder{
+		HeaderMap: make(http.Header),
+		Body:      new(bytes.Buffer),
+	}
+}
+
+// DefaultRemoteAddr is the default remote address to return in RemoteAddr if
+// an explicit DefaultRemoteAddr isn't set on ResponseRecorder.
+const DefaultRemoteAddr = "1.2.3.4"
+
+// Header returns the response headers.
+func (rw *ResponseRecorder) Header() http.Header {
+	return rw.HeaderMap
+}
+
+// Write always succeeds and writes to rw.Body, if not nil.
+func (rw *ResponseRecorder) Write(buf []byte) (int, error) {
+	if rw.Body != nil {
+		rw.Body.Write(buf)
+	}
+	if rw.Code == 0 {
+		rw.Code = http.StatusOK
+	}
+	return len(buf), nil
+}
+
+// WriteHeader sets rw.Code.
+func (rw *ResponseRecorder) WriteHeader(code int) {
+	rw.Code = code
+}
+
+// Flush sets rw.Flushed to true.
+func (rw *ResponseRecorder) Flush() {
+	rw.Flushed = true
+}
+
+// ----------------------------------------------------------------------------
+
+type FlashMessage struct {
+	Type    int
+	Message string
+}
+
+func TestFlashes(t *testing.T) {
+	var req *http.Request
+	var rsp *ResponseRecorder
+	var hdr http.Header
+	var err error
+	var ok bool
+	var cookies []string
+	var session *Session
+	var flashes []interface{}
+
+	store := NewCookieStore([]byte("secret-key"))
+
+	// Round 1 ----------------------------------------------------------------
+
+	req, _ = http.NewRequest("GET", "http://localhost:8080/", nil)
+	rsp = NewRecorder()
+	// Get a session.
+	if session, err = store.Get(req, "session-key"); err != nil {
+		t.Fatalf("Error getting session: %v", err)
+	}
+	// Get a flash.
+	flashes = session.Flashes()
+	if len(flashes) != 0 {
+		t.Errorf("Expected empty flashes; Got %v", flashes)
+	}
+	// Add some flashes.
+	session.AddFlash("foo")
+	session.AddFlash("bar")
+	// Custom key.
+	session.AddFlash("baz", "custom_key")
+	// Save.
+	if err = Save(req, rsp); err != nil {
+		t.Fatalf("Error saving session: %v", err)
+	}
+	hdr = rsp.Header()
+	cookies, ok = hdr["Set-Cookie"]
+	if !ok || len(cookies) != 1 {
+		t.Fatalf("No cookies. Header:", hdr)
+	}
+
+	// Round 2 ----------------------------------------------------------------
+
+	req, _ = http.NewRequest("GET", "http://localhost:8080/", nil)
+	req.Header.Add("Cookie", cookies[0])
+	rsp = NewRecorder()
+	// Get a session.
+	if session, err = store.Get(req, "session-key"); err != nil {
+		t.Fatalf("Error getting session: %v", err)
+	}
+	// Check all saved values.
+	flashes = session.Flashes()
+	if len(flashes) != 2 {
+		t.Fatalf("Expected flashes; Got %v", flashes)
+	}
+	if flashes[0] != "foo" || flashes[1] != "bar" {
+		t.Errorf("Expected foo,bar; Got %v", flashes)
+	}
+	flashes = session.Flashes()
+	if len(flashes) != 0 {
+		t.Errorf("Expected dumped flashes; Got %v", flashes)
+	}
+	// Custom key.
+	flashes = session.Flashes("custom_key")
+	if len(flashes) != 1 {
+		t.Errorf("Expected flashes; Got %v", flashes)
+	} else if flashes[0] != "baz" {
+		t.Errorf("Expected baz; Got %v", flashes)
+	}
+	flashes = session.Flashes("custom_key")
+	if len(flashes) != 0 {
+		t.Errorf("Expected dumped flashes; Got %v", flashes)
+	}
+
+	// Round 3 ----------------------------------------------------------------
+	// Custom type
+
+	req, _ = http.NewRequest("GET", "http://localhost:8080/", nil)
+	rsp = NewRecorder()
+	// Get a session.
+	if session, err = store.Get(req, "session-key"); err != nil {
+		t.Fatalf("Error getting session: %v", err)
+	}
+	// Get a flash.
+	flashes = session.Flashes()
+	if len(flashes) != 0 {
+		t.Errorf("Expected empty flashes; Got %v", flashes)
+	}
+	// Add some flashes.
+	session.AddFlash(&FlashMessage{42, "foo"})
+	// Save.
+	if err = Save(req, rsp); err != nil {
+		t.Fatalf("Error saving session: %v", err)
+	}
+	hdr = rsp.Header()
+	cookies, ok = hdr["Set-Cookie"]
+	if !ok || len(cookies) != 1 {
+		t.Fatalf("No cookies. Header:", hdr)
+	}
+
+	// Round 4 ----------------------------------------------------------------
+	// Custom type
+
+	req, _ = http.NewRequest("GET", "http://localhost:8080/", nil)
+	req.Header.Add("Cookie", cookies[0])
+	rsp = NewRecorder()
+	// Get a session.
+	if session, err = store.Get(req, "session-key"); err != nil {
+		t.Fatalf("Error getting session: %v", err)
+	}
+	// Check all saved values.
+	flashes = session.Flashes()
+	if len(flashes) != 1 {
+		t.Fatalf("Expected flashes; Got %v", flashes)
+	}
+	custom := flashes[0].(FlashMessage)
+	if custom.Type != 42 || custom.Message != "foo" {
+		t.Errorf("Expected %#v, got %#v", FlashMessage{42, "foo"}, custom)
+	}
+}
+
+func init() {
+	gob.Register(FlashMessage{})
+}
diff --git a/Godeps/_workspace/src/github.com/gorilla/sessions/store.go b/Godeps/_workspace/src/github.com/gorilla/sessions/store.go
new file mode 100644
index 0000000000000000000000000000000000000000..8d00cb3034625fd9136c29c01bb8bc444183cdec
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/gorilla/sessions/store.go
@@ -0,0 +1,235 @@
+// Copyright 2012 The Gorilla 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 sessions
+
+import (
+	"encoding/base32"
+	"io"
+	"net/http"
+	"os"
+	"strings"
+	"sync"
+
+	"github.com/gorilla/securecookie"
+)
+
+// Store is an interface for custom session stores.
+type Store interface {
+	Get(r *http.Request, name string) (*Session, error)
+	New(r *http.Request, name string) (*Session, error)
+	Save(r *http.Request, w http.ResponseWriter, s *Session) error
+}
+
+// CookieStore ----------------------------------------------------------------
+
+// NewCookieStore returns a new CookieStore.
+//
+// Keys are defined in pairs to allow key rotation, but the common case is
+// to set a single authentication key and optionally an encryption key.
+//
+// The first key in a pair is used for authentication and the second for
+// encryption. The encryption key can be set to nil or omitted in the last
+// pair, but the authentication key is required in all pairs.
+//
+// It is recommended to use an authentication key with 32 or 64 bytes.
+// The encryption key, if set, must be either 16, 24, or 32 bytes to select
+// AES-128, AES-192, or AES-256 modes.
+//
+// Use the convenience function securecookie.GenerateRandomKey() to create
+// strong keys.
+func NewCookieStore(keyPairs ...[]byte) *CookieStore {
+	return &CookieStore{
+		Codecs: securecookie.CodecsFromPairs(keyPairs...),
+		Options: &Options{
+			Path:   "/",
+			MaxAge: 86400 * 30,
+		},
+	}
+}
+
+// CookieStore stores sessions using secure cookies.
+type CookieStore struct {
+	Codecs  []securecookie.Codec
+	Options *Options // default configuration
+}
+
+// Get returns a session for the given name after adding it to the registry.
+//
+// It returns a new session if the sessions doesn't exist. Access IsNew on
+// the session to check if it is an existing session or a new one.
+//
+// It returns a new session and an error if the session exists but could
+// not be decoded.
+func (s *CookieStore) Get(r *http.Request, name string) (*Session, error) {
+	return GetRegistry(r).Get(s, name)
+}
+
+// New returns a session for the given name without adding it to the registry.
+//
+// The difference between New() and Get() is that calling New() twice will
+// decode the session data twice, while Get() registers and reuses the same
+// decoded session after the first call.
+func (s *CookieStore) New(r *http.Request, name string) (*Session, error) {
+	session := NewSession(s, name)
+	session.Options = &(*s.Options)
+	session.IsNew = true
+	var err error
+	if c, errCookie := r.Cookie(name); errCookie == nil {
+		err = securecookie.DecodeMulti(name, c.Value, &session.Values,
+			s.Codecs...)
+		if err == nil {
+			session.IsNew = false
+		}
+	}
+	return session, err
+}
+
+// Save adds a single session to the response.
+func (s *CookieStore) Save(r *http.Request, w http.ResponseWriter,
+	session *Session) error {
+	encoded, err := securecookie.EncodeMulti(session.Name(), session.Values,
+		s.Codecs...)
+	if err != nil {
+		return err
+	}
+	http.SetCookie(w, NewCookie(session.Name(), encoded, session.Options))
+	return nil
+}
+
+// FilesystemStore ------------------------------------------------------------
+
+var fileMutex sync.RWMutex
+
+// NewFilesystemStore returns a new FilesystemStore.
+//
+// The path argument is the directory where sessions will be saved. If empty
+// it will use os.TempDir().
+//
+// See NewCookieStore() for a description of the other parameters.
+func NewFilesystemStore(path string, keyPairs ...[]byte) *FilesystemStore {
+	if path == "" {
+		path = os.TempDir()
+	}
+	if path[len(path)-1] != '/' {
+		path += "/"
+	}
+	return &FilesystemStore{
+		Codecs: securecookie.CodecsFromPairs(keyPairs...),
+		Options: &Options{
+			Path:   "/",
+			MaxAge: 86400 * 30,
+		},
+		path: path,
+	}
+}
+
+// FilesystemStore stores sessions in the filesystem.
+//
+// It also serves as a referece for custom stores.
+//
+// This store is still experimental and not well tested. Feedback is welcome.
+type FilesystemStore struct {
+	Codecs  []securecookie.Codec
+	Options *Options // default configuration
+	path    string
+}
+
+// Get returns a session for the given name after adding it to the registry.
+//
+// See CookieStore.Get().
+func (s *FilesystemStore) Get(r *http.Request, name string) (*Session, error) {
+	return GetRegistry(r).Get(s, name)
+}
+
+// New returns a session for the given name without adding it to the registry.
+//
+// See CookieStore.New().
+func (s *FilesystemStore) New(r *http.Request, name string) (*Session, error) {
+	session := NewSession(s, name)
+	session.Options = &(*s.Options)
+	session.IsNew = true
+	var err error
+	if c, errCookie := r.Cookie(name); errCookie == nil {
+		err = securecookie.DecodeMulti(name, c.Value, &session.ID, s.Codecs...)
+		if err == nil {
+			err = s.load(session)
+			if err == nil {
+				session.IsNew = false
+			}
+		}
+	}
+	return session, err
+}
+
+// Save adds a single session to the response.
+func (s *FilesystemStore) Save(r *http.Request, w http.ResponseWriter,
+	session *Session) error {
+	if session.ID == "" {
+		// Because the ID is used in the filename, encode it to
+		// use alphanumeric characters only.
+		session.ID = strings.TrimRight(
+			base32.StdEncoding.EncodeToString(
+				securecookie.GenerateRandomKey(32)), "=")
+	}
+	if err := s.save(session); err != nil {
+		return err
+	}
+	encoded, err := securecookie.EncodeMulti(session.Name(), session.ID,
+		s.Codecs...)
+	if err != nil {
+		return err
+	}
+	http.SetCookie(w, NewCookie(session.Name(), encoded, session.Options))
+	return nil
+}
+
+// save writes encoded session.Values to a file.
+func (s *FilesystemStore) save(session *Session) error {
+	encoded, err := securecookie.EncodeMulti(session.Name(), session.Values,
+		s.Codecs...)
+	if err != nil {
+		return err
+	}
+	filename := s.path + "session_" + session.ID
+	fileMutex.Lock()
+	defer fileMutex.Unlock()
+	fp, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
+	if err != nil {
+		return err
+	}
+	if _, err = fp.Write([]byte(encoded)); err != nil {
+		return err
+	}
+	fp.Close()
+	return nil
+}
+
+// load reads a file and decodes its content into session.Values.
+func (s *FilesystemStore) load(session *Session) error {
+	filename := s.path + "session_" + session.ID
+	fp, err := os.OpenFile(filename, os.O_RDONLY, 0400)
+	if err != nil {
+		return err
+	}
+	defer fp.Close()
+	var fdata []byte
+	buf := make([]byte, 128)
+	for {
+		var n int
+		n, err = fp.Read(buf[0:])
+		fdata = append(fdata, buf[0:n]...)
+		if err != nil {
+			if err == io.EOF {
+				break
+			}
+			return err
+		}
+	}
+	if err = securecookie.DecodeMulti(session.Name(), string(fdata),
+		&session.Values, s.Codecs...); err != nil {
+		return err
+	}
+	return nil
+}
diff --git a/Godeps/_workspace/src/github.com/jmhodges/levigo/.gitignore b/Godeps/_workspace/src/github.com/jmhodges/levigo/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..2af17d56f074c1461c80d7df93b1ee98f679985b
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/jmhodges/levigo/.gitignore
@@ -0,0 +1,6 @@
+*.o
+*.a
+*.6
+*.out
+_testmain.go
+_obj
diff --git a/Godeps/_workspace/src/github.com/jmhodges/levigo/LICENSE b/Godeps/_workspace/src/github.com/jmhodges/levigo/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..c7c73befc3b514b8a07a1c524b1c0eebeb1e8c9d
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/jmhodges/levigo/LICENSE
@@ -0,0 +1,7 @@
+Copyright (c) 2012 Jeffrey M Hodges
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/Godeps/_workspace/src/github.com/jmhodges/levigo/README.md b/Godeps/_workspace/src/github.com/jmhodges/levigo/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..3ea196bf770a4782a7aabb6ab57e6dd06d4a6340
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/jmhodges/levigo/README.md
@@ -0,0 +1,52 @@
+# levigo
+
+levigo is a Go wrapper for LevelDB.
+
+The API has been godoc'ed and [is available on the
+web](http://godoc.org/github.com/jmhodges/levigo).
+
+Questions answered at `golang-nuts@googlegroups.com`.
+
+## Building
+
+You'll need the shared library build of
+[LevelDB](http://code.google.com/p/leveldb/) installed on your machine. The
+current LevelDB will build it by default.
+
+The minimum version of LevelDB required is currently 1.7. If you require the
+use of an older version of LevelDB, see the [fork of levigo for LevelDB
+1.4](https://github.com/jmhodges/levigo_leveldb_1.4). Prefer putting in the
+work to be up to date as LevelDB moves very quickly.
+
+Now, if you build LevelDB and put the shared library and headers in one of the
+standard places for your OS, you'll be able to simply run:
+
+    go get github.com/jmhodges/levigo
+
+But, suppose you put the shared LevelDB library somewhere weird like
+/path/to/lib and the headers were installed in /path/to/include. To install
+levigo remotely, you'll run:
+
+    CGO_CFLAGS="-I/path/to/leveldb/include" CGO_LDFLAGS="-L/path/to/leveldb/lib" go get github.com/jmhodges/levigo
+
+and there you go.
+
+In order to build with snappy, you'll have to explicitly add "-lsnappy" to the
+`CGO_LDFLAGS`. Supposing that both snappy and leveldb are in weird places,
+you'll run something like:
+
+    CGO_CFLAGS="-I/path/to/leveldb/include -I/path/to/snappy/include"
+    CGO_LDFLAGS="-L/path/to/leveldb/lib -L/path/to/snappy/lib -lsnappy" go get github.com/jmhodges/levigo
+
+(and make sure the -lsnappy is after the snappy library path!).
+
+Of course, these same rules apply when doing `go build`, as well.
+
+## Caveats
+
+Comparators and WriteBatch iterators must be written in C in your own
+library. This seems like a pain in the ass, but remember that you'll have the
+LevelDB C API available to your in your client package when you import levigo.
+
+An example of writing your own Comparator can be found in
+<https://github.com/jmhodges/levigo/blob/master/examples>.
diff --git a/Godeps/_workspace/src/github.com/jmhodges/levigo/batch.go b/Godeps/_workspace/src/github.com/jmhodges/levigo/batch.go
new file mode 100644
index 0000000000000000000000000000000000000000..8860966cc4760952c585194376e902a5ed9f0717
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/jmhodges/levigo/batch.go
@@ -0,0 +1,66 @@
+package levigo
+
+// #cgo LDFLAGS: -lleveldb
+// #include "leveldb/c.h"
+import "C"
+
+import (
+	"unsafe"
+)
+
+// WriteBatch is a batching of Puts, and Deletes to be written atomically to a
+// database. A WriteBatch is written when passed to DB.Write.
+//
+// To prevent memory leaks, call Close when the program no longer needs the
+// WriteBatch object.
+type WriteBatch struct {
+	wbatch *C.leveldb_writebatch_t
+}
+
+// NewWriteBatch creates a fully allocated WriteBatch.
+func NewWriteBatch() *WriteBatch {
+	wb := C.leveldb_writebatch_create()
+	return &WriteBatch{wb}
+}
+
+// Close releases the underlying memory of a WriteBatch.
+func (w *WriteBatch) Close() {
+	C.leveldb_writebatch_destroy(w.wbatch)
+}
+
+// Put places a key-value pair into the WriteBatch for writing later.
+//
+// Both the key and value byte slices may be reused as WriteBatch takes a copy
+// of them before returning.
+//
+func (w *WriteBatch) Put(key, value []byte) {
+	// leveldb_writebatch_put, and _delete call memcpy() (by way of
+	// Memtable::Add) when called, so we do not need to worry about these
+	// []byte being reclaimed by GC.
+	var k, v *C.char
+	if len(key) != 0 {
+		k = (*C.char)(unsafe.Pointer(&key[0]))
+	}
+	if len(value) != 0 {
+		v = (*C.char)(unsafe.Pointer(&value[0]))
+	}
+
+	lenk := len(key)
+	lenv := len(value)
+
+	C.leveldb_writebatch_put(w.wbatch, k, C.size_t(lenk), v, C.size_t(lenv))
+}
+
+// Delete queues a deletion of the data at key to be deleted later.
+//
+// The key byte slice may be reused safely. Delete takes a copy of
+// them before returning.
+func (w *WriteBatch) Delete(key []byte) {
+	C.leveldb_writebatch_delete(w.wbatch,
+		(*C.char)(unsafe.Pointer(&key[0])), C.size_t(len(key)))
+}
+
+// Clear removes all the enqueued Put and Deletes in the WriteBatch.
+func (w *WriteBatch) Clear() {
+	C.leveldb_writebatch_clear(w.wbatch)
+}
diff --git a/Godeps/_workspace/src/github.com/jmhodges/levigo/cache.go b/Godeps/_workspace/src/github.com/jmhodges/levigo/cache.go
new file mode 100644
index 0000000000000000000000000000000000000000..cf4da44c63a2f9546f186b884ab931982174c3eb
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/jmhodges/levigo/cache.go
@@ -0,0 +1,32 @@
+package levigo
+
+// #cgo LDFLAGS: -lleveldb
+// #include <stdint.h>
+// #include "leveldb/c.h"
+import "C"
+
+// Cache is a cache used to store data read from data in memory.
+//
+// Typically, NewLRUCache is all you will need, but advanced users may
+// implement their own *C.leveldb_cache_t and create a Cache.
+//
+// To prevent memory leaks, a Cache must have Close called on it when it is
+// no longer needed by the program. Note: if the process is shutting down,
+// this may not be necessary and could be avoided to shorten shutdown time.
+type Cache struct {
+	Cache *C.leveldb_cache_t
+}
+
+// NewLRUCache creates a new Cache object with the capacity given.
+//
+// To prevent memory leaks, Close should be called on the Cache when the
+// program no longer needs it. Note: if the process is shutting down, this may
+// not be necessary and could be avoided to shorten shutdown time.
+func NewLRUCache(capacity int) *Cache {
+	return &Cache{C.leveldb_cache_create_lru(C.size_t(capacity))}
+}
+
+// Close deallocates the underlying memory of the Cache object.
+func (c *Cache) Close() {
+	C.leveldb_cache_destroy(c.Cache)
+}
diff --git a/Godeps/_workspace/src/github.com/jmhodges/levigo/comparator.go b/Godeps/_workspace/src/github.com/jmhodges/levigo/comparator.go
new file mode 100644
index 0000000000000000000000000000000000000000..be5e6acaa96b7f044208f6e40d23aa130e50caf3
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/jmhodges/levigo/comparator.go
@@ -0,0 +1,13 @@
+package levigo
+
+// #cgo LDFLAGS: -lleveldb
+// #include "leveldb/c.h"
+import "C"
+
+// DestroyComparator deallocates a *C.leveldb_comparator_t.
+//
+// This is provided as a convienience to advanced users that have implemented
+// their own comparators in C in their own code.
+func DestroyComparator(cmp *C.leveldb_comparator_t) {
+	C.leveldb_comparator_destroy(cmp)
+}
diff --git a/Godeps/_workspace/src/github.com/jmhodges/levigo/conv.go b/Godeps/_workspace/src/github.com/jmhodges/levigo/conv.go
new file mode 100644
index 0000000000000000000000000000000000000000..79ca81030ce5bcfb5874f60a229317092021835c
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/jmhodges/levigo/conv.go
@@ -0,0 +1,19 @@
+package levigo
+
+// #include "leveldb/c.h"
+import "C"
+
+func boolToUchar(b bool) C.uchar {
+	uc := C.uchar(0)
+	if b {
+		uc = C.uchar(1)
+	}
+	return uc
+}
+
+func ucharToBool(uc C.uchar) bool {
+	if uc == C.uchar(0) {
+		return false
+	}
+	return true
+}
diff --git a/Godeps/_workspace/src/github.com/jmhodges/levigo/db.go b/Godeps/_workspace/src/github.com/jmhodges/levigo/db.go
new file mode 100644
index 0000000000000000000000000000000000000000..c9f0a9a56f887ab7a2b82a5deb33d8cf03e5e633
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/jmhodges/levigo/db.go
@@ -0,0 +1,328 @@
+package levigo
+
+/*
+#cgo LDFLAGS: -lleveldb
+#include <stdlib.h>
+#include "leveldb/c.h"
+
+// This function exists only to clean up lack-of-const warnings when
+// leveldb_approximate_sizes is called from Go-land.
+void levigo_leveldb_approximate_sizes(
+    leveldb_t* db,
+    int num_ranges,
+    char** range_start_key, const size_t* range_start_key_len,
+    char** range_limit_key, const size_t* range_limit_key_len,
+    uint64_t* sizes) {
+  leveldb_approximate_sizes(db,
+                            num_ranges,
+                            (const char* const*)range_start_key,
+                            range_start_key_len,
+                            (const char* const*)range_limit_key,
+                            range_limit_key_len,
+                            sizes);
+}
+*/
+import "C"
+
+import (
+	"unsafe"
+)
+
+type DatabaseError string
+
+func (e DatabaseError) Error() string {
+	return string(e)
+}
+
+// DB is a reusable handle to a LevelDB database on disk, created by Open.
+//
+// To avoid memory and file descriptor leaks, call Close when the process no
+// longer needs the handle. Calls to any DB method made after Close will
+// panic.
+//
+// The DB instance may be shared between goroutines. The usual data race
+// conditions will occur if the same key is written to from more than one, of
+// course.
+type DB struct {
+	Ldb *C.leveldb_t
+}
+
+// Range is a range of keys in the database. GetApproximateSizes calls with it
+// begin at the key Start and end right before the key Limit.
+type Range struct {
+	Start []byte
+	Limit []byte
+}
+
+// Snapshot provides a consistent view of read operations in a DB.
+//
+// Snapshot is used in read operations by setting it on a
+// ReadOptions. Snapshots are created by calling DB.NewSnapshot.
+//
+// To prevent memory leaks and resource strain in the database, the snapshot
+// returned must be released with DB.ReleaseSnapshot method on the DB that
+// created it.
+type Snapshot struct {
+	snap *C.leveldb_snapshot_t
+}
+
+// Open opens a database.
+//
+// Creating a new database is done by calling SetCreateIfMissing(true) on the
+// Options passed to Open.
+//
+// It is usually wise to set a Cache object on the Options with SetCache to
+// keep recently used data from that database in memory.
+func Open(dbname string, o *Options) (*DB, error) {
+	var errStr *C.char
+	ldbname := C.CString(dbname)
+	defer C.free(unsafe.Pointer(ldbname))
+
+	leveldb := C.leveldb_open(o.Opt, ldbname, &errStr)
+	if errStr != nil {
+		gs := C.GoString(errStr)
+		C.leveldb_free(unsafe.Pointer(errStr))
+		return nil, DatabaseError(gs)
+	}
+	return &DB{leveldb}, nil
+}
+
+// DestroyDatabase removes a database entirely, removing everything from the
+// filesystem.
+func DestroyDatabase(dbname string, o *Options) error {
+	var errStr *C.char
+	ldbname := C.CString(dbname)
+	defer C.free(unsafe.Pointer(ldbname))
+
+	C.leveldb_destroy_db(o.Opt, ldbname, &errStr)
+	if errStr != nil {
+		gs := C.GoString(errStr)
+		C.leveldb_free(unsafe.Pointer(errStr))
+		return DatabaseError(gs)
+	}
+	return nil
+}
+
+// RepairDatabase attempts to repair a database.
+//
+// If the database is unrepairable, an error is returned.
+func RepairDatabase(dbname string, o *Options) error {
+	var errStr *C.char
+	ldbname := C.CString(dbname)
+	defer C.free(unsafe.Pointer(ldbname))
+
+	C.leveldb_repair_db(o.Opt, ldbname, &errStr)
+	if errStr != nil {
+		gs := C.GoString(errStr)
+		C.leveldb_free(unsafe.Pointer(errStr))
+		return DatabaseError(gs)
+	}
+	return nil
+}
+
+// Put writes data associated with a key to the database.
+//
+// If a nil []byte is passed in as value, it will be returned by Get
+// as an zero-length slice. The WriteOptions passed in can be reused
+// by multiple calls to this and if the WriteOptions is left unchanged.
+//
+// The key and value byte slices may be reused safely. Put takes a copy of
+// them before returning.
+func (db *DB) Put(wo *WriteOptions, key, value []byte) error {
+	var errStr *C.char
+	// leveldb_put, _get, and _delete call memcpy() (by way of Memtable::Add)
+	// when called, so we do not need to worry about these []byte being
+	// reclaimed by GC.
+	var k, v *C.char
+	if len(key) != 0 {
+		k = (*C.char)(unsafe.Pointer(&key[0]))
+	}
+	if len(value) != 0 {
+		v = (*C.char)(unsafe.Pointer(&value[0]))
+	}
+
+	lenk := len(key)
+	lenv := len(value)
+	C.leveldb_put(
+		db.Ldb, wo.Opt, k, C.size_t(lenk), v, C.size_t(lenv), &errStr)
+
+	if errStr != nil {
+		gs := C.GoString(errStr)
+		C.leveldb_free(unsafe.Pointer(errStr))
+		return DatabaseError(gs)
+	}
+	return nil
+}
+
+// Get returns the data associated with the key from the database.
+//
+// If the key does not exist in the database, a nil []byte is returned. If the
+// key does exist, but the data is zero-length in the database, a zero-length
+// []byte will be returned.
+//
+// The key byte slice may be reused safely. Get takes a copy of
+// them before returning.
+func (db *DB) Get(ro *ReadOptions, key []byte) ([]byte, error) {
+	var errStr *C.char
+	var vallen C.size_t
+	var k *C.char
+	if len(key) != 0 {
+		k = (*C.char)(unsafe.Pointer(&key[0]))
+	}
+
+	value := C.leveldb_get(
+		db.Ldb, ro.Opt, k, C.size_t(len(key)), &vallen, &errStr)
+
+	if errStr != nil {
+		gs := C.GoString(errStr)
+		C.leveldb_free(unsafe.Pointer(errStr))
+		return nil, DatabaseError(gs)
+	}
+
+	if value == nil {
+		return nil, nil
+	}
+
+	defer C.leveldb_free(unsafe.Pointer(value))
+	return C.GoBytes(unsafe.Pointer(value), C.int(vallen)), nil
+}
+
+// Delete removes the data associated with the key from the database.
+//
+// The key byte slice may be reused safely. Delete takes a copy of
+// them before returning. The WriteOptions passed in can be reused by
+// multiple calls to this and if the WriteOptions is left unchanged.
+func (db *DB) Delete(wo *WriteOptions, key []byte) error {
+	var errStr *C.char
+	var k *C.char
+	if len(key) != 0 {
+		k = (*C.char)(unsafe.Pointer(&key[0]))
+	}
+
+	C.leveldb_delete(
+		db.Ldb, wo.Opt, k, C.size_t(len(key)), &errStr)
+
+	if errStr != nil {
+		gs := C.GoString(errStr)
+		C.leveldb_free(unsafe.Pointer(errStr))
+		return DatabaseError(gs)
+	}
+	return nil
+}
+
+// Write atomically writes a WriteBatch to disk. The WriteOptions
+// passed in can be reused by multiple calls to this and other methods.
+func (db *DB) Write(wo *WriteOptions, w *WriteBatch) error {
+	var errStr *C.char
+	C.leveldb_write(db.Ldb, wo.Opt, w.wbatch, &errStr)
+	if errStr != nil {
+		gs := C.GoString(errStr)
+		C.leveldb_free(unsafe.Pointer(errStr))
+		return DatabaseError(gs)
+	}
+	return nil
+}
+
+// NewIterator returns an Iterator over the the database that uses the
+// ReadOptions given.
+//
+// Often, this is used for large, offline bulk reads while serving live
+// traffic. In that case, it may be wise to disable caching so that the data
+// processed by the returned Iterator does not displace the already cached
+// data. This can be done by calling SetFillCache(false) on the ReadOptions
+// before passing it here.
+//
+// Similiarly, ReadOptions.SetSnapshot is also useful.
+//
+// The ReadOptions passed in can be reused by multiple calls to this
+// and other methods if the ReadOptions is left unchanged.
+func (db *DB) NewIterator(ro *ReadOptions) *Iterator {
+	it := C.leveldb_create_iterator(db.Ldb, ro.Opt)
+	return &Iterator{Iter: it}
+}
+
+// GetApproximateSizes returns the approximate number of bytes of file system
+// space used by one or more key ranges.
+//
+// The keys counted will begin at Range.Start and end on the key before
+// Range.Limit.
+func (db *DB) GetApproximateSizes(ranges []Range) []uint64 {
+	starts := make([]*C.char, len(ranges))
+	limits := make([]*C.char, len(ranges))
+	startLens := make([]C.size_t, len(ranges))
+	limitLens := make([]C.size_t, len(ranges))
+	for i, r := range ranges {
+		starts[i] = C.CString(string(r.Start))
+		startLens[i] = C.size_t(len(r.Start))
+		limits[i] = C.CString(string(r.Limit))
+		limitLens[i] = C.size_t(len(r.Limit))
+	}
+	sizes := make([]uint64, len(ranges))
+	numranges := C.int(len(ranges))
+	startsPtr := &starts[0]
+	limitsPtr := &limits[0]
+	startLensPtr := &startLens[0]
+	limitLensPtr := &limitLens[0]
+	sizesPtr := (*C.uint64_t)(&sizes[0])
+	C.levigo_leveldb_approximate_sizes(
+		db.Ldb, numranges, startsPtr, startLensPtr,
+		limitsPtr, limitLensPtr, sizesPtr)
+	for i := range ranges {
+		C.free(unsafe.Pointer(starts[i]))
+		C.free(unsafe.Pointer(limits[i]))
+	}
+	return sizes
+}
+
+// PropertyValue returns the value of a database property.
+//
+// Examples of properties include "leveldb.stats", "leveldb.sstables",
+// and "leveldb.num-files-at-level0".
+func (db *DB) PropertyValue(propName string) string {
+	cname := C.CString(propName)
+	value := C.GoString(C.leveldb_property_value(db.Ldb, cname))
+	C.free(unsafe.Pointer(cname))
+	return value
+}
+
+// NewSnapshot creates a new snapshot of the database.
+//
+// The Snapshot, when used in a ReadOptions, provides a consistent
+// view of state of the database at the the snapshot was created.
+//
+// To prevent memory leaks and resource strain in the database, the snapshot
+// returned must be released with DB.ReleaseSnapshot method on the DB that
+// created it.
+//
+// See the LevelDB documentation for details.
+func (db *DB) NewSnapshot() *Snapshot {
+	return &Snapshot{C.leveldb_create_snapshot(db.Ldb)}
+}
+
+// ReleaseSnapshot removes the snapshot from the database's list of snapshots,
+// and deallocates it.
+func (db *DB) ReleaseSnapshot(snap *Snapshot) {
+	C.leveldb_release_snapshot(db.Ldb, snap.snap)
+}
+
+// CompactRange runs a manual compaction on the Range of keys given. This is
+// not likely to be needed for typical usage.
+func (db *DB) CompactRange(r Range) {
+	var start, limit *C.char
+	if len(r.Start) != 0 {
+		start = (*C.char)(unsafe.Pointer(&r.Start[0]))
+	}
+	if len(r.Limit) != 0 {
+		limit = (*C.char)(unsafe.Pointer(&r.Limit[0]))
+	}
+	C.leveldb_compact_range(
+		db.Ldb, start, C.size_t(len(r.Start)), limit, C.size_t(len(r.Limit)))
+}
+
+// Close closes the database, rendering it unusable for I/O, by deallocating
+// the underlying handle.
+//
+// Any attempts to use the DB after Close is called will panic.
+func (db *DB) Close() {
+	C.leveldb_close(db.Ldb)
+}
diff --git a/Godeps/_workspace/src/github.com/jmhodges/levigo/doc.go b/Godeps/_workspace/src/github.com/jmhodges/levigo/doc.go
new file mode 100644
index 0000000000000000000000000000000000000000..ac6b293dd0712830b78f4cf914adcf81a82b2a9e
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/jmhodges/levigo/doc.go
@@ -0,0 +1,65 @@
+/*
+
+Package levigo provides the ability to create and access LevelDB databases.
+
+levigo.Open opens and creates databases.
+
+	opts := levigo.NewOptions()
+	opts.SetCache(levigo.NewLRUCache(3<<30))
+	opts.SetCreateIfMissing(true)
+	db, err := levigo.Open("/path/to/db", opts)
+
+The DB struct returned by Open provides DB.Get, DB.Put and DB.Delete to modify
+and query the database.
+
+	ro := levigo.NewReadOptions()
+	wo := levigo.NewWriteOptions()
+	// if ro and wo are not used again, be sure to Close them.
+	data, err := db.Get(ro, []byte("key"))
+	...
+	err = db.Put(wo, []byte("anotherkey"), data)
+	...
+	err = db.Delete(wo, []byte("key"))
+
+For bulk reads, use an Iterator. If you want to avoid disturbing your live
+traffic while doing the bulk read, be sure to call SetFillCache(false) on the
+ReadOptions you use when creating the Iterator.
+
+	ro := levigo.NewReadOptions()
+	ro.SetFillCache(false)
+	it := db.NewIterator(ro)
+	defer it.Close()
+	for it.Seek(mykey); it.Valid(); it.Next() {
+		munge(it.Key(), it.Value())
+	}
+	if err := it.GetError(); err != nil {
+		...
+	}
+
+Batched, atomic writes can be performed with a WriteBatch and
+DB.Write.
+
+	wb := levigo.NewWriteBatch()
+	// defer wb.Close or use wb.Clear and reuse.
+	wb.Delete([]byte("removed"))
+	wb.Put([]byte("added"), []byte("data"))
+	wb.Put([]byte("anotheradded"), []byte("more"))
+	err := db.Write(wo, wb)
+
+If your working dataset does not fit in memory, you'll want to add a bloom
+filter to your database. NewBloomFilter and Options.SetFilterPolicy is what
+you want. NewBloomFilter is amount of bits in the filter to use per key in
+your database.
+
+	filter := levigo.NewBloomFilter(10)
+	opts.SetFilterPolicy(filter)
+	db, err := levigo.Open("/path/to/db", opts)
+
+If you're using a custom comparator in your code, be aware you may have to
+make your own filter policy object.
+
+This documentation is not a complete discussion of LevelDB. Please read the
+LevelDB documentation <http://code.google.com/p/leveldb> for information on
+its operation. You'll find lots of goodies there.
+*/
+package levigo
diff --git a/Godeps/_workspace/src/github.com/jmhodges/levigo/env.go b/Godeps/_workspace/src/github.com/jmhodges/levigo/env.go
new file mode 100644
index 0000000000000000000000000000000000000000..af9f808ef37c7355326b79d856074c574b9e7eb6
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/jmhodges/levigo/env.go
@@ -0,0 +1,29 @@
+package levigo
+
+// #cgo LDFLAGS: -lleveldb
+// #include "leveldb/c.h"
+import "C"
+
+// Env is a system call environment used by a database.
+//
+// Typically, NewDefaultEnv is all you need. Advanced users may create their
+// own Env with a *C.leveldb_env_t of their own creation.
+//
+// To prevent memory leaks, an Env must have Close called on it when it is
+// no longer needed by the program.
+type Env struct {
+	Env *C.leveldb_env_t
+}
+
+// NewDefaultEnv creates a default environment for use in an Options.
+//
+// To prevent memory leaks, the Env returned should be deallocated with
+// Close.
+func NewDefaultEnv() *Env {
+	return &Env{C.leveldb_create_default_env()}
+}
+
+// Close deallocates the Env, freeing the underlying struct.
+func (env *Env) Close() {
+	C.leveldb_env_destroy(env.Env)
+}
diff --git a/Godeps/_workspace/src/github.com/jmhodges/levigo/examples/comparator_example.go b/Godeps/_workspace/src/github.com/jmhodges/levigo/examples/comparator_example.go
new file mode 100644
index 0000000000000000000000000000000000000000..1c1b0f2f1421fecbc65aeeb2c02acb1c2fa4fc62
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/jmhodges/levigo/examples/comparator_example.go
@@ -0,0 +1,46 @@
+package main
+
+/*
+#cgo LDFLAGS: -lleveldb
+#include <string.h>
+#include <leveldb/c.h>
+
+static void CmpDestroy(void* arg) { }
+
+static int CmpCompare(void* arg, const char* a, size_t alen,
+                      const char* b, size_t blen) {
+  int n = (alen < blen) ? alen : blen;
+  int r = memcmp(a, b, n);
+  if (r == 0) {
+    if (alen < blen) r = -1;
+    else if (alen > blen) r = +1;
+  }
+  return r;
+}
+
+static const char* CmpName(void* arg) {
+  return "foo";
+}
+
+static leveldb_comparator_t* CmpFooNew() {
+  return leveldb_comparator_create(NULL, CmpDestroy, CmpCompare, CmpName);
+}
+
+*/
+import "C"
+
+type Comparator struct {
+	Comparator *C.leveldb_comparator_t
+}
+
+func NewFooComparator() *Comparator {
+	return &Comparator{C.CmpFooNew()}
+}
+
+func (cmp *Comparator) Close() {
+	C.leveldb_comparator_destroy(cmp.Comparator)
+}
+
+func main() {
+	NewFooComparator().Close()
+}
diff --git a/Godeps/_workspace/src/github.com/jmhodges/levigo/filterpolicy.go b/Godeps/_workspace/src/github.com/jmhodges/levigo/filterpolicy.go
new file mode 100644
index 0000000000000000000000000000000000000000..37d7b430df51ec93286b769ff56d22db4e29e64e
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/jmhodges/levigo/filterpolicy.go
@@ -0,0 +1,32 @@
+package levigo
+
+// #cgo LDFLAGS: -lleveldb
+// #include <stdlib.h>
+// #include "leveldb/c.h"
+import "C"
+
+// FilterPolicy is a factory type that allows the LevelDB database to create a
+// filter, such as a bloom filter, that is stored in the sstables and used by
+// DB.Get to reduce reads.
+//
+// An instance of this struct may be supplied to Options when opening a
+// DB. Typical usage is to call NewBloomFilter to get an instance.
+//
+// To prevent memory leaks, a FilterPolicy must have Close called on it when
+// it is no longer needed by the program.
+type FilterPolicy struct {
+	Policy *C.leveldb_filterpolicy_t
+}
+
+// NewBloomFilter creates a filter policy that will create a bloom filter when
+// necessary with the given number of bits per key.
+//
+// See the FilterPolicy documentation for more.
+func NewBloomFilter(bitsPerKey int) *FilterPolicy {
+	policy := C.leveldb_filterpolicy_create_bloom(C.int(bitsPerKey))
+	return &FilterPolicy{policy}
+}
+
+func (fp *FilterPolicy) Close() {
+	C.leveldb_filterpolicy_destroy(fp.Policy)
+}
diff --git a/Godeps/_workspace/src/github.com/jmhodges/levigo/iterator.go b/Godeps/_workspace/src/github.com/jmhodges/levigo/iterator.go
new file mode 100644
index 0000000000000000000000000000000000000000..83c633f90b0a5809639c756980744c6006dd2786
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/jmhodges/levigo/iterator.go
@@ -0,0 +1,149 @@
+package levigo
+
+// #cgo LDFLAGS: -lleveldb
+// #include <stdlib.h>
+// #include "leveldb/c.h"
+import "C"
+
+import (
+	"unsafe"
+)
+
+type IteratorError string
+
+func (e IteratorError) Error() string {
+	return string(e)
+}
+
+// Iterator is a read-only iterator through a LevelDB database. It provides a
+// way to seek to specific keys and iterate through the keyspace from that
+// point, as well as access the values of those keys.
+//
+// Care must be taken when using an Iterator. If the method Valid returns
+// false, calls to Key, Value, Next, and Prev will result in panics. However,
+// Seek, SeekToFirst, SeekToLast, GetError, Valid, and Close will still be
+// safe to call.
+//
+// GetError will only return an error in the event of a LevelDB error. It will
+// return a nil on iterators that are simply invalid. Given that behavior,
+// GetError is not a replacement for a Valid.
+//
+// A typical use looks like:
+//
+// 	db := levigo.Open(...)
+//
+// 	it := db.NewIterator(readOpts)
+// 	defer it.Close()
+// 	for it.Seek(mykey); it.Valid(); it.Next() {
+// 		useKeyAndValue(it.Key(), it.Value())
+// 	}
+// 	if err := it.GetError() {
+// 		...
+// 	}
+//
+// To prevent memory leaks, an Iterator must have Close called on it when it
+// is no longer needed by the program.
+type Iterator struct {
+	Iter *C.leveldb_iterator_t
+}
+
+// Valid returns false only when an Iterator has iterated past either the
+// first or the last key in the database.
+func (it *Iterator) Valid() bool {
+	return ucharToBool(C.leveldb_iter_valid(it.Iter))
+}
+
+// Key returns a copy the key in the database the iterator currently holds.
+//
+// If Valid returns false, this method will panic.
+func (it *Iterator) Key() []byte {
+	var klen C.size_t
+	kdata := C.leveldb_iter_key(it.Iter, &klen)
+	if kdata == nil {
+		return nil
+	}
+	// Unlike DB.Get, the key, kdata, returned is not meant to be freed by the
+	// client. It's a direct reference to data managed by the iterator_t
+	// instead of a copy.  So, we must not free it here but simply copy it
+	// with GoBytes.
+	return C.GoBytes(unsafe.Pointer(kdata), C.int(klen))
+}
+
+// Value returns a copy of the value in the database the iterator currently
+// holds.
+//
+// If Valid returns false, this method will panic.
+func (it *Iterator) Value() []byte {
+	var vlen C.size_t
+	vdata := C.leveldb_iter_value(it.Iter, &vlen)
+	if vdata == nil {
+		return nil
+	}
+	// Unlike DB.Get, the value, vdata, returned is not meant to be freed by
+	// the client. It's a direct reference to data managed by the iterator_t
+	// instead of a copy. So, we must not free it here but simply copy it with
+	// GoBytes.
+	return C.GoBytes(unsafe.Pointer(vdata), C.int(vlen))
+}
+
+// Next moves the iterator to the next sequential key in the database, as
+// defined by the Comparator in the ReadOptions used to create this Iterator.
+//
+// If Valid returns false, this method will panic.
+func (it *Iterator) Next() {
+	C.leveldb_iter_next(it.Iter)
+}
+
+// Prev moves the iterator to the previous sequential key in the database, as
+// defined by the Comparator in the ReadOptions used to create this Iterator.
+//
+// If Valid returns false, this method will panic.
+func (it *Iterator) Prev() {
+	C.leveldb_iter_prev(it.Iter)
+}
+
+// SeekToFirst moves the iterator to the first key in the database, as defined
+// by the Comparator in the ReadOptions used to create this Iterator.
+//
+// This method is safe to call when Valid returns false.
+func (it *Iterator) SeekToFirst() {
+	C.leveldb_iter_seek_to_first(it.Iter)
+}
+
+// SeekToLast moves the iterator to the last key in the database, as defined
+// by the Comparator in the ReadOptions used to create this Iterator.
+//
+// This method is safe to call when Valid returns false.
+func (it *Iterator) SeekToLast() {
+	C.leveldb_iter_seek_to_last(it.Iter)
+}
+
+// Seek moves the iterator the position of the key given or, if the key
+// doesn't exist, the next key that does exist in the database. If the key
+// doesn't exist, and there is no next key, the Iterator becomes invalid.
+//
+// This method is safe to call when Valid returns false.
+func (it *Iterator) Seek(key []byte) {
+	C.leveldb_iter_seek(it.Iter, (*C.char)(unsafe.Pointer(&key[0])), C.size_t(len(key)))
+}
+
+// GetError returns an IteratorError from LevelDB if it had one during
+// iteration.
+//
+// This method is safe to call when Valid returns false.
+func (it *Iterator) GetError() error {
+	var errStr *C.char
+	C.leveldb_iter_get_error(it.Iter, &errStr)
+	if errStr != nil {
+		gs := C.GoString(errStr)
+		C.leveldb_free(unsafe.Pointer(errStr))
+		return IteratorError(gs)
+	}
+	return nil
+}
+
+// Close deallocates the given Iterator, freeing the underlying C struct.
+func (it *Iterator) Close() {
+	C.leveldb_iter_destroy(it.Iter)
+	it.Iter = nil
+}
diff --git a/Godeps/_workspace/src/github.com/jmhodges/levigo/leveldb_test.go b/Godeps/_workspace/src/github.com/jmhodges/levigo/leveldb_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..f4537fdc5db02a7b90f3c8095f8f9ea75609b6ff
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/jmhodges/levigo/leveldb_test.go
@@ -0,0 +1,359 @@
+package levigo
+
+import (
+	"bytes"
+	"fmt"
+	"math/rand"
+	"os"
+	"path/filepath"
+	"testing"
+	"time"
+)
+
+func init() {
+	rand.Seed(int64(time.Now().Nanosecond()))
+}
+
+// This testcase is a port of leveldb's c_test.c.
+func TestC(t *testing.T) {
+	if GetLevelDBMajorVersion() <= 0 {
+		t.Errorf("Major version cannot be less than zero")
+	}
+
+	dbname := tempDir(t)
+	defer deleteDBDirectory(t, dbname)
+	env := NewDefaultEnv()
+	cache := NewLRUCache(1 << 20)
+
+	options := NewOptions()
+	// options.SetComparator(cmp)
+	options.SetErrorIfExists(true)
+	options.SetCache(cache)
+	options.SetEnv(env)
+	options.SetInfoLog(nil)
+	options.SetWriteBufferSize(1 << 20)
+	options.SetParanoidChecks(true)
+	options.SetMaxOpenFiles(10)
+	options.SetBlockSize(1024)
+	options.SetBlockRestartInterval(8)
+	options.SetCompression(NoCompression)
+
+	roptions := NewReadOptions()
+	roptions.SetVerifyChecksums(true)
+	roptions.SetFillCache(false)
+
+	woptions := NewWriteOptions()
+	woptions.SetSync(true)
+
+	_ = DestroyDatabase(dbname, options)
+
+	db, err := Open(dbname, options)
+	if err == nil {
+		t.Errorf("Open on missing db should have failed")
+	}
+
+	options.SetCreateIfMissing(true)
+	db, err = Open(dbname, options)
+	if err != nil {
+		t.Fatalf("Open failed: %v", err)
+	}
+
+	putKey := []byte("foo")
+	putValue := []byte("hello")
+	err = db.Put(woptions, putKey, putValue)
+	if err != nil {
+		t.Errorf("Put failed: %v", err)
+	}
+
+	CheckGet(t, "after Put", db, roptions, putKey, putValue)
+
+	wb := NewWriteBatch()
+	wb.Put([]byte("foo"), []byte("a"))
+	wb.Clear()
+	wb.Put([]byte("bar"), []byte("b"))
+	wb.Put([]byte("box"), []byte("c"))
+	wb.Delete([]byte("bar"))
+	err = db.Write(woptions, wb)
+	if err != nil {
+		t.Errorf("Write batch failed: %v", err)
+	}
+	CheckGet(t, "after WriteBatch", db, roptions, []byte("foo"), []byte("hello"))
+	CheckGet(t, "after WriteBatch", db, roptions, []byte("bar"), nil)
+	CheckGet(t, "after WriteBatch", db, roptions, []byte("box"), []byte("c"))
+	// TODO: WriteBatch iteration isn't easy. Suffers same problems as
+	// Comparator.
+	// wbiter := &TestWBIter{t: t}
+	// wb.Iterate(wbiter)
+	// if wbiter.pos != 3 {
+	// 	t.Errorf("After Iterate, on the wrong pos: %d", wbiter.pos)
+	// }
+	wb.Close()
+
+	iter := db.NewIterator(roptions)
+	if iter.Valid() {
+		t.Errorf("Read iterator should not be valid, yet")
+	}
+	iter.SeekToFirst()
+	if !iter.Valid() {
+		t.Errorf("Read iterator should be valid after seeking to first record")
+	}
+	CheckIter(t, iter, []byte("box"), []byte("c"))
+	iter.Next()
+	CheckIter(t, iter, []byte("foo"), []byte("hello"))
+	iter.Prev()
+	CheckIter(t, iter, []byte("box"), []byte("c"))
+	iter.Prev()
+	if iter.Valid() {
+		t.Errorf("Read iterator should not be valid after go back past the first record")
+	}
+	iter.SeekToLast()
+	CheckIter(t, iter, []byte("foo"), []byte("hello"))
+	iter.Seek([]byte("b"))
+	CheckIter(t, iter, []byte("box"), []byte("c"))
+	if iter.GetError() != nil {
+		t.Errorf("Read iterator has an error we didn't expect: %v", iter.GetError())
+	}
+	iter.Close()
+
+	// approximate sizes
+	n := 20000
+	for i := 0; i < n; i++ {
+		keybuf := []byte(fmt.Sprintf("k%020d", i))
+		valbuf := []byte(fmt.Sprintf("v%020d", i))
+		err := db.Put(woptions, keybuf, valbuf)
+		if err != nil {
+			t.Errorf("Put error in approximate size test: %v", err)
+		}
+	}
+
+	ranges := []Range{
+		{[]byte("a"), []byte("k00000000000000010000")},
+		{[]byte("k00000000000000010000"), []byte("z")},
+	}
+	sizes := db.GetApproximateSizes(ranges)
+	if len(sizes) == 2 {
+		if sizes[0] <= 0 {
+			t.Errorf("First size range was %d", sizes[0])
+		}
+		if sizes[1] <= 0 {
+			t.Errorf("Second size range was %d", sizes[1])
+		}
+	} else {
+		t.Errorf("Expected 2 approx. sizes back, got %d", len(sizes))
+	}
+
+	// property
+	prop := db.PropertyValue("nosuchprop")
+	if prop != "" {
+		t.Errorf("property nosuchprop should not have a value")
+	}
+	prop = db.PropertyValue("leveldb.stats")
+	if prop == "" {
+		t.Errorf("property leveldb.stats should have a value")
+	}
+
+	// snapshot
+	snap := db.NewSnapshot()
+	err = db.Delete(woptions, []byte("foo"))
+	if err != nil {
+		t.Errorf("Delete during snapshot test errored: %v", err)
+	}
+	roptions.SetSnapshot(snap)
+	CheckGet(t, "from snapshot", db, roptions, []byte("foo"), []byte("hello"))
+	roptions.SetSnapshot(nil)
+	CheckGet(t, "from snapshot", db, roptions, []byte("foo"), nil)
+	db.ReleaseSnapshot(snap)
+
+	// repair
+	db.Close()
+	options.SetCreateIfMissing(false)
+	options.SetErrorIfExists(false)
+	err = RepairDatabase(dbname, options)
+	if err != nil {
+		t.Errorf("Repairing db failed: %v", err)
+	}
+	db, err = Open(dbname, options)
+	if err != nil {
+		t.Errorf("Unable to open repaired db: %v", err)
+	}
+	CheckGet(t, "repair", db, roptions, []byte("foo"), nil)
+	CheckGet(t, "repair", db, roptions, []byte("bar"), nil)
+	CheckGet(t, "repair", db, roptions, []byte("box"), []byte("c"))
+	options.SetCreateIfMissing(true)
+	options.SetErrorIfExists(true)
+
+	// filter
+	policy := NewBloomFilter(10)
+	db.Close()
+	DestroyDatabase(dbname, options)
+	options.SetFilterPolicy(policy)
+	db, err = Open(dbname, options)
+	if err != nil {
+		t.Fatalf("Unable to recreate db for filter tests: %v", err)
+	}
+	err = db.Put(woptions, []byte("foo"), []byte("foovalue"))
+	if err != nil {
+		t.Errorf("Unable to put 'foo' with filter: %v", err)
+	}
+	err = db.Put(woptions, []byte("bar"), []byte("barvalue"))
+	if err != nil {
+		t.Errorf("Unable to put 'bar' with filter: %v", err)
+	}
+	db.CompactRange(Range{nil, nil})
+	CheckGet(t, "filter", db, roptions, []byte("foo"), []byte("foovalue"))
+	CheckGet(t, "filter", db, roptions, []byte("bar"), []byte("barvalue"))
+	options.SetFilterPolicy(nil)
+	policy.Close()
+
+	// cleanup
+	db.Close()
+	options.Close()
+	roptions.Close()
+	woptions.Close()
+	cache.Close()
+	// DestroyComparator(cmp)
+	env.Close()
+}
+
+func TestNilSlicesInDb(t *testing.T) {
+	dbname := tempDir(t)
+	defer deleteDBDirectory(t, dbname)
+	options := NewOptions()
+	options.SetErrorIfExists(true)
+	options.SetCreateIfMissing(true)
+	ro := NewReadOptions()
+	_ = DestroyDatabase(dbname, options)
+	db, err := Open(dbname, options)
+	if err != nil {
+		t.Fatalf("Database could not be opened: %v", err)
+	}
+	defer db.Close()
+	val, err := db.Get(ro, []byte("missing"))
+	if err != nil {
+		t.Errorf("Get failed: %v", err)
+	}
+	if val != nil {
+		t.Errorf("A key not in the db should return nil, not %v", val)
+	}
+	wo := NewWriteOptions()
+	db.Put(wo, nil, []byte("love"))
+	val, err = db.Get(ro, nil)
+	if !bytes.Equal([]byte("love"), val) {
+		t.Errorf("Get should see the nil key: %v", val)
+	}
+	val, err = db.Get(ro, []byte{})
+	if !bytes.Equal([]byte("love"), val) {
+		t.Errorf("Get shouldn't distinguish between nil key and empty slice key: %v", val)
+	}
+
+	err = db.Put(wo, []byte("nilvalue"), nil)
+	if err != nil {
+		t.Errorf("nil value Put errored: %v", err)
+	}
+	// Compare with the []byte("missing") case. We expect Get to return a
+	// []byte{} here, but expect a nil returned there.
+	CheckGet(t, "nil value Put", db, ro, []byte("nilvalue"), []byte{})
+
+	err = db.Put(wo, []byte("emptyvalue"), []byte{})
+	if err != nil {
+		t.Errorf("empty value Put errored: %v", err)
+	}
+	CheckGet(t, "empty value Put", db, ro, []byte("emptyvalue"), []byte{})
+
+	err = db.Delete(wo, nil)
+	if err != nil {
+		t.Errorf("nil key Delete errored: %v", err)
+	}
+	err = db.Delete(wo, []byte{})
+	if err != nil {
+		t.Errorf("empty slice key Delete errored: %v", err)
+	}
+
+}
+
+func TestIterationValidityLimits(t *testing.T) {
+	dbname := tempDir(t)
+	defer deleteDBDirectory(t, dbname)
+	options := NewOptions()
+	options.SetErrorIfExists(true)
+	options.SetCreateIfMissing(true)
+	ro := NewReadOptions()
+	wo := NewWriteOptions()
+	_ = DestroyDatabase(dbname, options)
+	db, err := Open(dbname, options)
+	if err != nil {
+		t.Fatalf("Database could not be opened: %v", err)
+	}
+	defer db.Close()
+	db.Put(wo, []byte("bat"), []byte("somedata"))
+	db.Put(wo, []byte("done"), []byte("somedata"))
+	it := db.NewIterator(ro)
+	defer it.Close()
+	if it.Valid() {
+		t.Errorf("new Iterator was valid")
+	}
+	it.Seek([]byte("bat"))
+	if !it.Valid() {
+		t.Errorf("Seek to %#v failed.", []byte("bat"))
+	}
+	if !bytes.Equal([]byte("bat"), it.Key()) {
+		t.Errorf("did not seek to []byte(\"bat\")")
+	}
+	key := it.Key()
+	it.Next()
+	if bytes.Equal(key, it.Key()) {
+		t.Errorf("key should be a copy of last key")
+	}
+	it.Next()
+	if it.Valid() {
+		t.Errorf("iterating off the db should result in an invalid iterator")
+	}
+	err = it.GetError()
+	if err != nil {
+		t.Errorf("should not have seen an error on an invalid iterator")
+	}
+	it.Seek([]byte("bat"))
+	if !it.Valid() {
+		t.Errorf("Iterator should be valid again")
+	}
+}
+
+func CheckGet(t *testing.T, where string, db *DB, roptions *ReadOptions, key, expected []byte) {
+	getValue, err := db.Get(roptions, key)
+
+	if err != nil {
+		t.Errorf("%s, Get failed: %v", where, err)
+	}
+	if !bytes.Equal(getValue, expected) {
+		t.Errorf("%s, expected Get value %v, got %v", where, expected, getValue)
+	}
+}
+
+func WBIterCheckEqual(t *testing.T, where string, which string, pos int, expected, given []byte) {
+	if !bytes.Equal(expected, given) {
+		t.Errorf("%s at pos %d, %s expected: %v, got: %v", where, pos, which, expected, given)
+	}
+}
+
+func CheckIter(t *testing.T, it *Iterator, key, value []byte) {
+	if !bytes.Equal(key, it.Key()) {
+		t.Errorf("Iterator: expected key %v, got %v", key, it.Key())
+	}
+	if !bytes.Equal(value, it.Value()) {
+		t.Errorf("Iterator: expected value %v, got %v", value, it.Value())
+	}
+}
+
+func deleteDBDirectory(t *testing.T, dirPath string) {
+	err := os.RemoveAll(dirPath)
+	if err != nil {
+		t.Errorf("Unable to remove database directory: %s", dirPath)
+	}
+}
+
+func tempDir(t *testing.T) string {
+	bottom := fmt.Sprintf("levigo-test-%d", rand.Int())
+	path := filepath.Join(os.TempDir(), bottom)
+	deleteDBDirectory(t, path)
+	return path
+}
diff --git a/Godeps/_workspace/src/github.com/jmhodges/levigo/options.go b/Godeps/_workspace/src/github.com/jmhodges/levigo/options.go
new file mode 100644
index 0000000000000000000000000000000000000000..9a7c66c7269da2b5197db5a34d9781b119165add
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/jmhodges/levigo/options.go
@@ -0,0 +1,229 @@
+package levigo
+
+// #cgo LDFLAGS: -lleveldb
+// #include "leveldb/c.h"
+import "C"
+
+// CompressionOpt is a value for Options.SetCompression.
+type CompressionOpt int
+
+// Known compression arguments for Options.SetCompression.
+const (
+	NoCompression     = CompressionOpt(0)
+	SnappyCompression = CompressionOpt(1)
+)
+
+// Options represent all of the available options when opening a database with
+// Open. Options should be created with NewOptions.
+//
+// It is usually with to call SetCache with a cache object. Otherwise, all
+// data will be read off disk.
+//
+// To prevent memory leaks, Close must be called on an Options when the
+// program no longer needs it.
+type Options struct {
+	Opt *C.leveldb_options_t
+}
+
+// ReadOptions represent all of the available options when reading from a
+// database.
+//
+// To prevent memory leaks, Close must called on a ReadOptions when the
+// program no longer needs it.
+type ReadOptions struct {
+	Opt *C.leveldb_readoptions_t
+}
+
+// WriteOptions represent all of the available options when writeing from a
+// database.
+//
+// To prevent memory leaks, Close must called on a WriteOptions when the
+// program no longer needs it.
+type WriteOptions struct {
+	Opt *C.leveldb_writeoptions_t
+}
+
+// NewOptions allocates a new Options object.
+func NewOptions() *Options {
+	opt := C.leveldb_options_create()
+	return &Options{opt}
+}
+
+// NewReadOptions allocates a new ReadOptions object.
+func NewReadOptions() *ReadOptions {
+	opt := C.leveldb_readoptions_create()
+	return &ReadOptions{opt}
+}
+
+// NewWriteOptions allocates a new WriteOptions object.
+func NewWriteOptions() *WriteOptions {
+	opt := C.leveldb_writeoptions_create()
+	return &WriteOptions{opt}
+}
+
+// Close deallocates the Options, freeing its underlying C struct.
+func (o *Options) Close() {
+	C.leveldb_options_destroy(o.Opt)
+}
+
+// SetComparator sets the comparator to be used for all read and write
+// operations.
+//
+// The comparator that created a database must be the same one (technically,
+// one with the same name string) that is used to perform read and write
+// operations.
+//
+// The default comparator is usually sufficient.
+func (o *Options) SetComparator(cmp *C.leveldb_comparator_t) {
+	C.leveldb_options_set_comparator(o.Opt, cmp)
+}
+
+// SetErrorIfExists, if passed true, will cause the opening of a database that
+// already exists to throw an error.
+func (o *Options) SetErrorIfExists(error_if_exists bool) {
+	eie := boolToUchar(error_if_exists)
+	C.leveldb_options_set_error_if_exists(o.Opt, eie)
+}
+
+// SetCache places a cache object in the database when a database is opened.
+//
+// This is usually wise to use. See also ReadOptions.SetFillCache.
+func (o *Options) SetCache(cache *Cache) {
+	C.leveldb_options_set_cache(o.Opt, cache.Cache)
+}
+
+// SetEnv sets the Env object for the new database handle.
+func (o *Options) SetEnv(env *Env) {
+	C.leveldb_options_set_env(o.Opt, env.Env)
+}
+
+// SetInfoLog sets a *C.leveldb_logger_t object as the informational logger
+// for the database.
+func (o *Options) SetInfoLog(log *C.leveldb_logger_t) {
+	C.leveldb_options_set_info_log(o.Opt, log)
+}
+
+// SetWriteBufferSize sets the number of bytes the database will build up in
+// memory (backed by an unsorted log on disk) before converting to a sorted
+// on-disk file.
+func (o *Options) SetWriteBufferSize(s int) {
+	C.leveldb_options_set_write_buffer_size(o.Opt, C.size_t(s))
+}
+
+// SetParanoidChecks, when called with true, will cause the database to do
+// aggressive checking of the data it is processing and will stop early if it
+// detects errors.
+//
+// See the LevelDB documentation docs for details.
+func (o *Options) SetParanoidChecks(pc bool) {
+	C.leveldb_options_set_paranoid_checks(o.Opt, boolToUchar(pc))
+}
+
+// SetMaxOpenFiles sets the number of files than can be used at once by the
+// database.
+//
+// See the LevelDB documentation for details.
+func (o *Options) SetMaxOpenFiles(n int) {
+	C.leveldb_options_set_max_open_files(o.Opt, C.int(n))
+}
+
+// SetBlockSize sets the approximate size of user data packed per block.
+//
+// The default is roughly 4096 uncompressed bytes. A better setting depends on
+// your use case. See the LevelDB documentation for details.
+func (o *Options) SetBlockSize(s int) {
+	C.leveldb_options_set_block_size(o.Opt, C.size_t(s))
+}
+
+// SetBlockRestartInterval is the number of keys between restarts points for
+// delta encoding keys.
+//
+// Most clients should leave this parameter alone. See the LevelDB
+// documentation for details.
+func (o *Options) SetBlockRestartInterval(n int) {
+	C.leveldb_options_set_block_restart_interval(o.Opt, C.int(n))
+}
+
+// SetCompression sets whether to compress blocks using the specified
+// compresssion algorithm.
+//
+// The default value is SnappyCompression and it is fast enough that it is
+// unlikely you want to turn it off. The other option is NoCompression.
+//
+// If the LevelDB library was built without Snappy compression enabled, the
+// SnappyCompression setting will be ignored.
+func (o *Options) SetCompression(t CompressionOpt) {
+	C.leveldb_options_set_compression(o.Opt, C.int(t))
+}
+
+// SetCreateIfMissing causes Open to create a new database on disk if it does
+// not already exist.
+func (o *Options) SetCreateIfMissing(b bool) {
+	C.leveldb_options_set_create_if_missing(o.Opt, boolToUchar(b))
+}
+
+// SetFilterPolicy causes Open to create a new database that will uses filter
+// created from the filter policy passed in.
+func (o *Options) SetFilterPolicy(fp *FilterPolicy) {
+	var policy *C.leveldb_filterpolicy_t
+	if fp != nil {
+		policy = fp.Policy
+	}
+	C.leveldb_options_set_filter_policy(o.Opt, policy)
+}
+
+// Close deallocates the ReadOptions, freeing its underlying C struct.
+func (ro *ReadOptions) Close() {
+	C.leveldb_readoptions_destroy(ro.Opt)
+}
+
+// SetVerifyChecksums controls whether all data read with this ReadOptions
+// will be verified against corresponding checksums.
+//
+// It defaults to false. See the LevelDB documentation for details.
+func (ro *ReadOptions) SetVerifyChecksums(b bool) {
+	C.leveldb_readoptions_set_verify_checksums(ro.Opt, boolToUchar(b))
+}
+
+// SetFillCache controls whether reads performed with this ReadOptions will
+// fill the Cache of the server. It defaults to true.
+//
+// It is useful to turn this off on ReadOptions for DB.Iterator (and DB.Get)
+// calls used in offline threads to prevent bulk scans from flushing out live
+// user data in the cache.
+//
+// See also Options.SetCache
+func (ro *ReadOptions) SetFillCache(b bool) {
+	C.leveldb_readoptions_set_fill_cache(ro.Opt, boolToUchar(b))
+}
+
+// SetSnapshot causes reads to provided as they were when the passed in
+// Snapshot was created by DB.NewSnapshot. This is useful for getting
+// consistent reads during a bulk operation.
+//
+// See the LevelDB documentation for details.
+func (ro *ReadOptions) SetSnapshot(snap *Snapshot) {
+	var s *C.leveldb_snapshot_t
+	if snap != nil {
+		s = snap.snap
+	}
+	C.leveldb_readoptions_set_snapshot(ro.Opt, s)
+}
+
+// Close deallocates the WriteOptions, freeing its underlying C struct.
+func (wo *WriteOptions) Close() {
+	C.leveldb_writeoptions_destroy(wo.Opt)
+}
+
+// SetSync controls whether each write performed with this WriteOptions will
+// be flushed from the operating system buffer cache before the write is
+// considered complete.
+//
+// If called with true, this will signficantly slow down writes. If called
+// with false, and the host machine crashes, some recent writes may be
+// lost. The default is false.
+//
+// See the LevelDB documentation for details.
+func (wo *WriteOptions) SetSync(b bool) {
+	C.leveldb_writeoptions_set_sync(wo.Opt, boolToUchar(b))
+}
diff --git a/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/readerutil.go b/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/readerutil.go
new file mode 100644
index 0000000000000000000000000000000000000000..5e6cb77e80b9771dfaf8fe69068de962cd72cc9e
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/readerutil.go
@@ -0,0 +1,434 @@
+// Package readerutil implements io.Reader utility functions.
+package readerutil
+
+import "bufio"
+import "encoding/binary"
+import "errors"
+import "io"
+import "os"
+import "unicode"
+import "unicode/utf16"
+import "unicode/utf8"
+
+var ErrUnknownEncoding = errors.New("readerutil.NewLineReader: unknown encoding.")
+
+// NewByteReader returns a new io.ByteReader based on the provided io.Reader.
+func NewByteReader(r io.Reader) io.ByteReader {
+	return byteReader{Reader: r}
+}
+
+// byteReader implements the io.ByteReader interface.
+type byteReader struct {
+	io.Reader
+}
+
+// ReadByte reads and returns the next byte from the input. If no byte is
+// available, err will be set.
+func (r byteReader) ReadByte() (c byte, err error) {
+	return ReadByte(r)
+}
+
+// ReadByte reads and returns the next byte from the provided io.Reader.
+func ReadByte(r io.Reader) (c byte, err error) {
+	buf := make([]byte, 1)
+	_, err = io.ReadFull(r, buf)
+	if err != nil {
+		return 0, err
+	}
+
+	return buf[0], nil
+}
+
+// A Peeker is an io.ReadSeeker that can also peek ahead.
+//
+// Peek returns the next n bytes without advancing the reader. The error is EOF
+// only if no bytes were read. If an EOF happens after reading some but not all
+// the bytes, ReadFull returns ErrUnexpectedEOF.
+type Peeker interface {
+	io.ReadSeeker
+	Peek(n int) (buf []byte, err error)
+}
+
+// peeker implements the Peeker interface.
+type peeker struct {
+	io.ReadSeeker
+}
+
+// NewPeeker returns a new Peeker based on the provided io.ReadSeeker.
+func NewPeeker(r io.ReadSeeker) Peeker {
+	return peeker{ReadSeeker: r}
+}
+
+// Peek returns the next n bytes without advancing the reader. The error is EOF
+// only if no bytes were read. If an EOF happens after reading some but not all
+// the bytes, ReadFull returns ErrUnexpectedEOF.
+func (r peeker) Peek(n int) (buf []byte, err error) {
+	// Record original position.
+	orig, err := r.Seek(0, os.SEEK_CUR)
+	if err != nil {
+		return nil, err
+	}
+
+	// Read content, but check error after position reset.
+	buf = make([]byte, n)
+	m, e := io.ReadFull(r, buf)
+
+	// Reset original position.
+	_, err = r.Seek(orig, os.SEEK_SET)
+	if err != nil {
+		return nil, err
+	}
+
+	if e != nil && e != io.ErrUnexpectedEOF {
+		// Return read error.
+		return nil, e
+	}
+
+	if m < n {
+		// Short read.
+		buf = buf[:m]
+	}
+
+	return buf, e
+}
+
+// A BinaryPeeker is an io.ReadSeeker that can also peek ahead.
+//
+// Peek reads structured binary data without advancing the reader. Data must be
+// a pointer to a fixed-size value or a slice of fixed-size values. Bytes read
+// from r are decoded using the receiver's byte order and written to successive
+// fields of the data. When reading into structs, the field data for fields with
+// blank (_) field names is skipped; i.e., blank field names may be used for
+// padding.
+type BinaryPeeker interface {
+	io.ReadSeeker
+	Peek(data interface{}) (err error)
+}
+
+// binaryPeeker implements the BinaryPeeker interface.
+type binaryPeeker struct {
+	io.ReadSeeker
+	order binary.ByteOrder
+}
+
+// NewBinaryPeeker returns a new BinaryPeeker based on the provided
+// io.ReadSeeker.
+func NewBinaryPeeker(r io.ReadSeeker, order binary.ByteOrder) BinaryPeeker {
+	return binaryPeeker{ReadSeeker: r, order: order}
+}
+
+// Peek reads structured binary data without advancing the reader. Data must be
+// a pointer to a fixed-size value or a slice of fixed-size values. Bytes read
+// from r are decoded using the receiver's byte order and written to successive
+// fields of the data. When reading into structs, the field data for fields with
+// blank (_) field names is skipped; i.e., blank field names may be used for
+// padding.
+func (r binaryPeeker) Peek(data interface{}) (err error) {
+	// Record original position.
+	orig, err := r.Seek(0, os.SEEK_CUR)
+	if err != nil {
+		return err
+	}
+
+	// Read content, but check error after position reset.
+	e := binary.Read(r, r.order, data)
+
+	// Reset original position.
+	_, err = r.Seek(orig, os.SEEK_SET)
+	if err != nil {
+		return err
+	}
+
+	if e != nil {
+		// Return read error.
+		return e
+	}
+
+	return nil
+}
+
+// Size returns the total size in bytes of the provided io.Seeker. The original
+// position is preserved.
+func Size(r io.Seeker) (n int64, err error) {
+	// Record original position.
+	orig, err := r.Seek(0, os.SEEK_CUR)
+	if err != nil {
+		return 0, err
+	}
+
+	// Seek end position.
+	end, err := r.Seek(0, os.SEEK_END)
+	if err != nil {
+		return 0, err
+	}
+
+	// Reset original position.
+	_, err = r.Seek(orig, os.SEEK_SET)
+	if err != nil {
+		return 0, err
+	}
+
+	return end, nil
+}
+
+// IsUTF8 decodes a chunk of data as UTF-8 and returns true if no decoding
+// errors occured and at least 75% of the decoded runes are graphic or space and
+// within the ASCII range.
+func IsUTF8(r io.ReadSeeker) (ok bool, err error) {
+	// Read a chunk of at most 256 bytes.
+	const chunkSize = 256
+	rr := NewPeeker(r)
+	buf, err := rr.Peek(chunkSize)
+	if err != nil && err != io.ErrUnexpectedEOF {
+		return false, err
+	}
+
+	// Decode the chunk as UTF-8. Make sure that no short rune reads are
+	// performed.
+	var printableCount, total float64
+	for utf8.FullRune(buf) {
+		r, size := utf8.DecodeRune(buf)
+		if r == utf8.RuneError {
+			// No rune errors should occur in valid UTF-8.
+			return false, nil
+		}
+		if isPrintable(r) {
+			// Record printable runes.
+			printableCount++
+		}
+		total++
+		buf = buf[size:]
+	}
+
+	if total < 1 {
+		// No valid UTF-8 runes located.
+		return false, nil
+	}
+
+	if printableCount/total >= 0.75 {
+		// Assume that the data is UTF-8, since at least 75% of the runes are
+		// graphic or space and within the ASCII range.
+		return true, nil
+	}
+
+	return false, nil
+}
+
+// IsUTF16 decodes a chunk of data as UTF-16 with the specified byte order and
+// returns true if a valid BOM byte sequence was located or no decoding errors
+// occured and at least 75% of the decoded runes are graphic or space and within
+// the ASCII range.
+func IsUTF16(r io.ReadSeeker, order binary.ByteOrder) (ok bool, err error) {
+	// Verify file size.
+	size, err := Size(r)
+	if err != nil {
+		return false, err
+	}
+	if size < 2 || size%2 != 0 {
+		// UTF-16 must be dividable by 2.
+		return false, nil
+	}
+
+	// Peek for UTF-16 BOM byte sequence.
+	const BOM = 0xFEFF
+	var bom uint16
+	rr := NewBinaryPeeker(r, order)
+	err = rr.Peek(&bom)
+	if err != nil {
+		return false, err
+	}
+	if bom == BOM {
+		return true, nil
+	}
+
+	// Read a chunk of at most 256 bytes.
+	chunkSize := 256
+	if size < int64(chunkSize) {
+		chunkSize = int(size)
+	}
+	buf := make([]uint16, chunkSize/2)
+	err = rr.Peek(buf)
+	if err != nil {
+		return false, err
+	}
+
+	// Make sure that no short rune reads are performed.
+	const (
+		// 0xd800-0xdc00 encodes the high 10 bits of a pair.
+		// 0xdc00-0xe000 encodes the low 10 bits of a pair.
+		// the value is those 20 bits plus 0x10000.
+		surr1 = 0xd800
+		surr2 = 0xdc00
+		surr3 = 0xe000
+	)
+	if surr1 <= buf[len(buf)-1] && buf[len(buf)-1] < surr2 {
+		// Ignore the last rune if it is the first surrogate of a pair.
+		buf = buf[:len(buf)-1]
+	}
+
+	// Decode the chunk as UTF-16.
+	var printableCount, total float64
+	for _, r := range utf16.Decode(buf) {
+		if r == unicode.ReplacementChar {
+			// No rune errors should occur in valid UTF-16.
+			return false, nil
+		}
+		if isPrintable(r) {
+			// Record printable runes.
+			printableCount++
+		}
+		total++
+	}
+
+	if total < 1 {
+		// No valid UTF-8 runes located.
+		return false, nil
+	}
+
+	if printableCount/total >= 0.75 {
+		// Assume that the data is UTF-16, since at least 75% of the runes are
+		// graphic or space and within the ASCII range.
+		return true, nil
+	}
+
+	return false, nil
+}
+
+// isPrintable returns true if the provided rune is graphic or space and within
+// the ASCII range.
+func isPrintable(r rune) bool {
+	if r > unicode.MaxASCII {
+		return false
+	}
+	return unicode.IsGraphic(r) || unicode.IsSpace(r)
+}
+
+// LineReader implements the ReadLine method.
+//
+// ReadLine returns a single line, not including the end-of-line bytes. ReadLine
+// either returns a valid line (can be empty) or it returns an error, never
+// both.
+type LineReader interface {
+	ReadLine() (line string, err error)
+}
+
+// NewLineReader returns a LineReader that reads from r. If able to determine
+// the encoding it decodes each line to UTF-8.
+func NewLineReader(r io.ReadSeeker) (lr LineReader, err error) {
+	// UTF-8.
+	ok, err := IsUTF8(r)
+	if err != nil {
+		return nil, err
+	}
+	if ok {
+		lr = newLineReaderUTF8(r)
+		return lr, nil
+	}
+
+	// UTF-16 little endian.
+	ok, err = IsUTF16(r, binary.LittleEndian)
+	if err != nil {
+		return nil, err
+	}
+	if ok {
+		lr = newLineReaderUTF16(r, binary.LittleEndian)
+		return lr, nil
+	}
+
+	// UTF-16 big endian.
+	ok, err = IsUTF16(r, binary.BigEndian)
+	if err != nil {
+		return nil, err
+	}
+	if ok {
+		lr = newLineReaderUTF16(r, binary.BigEndian)
+		return lr, nil
+	}
+
+	return nil, ErrUnknownEncoding
+}
+
+// lineReaderUTF8 implements the LineReader interface for UTF-8 encoded data.
+type lineReaderUTF8 struct {
+	*bufio.Reader
+}
+
+// newLineReaderUTF8 returns a new LineReader for UTF-8 encoded data.
+func newLineReaderUTF8(r io.Reader) (lr *lineReaderUTF8) {
+	lr = &lineReaderUTF8{
+		Reader: bufio.NewReader(r),
+	}
+	return lr
+}
+
+// ReadLine returns a single line, not including the end-of-line bytes. ReadLine
+// either returns a valid line (can be empty) or it returns an error, never
+// both.
+func (lr *lineReaderUTF8) ReadLine() (line string, err error) {
+	// Read line.
+	line, err = lr.ReadString('\n')
+	if err != nil && len(line) == 0 {
+		// Only return io.EOF if no bytes have been read.
+		return "", err
+	}
+
+	// Drop the end-of-line bytes.
+	if len(line) > 0 && line[len(line)-1] == '\n' {
+		drop := 1
+		if len(line) > 1 && line[len(line)-2] == '\r' {
+			drop = 2
+		}
+		line = line[:len(line)-drop]
+	}
+
+	return line, nil
+}
+
+// lineReaderUTF16 implements the LineReader interface for UTF-16 encoded data.
+type lineReaderUTF16 struct {
+	io.Reader
+	order binary.ByteOrder
+}
+
+// newLineReaderUTF16 returns a new LineReader for UTF-16 encoded data with the
+// specified byte order.
+func newLineReaderUTF16(r io.Reader, order binary.ByteOrder) (lr *lineReaderUTF16) {
+	lr = &lineReaderUTF16{
+		Reader: r,
+		order:  order,
+	}
+	return lr
+}
+
+// ReadLine returns a single line, not including the end-of-line bytes. ReadLine
+// either returns a valid line (can be empty) or it returns an error, never
+// both.
+func (lr *lineReaderUTF16) ReadLine() (line string, err error) {
+	// Read line.
+	buf := make([]uint16, 0)
+	for {
+		var v uint16
+		err = binary.Read(lr, lr.order, &v)
+		if err != nil {
+			if len(buf) > 0 {
+				// Break at io.EOF if data has been read.
+				break
+			}
+			// Only return io.EOF if no bytes have been read.
+			return "", err
+		}
+		if v == '\n' {
+			// Break at newline.
+			break
+		}
+		buf = append(buf, v)
+	}
+	line = string(utf16.Decode(buf))
+
+	// Drop the end-of-line bytes.
+	if len(line) > 0 && line[len(line)-1] == '\r' {
+		line = line[:len(line)-1]
+	}
+
+	return line, nil
+}
diff --git a/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/readerutil_test.go b/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/readerutil_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..b7568ce12a11fbda147869794158f6b47a2f02be
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/readerutil_test.go
@@ -0,0 +1,221 @@
+package readerutil
+
+import "encoding/binary"
+import "io"
+import "os"
+import "testing"
+
+type testSize struct {
+	path string
+	want int64 // size in bytes.
+}
+
+func TestSize(t *testing.T) {
+	golden := []testSize{
+		{path: "testdata/utf16be_crlf.txt", want: 62},
+		{path: "testdata/utf16be.txt", want: 56},
+		{path: "testdata/utf16le_crlf.txt", want: 62},
+		{path: "testdata/utf16le.txt", want: 56},
+		{path: "testdata/utf8_crlf.txt", want: 35},
+		{path: "testdata/utf8.txt", want: 32},
+	}
+	for _, g := range golden {
+		fr, err := os.Open(g.path)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+		defer fr.Close()
+
+		// Verify file size.
+		got, err := Size(fr)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+		if got != g.want {
+			t.Errorf("%s: expected %d, got %d.", g.path, g.want, got)
+			continue
+		}
+	}
+}
+
+type testIsUTF8 struct {
+	path string
+	want bool
+}
+
+func TestIsUTF8(t *testing.T) {
+	golden := []testIsUTF8{
+		{path: "testdata/utf16be_crlf.txt", want: false},
+		{path: "testdata/utf16be.txt", want: false},
+		{path: "testdata/utf16le_crlf.txt", want: false},
+		{path: "testdata/utf16le.txt", want: false},
+		{path: "testdata/utf8_crlf.txt", want: true},
+		{path: "testdata/utf8.txt", want: true},
+	}
+	for _, g := range golden {
+		fr, err := os.Open(g.path)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+		defer fr.Close()
+
+		// Verify file encoding.
+		got, err := IsUTF8(fr)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+		if got != g.want {
+			t.Errorf("%s: expected %t, got %t.", g.path, g.want, got)
+			continue
+		}
+	}
+}
+
+type testIsUTF16 struct {
+	path  string
+	order binary.ByteOrder
+	want  bool
+}
+
+func TestIsUTF16(t *testing.T) {
+	golden := []testIsUTF16{
+		{path: "testdata/utf16be_crlf.txt", order: binary.BigEndian, want: true},
+		{path: "testdata/utf16be_crlf.txt", order: binary.LittleEndian, want: false},
+		{path: "testdata/utf16be.txt", order: binary.BigEndian, want: true},
+		{path: "testdata/utf16be.txt", order: binary.LittleEndian, want: false},
+		{path: "testdata/utf16le_crlf.txt", order: binary.BigEndian, want: false},
+		{path: "testdata/utf16le_crlf.txt", order: binary.LittleEndian, want: true},
+		{path: "testdata/utf16le.txt", order: binary.BigEndian, want: false},
+		{path: "testdata/utf16le.txt", order: binary.LittleEndian, want: true},
+		{path: "testdata/utf8_crlf.txt", order: binary.BigEndian, want: false},
+		{path: "testdata/utf8_crlf.txt", order: binary.LittleEndian, want: false},
+		{path: "testdata/utf8.txt", order: binary.BigEndian, want: false},
+		{path: "testdata/utf8.txt", order: binary.LittleEndian, want: false},
+	}
+	for _, g := range golden {
+		fr, err := os.Open(g.path)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+		defer fr.Close()
+
+		// Verify file encoding.
+		got, err := IsUTF16(fr, g.order)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+		if got != g.want {
+			t.Errorf("%s: expected %t, got %t.", g.path, g.want, got)
+			continue
+		}
+	}
+}
+
+type testNewLineReader struct {
+	path  string
+	lines []string
+}
+
+func TestNewLineReader(t *testing.T) {
+	golden := []testNewLineReader{
+		{
+			path: "testdata/utf16be_crlf.txt",
+			lines: []string{
+				"testing 123",
+				"",
+				"hello 世界",
+				"mewmew",
+			},
+		},
+		{
+			path: "testdata/utf16be.txt",
+			lines: []string{
+				"testing 123",
+				"",
+				"hello 世界",
+				"mewmew",
+			},
+		},
+		{
+			path: "testdata/utf16le_crlf.txt",
+			lines: []string{
+				"testing 123",
+				"",
+				"hello 世界",
+				"mewmew",
+			},
+		},
+		{
+			path: "testdata/utf16le.txt",
+			lines: []string{
+				"testing 123",
+				"",
+				"hello 世界",
+				"mewmew",
+			},
+		},
+		{
+			path: "testdata/utf8_crlf.txt",
+			lines: []string{
+				"testing 123",
+				"",
+				"hello 世界",
+				"mewmew",
+			},
+		},
+		{
+			path: "testdata/utf8.txt",
+			lines: []string{
+				"testing 123",
+				"",
+				"hello 世界",
+				"mewmew",
+			},
+		},
+	}
+	for _, g := range golden {
+		fr, err := os.Open(g.path)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+		defer fr.Close()
+
+		// Verify lines.
+		lr, err := NewLineReader(fr)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+		lineNum := 0
+		for {
+			got, err := lr.ReadLine()
+			if err != nil {
+				if err != io.EOF {
+					t.Error(err)
+				}
+				// break on io.EOF
+				break
+			}
+			if lineNum >= len(g.lines) {
+				t.Errorf("lines slice out of bounds (%d >= %d).", lineNum, len(g.lines))
+				break
+			}
+			want := g.lines[lineNum]
+			lineNum++
+			if got != want {
+				t.Errorf("%s: expected %q, got %q.", g.path, want, got)
+				continue
+			}
+		}
+		if lineNum != len(g.lines) {
+			t.Errorf("tested %d out of %d lines.", lineNum, len(g.lines))
+		}
+	}
+}
diff --git a/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/testdata/utf16be.txt b/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/testdata/utf16be.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f0f6004902dd1e4b0274f1de4c9bc64268d929c2
Binary files /dev/null and b/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/testdata/utf16be.txt differ
diff --git a/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/testdata/utf16be_crlf.txt b/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/testdata/utf16be_crlf.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7dbc6624504374d2079d17d02727015331e7ddd9
Binary files /dev/null and b/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/testdata/utf16be_crlf.txt differ
diff --git a/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/testdata/utf16le.txt b/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/testdata/utf16le.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e9d9024f452d8530f8d98dd358ea24536c903319
Binary files /dev/null and b/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/testdata/utf16le.txt differ
diff --git a/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/testdata/utf16le_crlf.txt b/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/testdata/utf16le_crlf.txt
new file mode 100644
index 0000000000000000000000000000000000000000..34b4d49be7c2af1cd34bf5f7bdecfb8d7ee9b670
Binary files /dev/null and b/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/testdata/utf16le_crlf.txt differ
diff --git a/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/testdata/utf8.txt b/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/testdata/utf8.txt
new file mode 100644
index 0000000000000000000000000000000000000000..152097b88070460370844a024c2195dabacf13b7
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/testdata/utf8.txt
@@ -0,0 +1,4 @@
+testing 123
+
+hello 世界
+mewmew
\ No newline at end of file
diff --git a/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/testdata/utf8_crlf.txt b/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/testdata/utf8_crlf.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7abdbce43dd4012fb63b65e29efa6fbea81d74cc
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/mewkiz/pkg/readerutil/testdata/utf8_crlf.txt
@@ -0,0 +1,4 @@
+testing 123
+
+hello 世界
+mewmew
\ No newline at end of file
diff --git a/Godeps/_workspace/src/golang.org/x/text/transform/examples_test.go b/Godeps/_workspace/src/golang.org/x/text/transform/examples_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..f2e284dba52b19696bcc0afb7f1cf256a4c4e0d8
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/text/transform/examples_test.go
@@ -0,0 +1,37 @@
+// 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_test
+
+import (
+	"fmt"
+	"unicode"
+
+	"golang.org/x/text/transform"
+	"golang.org/x/text/unicode/norm"
+)
+
+func ExampleRemoveFunc() {
+	input := []byte(`tschüß; до свидания`)
+
+	b := make([]byte, len(input))
+
+	t := transform.RemoveFunc(unicode.IsSpace)
+	n, _, _ := t.Transform(b, input, true)
+	fmt.Println(string(b[:n]))
+
+	t = transform.RemoveFunc(func(r rune) bool {
+		return !unicode.Is(unicode.Latin, r)
+	})
+	n, _, _ = t.Transform(b, input, true)
+	fmt.Println(string(b[:n]))
+
+	n, _, _ = t.Transform(b, norm.NFD.Bytes(input), true)
+	fmt.Println(string(b[:n]))
+
+	// Output:
+	// tschüß;досвидания
+	// tschüß
+	// tschuß
+}
diff --git a/Godeps/_workspace/src/golang.org/x/text/transform/transform.go b/Godeps/_workspace/src/golang.org/x/text/transform/transform.go
new file mode 100644
index 0000000000000000000000000000000000000000..157ee789211f649eb221cab227d796f7146c9cfc
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/text/transform/transform.go
@@ -0,0 +1,616 @@
+// 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 (
+	"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")
+
+	// 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()
+}
+
+// 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 && 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
+			}
+		} else {
+			n += nSrc
+		}
+		switch {
+		case err == ErrShortDst && (nDst > 0 || nSrc > 0):
+		case err == ErrShortSrc && 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
+			return n, nil
+		case err == nil && w.n > 0:
+			return n, errInconsistentByteCount
+		default:
+			return n, err
+		}
+	}
+}
+
+// Close implements the io.Closer interface.
+func (w *Writer) Close() error {
+	for src := w.src[:w.n]; len(src) > 0; {
+		nDst, nSrc, err := w.t.Transform(w.dst, src, true)
+		if nDst == 0 {
+			return err
+		}
+		if _, werr := w.w.Write(w.dst[:nDst]); werr != nil {
+			return werr
+		}
+		if err != ErrShortDst {
+			return err
+		}
+		src = src[nSrc:]
+	}
+	return nil
+}
+
+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
+}
+
+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 Transformer that copies src to dst.
+	Nop Transformer = 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
+	}
+}
+
+// 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
+}
+
+// RemoveFunc returns a Transformer that removes from the input all runes r for
+// which f(r) is true. Illegal bytes in the input are replaced by RuneError.
+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 <= 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) {
+	if s == "" {
+		return "", 0, nil
+	}
+
+	t.Reset()
+
+	// 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]
+
+	// Avoid allocation if the transformed string is identical to the original.
+	// After this loop, pDst will point to the furthest point in s for which it
+	// could be detected that t gives equal results, src[:nSrc] will
+	// indicated the last processed chunk of s for which the output is not equal
+	// and dst[:nDst] will be the transform of this chunk.
+	var nDst, nSrc int
+	pDst := 0 // Used as index in both src and dst in this loop.
+	for {
+		n := copy(src, s[pDst:])
+		nDst, nSrc, err = t.Transform(dst, src[:n], pDst+n == len(s))
+
+		// Note 1: we will not enter the loop with pDst == len(s) and we will
+		// not end the loop with it either. So if nSrc is 0, this means there is
+		// some kind of error from which we cannot recover given the current
+		// buffer sizes. We will give up in this case.
+		// Note 2: it is not entirely correct to simply do a bytes.Equal as
+		// a Transformer may buffer internally. It will work in most cases,
+		// though, and no harm is done if it doesn't work.
+		// TODO:  let transformers implement an optional Spanner interface, akin
+		// to norm's QuickSpan. This would even allow us to avoid any allocation.
+		if nSrc == 0 || !bytes.Equal(dst[:nDst], src[:nSrc]) {
+			break
+		}
+
+		if pDst += nDst; pDst == len(s) {
+			return s, pDst, nil
+		}
+	}
+
+	// Move the bytes seen so far to dst.
+	pSrc := pDst + nSrc
+	if pDst+nDst <= initialBufSize {
+		copy(dst[pDst:], dst[:nDst])
+	} else {
+		b := make([]byte, len(s)+nDst-nSrc)
+		copy(b[pDst:], dst[:nDst])
+		dst = b
+	}
+	copy(dst, s[:pDst])
+	pDst += nDst
+
+	if err != nil && err != ErrShortDst && err != ErrShortSrc {
+		return string(dst[:pDst]), pSrc, err
+	}
+
+	// Complete the string with the remainder.
+	for {
+		n := copy(src, s[pSrc:])
+		nDst, nSrc, err = t.Transform(dst[pDst:], src[:n], pSrc+n == len(s))
+		pDst += nDst
+		pSrc += nSrc
+
+		switch err {
+		case nil:
+			if pSrc == len(s) {
+				return string(dst[:pDst]), pSrc, nil
+			}
+		case ErrShortDst:
+			// Do not grow as long as we can make progress. This may avoid
+			// excessive allocations.
+			if nDst == 0 {
+				dst = grow(dst, pDst)
+			}
+		case ErrShortSrc:
+			if nSrc == 0 {
+				src = grow(src, 0)
+			}
+		default:
+			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) {
+	t.Reset()
+	dst := make([]byte, len(b))
+	pDst, pSrc := 0, 0
+	for {
+		nDst, nSrc, err := t.Transform(dst[pDst:], b[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/Godeps/_workspace/src/golang.org/x/text/transform/transform_test.go b/Godeps/_workspace/src/golang.org/x/text/transform/transform_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..b463f4f1b37d1761cca7acc95db7b3682159ca09
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/text/transform/transform_test.go
@@ -0,0 +1,1082 @@
+// 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
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"io/ioutil"
+	"strconv"
+	"strings"
+	"testing"
+	"time"
+	"unicode/utf8"
+)
+
+type lowerCaseASCII struct{ NopResetter }
+
+func (lowerCaseASCII) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+	n := len(src)
+	if n > len(dst) {
+		n, err = len(dst), ErrShortDst
+	}
+	for i, c := range src[:n] {
+		if 'A' <= c && c <= 'Z' {
+			c += 'a' - 'A'
+		}
+		dst[i] = c
+	}
+	return n, n, err
+}
+
+var errYouMentionedX = errors.New("you mentioned X")
+
+type dontMentionX struct{ NopResetter }
+
+func (dontMentionX) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+	n := len(src)
+	if n > len(dst) {
+		n, err = len(dst), ErrShortDst
+	}
+	for i, c := range src[:n] {
+		if c == 'X' {
+			return i, i, errYouMentionedX
+		}
+		dst[i] = c
+	}
+	return n, n, err
+}
+
+// doublerAtEOF is a strange Transformer that transforms "this" to "tthhiiss",
+// but only if atEOF is true.
+type doublerAtEOF struct{ NopResetter }
+
+func (doublerAtEOF) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+	if !atEOF {
+		return 0, 0, ErrShortSrc
+	}
+	for i, c := range src {
+		if 2*i+2 >= len(dst) {
+			return 2 * i, i, ErrShortDst
+		}
+		dst[2*i+0] = c
+		dst[2*i+1] = c
+	}
+	return 2 * len(src), len(src), nil
+}
+
+// rleDecode and rleEncode implement a toy run-length encoding: "aabbbbbbbbbb"
+// is encoded as "2a10b". The decoding is assumed to not contain any numbers.
+
+type rleDecode struct{ NopResetter }
+
+func (rleDecode) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+loop:
+	for len(src) > 0 {
+		n := 0
+		for i, c := range src {
+			if '0' <= c && c <= '9' {
+				n = 10*n + int(c-'0')
+				continue
+			}
+			if i == 0 {
+				return nDst, nSrc, errors.New("rleDecode: bad input")
+			}
+			if n > len(dst) {
+				return nDst, nSrc, ErrShortDst
+			}
+			for j := 0; j < n; j++ {
+				dst[j] = c
+			}
+			dst, src = dst[n:], src[i+1:]
+			nDst, nSrc = nDst+n, nSrc+i+1
+			continue loop
+		}
+		if atEOF {
+			return nDst, nSrc, errors.New("rleDecode: bad input")
+		}
+		return nDst, nSrc, ErrShortSrc
+	}
+	return nDst, nSrc, nil
+}
+
+type rleEncode struct {
+	NopResetter
+
+	// allowStutter means that "xxxxxxxx" can be encoded as "5x3x"
+	// instead of always as "8x".
+	allowStutter bool
+}
+
+func (e rleEncode) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+	for len(src) > 0 {
+		n, c0 := len(src), src[0]
+		for i, c := range src[1:] {
+			if c != c0 {
+				n = i + 1
+				break
+			}
+		}
+		if n == len(src) && !atEOF && !e.allowStutter {
+			return nDst, nSrc, ErrShortSrc
+		}
+		s := strconv.Itoa(n)
+		if len(s) >= len(dst) {
+			return nDst, nSrc, ErrShortDst
+		}
+		copy(dst, s)
+		dst[len(s)] = c0
+		dst, src = dst[len(s)+1:], src[n:]
+		nDst, nSrc = nDst+len(s)+1, nSrc+n
+	}
+	return nDst, nSrc, nil
+}
+
+// trickler consumes all input bytes, but writes a single byte at a time to dst.
+type trickler []byte
+
+func (t *trickler) Reset() {
+	*t = nil
+}
+
+func (t *trickler) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+	*t = append(*t, src...)
+	if len(*t) == 0 {
+		return 0, 0, nil
+	}
+	if len(dst) == 0 {
+		return 0, len(src), ErrShortDst
+	}
+	dst[0] = (*t)[0]
+	*t = (*t)[1:]
+	if len(*t) > 0 {
+		err = ErrShortDst
+	}
+	return 1, len(src), err
+}
+
+// delayedTrickler is like trickler, but delays writing output to dst. This is
+// highly unlikely to be relevant in practice, but it seems like a good idea
+// to have some tolerance as long as progress can be detected.
+type delayedTrickler []byte
+
+func (t *delayedTrickler) Reset() {
+	*t = nil
+}
+func (t *delayedTrickler) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+	if len(*t) > 0 && len(dst) > 0 {
+		dst[0] = (*t)[0]
+		*t = (*t)[1:]
+		nDst = 1
+	}
+	*t = append(*t, src...)
+	if len(*t) > 0 {
+		err = ErrShortDst
+	}
+	return nDst, len(src), err
+}
+
+type testCase struct {
+	desc     string
+	t        Transformer
+	src      string
+	dstSize  int
+	srcSize  int
+	ioSize   int
+	wantStr  string
+	wantErr  error
+	wantIter int // number of iterations taken; 0 means we don't care.
+}
+
+func (t testCase) String() string {
+	return tstr(t.t) + "; " + t.desc
+}
+
+func tstr(t Transformer) string {
+	if stringer, ok := t.(fmt.Stringer); ok {
+		return stringer.String()
+	}
+	s := fmt.Sprintf("%T", t)
+	return s[1+strings.Index(s, "."):]
+}
+
+func (c chain) String() string {
+	buf := &bytes.Buffer{}
+	buf.WriteString("Chain(")
+	for i, l := range c.link[:len(c.link)-1] {
+		if i != 0 {
+			fmt.Fprint(buf, ", ")
+		}
+		buf.WriteString(tstr(l.t))
+	}
+	buf.WriteString(")")
+	return buf.String()
+}
+
+var testCases = []testCase{
+	{
+		desc:    "empty",
+		t:       lowerCaseASCII{},
+		src:     "",
+		dstSize: 100,
+		srcSize: 100,
+		wantStr: "",
+	},
+
+	{
+		desc:    "basic",
+		t:       lowerCaseASCII{},
+		src:     "Hello WORLD.",
+		dstSize: 100,
+		srcSize: 100,
+		wantStr: "hello world.",
+	},
+
+	{
+		desc:    "small dst",
+		t:       lowerCaseASCII{},
+		src:     "Hello WORLD.",
+		dstSize: 3,
+		srcSize: 100,
+		wantStr: "hello world.",
+	},
+
+	{
+		desc:    "small src",
+		t:       lowerCaseASCII{},
+		src:     "Hello WORLD.",
+		dstSize: 100,
+		srcSize: 4,
+		wantStr: "hello world.",
+	},
+
+	{
+		desc:    "small buffers",
+		t:       lowerCaseASCII{},
+		src:     "Hello WORLD.",
+		dstSize: 3,
+		srcSize: 4,
+		wantStr: "hello world.",
+	},
+
+	{
+		desc:    "very small buffers",
+		t:       lowerCaseASCII{},
+		src:     "Hello WORLD.",
+		dstSize: 1,
+		srcSize: 1,
+		wantStr: "hello world.",
+	},
+
+	{
+		desc:    "basic",
+		t:       dontMentionX{},
+		src:     "The First Rule of Transform Club: don't mention Mister X, ever.",
+		dstSize: 100,
+		srcSize: 100,
+		wantStr: "The First Rule of Transform Club: don't mention Mister ",
+		wantErr: errYouMentionedX,
+	},
+
+	{
+		desc:    "small buffers",
+		t:       dontMentionX{},
+		src:     "The First Rule of Transform Club: don't mention Mister X, ever.",
+		dstSize: 10,
+		srcSize: 10,
+		wantStr: "The First Rule of Transform Club: don't mention Mister ",
+		wantErr: errYouMentionedX,
+	},
+
+	{
+		desc:    "very small buffers",
+		t:       dontMentionX{},
+		src:     "The First Rule of Transform Club: don't mention Mister X, ever.",
+		dstSize: 1,
+		srcSize: 1,
+		wantStr: "The First Rule of Transform Club: don't mention Mister ",
+		wantErr: errYouMentionedX,
+	},
+
+	{
+		desc:    "only transform at EOF",
+		t:       doublerAtEOF{},
+		src:     "this",
+		dstSize: 100,
+		srcSize: 100,
+		wantStr: "tthhiiss",
+	},
+
+	{
+		desc:    "basic",
+		t:       rleDecode{},
+		src:     "1a2b3c10d11e0f1g",
+		dstSize: 100,
+		srcSize: 100,
+		wantStr: "abbcccddddddddddeeeeeeeeeeeg",
+	},
+
+	{
+		desc:    "long",
+		t:       rleDecode{},
+		src:     "12a23b34c45d56e99z",
+		dstSize: 100,
+		srcSize: 100,
+		wantStr: strings.Repeat("a", 12) +
+			strings.Repeat("b", 23) +
+			strings.Repeat("c", 34) +
+			strings.Repeat("d", 45) +
+			strings.Repeat("e", 56) +
+			strings.Repeat("z", 99),
+	},
+
+	{
+		desc:    "tight buffers",
+		t:       rleDecode{},
+		src:     "1a2b3c10d11e0f1g",
+		dstSize: 11,
+		srcSize: 3,
+		wantStr: "abbcccddddddddddeeeeeeeeeeeg",
+	},
+
+	{
+		desc:    "short dst",
+		t:       rleDecode{},
+		src:     "1a2b3c10d11e0f1g",
+		dstSize: 10,
+		srcSize: 3,
+		wantStr: "abbcccdddddddddd",
+		wantErr: ErrShortDst,
+	},
+
+	{
+		desc:    "short src",
+		t:       rleDecode{},
+		src:     "1a2b3c10d11e0f1g",
+		dstSize: 11,
+		srcSize: 2,
+		ioSize:  2,
+		wantStr: "abbccc",
+		wantErr: ErrShortSrc,
+	},
+
+	{
+		desc:    "basic",
+		t:       rleEncode{},
+		src:     "abbcccddddddddddeeeeeeeeeeeg",
+		dstSize: 100,
+		srcSize: 100,
+		wantStr: "1a2b3c10d11e1g",
+	},
+
+	{
+		desc: "long",
+		t:    rleEncode{},
+		src: strings.Repeat("a", 12) +
+			strings.Repeat("b", 23) +
+			strings.Repeat("c", 34) +
+			strings.Repeat("d", 45) +
+			strings.Repeat("e", 56) +
+			strings.Repeat("z", 99),
+		dstSize: 100,
+		srcSize: 100,
+		wantStr: "12a23b34c45d56e99z",
+	},
+
+	{
+		desc:    "tight buffers",
+		t:       rleEncode{},
+		src:     "abbcccddddddddddeeeeeeeeeeeg",
+		dstSize: 3,
+		srcSize: 12,
+		wantStr: "1a2b3c10d11e1g",
+	},
+
+	{
+		desc:    "short dst",
+		t:       rleEncode{},
+		src:     "abbcccddddddddddeeeeeeeeeeeg",
+		dstSize: 2,
+		srcSize: 12,
+		wantStr: "1a2b3c",
+		wantErr: ErrShortDst,
+	},
+
+	{
+		desc:    "short src",
+		t:       rleEncode{},
+		src:     "abbcccddddddddddeeeeeeeeeeeg",
+		dstSize: 3,
+		srcSize: 11,
+		ioSize:  11,
+		wantStr: "1a2b3c10d",
+		wantErr: ErrShortSrc,
+	},
+
+	{
+		desc:    "allowStutter = false",
+		t:       rleEncode{allowStutter: false},
+		src:     "aaaabbbbbbbbccccddddd",
+		dstSize: 10,
+		srcSize: 10,
+		wantStr: "4a8b4c5d",
+	},
+
+	{
+		desc:    "allowStutter = true",
+		t:       rleEncode{allowStutter: true},
+		src:     "aaaabbbbbbbbccccddddd",
+		dstSize: 10,
+		srcSize: 10,
+		ioSize:  10,
+		wantStr: "4a6b2b4c4d1d",
+	},
+
+	{
+		desc:    "trickler",
+		t:       &trickler{},
+		src:     "abcdefghijklm",
+		dstSize: 3,
+		srcSize: 15,
+		wantStr: "abcdefghijklm",
+	},
+
+	{
+		desc:    "delayedTrickler",
+		t:       &delayedTrickler{},
+		src:     "abcdefghijklm",
+		dstSize: 3,
+		srcSize: 15,
+		wantStr: "abcdefghijklm",
+	},
+}
+
+func TestReader(t *testing.T) {
+	for _, tc := range testCases {
+		r := NewReader(strings.NewReader(tc.src), tc.t)
+		// Differently sized dst and src buffers are not part of the
+		// exported API. We override them manually.
+		r.dst = make([]byte, tc.dstSize)
+		r.src = make([]byte, tc.srcSize)
+		got, err := ioutil.ReadAll(r)
+		str := string(got)
+		if str != tc.wantStr || err != tc.wantErr {
+			t.Errorf("%s:\ngot  %q, %v\nwant %q, %v", tc, str, err, tc.wantStr, tc.wantErr)
+		}
+	}
+}
+
+func TestWriter(t *testing.T) {
+	tests := append(testCases, chainTests()...)
+	for _, tc := range tests {
+		sizes := []int{1, 2, 3, 4, 5, 10, 100, 1000}
+		if tc.ioSize > 0 {
+			sizes = []int{tc.ioSize}
+		}
+		for _, sz := range sizes {
+			bb := &bytes.Buffer{}
+			w := NewWriter(bb, tc.t)
+			// Differently sized dst and src buffers are not part of the
+			// exported API. We override them manually.
+			w.dst = make([]byte, tc.dstSize)
+			w.src = make([]byte, tc.srcSize)
+			src := make([]byte, sz)
+			var err error
+			for b := tc.src; len(b) > 0 && err == nil; {
+				n := copy(src, b)
+				b = b[n:]
+				m := 0
+				m, err = w.Write(src[:n])
+				if m != n && err == nil {
+					t.Errorf("%s:%d: did not consume all bytes %d < %d", tc, sz, m, n)
+				}
+			}
+			if err == nil {
+				err = w.Close()
+			}
+			str := bb.String()
+			if str != tc.wantStr || err != tc.wantErr {
+				t.Errorf("%s:%d:\ngot  %q, %v\nwant %q, %v", tc, sz, str, err, tc.wantStr, tc.wantErr)
+			}
+		}
+	}
+}
+
+func TestNop(t *testing.T) {
+	testCases := []struct {
+		str     string
+		dstSize int
+		err     error
+	}{
+		{"", 0, nil},
+		{"", 10, nil},
+		{"a", 0, ErrShortDst},
+		{"a", 1, nil},
+		{"a", 10, nil},
+	}
+	for i, tc := range testCases {
+		dst := make([]byte, tc.dstSize)
+		nDst, nSrc, err := Nop.Transform(dst, []byte(tc.str), true)
+		want := tc.str
+		if tc.dstSize < len(want) {
+			want = want[:tc.dstSize]
+		}
+		if got := string(dst[:nDst]); got != want || err != tc.err || nSrc != nDst {
+			t.Errorf("%d:\ngot %q, %d, %v\nwant %q, %d, %v", i, got, nSrc, err, want, nDst, tc.err)
+		}
+	}
+}
+
+func TestDiscard(t *testing.T) {
+	testCases := []struct {
+		str     string
+		dstSize int
+	}{
+		{"", 0},
+		{"", 10},
+		{"a", 0},
+		{"ab", 10},
+	}
+	for i, tc := range testCases {
+		nDst, nSrc, err := Discard.Transform(make([]byte, tc.dstSize), []byte(tc.str), true)
+		if nDst != 0 || nSrc != len(tc.str) || err != nil {
+			t.Errorf("%d:\ngot %q, %d, %v\nwant 0, %d, nil", i, nDst, nSrc, err, len(tc.str))
+		}
+	}
+}
+
+// mkChain creates a Chain transformer. x must be alternating between transformer
+// and bufSize, like T, (sz, T)*
+func mkChain(x ...interface{}) *chain {
+	t := []Transformer{}
+	for i := 0; i < len(x); i += 2 {
+		t = append(t, x[i].(Transformer))
+	}
+	c := Chain(t...).(*chain)
+	for i, j := 1, 1; i < len(x); i, j = i+2, j+1 {
+		c.link[j].b = make([]byte, x[i].(int))
+	}
+	return c
+}
+
+func chainTests() []testCase {
+	return []testCase{
+		{
+			desc:     "nil error",
+			t:        mkChain(rleEncode{}, 100, lowerCaseASCII{}),
+			src:      "ABB",
+			dstSize:  100,
+			srcSize:  100,
+			wantStr:  "1a2b",
+			wantErr:  nil,
+			wantIter: 1,
+		},
+
+		{
+			desc:    "short dst buffer",
+			t:       mkChain(lowerCaseASCII{}, 3, rleDecode{}),
+			src:     "1a2b3c10d11e0f1g",
+			dstSize: 10,
+			srcSize: 3,
+			wantStr: "abbcccdddddddddd",
+			wantErr: ErrShortDst,
+		},
+
+		{
+			desc:    "short internal dst buffer",
+			t:       mkChain(lowerCaseASCII{}, 3, rleDecode{}, 10, Nop),
+			src:     "1a2b3c10d11e0f1g",
+			dstSize: 100,
+			srcSize: 3,
+			wantStr: "abbcccdddddddddd",
+			wantErr: errShortInternal,
+		},
+
+		{
+			desc:    "short internal dst buffer from input",
+			t:       mkChain(rleDecode{}, 10, Nop),
+			src:     "1a2b3c10d11e0f1g",
+			dstSize: 100,
+			srcSize: 3,
+			wantStr: "abbcccdddddddddd",
+			wantErr: errShortInternal,
+		},
+
+		{
+			desc:    "empty short internal dst buffer",
+			t:       mkChain(lowerCaseASCII{}, 3, rleDecode{}, 10, Nop),
+			src:     "4a7b11e0f1g",
+			dstSize: 100,
+			srcSize: 3,
+			wantStr: "aaaabbbbbbb",
+			wantErr: errShortInternal,
+		},
+
+		{
+			desc:    "empty short internal dst buffer from input",
+			t:       mkChain(rleDecode{}, 10, Nop),
+			src:     "4a7b11e0f1g",
+			dstSize: 100,
+			srcSize: 3,
+			wantStr: "aaaabbbbbbb",
+			wantErr: errShortInternal,
+		},
+
+		{
+			desc:     "short internal src buffer after full dst buffer",
+			t:        mkChain(Nop, 5, rleEncode{}, 10, Nop),
+			src:      "cccccddddd",
+			dstSize:  100,
+			srcSize:  100,
+			wantStr:  "",
+			wantErr:  errShortInternal,
+			wantIter: 1,
+		},
+
+		{
+			desc:    "short internal src buffer after short dst buffer; test lastFull",
+			t:       mkChain(rleDecode{}, 5, rleEncode{}, 4, Nop),
+			src:     "2a1b4c6d",
+			dstSize: 100,
+			srcSize: 100,
+			wantStr: "2a1b",
+			wantErr: errShortInternal,
+		},
+
+		{
+			desc:     "short internal src buffer after successful complete fill",
+			t:        mkChain(Nop, 3, rleDecode{}),
+			src:      "123a4b",
+			dstSize:  4,
+			srcSize:  3,
+			wantStr:  "",
+			wantErr:  errShortInternal,
+			wantIter: 1,
+		},
+
+		{
+			desc:    "short internal src buffer after short dst buffer; test lastFull",
+			t:       mkChain(rleDecode{}, 5, rleEncode{}),
+			src:     "2a1b4c6d",
+			dstSize: 4,
+			srcSize: 100,
+			wantStr: "2a1b",
+			wantErr: errShortInternal,
+		},
+
+		{
+			desc:    "short src buffer",
+			t:       mkChain(rleEncode{}, 5, Nop),
+			src:     "abbcccddddeeeee",
+			dstSize: 4,
+			srcSize: 4,
+			ioSize:  4,
+			wantStr: "1a2b3c",
+			wantErr: ErrShortSrc,
+		},
+
+		{
+			desc:     "process all in one go",
+			t:        mkChain(rleEncode{}, 5, Nop),
+			src:      "abbcccddddeeeeeffffff",
+			dstSize:  100,
+			srcSize:  100,
+			wantStr:  "1a2b3c4d5e6f",
+			wantErr:  nil,
+			wantIter: 1,
+		},
+
+		{
+			desc:    "complete processing downstream after error",
+			t:       mkChain(dontMentionX{}, 2, rleDecode{}, 5, Nop),
+			src:     "3a4b5eX",
+			dstSize: 100,
+			srcSize: 100,
+			ioSize:  100,
+			wantStr: "aaabbbbeeeee",
+			wantErr: errYouMentionedX,
+		},
+
+		{
+			desc:    "return downstream fatal errors first (followed by short dst)",
+			t:       mkChain(dontMentionX{}, 8, rleDecode{}, 4, Nop),
+			src:     "3a4b5eX",
+			dstSize: 100,
+			srcSize: 100,
+			ioSize:  100,
+			wantStr: "aaabbbb",
+			wantErr: errShortInternal,
+		},
+
+		{
+			desc:    "return downstream fatal errors first (followed by short src)",
+			t:       mkChain(dontMentionX{}, 5, Nop, 1, rleDecode{}),
+			src:     "1a5bX",
+			dstSize: 100,
+			srcSize: 100,
+			ioSize:  100,
+			wantStr: "",
+			wantErr: errShortInternal,
+		},
+
+		{
+			desc:    "short internal",
+			t:       mkChain(Nop, 11, rleEncode{}, 3, Nop),
+			src:     "abbcccddddddddddeeeeeeeeeeeg",
+			dstSize: 3,
+			srcSize: 100,
+			wantStr: "1a2b3c10d",
+			wantErr: errShortInternal,
+		},
+	}
+}
+
+func doTransform(tc testCase) (res string, iter int, err error) {
+	tc.t.Reset()
+	dst := make([]byte, tc.dstSize)
+	out, in := make([]byte, 0, 2*len(tc.src)), []byte(tc.src)
+	for {
+		iter++
+		src, atEOF := in, true
+		if len(src) > tc.srcSize {
+			src, atEOF = src[:tc.srcSize], false
+		}
+		nDst, nSrc, err := tc.t.Transform(dst, src, atEOF)
+		out = append(out, dst[:nDst]...)
+		in = in[nSrc:]
+		switch {
+		case err == nil && len(in) != 0:
+		case err == ErrShortSrc && nSrc > 0:
+		case err == ErrShortDst && (nDst > 0 || nSrc > 0):
+		default:
+			return string(out), iter, err
+		}
+	}
+}
+
+func TestChain(t *testing.T) {
+	if c, ok := Chain().(nop); !ok {
+		t.Errorf("empty chain: %v; want Nop", c)
+	}
+
+	// Test Chain for a single Transformer.
+	for _, tc := range testCases {
+		tc.t = Chain(tc.t)
+		str, _, err := doTransform(tc)
+		if str != tc.wantStr || err != tc.wantErr {
+			t.Errorf("%s:\ngot  %q, %v\nwant %q, %v", tc, str, err, tc.wantStr, tc.wantErr)
+		}
+	}
+
+	tests := chainTests()
+	sizes := []int{1, 2, 3, 4, 5, 7, 10, 100, 1000}
+	addTest := func(tc testCase, t *chain) {
+		if t.link[0].t != tc.t && tc.wantErr == ErrShortSrc {
+			tc.wantErr = errShortInternal
+		}
+		if t.link[len(t.link)-2].t != tc.t && tc.wantErr == ErrShortDst {
+			tc.wantErr = errShortInternal
+		}
+		tc.t = t
+		tests = append(tests, tc)
+	}
+	for _, tc := range testCases {
+		for _, sz := range sizes {
+			tt := tc
+			tt.dstSize = sz
+			addTest(tt, mkChain(tc.t, tc.dstSize, Nop))
+			addTest(tt, mkChain(tc.t, tc.dstSize, Nop, 2, Nop))
+			addTest(tt, mkChain(Nop, tc.srcSize, tc.t, tc.dstSize, Nop))
+			if sz >= tc.dstSize && (tc.wantErr != ErrShortDst || sz == tc.dstSize) {
+				addTest(tt, mkChain(Nop, tc.srcSize, tc.t))
+				addTest(tt, mkChain(Nop, 100, Nop, tc.srcSize, tc.t))
+			}
+		}
+	}
+	for _, tc := range testCases {
+		tt := tc
+		tt.dstSize = 1
+		tt.wantStr = ""
+		addTest(tt, mkChain(tc.t, tc.dstSize, Discard))
+		addTest(tt, mkChain(Nop, tc.srcSize, tc.t, tc.dstSize, Discard))
+		addTest(tt, mkChain(Nop, tc.srcSize, tc.t, tc.dstSize, Nop, tc.dstSize, Discard))
+	}
+	for _, tc := range testCases {
+		tt := tc
+		tt.dstSize = 100
+		tt.wantStr = strings.Replace(tc.src, "0f", "", -1)
+		// Chain encoders and decoders.
+		if _, ok := tc.t.(rleEncode); ok && tc.wantErr == nil {
+			addTest(tt, mkChain(tc.t, tc.dstSize, Nop, 1000, rleDecode{}))
+			addTest(tt, mkChain(tc.t, tc.dstSize, Nop, tc.dstSize, rleDecode{}))
+			addTest(tt, mkChain(Nop, tc.srcSize, tc.t, tc.dstSize, Nop, 100, rleDecode{}))
+			// decoding needs larger destinations
+			addTest(tt, mkChain(Nop, tc.srcSize, tc.t, tc.dstSize, rleDecode{}, 100, Nop))
+			addTest(tt, mkChain(Nop, tc.srcSize, tc.t, tc.dstSize, Nop, 100, rleDecode{}, 100, Nop))
+		} else if _, ok := tc.t.(rleDecode); ok && tc.wantErr == nil {
+			// The internal buffer size may need to be the sum of the maximum segment
+			// size of the two encoders!
+			addTest(tt, mkChain(tc.t, 2*tc.dstSize, rleEncode{}))
+			addTest(tt, mkChain(tc.t, tc.dstSize, Nop, 101, rleEncode{}))
+			addTest(tt, mkChain(Nop, tc.srcSize, tc.t, tc.dstSize, Nop, 100, rleEncode{}))
+			addTest(tt, mkChain(Nop, tc.srcSize, tc.t, tc.dstSize, Nop, 200, rleEncode{}, 100, Nop))
+		}
+	}
+	for _, tc := range tests {
+		str, iter, err := doTransform(tc)
+		mi := tc.wantIter != 0 && tc.wantIter != iter
+		if str != tc.wantStr || err != tc.wantErr || mi {
+			t.Errorf("%s:\ngot  iter:%d, %q, %v\nwant iter:%d, %q, %v", tc, iter, str, err, tc.wantIter, tc.wantStr, tc.wantErr)
+		}
+		break
+	}
+}
+
+func TestRemoveFunc(t *testing.T) {
+	filter := RemoveFunc(func(r rune) bool {
+		return strings.IndexRune("ab\u0300\u1234,", r) != -1
+	})
+	tests := []testCase{
+		{
+			src:     ",",
+			wantStr: "",
+		},
+
+		{
+			src:     "c",
+			wantStr: "c",
+		},
+
+		{
+			src:     "\u2345",
+			wantStr: "\u2345",
+		},
+
+		{
+			src:     "tschüß",
+			wantStr: "tschüß",
+		},
+
+		{
+			src:     ",до,свидания,",
+			wantStr: "досвидания",
+		},
+
+		{
+			src:     "a\xbd\xb2=\xbc ⌘",
+			wantStr: "\uFFFD\uFFFD=\uFFFD ⌘",
+		},
+
+		{
+			// If we didn't replace illegal bytes with RuneError, the result
+			// would be \u0300 or the code would need to be more complex.
+			src:     "\xcc\u0300\x80",
+			wantStr: "\uFFFD\uFFFD",
+		},
+
+		{
+			src:      "\xcc\u0300\x80",
+			dstSize:  3,
+			wantStr:  "\uFFFD\uFFFD",
+			wantIter: 2,
+		},
+
+		{
+			// Test a long buffer greater than the internal buffer size
+			src:      "hello\xcc\xcc\xccworld",
+			srcSize:  13,
+			wantStr:  "hello\uFFFD\uFFFD\uFFFDworld",
+			wantIter: 1,
+		},
+
+		{
+			src:     "\u2345",
+			dstSize: 2,
+			wantStr: "",
+			wantErr: ErrShortDst,
+		},
+
+		{
+			src:     "\xcc",
+			dstSize: 2,
+			wantStr: "",
+			wantErr: ErrShortDst,
+		},
+
+		{
+			src:     "\u0300",
+			dstSize: 2,
+			srcSize: 1,
+			wantStr: "",
+			wantErr: ErrShortSrc,
+		},
+
+		{
+			t: RemoveFunc(func(r rune) bool {
+				return r == utf8.RuneError
+			}),
+			src:     "\xcc\u0300\x80",
+			wantStr: "\u0300",
+		},
+	}
+
+	for _, tc := range tests {
+		tc.desc = tc.src
+		if tc.t == nil {
+			tc.t = filter
+		}
+		if tc.dstSize == 0 {
+			tc.dstSize = 100
+		}
+		if tc.srcSize == 0 {
+			tc.srcSize = 100
+		}
+		str, iter, err := doTransform(tc)
+		mi := tc.wantIter != 0 && tc.wantIter != iter
+		if str != tc.wantStr || err != tc.wantErr || mi {
+			t.Errorf("%+q:\ngot  iter:%d, %+q, %v\nwant iter:%d, %+q, %v", tc.src, iter, str, err, tc.wantIter, tc.wantStr, tc.wantErr)
+		}
+
+		tc.src = str
+		idem, _, _ := doTransform(tc)
+		if str != idem {
+			t.Errorf("%+q: found %+q; want %+q", tc.src, idem, str)
+		}
+	}
+}
+
+func testString(t *testing.T, f func(Transformer, string) (string, int, error)) {
+	for _, tt := range append(testCases, chainTests()...) {
+		if tt.desc == "allowStutter = true" {
+			// We don't have control over the buffer size, so we eliminate tests
+			// that depend on a specific buffer size being set.
+			continue
+		}
+		if tt.wantErr == ErrShortDst || tt.wantErr == ErrShortSrc {
+			// The result string will be different.
+			continue
+		}
+		got, n, err := f(tt.t, tt.src)
+		if tt.wantErr != err {
+			t.Errorf("%s:error: got %v; want %v", tt.desc, err, tt.wantErr)
+		}
+		if got, want := err == nil, n == len(tt.src); got != want {
+			t.Errorf("%s:n: got %v; want %v", tt.desc, got, want)
+		}
+		if got != tt.wantStr {
+			t.Errorf("%s:string: got %q; want %q", tt.desc, got, tt.wantStr)
+		}
+	}
+}
+
+func TestBytes(t *testing.T) {
+	testString(t, func(z Transformer, s string) (string, int, error) {
+		b, n, err := Bytes(z, []byte(s))
+		return string(b), n, err
+	})
+}
+
+func TestString(t *testing.T) {
+	testString(t, String)
+
+	// Overrun the internal destination buffer.
+	for i, s := range []string{
+		strings.Repeat("a", initialBufSize-1),
+		strings.Repeat("a", initialBufSize+0),
+		strings.Repeat("a", initialBufSize+1),
+		strings.Repeat("A", initialBufSize-1),
+		strings.Repeat("A", initialBufSize+0),
+		strings.Repeat("A", initialBufSize+1),
+		strings.Repeat("A", 2*initialBufSize-1),
+		strings.Repeat("A", 2*initialBufSize+0),
+		strings.Repeat("A", 2*initialBufSize+1),
+		strings.Repeat("a", initialBufSize-2) + "A",
+		strings.Repeat("a", initialBufSize-1) + "A",
+		strings.Repeat("a", initialBufSize+0) + "A",
+		strings.Repeat("a", initialBufSize+1) + "A",
+	} {
+		got, _, _ := String(lowerCaseASCII{}, s)
+		if want := strings.ToLower(s); got != want {
+			t.Errorf("%d:dst buffer test: got %s (%d); want %s (%d)", i, got, len(got), want, len(want))
+		}
+	}
+
+	// Overrun the internal source buffer.
+	for i, s := range []string{
+		strings.Repeat("a", initialBufSize-1),
+		strings.Repeat("a", initialBufSize+0),
+		strings.Repeat("a", initialBufSize+1),
+		strings.Repeat("a", 2*initialBufSize+1),
+		strings.Repeat("a", 2*initialBufSize+0),
+		strings.Repeat("a", 2*initialBufSize+1),
+	} {
+		got, _, _ := String(rleEncode{}, s)
+		if want := fmt.Sprintf("%da", len(s)); got != want {
+			t.Errorf("%d:src buffer test: got %s (%d); want %s (%d)", i, got, len(got), want, len(want))
+		}
+	}
+
+	// Test allocations for non-changing strings.
+	// Note we still need to allocate a single buffer.
+	for i, s := range []string{
+		"",
+		"123",
+		"123456789",
+		strings.Repeat("a", initialBufSize),
+		strings.Repeat("a", 10*initialBufSize),
+	} {
+		if n := testing.AllocsPerRun(5, func() { String(&lowerCaseASCII{}, s) }); n > 1 {
+			t.Errorf("%d: #allocs was %f; want 1", i, n)
+		}
+	}
+}
+
+// TestBytesAllocation tests that buffer growth stays limited with the trickler
+// transformer, which behaves oddly but within spec. In case buffer growth is
+// not correctly handled, the test will either panic with a failed allocation or
+// thrash. To ensure the tests terminate under the last condition, we time out
+// after some sufficiently long period of time.
+func TestBytesAllocation(t *testing.T) {
+	done := make(chan bool)
+	go func() {
+		in := bytes.Repeat([]byte{'a'}, 1000)
+		tr := trickler(make([]byte, 1))
+		Bytes(&tr, in)
+		done <- true
+	}()
+	select {
+	case <-done:
+	case <-time.After(3 * time.Second):
+		t.Error("time out, likely due to excessive allocation")
+	}
+}
+
+// TestStringAllocation tests that buffer growth stays limited with the trickler
+// transformer, which behaves oddly but within spec. In case buffer growth is
+// not correctly handled, the test will either panic with a failed allocation or
+// thrash. To ensure the tests terminate under the last condition, we time out
+// after some sufficiently long period of time.
+func TestStringAllocation(t *testing.T) {
+	done := make(chan bool)
+	go func() {
+		in := strings.Repeat("a", 1000)
+		tr := trickler(make([]byte, 1))
+		String(&tr, in)
+		done <- true
+	}()
+	select {
+	case <-done:
+	case <-time.After(3 * time.Second):
+		t.Error("time out, likely due to excessive allocation")
+	}
+}
+
+func BenchmarkStringLower(b *testing.B) {
+	in := strings.Repeat("a", 4096)
+	for i := 0; i < b.N; i++ {
+		String(&lowerCaseASCII{}, in)
+	}
+}
diff --git a/Makefile b/Makefile
index 74280382015cdff1e2bb036398d223b00990aaeb..57cf8999e295bbd1db415d50394421f7ab8e351b 100644
--- a/Makefile
+++ b/Makefile
@@ -14,11 +14,11 @@ sysconfdir = /etc/djrandom
 all: version.go $(JS_TARGET)
 
 install-client:
-	go get ./client/... && go install ./client/...
+	godep go install ./client/...
 
 install: all
 	(for dir in server services mapreduce ; do \
-	 go get ./$${dir}/... && go install ./$${dir}/... ; done)
+	 godep go install ./$${dir}/... ; done)
 	rsync -ar ./ui/static/ $(sysconfdir)/static/
 	rsync -ar ./ui/templates/ $(sysconfdir)/templates/
 	install -m 755 -o root -g root djrandom.init /etc/init.d/djrandom