summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/.gitignore4
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/LICENSE20
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/Makefile18
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/README.md858
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/appveyor.yml18
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_386.go10
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_amd64.go10
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_arm.go28
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_arm64.go12
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_linux.go10
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_openbsd.go27
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_ppc.go9
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_ppc64.go9
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_ppc64le.go12
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_s390x.go12
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_unix.go89
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_unix_solaris.go90
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_windows.go144
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/boltsync_unix.go8
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/bucket.go778
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/bucket_test.go1909
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/cmd/bolt/main.go1740
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/cmd/bolt/main_test.go356
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/cursor.go400
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/cursor_test.go817
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/db.go1036
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/db_test.go1706
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/doc.go44
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/errors.go71
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/freelist.go248
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/freelist_test.go158
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/node.go604
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/node_test.go156
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/page.go178
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/page_test.go72
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/quick_test.go79
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/simulation_test.go329
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/tx.go682
-rw-r--r--cmd/ponzu/vendor/github.com/boltdb/bolt/tx_test.go716
-rw-r--r--cmd/ponzu/vendor/github.com/gorilla/schema/.travis.yml19
-rw-r--r--cmd/ponzu/vendor/github.com/gorilla/schema/LICENSE27
-rw-r--r--cmd/ponzu/vendor/github.com/gorilla/schema/README.md66
-rw-r--r--cmd/ponzu/vendor/github.com/gorilla/schema/cache.go261
-rw-r--r--cmd/ponzu/vendor/github.com/gorilla/schema/converter.go145
-rw-r--r--cmd/ponzu/vendor/github.com/gorilla/schema/decoder.go343
-rw-r--r--cmd/ponzu/vendor/github.com/gorilla/schema/decoder_test.go1460
-rw-r--r--cmd/ponzu/vendor/github.com/gorilla/schema/doc.go148
-rw-r--r--cmd/ponzu/vendor/github.com/nilslice/jwt/LICENSE19
-rw-r--r--cmd/ponzu/vendor/github.com/nilslice/jwt/README.md43
-rw-r--r--cmd/ponzu/vendor/github.com/nilslice/jwt/doc.go40
-rw-r--r--cmd/ponzu/vendor/github.com/nilslice/jwt/jwt.go204
-rw-r--r--cmd/ponzu/vendor/github.com/nilslice/rand/README.md2
-rw-r--r--cmd/ponzu/vendor/github.com/nilslice/rand/rand.go38
-rw-r--r--cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/base64.go35
-rw-r--r--cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/bcrypt.go294
-rw-r--r--cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go226
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/transform/examples_test.go37
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/transform/transform.go705
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/transform/transform_test.go1317
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/unicode/norm/composition.go514
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/unicode/norm/composition_test.go130
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/unicode/norm/example_iter_test.go82
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/unicode/norm/example_test.go27
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/unicode/norm/forminfo.go256
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/unicode/norm/forminfo_test.go54
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/unicode/norm/input.go105
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/unicode/norm/iter.go450
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/unicode/norm/iter_test.go98
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/unicode/norm/maketables.go978
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/unicode/norm/norm_test.go14
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/unicode/norm/normalize.go608
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/unicode/norm/normalize_test.go1226
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/unicode/norm/readwriter.go126
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/unicode/norm/readwriter_test.go56
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/unicode/norm/tables.go7627
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/unicode/norm/transform.go88
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/unicode/norm/transform_test.go101
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/unicode/norm/trie.go54
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/unicode/norm/triegen.go117
-rw-r--r--cmd/ponzu/vendor/golang.org/x/text/unicode/norm/ucd_test.go275
80 files changed, 31882 insertions, 0 deletions
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/.gitignore b/cmd/ponzu/vendor/github.com/boltdb/bolt/.gitignore
new file mode 100644
index 0000000..c7bd2b7
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/.gitignore
@@ -0,0 +1,4 @@
+*.prof
+*.test
+*.swp
+/bin/
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/LICENSE b/cmd/ponzu/vendor/github.com/boltdb/bolt/LICENSE
new file mode 100644
index 0000000..004e77f
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2013 Ben Johnson
+
+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/cmd/ponzu/vendor/github.com/boltdb/bolt/Makefile b/cmd/ponzu/vendor/github.com/boltdb/bolt/Makefile
new file mode 100644
index 0000000..e035e63
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/Makefile
@@ -0,0 +1,18 @@
+BRANCH=`git rev-parse --abbrev-ref HEAD`
+COMMIT=`git rev-parse --short HEAD`
+GOLDFLAGS="-X main.branch $(BRANCH) -X main.commit $(COMMIT)"
+
+default: build
+
+race:
+ @go test -v -race -test.run="TestSimulate_(100op|1000op)"
+
+# go get github.com/kisielk/errcheck
+errcheck:
+ @errcheck -ignorepkg=bytes -ignore=os:Remove github.com/boltdb/bolt
+
+test:
+ @go test -v -cover .
+ @go test -v ./cmd/bolt
+
+.PHONY: fmt test
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/README.md b/cmd/ponzu/vendor/github.com/boltdb/bolt/README.md
new file mode 100644
index 0000000..b654502
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/README.md
@@ -0,0 +1,858 @@
+Bolt [![Coverage Status](https://coveralls.io/repos/boltdb/bolt/badge.svg?branch=master)](https://coveralls.io/r/boltdb/bolt?branch=master) [![GoDoc](https://godoc.org/github.com/boltdb/bolt?status.svg)](https://godoc.org/github.com/boltdb/bolt) ![Version](https://img.shields.io/badge/version-1.2.1-green.svg)
+====
+
+Bolt is a pure Go key/value store inspired by [Howard Chu's][hyc_symas]
+[LMDB project][lmdb]. The goal of the project is to provide a simple,
+fast, and reliable database for projects that don't require a full database
+server such as Postgres or MySQL.
+
+Since Bolt is meant to be used as such a low-level piece of functionality,
+simplicity is key. The API will be small and only focus on getting values
+and setting values. That's it.
+
+[hyc_symas]: https://twitter.com/hyc_symas
+[lmdb]: http://symas.com/mdb/
+
+## Project Status
+
+Bolt is stable, the API is fixed, and the file format is fixed. Full unit
+test coverage and randomized black box testing are used to ensure database
+consistency and thread safety. Bolt is currently used in high-load production
+environments serving databases as large as 1TB. Many companies such as
+Shopify and Heroku use Bolt-backed services every day.
+
+## Table of Contents
+
+- [Getting Started](#getting-started)
+ - [Installing](#installing)
+ - [Opening a database](#opening-a-database)
+ - [Transactions](#transactions)
+ - [Read-write transactions](#read-write-transactions)
+ - [Read-only transactions](#read-only-transactions)
+ - [Batch read-write transactions](#batch-read-write-transactions)
+ - [Managing transactions manually](#managing-transactions-manually)
+ - [Using buckets](#using-buckets)
+ - [Using key/value pairs](#using-keyvalue-pairs)
+ - [Autoincrementing integer for the bucket](#autoincrementing-integer-for-the-bucket)
+ - [Iterating over keys](#iterating-over-keys)
+ - [Prefix scans](#prefix-scans)
+ - [Range scans](#range-scans)
+ - [ForEach()](#foreach)
+ - [Nested buckets](#nested-buckets)
+ - [Database backups](#database-backups)
+ - [Statistics](#statistics)
+ - [Read-Only Mode](#read-only-mode)
+ - [Mobile Use (iOS/Android)](#mobile-use-iosandroid)
+- [Resources](#resources)
+- [Comparison with other databases](#comparison-with-other-databases)
+ - [Postgres, MySQL, & other relational databases](#postgres-mysql--other-relational-databases)
+ - [LevelDB, RocksDB](#leveldb-rocksdb)
+ - [LMDB](#lmdb)
+- [Caveats & Limitations](#caveats--limitations)
+- [Reading the Source](#reading-the-source)
+- [Other Projects Using Bolt](#other-projects-using-bolt)
+
+## Getting Started
+
+### Installing
+
+To start using Bolt, install Go and run `go get`:
+
+```sh
+$ go get github.com/boltdb/bolt/...
+```
+
+This will retrieve the library and install the `bolt` command line utility into
+your `$GOBIN` path.
+
+
+### Opening a database
+
+The top-level object in Bolt is a `DB`. It is represented as a single file on
+your disk and represents a consistent snapshot of your data.
+
+To open your database, simply use the `bolt.Open()` function:
+
+```go
+package main
+
+import (
+ "log"
+
+ "github.com/boltdb/bolt"
+)
+
+func main() {
+ // Open the my.db data file in your current directory.
+ // It will be created if it doesn't exist.
+ db, err := bolt.Open("my.db", 0600, nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer db.Close()
+
+ ...
+}
+```
+
+Please note that Bolt obtains a file lock on the data file so multiple processes
+cannot open the same database at the same time. Opening an already open Bolt
+database will cause it to hang until the other process closes it. To prevent
+an indefinite wait you can pass a timeout option to the `Open()` function:
+
+```go
+db, err := bolt.Open("my.db", 0600, &bolt.Options{Timeout: 1 * time.Second})
+```
+
+
+### Transactions
+
+Bolt allows only one read-write transaction at a time but allows as many
+read-only transactions as you want at a time. Each transaction has a consistent
+view of the data as it existed when the transaction started.
+
+Individual transactions and all objects created from them (e.g. buckets, keys)
+are not thread safe. To work with data in multiple goroutines you must start
+a transaction for each one or use locking to ensure only one goroutine accesses
+a transaction at a time. Creating transaction from the `DB` is thread safe.
+
+Read-only transactions and read-write transactions should not depend on one
+another and generally shouldn't be opened simultaneously in the same goroutine.
+This can cause a deadlock as the read-write transaction needs to periodically
+re-map the data file but it cannot do so while a read-only transaction is open.
+
+
+#### Read-write transactions
+
+To start a read-write transaction, you can use the `DB.Update()` function:
+
+```go
+err := db.Update(func(tx *bolt.Tx) error {
+ ...
+ return nil
+})
+```
+
+Inside the closure, you have a consistent view of the database. You commit the
+transaction by returning `nil` at the end. You can also rollback the transaction
+at any point by returning an error. All database operations are allowed inside
+a read-write transaction.
+
+Always check the return error as it will report any disk failures that can cause
+your transaction to not complete. If you return an error within your closure
+it will be passed through.
+
+
+#### Read-only transactions
+
+To start a read-only transaction, you can use the `DB.View()` function:
+
+```go
+err := db.View(func(tx *bolt.Tx) error {
+ ...
+ return nil
+})
+```
+
+You also get a consistent view of the database within this closure, however,
+no mutating operations are allowed within a read-only transaction. You can only
+retrieve buckets, retrieve values, and copy the database within a read-only
+transaction.
+
+
+#### Batch read-write transactions
+
+Each `DB.Update()` waits for disk to commit the writes. This overhead
+can be minimized by combining multiple updates with the `DB.Batch()`
+function:
+
+```go
+err := db.Batch(func(tx *bolt.Tx) error {
+ ...
+ return nil
+})
+```
+
+Concurrent Batch calls are opportunistically combined into larger
+transactions. Batch is only useful when there are multiple goroutines
+calling it.
+
+The trade-off is that `Batch` can call the given
+function multiple times, if parts of the transaction fail. The
+function must be idempotent and side effects must take effect only
+after a successful return from `DB.Batch()`.
+
+For example: don't display messages from inside the function, instead
+set variables in the enclosing scope:
+
+```go
+var id uint64
+err := db.Batch(func(tx *bolt.Tx) error {
+ // Find last key in bucket, decode as bigendian uint64, increment
+ // by one, encode back to []byte, and add new key.
+ ...
+ id = newValue
+ return nil
+})
+if err != nil {
+ return ...
+}
+fmt.Println("Allocated ID %d", id)
+```
+
+
+#### Managing transactions manually
+
+The `DB.View()` and `DB.Update()` functions are wrappers around the `DB.Begin()`
+function. These helper functions will start the transaction, execute a function,
+and then safely close your transaction if an error is returned. This is the
+recommended way to use Bolt transactions.
+
+However, sometimes you may want to manually start and end your transactions.
+You can use the `DB.Begin()` function directly but **please** be sure to close
+the transaction.
+
+```go
+// Start a writable transaction.
+tx, err := db.Begin(true)
+if err != nil {
+ return err
+}
+defer tx.Rollback()
+
+// Use the transaction...
+_, err := tx.CreateBucket([]byte("MyBucket"))
+if err != nil {
+ return err
+}
+
+// Commit the transaction and check for error.
+if err := tx.Commit(); err != nil {
+ return err
+}
+```
+
+The first argument to `DB.Begin()` is a boolean stating if the transaction
+should be writable.
+
+
+### Using buckets
+
+Buckets are collections of key/value pairs within the database. All keys in a
+bucket must be unique. You can create a bucket using the `DB.CreateBucket()`
+function:
+
+```go
+db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("MyBucket"))
+ if err != nil {
+ return fmt.Errorf("create bucket: %s", err)
+ }
+ return nil
+})
+```
+
+You can also create a bucket only if it doesn't exist by using the
+`Tx.CreateBucketIfNotExists()` function. It's a common pattern to call this
+function for all your top-level buckets after you open your database so you can
+guarantee that they exist for future transactions.
+
+To delete a bucket, simply call the `Tx.DeleteBucket()` function.
+
+
+### Using key/value pairs
+
+To save a key/value pair to a bucket, use the `Bucket.Put()` function:
+
+```go
+db.Update(func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("MyBucket"))
+ err := b.Put([]byte("answer"), []byte("42"))
+ return err
+})
+```
+
+This will set the value of the `"answer"` key to `"42"` in the `MyBucket`
+bucket. To retrieve this value, we can use the `Bucket.Get()` function:
+
+```go
+db.View(func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("MyBucket"))
+ v := b.Get([]byte("answer"))
+ fmt.Printf("The answer is: %s\n", v)
+ return nil
+})
+```
+
+The `Get()` function does not return an error because its operation is
+guaranteed to work (unless there is some kind of system failure). If the key
+exists then it will return its byte slice value. If it doesn't exist then it
+will return `nil`. It's important to note that you can have a zero-length value
+set to a key which is different than the key not existing.
+
+Use the `Bucket.Delete()` function to delete a key from the bucket.
+
+Please note that values returned from `Get()` are only valid while the
+transaction is open. If you need to use a value outside of the transaction
+then you must use `copy()` to copy it to another byte slice.
+
+
+### Autoincrementing integer for the bucket
+By using the `NextSequence()` function, you can let Bolt determine a sequence
+which can be used as the unique identifier for your key/value pairs. See the
+example below.
+
+```go
+// CreateUser saves u to the store. The new user ID is set on u once the data is persisted.
+func (s *Store) CreateUser(u *User) error {
+ return s.db.Update(func(tx *bolt.Tx) error {
+ // Retrieve the users bucket.
+ // This should be created when the DB is first opened.
+ b := tx.Bucket([]byte("users"))
+
+ // Generate ID for the user.
+ // This returns an error only if the Tx is closed or not writeable.
+ // That can't happen in an Update() call so I ignore the error check.
+ id, _ := b.NextSequence()
+ u.ID = int(id)
+
+ // Marshal user data into bytes.
+ buf, err := json.Marshal(u)
+ if err != nil {
+ return err
+ }
+
+ // Persist bytes to users bucket.
+ return b.Put(itob(u.ID), buf)
+ })
+}
+
+// itob returns an 8-byte big endian representation of v.
+func itob(v int) []byte {
+ b := make([]byte, 8)
+ binary.BigEndian.PutUint64(b, uint64(v))
+ return b
+}
+
+type User struct {
+ ID int
+ ...
+}
+```
+
+### Iterating over keys
+
+Bolt stores its keys in byte-sorted order within a bucket. This makes sequential
+iteration over these keys extremely fast. To iterate over keys we'll use a
+`Cursor`:
+
+```go
+db.View(func(tx *bolt.Tx) error {
+ // Assume bucket exists and has keys
+ b := tx.Bucket([]byte("MyBucket"))
+
+ c := b.Cursor()
+
+ for k, v := c.First(); k != nil; k, v = c.Next() {
+ fmt.Printf("key=%s, value=%s\n", k, v)
+ }
+
+ return nil
+})
+```
+
+The cursor allows you to move to a specific point in the list of keys and move
+forward or backward through the keys one at a time.
+
+The following functions are available on the cursor:
+
+```
+First() Move to the first key.
+Last() Move to the last key.
+Seek() Move to a specific key.
+Next() Move to the next key.
+Prev() Move to the previous key.
+```
+
+Each of those functions has a return signature of `(key []byte, value []byte)`.
+When you have iterated to the end of the cursor then `Next()` will return a
+`nil` key. You must seek to a position using `First()`, `Last()`, or `Seek()`
+before calling `Next()` or `Prev()`. If you do not seek to a position then
+these functions will return a `nil` key.
+
+During iteration, if the key is non-`nil` but the value is `nil`, that means
+the key refers to a bucket rather than a value. Use `Bucket.Bucket()` to
+access the sub-bucket.
+
+
+#### Prefix scans
+
+To iterate over a key prefix, you can combine `Seek()` and `bytes.HasPrefix()`:
+
+```go
+db.View(func(tx *bolt.Tx) error {
+ // Assume bucket exists and has keys
+ c := tx.Bucket([]byte("MyBucket")).Cursor()
+
+ prefix := []byte("1234")
+ for k, v := c.Seek(prefix); bytes.HasPrefix(k, prefix); k, v = c.Next() {
+ fmt.Printf("key=%s, value=%s\n", k, v)
+ }
+
+ return nil
+})
+```
+
+#### Range scans
+
+Another common use case is scanning over a range such as a time range. If you
+use a sortable time encoding such as RFC3339 then you can query a specific
+date range like this:
+
+```go
+db.View(func(tx *bolt.Tx) error {
+ // Assume our events bucket exists and has RFC3339 encoded time keys.
+ c := tx.Bucket([]byte("Events")).Cursor()
+
+ // Our time range spans the 90's decade.
+ min := []byte("1990-01-01T00:00:00Z")
+ max := []byte("2000-01-01T00:00:00Z")
+
+ // Iterate over the 90's.
+ for k, v := c.Seek(min); k != nil && bytes.Compare(k, max) <= 0; k, v = c.Next() {
+ fmt.Printf("%s: %s\n", k, v)
+ }
+
+ return nil
+})
+```
+
+Note that, while RFC3339 is sortable, the Golang implementation of RFC3339Nano does not use a fixed number of digits after the decimal point and is therefore not sortable.
+
+
+#### ForEach()
+
+You can also use the function `ForEach()` if you know you'll be iterating over
+all the keys in a bucket:
+
+```go
+db.View(func(tx *bolt.Tx) error {
+ // Assume bucket exists and has keys
+ b := tx.Bucket([]byte("MyBucket"))
+
+ b.ForEach(func(k, v []byte) error {
+ fmt.Printf("key=%s, value=%s\n", k, v)
+ return nil
+ })
+ return nil
+})
+```
+
+Please note that keys and values in `ForEach()` are only valid while
+the transaction is open. If you need to use a key or value outside of
+the transaction, you must use `copy()` to copy it to another byte
+slice.
+
+### Nested buckets
+
+You can also store a bucket in a key to create nested buckets. The API is the
+same as the bucket management API on the `DB` object:
+
+```go
+func (*Bucket) CreateBucket(key []byte) (*Bucket, error)
+func (*Bucket) CreateBucketIfNotExists(key []byte) (*Bucket, error)
+func (*Bucket) DeleteBucket(key []byte) error
+```
+
+
+### Database backups
+
+Bolt is a single file so it's easy to backup. You can use the `Tx.WriteTo()`
+function to write a consistent view of the database to a writer. If you call
+this from a read-only transaction, it will perform a hot backup and not block
+your other database reads and writes.
+
+By default, it will use a regular file handle which will utilize the operating
+system's page cache. See the [`Tx`](https://godoc.org/github.com/boltdb/bolt#Tx)
+documentation for information about optimizing for larger-than-RAM datasets.
+
+One common use case is to backup over HTTP so you can use tools like `cURL` to
+do database backups:
+
+```go
+func BackupHandleFunc(w http.ResponseWriter, req *http.Request) {
+ err := db.View(func(tx *bolt.Tx) error {
+ w.Header().Set("Content-Type", "application/octet-stream")
+ w.Header().Set("Content-Disposition", `attachment; filename="my.db"`)
+ w.Header().Set("Content-Length", strconv.Itoa(int(tx.Size())))
+ _, err := tx.WriteTo(w)
+ return err
+ })
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ }
+}
+```
+
+Then you can backup using this command:
+
+```sh
+$ curl http://localhost/backup > my.db
+```
+
+Or you can open your browser to `http://localhost/backup` and it will download
+automatically.
+
+If you want to backup to another file you can use the `Tx.CopyFile()` helper
+function.
+
+
+### Statistics
+
+The database keeps a running count of many of the internal operations it
+performs so you can better understand what's going on. By grabbing a snapshot
+of these stats at two points in time we can see what operations were performed
+in that time range.
+
+For example, we could start a goroutine to log stats every 10 seconds:
+
+```go
+go func() {
+ // Grab the initial stats.
+ prev := db.Stats()
+
+ for {
+ // Wait for 10s.
+ time.Sleep(10 * time.Second)
+
+ // Grab the current stats and diff them.
+ stats := db.Stats()
+ diff := stats.Sub(&prev)
+
+ // Encode stats to JSON and print to STDERR.
+ json.NewEncoder(os.Stderr).Encode(diff)
+
+ // Save stats for the next loop.
+ prev = stats
+ }
+}()
+```
+
+It's also useful to pipe these stats to a service such as statsd for monitoring
+or to provide an HTTP endpoint that will perform a fixed-length sample.
+
+
+### Read-Only Mode
+
+Sometimes it is useful to create a shared, read-only Bolt database. To this,
+set the `Options.ReadOnly` flag when opening your database. Read-only mode
+uses a shared lock to allow multiple processes to read from the database but
+it will block any processes from opening the database in read-write mode.
+
+```go
+db, err := bolt.Open("my.db", 0666, &bolt.Options{ReadOnly: true})
+if err != nil {
+ log.Fatal(err)
+}
+```
+
+### Mobile Use (iOS/Android)
+
+Bolt is able to run on mobile devices by leveraging the binding feature of the
+[gomobile](https://github.com/golang/mobile) tool. Create a struct that will
+contain your database logic and a reference to a `*bolt.DB` with a initializing
+constructor that takes in a filepath where the database file will be stored.
+Neither Android nor iOS require extra permissions or cleanup from using this method.
+
+```go
+func NewBoltDB(filepath string) *BoltDB {
+ db, err := bolt.Open(filepath+"/demo.db", 0600, nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ return &BoltDB{db}
+}
+
+type BoltDB struct {
+ db *bolt.DB
+ ...
+}
+
+func (b *BoltDB) Path() string {
+ return b.db.Path()
+}
+
+func (b *BoltDB) Close() {
+ b.db.Close()
+}
+```
+
+Database logic should be defined as methods on this wrapper struct.
+
+To initialize this struct from the native language (both platforms now sync
+their local storage to the cloud. These snippets disable that functionality for the
+database file):
+
+#### Android
+
+```java
+String path;
+if (android.os.Build.VERSION.SDK_INT >=android.os.Build.VERSION_CODES.LOLLIPOP){
+ path = getNoBackupFilesDir().getAbsolutePath();
+} else{
+ path = getFilesDir().getAbsolutePath();
+}
+Boltmobiledemo.BoltDB boltDB = Boltmobiledemo.NewBoltDB(path)
+```
+
+#### iOS
+
+```objc
+- (void)demo {
+ NSString* path = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
+ NSUserDomainMask,
+ YES) objectAtIndex:0];
+ GoBoltmobiledemoBoltDB * demo = GoBoltmobiledemoNewBoltDB(path);
+ [self addSkipBackupAttributeToItemAtPath:demo.path];
+ //Some DB Logic would go here
+ [demo close];
+}
+
+- (BOOL)addSkipBackupAttributeToItemAtPath:(NSString *) filePathString
+{
+ NSURL* URL= [NSURL fileURLWithPath: filePathString];
+ assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]);
+
+ NSError *error = nil;
+ BOOL success = [URL setResourceValue: [NSNumber numberWithBool: YES]
+ forKey: NSURLIsExcludedFromBackupKey error: &error];
+ if(!success){
+ NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent], error);
+ }
+ return success;
+}
+
+```
+
+## Resources
+
+For more information on getting started with Bolt, check out the following articles:
+
+* [Intro to BoltDB: Painless Performant Persistence](http://npf.io/2014/07/intro-to-boltdb-painless-performant-persistence/) by [Nate Finch](https://github.com/natefinch).
+* [Bolt -- an embedded key/value database for Go](https://www.progville.com/go/bolt-embedded-db-golang/) by Progville
+
+
+## Comparison with other databases
+
+### Postgres, MySQL, & other relational databases
+
+Relational databases structure data into rows and are only accessible through
+the use of SQL. This approach provides flexibility in how you store and query
+your data but also incurs overhead in parsing and planning SQL statements. Bolt
+accesses all data by a byte slice key. This makes Bolt fast to read and write
+data by key but provides no built-in support for joining values together.
+
+Most relational databases (with the exception of SQLite) are standalone servers
+that run separately from your application. This gives your systems
+flexibility to connect multiple application servers to a single database
+server but also adds overhead in serializing and transporting data over the
+network. Bolt runs as a library included in your application so all data access
+has to go through your application's process. This brings data closer to your
+application but limits multi-process access to the data.
+
+
+### LevelDB, RocksDB
+
+LevelDB and its derivatives (RocksDB, HyperLevelDB) are similar to Bolt in that
+they are libraries bundled into the application, however, their underlying
+structure is a log-structured merge-tree (LSM tree). An LSM tree optimizes
+random writes by using a write ahead log and multi-tiered, sorted files called
+SSTables. Bolt uses a B+tree internally and only a single file. Both approaches
+have trade-offs.
+
+If you require a high random write throughput (>10,000 w/sec) or you need to use
+spinning disks then LevelDB could be a good choice. If your application is
+read-heavy or does a lot of range scans then Bolt could be a good choice.
+
+One other important consideration is that LevelDB does not have transactions.
+It supports batch writing of key/values pairs and it supports read snapshots
+but it will not give you the ability to do a compare-and-swap operation safely.
+Bolt supports fully serializable ACID transactions.
+
+
+### LMDB
+
+Bolt was originally a port of LMDB so it is architecturally similar. Both use
+a B+tree, have ACID semantics with fully serializable transactions, and support
+lock-free MVCC using a single writer and multiple readers.
+
+The two projects have somewhat diverged. LMDB heavily focuses on raw performance
+while Bolt has focused on simplicity and ease of use. For example, LMDB allows
+several unsafe actions such as direct writes for the sake of performance. Bolt
+opts to disallow actions which can leave the database in a corrupted state. The
+only exception to this in Bolt is `DB.NoSync`.
+
+There are also a few differences in API. LMDB requires a maximum mmap size when
+opening an `mdb_env` whereas Bolt will handle incremental mmap resizing
+automatically. LMDB overloads the getter and setter functions with multiple
+flags whereas Bolt splits these specialized cases into their own functions.
+
+
+## Caveats & Limitations
+
+It's important to pick the right tool for the job and Bolt is no exception.
+Here are a few things to note when evaluating and using Bolt:
+
+* Bolt is good for read intensive workloads. Sequential write performance is
+ also fast but random writes can be slow. You can use `DB.Batch()` or add a
+ write-ahead log to help mitigate this issue.
+
+* Bolt uses a B+tree internally so there can be a lot of random page access.
+ SSDs provide a significant performance boost over spinning disks.
+
+* Try to avoid long running read transactions. Bolt uses copy-on-write so
+ old pages cannot be reclaimed while an old transaction is using them.
+
+* Byte slices returned from Bolt are only valid during a transaction. Once the
+ transaction has been committed or rolled back then the memory they point to
+ can be reused by a new page or can be unmapped from virtual memory and you'll
+ see an `unexpected fault address` panic when accessing it.
+
+* Be careful when using `Bucket.FillPercent`. Setting a high fill percent for
+ buckets that have random inserts will cause your database to have very poor
+ page utilization.
+
+* Use larger buckets in general. Smaller buckets causes poor page utilization
+ once they become larger than the page size (typically 4KB).
+
+* Bulk loading a lot of random writes into a new bucket can be slow as the
+ page will not split until the transaction is committed. Randomly inserting
+ more than 100,000 key/value pairs into a single new bucket in a single
+ transaction is not advised.
+
+* Bolt uses a memory-mapped file so the underlying operating system handles the
+ caching of the data. Typically, the OS will cache as much of the file as it
+ can in memory and will release memory as needed to other processes. This means
+ that Bolt can show very high memory usage when working with large databases.
+ However, this is expected and the OS will release memory as needed. Bolt can
+ handle databases much larger than the available physical RAM, provided its
+ memory-map fits in the process virtual address space. It may be problematic
+ on 32-bits systems.
+
+* The data structures in the Bolt database are memory mapped so the data file
+ will be endian specific. This means that you cannot copy a Bolt file from a
+ little endian machine to a big endian machine and have it work. For most
+ users this is not a concern since most modern CPUs are little endian.
+
+* Because of the way pages are laid out on disk, Bolt cannot truncate data files
+ and return free pages back to the disk. Instead, Bolt maintains a free list
+ of unused pages within its data file. These free pages can be reused by later
+ transactions. This works well for many use cases as databases generally tend
+ to grow. However, it's important to note that deleting large chunks of data
+ will not allow you to reclaim that space on disk.
+
+ For more information on page allocation, [see this comment][page-allocation].
+
+[page-allocation]: https://github.com/boltdb/bolt/issues/308#issuecomment-74811638
+
+
+## Reading the Source
+
+Bolt is a relatively small code base (<3KLOC) for an embedded, serializable,
+transactional key/value database so it can be a good starting point for people
+interested in how databases work.
+
+The best places to start are the main entry points into Bolt:
+
+- `Open()` - Initializes the reference to the database. It's responsible for
+ creating the database if it doesn't exist, obtaining an exclusive lock on the
+ file, reading the meta pages, & memory-mapping the file.
+
+- `DB.Begin()` - Starts a read-only or read-write transaction depending on the
+ value of the `writable` argument. This requires briefly obtaining the "meta"
+ lock to keep track of open transactions. Only one read-write transaction can
+ exist at a time so the "rwlock" is acquired during the life of a read-write
+ transaction.
+
+- `Bucket.Put()` - Writes a key/value pair into a bucket. After validating the
+ arguments, a cursor is used to traverse the B+tree to the page and position
+ where they key & value will be written. Once the position is found, the bucket
+ materializes the underlying page and the page's parent pages into memory as
+ "nodes". These nodes are where mutations occur during read-write transactions.
+ These changes get flushed to disk during commit.
+
+- `Bucket.Get()` - Retrieves a key/value pair from a bucket. This uses a cursor
+ to move to the page & position of a key/value pair. During a read-only
+ transaction, the key and value data is returned as a direct reference to the
+ underlying mmap file so there's no allocation overhead. For read-write
+ transactions, this data may reference the mmap file or one of the in-memory
+ node values.
+
+- `Cursor` - This object is simply for traversing the B+tree of on-disk pages
+ or in-memory nodes. It can seek to a specific key, move to the first or last
+ value, or it can move forward or backward. The cursor handles the movement up
+ and down the B+tree transparently to the end user.
+
+- `Tx.Commit()` - Converts the in-memory dirty nodes and the list of free pages
+ into pages to be written to disk. Writing to disk then occurs in two phases.
+ First, the dirty pages are written to disk and an `fsync()` occurs. Second, a
+ new meta page with an incremented transaction ID is written and another
+ `fsync()` occurs. This two phase write ensures that partially written data
+ pages are ignored in the event of a crash since the meta page pointing to them
+ is never written. Partially written meta pages are invalidated because they
+ are written with a checksum.
+
+If you have additional notes that could be helpful for others, please submit
+them via pull request.
+
+
+## Other Projects Using Bolt
+
+Below is a list of public, open source projects that use Bolt:
+
+* [BoltDbWeb](https://github.com/evnix/boltdbweb) - A web based GUI for BoltDB files.
+* [Operation Go: A Routine Mission](http://gocode.io) - An online programming game for Golang using Bolt for user accounts and a leaderboard.
+* [Bazil](https://bazil.org/) - A file system that lets your data reside where it is most convenient for it to reside.
+* [DVID](https://github.com/janelia-flyem/dvid) - Added Bolt as optional storage engine and testing it against Basho-tuned leveldb.
+* [Skybox Analytics](https://github.com/skybox/skybox) - A standalone funnel analysis tool for web analytics.
+* [Scuttlebutt](https://github.com/benbjohnson/scuttlebutt) - Uses Bolt to store and process all Twitter mentions of GitHub projects.
+* [Wiki](https://github.com/peterhellberg/wiki) - A tiny wiki using Goji, BoltDB and Blackfriday.
+* [ChainStore](https://github.com/pressly/chainstore) - Simple key-value interface to a variety of storage engines organized as a chain of operations.
+* [MetricBase](https://github.com/msiebuhr/MetricBase) - Single-binary version of Graphite.
+* [Gitchain](https://github.com/gitchain/gitchain) - Decentralized, peer-to-peer Git repositories aka "Git meets Bitcoin".
+* [event-shuttle](https://github.com/sclasen/event-shuttle) - A Unix system service to collect and reliably deliver messages to Kafka.
+* [ipxed](https://github.com/kelseyhightower/ipxed) - Web interface and api for ipxed.
+* [BoltStore](https://github.com/yosssi/boltstore) - Session store using Bolt.
+* [photosite/session](https://godoc.org/bitbucket.org/kardianos/photosite/session) - Sessions for a photo viewing site.
+* [LedisDB](https://github.com/siddontang/ledisdb) - A high performance NoSQL, using Bolt as optional storage.
+* [ipLocator](https://github.com/AndreasBriese/ipLocator) - A fast ip-geo-location-server using bolt with bloom filters.
+* [cayley](https://github.com/google/cayley) - Cayley is an open-source graph database using Bolt as optional backend.
+* [bleve](http://www.blevesearch.com/) - A pure Go search engine similar to ElasticSearch that uses Bolt as the default storage backend.
+* [tentacool](https://github.com/optiflows/tentacool) - REST api server to manage system stuff (IP, DNS, Gateway...) on a linux server.
+* [Seaweed File System](https://github.com/chrislusf/seaweedfs) - Highly scalable distributed key~file system with O(1) disk read.
+* [InfluxDB](https://influxdata.com) - Scalable datastore for metrics, events, and real-time analytics.
+* [Freehold](http://tshannon.bitbucket.org/freehold/) - An open, secure, and lightweight platform for your files and data.
+* [Prometheus Annotation Server](https://github.com/oliver006/prom_annotation_server) - Annotation server for PromDash & Prometheus service monitoring system.
+* [Consul](https://github.com/hashicorp/consul) - Consul is service discovery and configuration made easy. Distributed, highly available, and datacenter-aware.
+* [Kala](https://github.com/ajvb/kala) - Kala is a modern job scheduler optimized to run on a single node. It is persistent, JSON over HTTP API, ISO 8601 duration notation, and dependent jobs.
+* [drive](https://github.com/odeke-em/drive) - drive is an unofficial Google Drive command line client for \*NIX operating systems.
+* [stow](https://github.com/djherbis/stow) - a persistence manager for objects
+ backed by boltdb.
+* [buckets](https://github.com/joyrexus/buckets) - a bolt wrapper streamlining
+ simple tx and key scans.
+* [mbuckets](https://github.com/abhigupta912/mbuckets) - A Bolt wrapper that allows easy operations on multi level (nested) buckets.
+* [Request Baskets](https://github.com/darklynx/request-baskets) - A web service to collect arbitrary HTTP requests and inspect them via REST API or simple web UI, similar to [RequestBin](http://requestb.in/) service
+* [Go Report Card](https://goreportcard.com/) - Go code quality report cards as a (free and open source) service.
+* [Boltdb Boilerplate](https://github.com/bobintornado/boltdb-boilerplate) - Boilerplate wrapper around bolt aiming to make simple calls one-liners.
+* [lru](https://github.com/crowdriff/lru) - Easy to use Bolt-backed Least-Recently-Used (LRU) read-through cache with chainable remote stores.
+* [Storm](https://github.com/asdine/storm) - Simple and powerful ORM for BoltDB.
+* [GoWebApp](https://github.com/josephspurrier/gowebapp) - A basic MVC web application in Go using BoltDB.
+* [SimpleBolt](https://github.com/xyproto/simplebolt) - A simple way to use BoltDB. Deals mainly with strings.
+* [Algernon](https://github.com/xyproto/algernon) - A HTTP/2 web server with built-in support for Lua. Uses BoltDB as the default database backend.
+* [MuLiFS](https://github.com/dankomiocevic/mulifs) - Music Library Filesystem creates a filesystem to organise your music files.
+* [GoShort](https://github.com/pankajkhairnar/goShort) - GoShort is a URL shortener written in Golang and BoltDB for persistent key/value storage and for routing it's using high performent HTTPRouter.
+* [torrent](https://github.com/anacrolix/torrent) - Full-featured BitTorrent client package and utilities in Go. BoltDB is a storage backend in development.
+* [gopherpit](https://github.com/gopherpit/gopherpit) - A web service to manage Go remote import paths with custom domains
+
+If you are using Bolt in a project please send a pull request to add it to the list.
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/appveyor.yml b/cmd/ponzu/vendor/github.com/boltdb/bolt/appveyor.yml
new file mode 100644
index 0000000..6e26e94
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/appveyor.yml
@@ -0,0 +1,18 @@
+version: "{build}"
+
+os: Windows Server 2012 R2
+
+clone_folder: c:\gopath\src\github.com\boltdb\bolt
+
+environment:
+ GOPATH: c:\gopath
+
+install:
+ - echo %PATH%
+ - echo %GOPATH%
+ - go version
+ - go env
+ - go get -v -t ./...
+
+build_script:
+ - go test -v ./...
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_386.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_386.go
new file mode 100644
index 0000000..820d533
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_386.go
@@ -0,0 +1,10 @@
+package bolt
+
+// maxMapSize represents the largest mmap size supported by Bolt.
+const maxMapSize = 0x7FFFFFFF // 2GB
+
+// maxAllocSize is the size used when creating array pointers.
+const maxAllocSize = 0xFFFFFFF
+
+// Are unaligned load/stores broken on this arch?
+var brokenUnaligned = false
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_amd64.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_amd64.go
new file mode 100644
index 0000000..98fafdb
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_amd64.go
@@ -0,0 +1,10 @@
+package bolt
+
+// maxMapSize represents the largest mmap size supported by Bolt.
+const maxMapSize = 0xFFFFFFFFFFFF // 256TB
+
+// maxAllocSize is the size used when creating array pointers.
+const maxAllocSize = 0x7FFFFFFF
+
+// Are unaligned load/stores broken on this arch?
+var brokenUnaligned = false
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_arm.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_arm.go
new file mode 100644
index 0000000..7e5cb4b
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_arm.go
@@ -0,0 +1,28 @@
+package bolt
+
+import "unsafe"
+
+// maxMapSize represents the largest mmap size supported by Bolt.
+const maxMapSize = 0x7FFFFFFF // 2GB
+
+// maxAllocSize is the size used when creating array pointers.
+const maxAllocSize = 0xFFFFFFF
+
+// Are unaligned load/stores broken on this arch?
+var brokenUnaligned bool
+
+func init() {
+ // Simple check to see whether this arch handles unaligned load/stores
+ // correctly.
+
+ // ARM9 and older devices require load/stores to be from/to aligned
+ // addresses. If not, the lower 2 bits are cleared and that address is
+ // read in a jumbled up order.
+
+ // See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka15414.html
+
+ raw := [6]byte{0xfe, 0xef, 0x11, 0x22, 0x22, 0x11}
+ val := *(*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(&raw)) + 2))
+
+ brokenUnaligned = val != 0x11222211
+}
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_arm64.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_arm64.go
new file mode 100644
index 0000000..b26d84f
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_arm64.go
@@ -0,0 +1,12 @@
+// +build arm64
+
+package bolt
+
+// maxMapSize represents the largest mmap size supported by Bolt.
+const maxMapSize = 0xFFFFFFFFFFFF // 256TB
+
+// maxAllocSize is the size used when creating array pointers.
+const maxAllocSize = 0x7FFFFFFF
+
+// Are unaligned load/stores broken on this arch?
+var brokenUnaligned = false
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_linux.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_linux.go
new file mode 100644
index 0000000..2b67666
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_linux.go
@@ -0,0 +1,10 @@
+package bolt
+
+import (
+ "syscall"
+)
+
+// fdatasync flushes written data to a file descriptor.
+func fdatasync(db *DB) error {
+ return syscall.Fdatasync(int(db.file.Fd()))
+}
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_openbsd.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_openbsd.go
new file mode 100644
index 0000000..7058c3d
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_openbsd.go
@@ -0,0 +1,27 @@
+package bolt
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+const (
+ msAsync = 1 << iota // perform asynchronous writes
+ msSync // perform synchronous writes
+ msInvalidate // invalidate cached data
+)
+
+func msync(db *DB) error {
+ _, _, errno := syscall.Syscall(syscall.SYS_MSYNC, uintptr(unsafe.Pointer(db.data)), uintptr(db.datasz), msInvalidate)
+ if errno != 0 {
+ return errno
+ }
+ return nil
+}
+
+func fdatasync(db *DB) error {
+ if db.data != nil {
+ return msync(db)
+ }
+ return db.file.Sync()
+}
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_ppc.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_ppc.go
new file mode 100644
index 0000000..645ddc3
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_ppc.go
@@ -0,0 +1,9 @@
+// +build ppc
+
+package bolt
+
+// maxMapSize represents the largest mmap size supported by Bolt.
+const maxMapSize = 0x7FFFFFFF // 2GB
+
+// maxAllocSize is the size used when creating array pointers.
+const maxAllocSize = 0xFFFFFFF
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_ppc64.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_ppc64.go
new file mode 100644
index 0000000..2dc6be0
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_ppc64.go
@@ -0,0 +1,9 @@
+// +build ppc64
+
+package bolt
+
+// maxMapSize represents the largest mmap size supported by Bolt.
+const maxMapSize = 0xFFFFFFFFFFFF // 256TB
+
+// maxAllocSize is the size used when creating array pointers.
+const maxAllocSize = 0x7FFFFFFF
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_ppc64le.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_ppc64le.go
new file mode 100644
index 0000000..8c143bc
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_ppc64le.go
@@ -0,0 +1,12 @@
+// +build ppc64le
+
+package bolt
+
+// maxMapSize represents the largest mmap size supported by Bolt.
+const maxMapSize = 0xFFFFFFFFFFFF // 256TB
+
+// maxAllocSize is the size used when creating array pointers.
+const maxAllocSize = 0x7FFFFFFF
+
+// Are unaligned load/stores broken on this arch?
+var brokenUnaligned = false
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_s390x.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_s390x.go
new file mode 100644
index 0000000..d7c39af
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_s390x.go
@@ -0,0 +1,12 @@
+// +build s390x
+
+package bolt
+
+// maxMapSize represents the largest mmap size supported by Bolt.
+const maxMapSize = 0xFFFFFFFFFFFF // 256TB
+
+// maxAllocSize is the size used when creating array pointers.
+const maxAllocSize = 0x7FFFFFFF
+
+// Are unaligned load/stores broken on this arch?
+var brokenUnaligned = false
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_unix.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_unix.go
new file mode 100644
index 0000000..cad62dd
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_unix.go
@@ -0,0 +1,89 @@
+// +build !windows,!plan9,!solaris
+
+package bolt
+
+import (
+ "fmt"
+ "os"
+ "syscall"
+ "time"
+ "unsafe"
+)
+
+// flock acquires an advisory lock on a file descriptor.
+func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error {
+ var t time.Time
+ for {
+ // If we're beyond our timeout then return an error.
+ // This can only occur after we've attempted a flock once.
+ if t.IsZero() {
+ t = time.Now()
+ } else if timeout > 0 && time.Since(t) > timeout {
+ return ErrTimeout
+ }
+ flag := syscall.LOCK_SH
+ if exclusive {
+ flag = syscall.LOCK_EX
+ }
+
+ // Otherwise attempt to obtain an exclusive lock.
+ err := syscall.Flock(int(db.file.Fd()), flag|syscall.LOCK_NB)
+ if err == nil {
+ return nil
+ } else if err != syscall.EWOULDBLOCK {
+ return err
+ }
+
+ // Wait for a bit and try again.
+ time.Sleep(50 * time.Millisecond)
+ }
+}
+
+// funlock releases an advisory lock on a file descriptor.
+func funlock(db *DB) error {
+ return syscall.Flock(int(db.file.Fd()), syscall.LOCK_UN)
+}
+
+// mmap memory maps a DB's data file.
+func mmap(db *DB, sz int) error {
+ // Map the data file to memory.
+ b, err := syscall.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED|db.MmapFlags)
+ if err != nil {
+ return err
+ }
+
+ // Advise the kernel that the mmap is accessed randomly.
+ if err := madvise(b, syscall.MADV_RANDOM); err != nil {
+ return fmt.Errorf("madvise: %s", err)
+ }
+
+ // Save the original byte slice and convert to a byte array pointer.
+ db.dataref = b
+ db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0]))
+ db.datasz = sz
+ return nil
+}
+
+// munmap unmaps a DB's data file from memory.
+func munmap(db *DB) error {
+ // Ignore the unmap if we have no mapped data.
+ if db.dataref == nil {
+ return nil
+ }
+
+ // Unmap using the original byte slice.
+ err := syscall.Munmap(db.dataref)
+ db.dataref = nil
+ db.data = nil
+ db.datasz = 0
+ return err
+}
+
+// NOTE: This function is copied from stdlib because it is not available on darwin.
+func madvise(b []byte, advice int) (err error) {
+ _, _, e1 := syscall.Syscall(syscall.SYS_MADVISE, uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), uintptr(advice))
+ if e1 != 0 {
+ err = e1
+ }
+ return
+}
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_unix_solaris.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_unix_solaris.go
new file mode 100644
index 0000000..307bf2b
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_unix_solaris.go
@@ -0,0 +1,90 @@
+package bolt
+
+import (
+ "fmt"
+ "os"
+ "syscall"
+ "time"
+ "unsafe"
+
+ "golang.org/x/sys/unix"
+)
+
+// flock acquires an advisory lock on a file descriptor.
+func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error {
+ var t time.Time
+ for {
+ // If we're beyond our timeout then return an error.
+ // This can only occur after we've attempted a flock once.
+ if t.IsZero() {
+ t = time.Now()
+ } else if timeout > 0 && time.Since(t) > timeout {
+ return ErrTimeout
+ }
+ var lock syscall.Flock_t
+ lock.Start = 0
+ lock.Len = 0
+ lock.Pid = 0
+ lock.Whence = 0
+ lock.Pid = 0
+ if exclusive {
+ lock.Type = syscall.F_WRLCK
+ } else {
+ lock.Type = syscall.F_RDLCK
+ }
+ err := syscall.FcntlFlock(db.file.Fd(), syscall.F_SETLK, &lock)
+ if err == nil {
+ return nil
+ } else if err != syscall.EAGAIN {
+ return err
+ }
+
+ // Wait for a bit and try again.
+ time.Sleep(50 * time.Millisecond)
+ }
+}
+
+// funlock releases an advisory lock on a file descriptor.
+func funlock(db *DB) error {
+ var lock syscall.Flock_t
+ lock.Start = 0
+ lock.Len = 0
+ lock.Type = syscall.F_UNLCK
+ lock.Whence = 0
+ return syscall.FcntlFlock(uintptr(db.file.Fd()), syscall.F_SETLK, &lock)
+}
+
+// mmap memory maps a DB's data file.
+func mmap(db *DB, sz int) error {
+ // Map the data file to memory.
+ b, err := unix.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED|db.MmapFlags)
+ if err != nil {
+ return err
+ }
+
+ // Advise the kernel that the mmap is accessed randomly.
+ if err := unix.Madvise(b, syscall.MADV_RANDOM); err != nil {
+ return fmt.Errorf("madvise: %s", err)
+ }
+
+ // Save the original byte slice and convert to a byte array pointer.
+ db.dataref = b
+ db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0]))
+ db.datasz = sz
+ return nil
+}
+
+// munmap unmaps a DB's data file from memory.
+func munmap(db *DB) error {
+ // Ignore the unmap if we have no mapped data.
+ if db.dataref == nil {
+ return nil
+ }
+
+ // Unmap using the original byte slice.
+ err := unix.Munmap(db.dataref)
+ db.dataref = nil
+ db.data = nil
+ db.datasz = 0
+ return err
+}
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_windows.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_windows.go
new file mode 100644
index 0000000..d538e6a
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/bolt_windows.go
@@ -0,0 +1,144 @@
+package bolt
+
+import (
+ "fmt"
+ "os"
+ "syscall"
+ "time"
+ "unsafe"
+)
+
+// LockFileEx code derived from golang build filemutex_windows.go @ v1.5.1
+var (
+ modkernel32 = syscall.NewLazyDLL("kernel32.dll")
+ procLockFileEx = modkernel32.NewProc("LockFileEx")
+ procUnlockFileEx = modkernel32.NewProc("UnlockFileEx")
+)
+
+const (
+ lockExt = ".lock"
+
+ // see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx
+ flagLockExclusive = 2
+ flagLockFailImmediately = 1
+
+ // see https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx
+ errLockViolation syscall.Errno = 0x21
+)
+
+func lockFileEx(h syscall.Handle, flags, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) {
+ r, _, err := procLockFileEx.Call(uintptr(h), uintptr(flags), uintptr(reserved), uintptr(locklow), uintptr(lockhigh), uintptr(unsafe.Pointer(ol)))
+ if r == 0 {
+ return err
+ }
+ return nil
+}
+
+func unlockFileEx(h syscall.Handle, reserved, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) {
+ r, _, err := procUnlockFileEx.Call(uintptr(h), uintptr(reserved), uintptr(locklow), uintptr(lockhigh), uintptr(unsafe.Pointer(ol)), 0)
+ if r == 0 {
+ return err
+ }
+ return nil
+}
+
+// fdatasync flushes written data to a file descriptor.
+func fdatasync(db *DB) error {
+ return db.file.Sync()
+}
+
+// flock acquires an advisory lock on a file descriptor.
+func flock(db *DB, mode os.FileMode, exclusive bool, timeout time.Duration) error {
+ // Create a separate lock file on windows because a process
+ // cannot share an exclusive lock on the same file. This is
+ // needed during Tx.WriteTo().
+ f, err := os.OpenFile(db.path+lockExt, os.O_CREATE, mode)
+ if err != nil {
+ return err
+ }
+ db.lockfile = f
+
+ var t time.Time
+ for {
+ // If we're beyond our timeout then return an error.
+ // This can only occur after we've attempted a flock once.
+ if t.IsZero() {
+ t = time.Now()
+ } else if timeout > 0 && time.Since(t) > timeout {
+ return ErrTimeout
+ }
+
+ var flag uint32 = flagLockFailImmediately
+ if exclusive {
+ flag |= flagLockExclusive
+ }
+
+ err := lockFileEx(syscall.Handle(db.lockfile.Fd()), flag, 0, 1, 0, &syscall.Overlapped{})
+ if err == nil {
+ return nil
+ } else if err != errLockViolation {
+ return err
+ }
+
+ // Wait for a bit and try again.
+ time.Sleep(50 * time.Millisecond)
+ }
+}
+
+// funlock releases an advisory lock on a file descriptor.
+func funlock(db *DB) error {
+ err := unlockFileEx(syscall.Handle(db.lockfile.Fd()), 0, 1, 0, &syscall.Overlapped{})
+ db.lockfile.Close()
+ os.Remove(db.path+lockExt)
+ return err
+}
+
+// mmap memory maps a DB's data file.
+// Based on: https://github.com/edsrzf/mmap-go
+func mmap(db *DB, sz int) error {
+ if !db.readOnly {
+ // Truncate the database to the size of the mmap.
+ if err := db.file.Truncate(int64(sz)); err != nil {
+ return fmt.Errorf("truncate: %s", err)
+ }
+ }
+
+ // Open a file mapping handle.
+ sizelo := uint32(sz >> 32)
+ sizehi := uint32(sz) & 0xffffffff
+ h, errno := syscall.CreateFileMapping(syscall.Handle(db.file.Fd()), nil, syscall.PAGE_READONLY, sizelo, sizehi, nil)
+ if h == 0 {
+ return os.NewSyscallError("CreateFileMapping", errno)
+ }
+
+ // Create the memory map.
+ addr, errno := syscall.MapViewOfFile(h, syscall.FILE_MAP_READ, 0, 0, uintptr(sz))
+ if addr == 0 {
+ return os.NewSyscallError("MapViewOfFile", errno)
+ }
+
+ // Close mapping handle.
+ if err := syscall.CloseHandle(syscall.Handle(h)); err != nil {
+ return os.NewSyscallError("CloseHandle", err)
+ }
+
+ // Convert to a byte array.
+ db.data = ((*[maxMapSize]byte)(unsafe.Pointer(addr)))
+ db.datasz = sz
+
+ return nil
+}
+
+// munmap unmaps a pointer from a file.
+// Based on: https://github.com/edsrzf/mmap-go
+func munmap(db *DB) error {
+ if db.data == nil {
+ return nil
+ }
+
+ addr := (uintptr)(unsafe.Pointer(&db.data[0]))
+ if err := syscall.UnmapViewOfFile(addr); err != nil {
+ return os.NewSyscallError("UnmapViewOfFile", err)
+ }
+ return nil
+}
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/boltsync_unix.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/boltsync_unix.go
new file mode 100644
index 0000000..f504425
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/boltsync_unix.go
@@ -0,0 +1,8 @@
+// +build !windows,!plan9,!linux,!openbsd
+
+package bolt
+
+// fdatasync flushes written data to a file descriptor.
+func fdatasync(db *DB) error {
+ return db.file.Sync()
+}
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/bucket.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/bucket.go
new file mode 100644
index 0000000..511ce72
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/bucket.go
@@ -0,0 +1,778 @@
+package bolt
+
+import (
+ "bytes"
+ "fmt"
+ "unsafe"
+)
+
+const (
+ // MaxKeySize is the maximum length of a key, in bytes.
+ MaxKeySize = 32768
+
+ // MaxValueSize is the maximum length of a value, in bytes.
+ MaxValueSize = (1 << 31) - 2
+)
+
+const (
+ maxUint = ^uint(0)
+ minUint = 0
+ maxInt = int(^uint(0) >> 1)
+ minInt = -maxInt - 1
+)
+
+const bucketHeaderSize = int(unsafe.Sizeof(bucket{}))
+
+const (
+ minFillPercent = 0.1
+ maxFillPercent = 1.0
+)
+
+// DefaultFillPercent is the percentage that split pages are filled.
+// This value can be changed by setting Bucket.FillPercent.
+const DefaultFillPercent = 0.5
+
+// Bucket represents a collection of key/value pairs inside the database.
+type Bucket struct {
+ *bucket
+ tx *Tx // the associated transaction
+ buckets map[string]*Bucket // subbucket cache
+ page *page // inline page reference
+ rootNode *node // materialized node for the root page.
+ nodes map[pgid]*node // node cache
+
+ // Sets the threshold for filling nodes when they split. By default,
+ // the bucket will fill to 50% but it can be useful to increase this
+ // amount if you know that your write workloads are mostly append-only.
+ //
+ // This is non-persisted across transactions so it must be set in every Tx.
+ FillPercent float64
+}
+
+// bucket represents the on-file representation of a bucket.
+// This is stored as the "value" of a bucket key. If the bucket is small enough,
+// then its root page can be stored inline in the "value", after the bucket
+// header. In the case of inline buckets, the "root" will be 0.
+type bucket struct {
+ root pgid // page id of the bucket's root-level page
+ sequence uint64 // monotonically incrementing, used by NextSequence()
+}
+
+// newBucket returns a new bucket associated with a transaction.
+func newBucket(tx *Tx) Bucket {
+ var b = Bucket{tx: tx, FillPercent: DefaultFillPercent}
+ if tx.writable {
+ b.buckets = make(map[string]*Bucket)
+ b.nodes = make(map[pgid]*node)
+ }
+ return b
+}
+
+// Tx returns the tx of the bucket.
+func (b *Bucket) Tx() *Tx {
+ return b.tx
+}
+
+// Root returns the root of the bucket.
+func (b *Bucket) Root() pgid {
+ return b.root
+}
+
+// Writable returns whether the bucket is writable.
+func (b *Bucket) Writable() bool {
+ return b.tx.writable
+}
+
+// Cursor creates a cursor associated with the bucket.
+// The cursor is only valid as long as the transaction is open.
+// Do not use a cursor after the transaction is closed.
+func (b *Bucket) Cursor() *Cursor {
+ // Update transaction statistics.
+ b.tx.stats.CursorCount++
+
+ // Allocate and return a cursor.
+ return &Cursor{
+ bucket: b,
+ stack: make([]elemRef, 0),
+ }
+}
+
+// Bucket retrieves a nested bucket by name.
+// Returns nil if the bucket does not exist.
+// The bucket instance is only valid for the lifetime of the transaction.
+func (b *Bucket) Bucket(name []byte) *Bucket {
+ if b.buckets != nil {
+ if child := b.buckets[string(name)]; child != nil {
+ return child
+ }
+ }
+
+ // Move cursor to key.
+ c := b.Cursor()
+ k, v, flags := c.seek(name)
+
+ // Return nil if the key doesn't exist or it is not a bucket.
+ if !bytes.Equal(name, k) || (flags&bucketLeafFlag) == 0 {
+ return nil
+ }
+
+ // Otherwise create a bucket and cache it.
+ var child = b.openBucket(v)
+ if b.buckets != nil {
+ b.buckets[string(name)] = child
+ }
+
+ return child
+}
+
+// Helper method that re-interprets a sub-bucket value
+// from a parent into a Bucket
+func (b *Bucket) openBucket(value []byte) *Bucket {
+ var child = newBucket(b.tx)
+
+ // If unaligned load/stores are broken on this arch and value is
+ // unaligned simply clone to an aligned byte array.
+ unaligned := brokenUnaligned && uintptr(unsafe.Pointer(&value[0]))&3 != 0
+
+ if unaligned {
+ value = cloneBytes(value)
+ }
+
+ // If this is a writable transaction then we need to copy the bucket entry.
+ // Read-only transactions can point directly at the mmap entry.
+ if b.tx.writable && !unaligned {
+ child.bucket = &bucket{}
+ *child.bucket = *(*bucket)(unsafe.Pointer(&value[0]))
+ } else {
+ child.bucket = (*bucket)(unsafe.Pointer(&value[0]))
+ }
+
+ // Save a reference to the inline page if the bucket is inline.
+ if child.root == 0 {
+ child.page = (*page)(unsafe.Pointer(&value[bucketHeaderSize]))
+ }
+
+ return &child
+}
+
+// CreateBucket creates a new bucket at the given key and returns the new bucket.
+// Returns an error if the key already exists, if the bucket name is blank, or if the bucket name is too long.
+// The bucket instance is only valid for the lifetime of the transaction.
+func (b *Bucket) CreateBucket(key []byte) (*Bucket, error) {
+ if b.tx.db == nil {
+ return nil, ErrTxClosed
+ } else if !b.tx.writable {
+ return nil, ErrTxNotWritable
+ } else if len(key) == 0 {
+ return nil, ErrBucketNameRequired
+ }
+
+ // Move cursor to correct position.
+ c := b.Cursor()
+ k, _, flags := c.seek(key)
+
+ // Return an error if there is an existing key.
+ if bytes.Equal(key, k) {
+ if (flags & bucketLeafFlag) != 0 {
+ return nil, ErrBucketExists
+ } else {
+ return nil, ErrIncompatibleValue
+ }
+ }
+
+ // Create empty, inline bucket.
+ var bucket = Bucket{
+ bucket: &bucket{},
+ rootNode: &node{isLeaf: true},
+ FillPercent: DefaultFillPercent,
+ }
+ var value = bucket.write()
+
+ // Insert into node.
+ key = cloneBytes(key)
+ c.node().put(key, key, value, 0, bucketLeafFlag)
+
+ // Since subbuckets are not allowed on inline buckets, we need to
+ // dereference the inline page, if it exists. This will cause the bucket
+ // to be treated as a regular, non-inline bucket for the rest of the tx.
+ b.page = nil
+
+ return b.Bucket(key), nil
+}
+
+// CreateBucketIfNotExists creates a new bucket if it doesn't already exist and returns a reference to it.
+// Returns an error if the bucket name is blank, or if the bucket name is too long.
+// The bucket instance is only valid for the lifetime of the transaction.
+func (b *Bucket) CreateBucketIfNotExists(key []byte) (*Bucket, error) {
+ child, err := b.CreateBucket(key)
+ if err == ErrBucketExists {
+ return b.Bucket(key), nil
+ } else if err != nil {
+ return nil, err
+ }
+ return child, nil
+}
+
+// DeleteBucket deletes a bucket at the given key.
+// Returns an error if the bucket does not exists, or if the key represents a non-bucket value.
+func (b *Bucket) DeleteBucket(key []byte) error {
+ if b.tx.db == nil {
+ return ErrTxClosed
+ } else if !b.Writable() {
+ return ErrTxNotWritable
+ }
+
+ // Move cursor to correct position.
+ c := b.Cursor()
+ k, _, flags := c.seek(key)
+
+ // Return an error if bucket doesn't exist or is not a bucket.
+ if !bytes.Equal(key, k) {
+ return ErrBucketNotFound
+ } else if (flags & bucketLeafFlag) == 0 {
+ return ErrIncompatibleValue
+ }
+
+ // Recursively delete all child buckets.
+ child := b.Bucket(key)
+ err := child.ForEach(func(k, v []byte) error {
+ if v == nil {
+ if err := child.DeleteBucket(k); err != nil {
+ return fmt.Errorf("delete bucket: %s", err)
+ }
+ }
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+
+ // Remove cached copy.
+ delete(b.buckets, string(key))
+
+ // Release all bucket pages to freelist.
+ child.nodes = nil
+ child.rootNode = nil
+ child.free()
+
+ // Delete the node if we have a matching key.
+ c.node().del(key)
+
+ return nil
+}
+
+// Get retrieves the value for a key in the bucket.
+// Returns a nil value if the key does not exist or if the key is a nested bucket.
+// The returned value is only valid for the life of the transaction.
+func (b *Bucket) Get(key []byte) []byte {
+ k, v, flags := b.Cursor().seek(key)
+
+ // Return nil if this is a bucket.
+ if (flags & bucketLeafFlag) != 0 {
+ return nil
+ }
+
+ // If our target node isn't the same key as what's passed in then return nil.
+ if !bytes.Equal(key, k) {
+ return nil
+ }
+ return v
+}
+
+// Put sets the value for a key in the bucket.
+// If the key exist then its previous value will be overwritten.
+// Supplied value must remain valid for the life of the transaction.
+// Returns an error if the bucket was created from a read-only transaction, if the key is blank, if the key is too large, or if the value is too large.
+func (b *Bucket) Put(key []byte, value []byte) error {
+ if b.tx.db == nil {
+ return ErrTxClosed
+ } else if !b.Writable() {
+ return ErrTxNotWritable
+ } else if len(key) == 0 {
+ return ErrKeyRequired
+ } else if len(key) > MaxKeySize {
+ return ErrKeyTooLarge
+ } else if int64(len(value)) > MaxValueSize {
+ return ErrValueTooLarge
+ }
+
+ // Move cursor to correct position.
+ c := b.Cursor()
+ k, _, flags := c.seek(key)
+
+ // Return an error if there is an existing key with a bucket value.
+ if bytes.Equal(key, k) && (flags&bucketLeafFlag) != 0 {
+ return ErrIncompatibleValue
+ }
+
+ // Insert into node.
+ key = cloneBytes(key)
+ c.node().put(key, key, value, 0, 0)
+
+ return nil
+}
+
+// Delete removes a key from the bucket.
+// If the key does not exist then nothing is done and a nil error is returned.
+// Returns an error if the bucket was created from a read-only transaction.
+func (b *Bucket) Delete(key []byte) error {
+ if b.tx.db == nil {
+ return ErrTxClosed
+ } else if !b.Writable() {
+ return ErrTxNotWritable
+ }
+
+ // Move cursor to correct position.
+ c := b.Cursor()
+ _, _, flags := c.seek(key)
+
+ // Return an error if there is already existing bucket value.
+ if (flags & bucketLeafFlag) != 0 {
+ return ErrIncompatibleValue
+ }
+
+ // Delete the node if we have a matching key.
+ c.node().del(key)
+
+ return nil
+}
+
+// Sequence returns the current integer for the bucket without incrementing it.
+func (b *Bucket) Sequence() uint64 { return b.bucket.sequence }
+
+// SetSequence updates the sequence number for the bucket.
+func (b *Bucket) SetSequence(v uint64) error {
+ if b.tx.db == nil {
+ return ErrTxClosed
+ } else if !b.Writable() {
+ return ErrTxNotWritable
+ }
+
+ // Materialize the root node if it hasn't been already so that the
+ // bucket will be saved during commit.
+ if b.rootNode == nil {
+ _ = b.node(b.root, nil)
+ }
+
+ // Increment and return the sequence.
+ b.bucket.sequence = v
+ return nil
+}
+
+// NextSequence returns an autoincrementing integer for the bucket.
+func (b *Bucket) NextSequence() (uint64, error) {
+ if b.tx.db == nil {
+ return 0, ErrTxClosed
+ } else if !b.Writable() {
+ return 0, ErrTxNotWritable
+ }
+
+ // Materialize the root node if it hasn't been already so that the
+ // bucket will be saved during commit.
+ if b.rootNode == nil {
+ _ = b.node(b.root, nil)
+ }
+
+ // Increment and return the sequence.
+ b.bucket.sequence++
+ return b.bucket.sequence, nil
+}
+
+// ForEach executes a function for each key/value pair in a bucket.
+// If the provided function returns an error then the iteration is stopped and
+// the error is returned to the caller. The provided function must not modify
+// the bucket; this will result in undefined behavior.
+func (b *Bucket) ForEach(fn func(k, v []byte) error) error {
+ if b.tx.db == nil {
+ return ErrTxClosed
+ }
+ c := b.Cursor()
+ for k, v := c.First(); k != nil; k, v = c.Next() {
+ if err := fn(k, v); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// Stat returns stats on a bucket.
+func (b *Bucket) Stats() BucketStats {
+ var s, subStats BucketStats
+ pageSize := b.tx.db.pageSize
+ s.BucketN += 1
+ if b.root == 0 {
+ s.InlineBucketN += 1
+ }
+ b.forEachPage(func(p *page, depth int) {
+ if (p.flags & leafPageFlag) != 0 {
+ s.KeyN += int(p.count)
+
+ // used totals the used bytes for the page
+ used := pageHeaderSize
+
+ if p.count != 0 {
+ // If page has any elements, add all element headers.
+ used += leafPageElementSize * int(p.count-1)
+
+ // Add all element key, value sizes.
+ // The computation takes advantage of the fact that the position
+ // of the last element's key/value equals to the total of the sizes
+ // of all previous elements' keys and values.
+ // It also includes the last element's header.
+ lastElement := p.leafPageElement(p.count - 1)
+ used += int(lastElement.pos + lastElement.ksize + lastElement.vsize)
+ }
+
+ if b.root == 0 {
+ // For inlined bucket just update the inline stats
+ s.InlineBucketInuse += used
+ } else {
+ // For non-inlined bucket update all the leaf stats
+ s.LeafPageN++
+ s.LeafInuse += used
+ s.LeafOverflowN += int(p.overflow)
+
+ // Collect stats from sub-buckets.
+ // Do that by iterating over all element headers
+ // looking for the ones with the bucketLeafFlag.
+ for i := uint16(0); i < p.count; i++ {
+ e := p.leafPageElement(i)
+ if (e.flags & bucketLeafFlag) != 0 {
+ // For any bucket element, open the element value
+ // and recursively call Stats on the contained bucket.
+ subStats.Add(b.openBucket(e.value()).Stats())
+ }
+ }
+ }
+ } else if (p.flags & branchPageFlag) != 0 {
+ s.BranchPageN++
+ lastElement := p.branchPageElement(p.count - 1)
+
+ // used totals the used bytes for the page
+ // Add header and all element headers.
+ used := pageHeaderSize + (branchPageElementSize * int(p.count-1))
+
+ // Add size of all keys and values.
+ // Again, use the fact that last element's position equals to
+ // the total of key, value sizes of all previous elements.
+ used += int(lastElement.pos + lastElement.ksize)
+ s.BranchInuse += used
+ s.BranchOverflowN += int(p.overflow)
+ }
+
+ // Keep track of maximum page depth.
+ if depth+1 > s.Depth {
+ s.Depth = (depth + 1)
+ }
+ })
+
+ // Alloc stats can be computed from page counts and pageSize.
+ s.BranchAlloc = (s.BranchPageN + s.BranchOverflowN) * pageSize
+ s.LeafAlloc = (s.LeafPageN + s.LeafOverflowN) * pageSize
+
+ // Add the max depth of sub-buckets to get total nested depth.
+ s.Depth += subStats.Depth
+ // Add the stats for all sub-buckets
+ s.Add(subStats)
+ return s
+}
+
+// forEachPage iterates over every page in a bucket, including inline pages.
+func (b *Bucket) forEachPage(fn func(*page, int)) {
+ // If we have an inline page then just use that.
+ if b.page != nil {
+ fn(b.page, 0)
+ return
+ }
+
+ // Otherwise traverse the page hierarchy.
+ b.tx.forEachPage(b.root, 0, fn)
+}
+
+// forEachPageNode iterates over every page (or node) in a bucket.
+// This also includes inline pages.
+func (b *Bucket) forEachPageNode(fn func(*page, *node, int)) {
+ // If we have an inline page or root node then just use that.
+ if b.page != nil {
+ fn(b.page, nil, 0)
+ return
+ }
+ b._forEachPageNode(b.root, 0, fn)
+}
+
+func (b *Bucket) _forEachPageNode(pgid pgid, depth int, fn func(*page, *node, int)) {
+ var p, n = b.pageNode(pgid)
+
+ // Execute function.
+ fn(p, n, depth)
+
+ // Recursively loop over children.
+ if p != nil {
+ if (p.flags & branchPageFlag) != 0 {
+ for i := 0; i < int(p.count); i++ {
+ elem := p.branchPageElement(uint16(i))
+ b._forEachPageNode(elem.pgid, depth+1, fn)
+ }
+ }
+ } else {
+ if !n.isLeaf {
+ for _, inode := range n.inodes {
+ b._forEachPageNode(inode.pgid, depth+1, fn)
+ }
+ }
+ }
+}
+
+// spill writes all the nodes for this bucket to dirty pages.
+func (b *Bucket) spill() error {
+ // Spill all child buckets first.
+ for name, child := range b.buckets {
+ // If the child bucket is small enough and it has no child buckets then
+ // write it inline into the parent bucket's page. Otherwise spill it
+ // like a normal bucket and make the parent value a pointer to the page.
+ var value []byte
+ if child.inlineable() {
+ child.free()
+ value = child.write()
+ } else {
+ if err := child.spill(); err != nil {
+ return err
+ }
+
+ // Update the child bucket header in this bucket.
+ value = make([]byte, unsafe.Sizeof(bucket{}))
+ var bucket = (*bucket)(unsafe.Pointer(&value[0]))
+ *bucket = *child.bucket
+ }
+
+ // Skip writing the bucket if there are no materialized nodes.
+ if child.rootNode == nil {
+ continue
+ }
+
+ // Update parent node.
+ var c = b.Cursor()
+ k, _, flags := c.seek([]byte(name))
+ if !bytes.Equal([]byte(name), k) {
+ panic(fmt.Sprintf("misplaced bucket header: %x -> %x", []byte(name), k))
+ }
+ if flags&bucketLeafFlag == 0 {
+ panic(fmt.Sprintf("unexpected bucket header flag: %x", flags))
+ }
+ c.node().put([]byte(name), []byte(name), value, 0, bucketLeafFlag)
+ }
+
+ // Ignore if there's not a materialized root node.
+ if b.rootNode == nil {
+ return nil
+ }
+
+ // Spill nodes.
+ if err := b.rootNode.spill(); err != nil {
+ return err
+ }
+ b.rootNode = b.rootNode.root()
+
+ // Update the root node for this bucket.
+ if b.rootNode.pgid >= b.tx.meta.pgid {
+ panic(fmt.Sprintf("pgid (%d) above high water mark (%d)", b.rootNode.pgid, b.tx.meta.pgid))
+ }
+ b.root = b.rootNode.pgid
+
+ return nil
+}
+
+// inlineable returns true if a bucket is small enough to be written inline
+// and if it contains no subbuckets. Otherwise returns false.
+func (b *Bucket) inlineable() bool {
+ var n = b.rootNode
+
+ // Bucket must only contain a single leaf node.
+ if n == nil || !n.isLeaf {
+ return false
+ }
+
+ // Bucket is not inlineable if it contains subbuckets or if it goes beyond
+ // our threshold for inline bucket size.
+ var size = pageHeaderSize
+ for _, inode := range n.inodes {
+ size += leafPageElementSize + len(inode.key) + len(inode.value)
+
+ if inode.flags&bucketLeafFlag != 0 {
+ return false
+ } else if size > b.maxInlineBucketSize() {
+ return false
+ }
+ }
+
+ return true
+}
+
+// Returns the maximum total size of a bucket to make it a candidate for inlining.
+func (b *Bucket) maxInlineBucketSize() int {
+ return b.tx.db.pageSize / 4
+}
+
+// write allocates and writes a bucket to a byte slice.
+func (b *Bucket) write() []byte {
+ // Allocate the appropriate size.
+ var n = b.rootNode
+ var value = make([]byte, bucketHeaderSize+n.size())
+
+ // Write a bucket header.
+ var bucket = (*bucket)(unsafe.Pointer(&value[0]))
+ *bucket = *b.bucket
+
+ // Convert byte slice to a fake page and write the root node.
+ var p = (*page)(unsafe.Pointer(&value[bucketHeaderSize]))
+ n.write(p)
+
+ return value
+}
+
+// rebalance attempts to balance all nodes.
+func (b *Bucket) rebalance() {
+ for _, n := range b.nodes {
+ n.rebalance()
+ }
+ for _, child := range b.buckets {
+ child.rebalance()
+ }
+}
+
+// node creates a node from a page and associates it with a given parent.
+func (b *Bucket) node(pgid pgid, parent *node) *node {
+ _assert(b.nodes != nil, "nodes map expected")
+
+ // Retrieve node if it's already been created.
+ if n := b.nodes[pgid]; n != nil {
+ return n
+ }
+
+ // Otherwise create a node and cache it.
+ n := &node{bucket: b, parent: parent}
+ if parent == nil {
+ b.rootNode = n
+ } else {
+ parent.children = append(parent.children, n)
+ }
+
+ // Use the inline page if this is an inline bucket.
+ var p = b.page
+ if p == nil {
+ p = b.tx.page(pgid)
+ }
+
+ // Read the page into the node and cache it.
+ n.read(p)
+ b.nodes[pgid] = n
+
+ // Update statistics.
+ b.tx.stats.NodeCount++
+
+ return n
+}
+
+// free recursively frees all pages in the bucket.
+func (b *Bucket) free() {
+ if b.root == 0 {
+ return
+ }
+
+ var tx = b.tx
+ b.forEachPageNode(func(p *page, n *node, _ int) {
+ if p != nil {
+ tx.db.freelist.free(tx.meta.txid, p)
+ } else {
+ n.free()
+ }
+ })
+ b.root = 0
+}
+
+// dereference removes all references to the old mmap.
+func (b *Bucket) dereference() {
+ if b.rootNode != nil {
+ b.rootNode.root().dereference()
+ }
+
+ for _, child := range b.buckets {
+ child.dereference()
+ }
+}
+
+// pageNode returns the in-memory node, if it exists.
+// Otherwise returns the underlying page.
+func (b *Bucket) pageNode(id pgid) (*page, *node) {
+ // Inline buckets have a fake page embedded in their value so treat them
+ // differently. We'll return the rootNode (if available) or the fake page.
+ if b.root == 0 {
+ if id != 0 {
+ panic(fmt.Sprintf("inline bucket non-zero page access(2): %d != 0", id))
+ }
+ if b.rootNode != nil {
+ return nil, b.rootNode
+ }
+ return b.page, nil
+ }
+
+ // Check the node cache for non-inline buckets.
+ if b.nodes != nil {
+ if n := b.nodes[id]; n != nil {
+ return nil, n
+ }
+ }
+
+ // Finally lookup the page from the transaction if no node is materialized.
+ return b.tx.page(id), nil
+}
+
+// BucketStats records statistics about resources used by a bucket.
+type BucketStats struct {
+ // Page count statistics.
+ BranchPageN int // number of logical branch pages
+ BranchOverflowN int // number of physical branch overflow pages
+ LeafPageN int // number of logical leaf pages
+ LeafOverflowN int // number of physical leaf overflow pages
+
+ // Tree statistics.
+ KeyN int // number of keys/value pairs
+ Depth int // number of levels in B+tree
+
+ // Page size utilization.
+ BranchAlloc int // bytes allocated for physical branch pages
+ BranchInuse int // bytes actually used for branch data
+ LeafAlloc int // bytes allocated for physical leaf pages
+ LeafInuse int // bytes actually used for leaf data
+
+ // Bucket statistics
+ BucketN int // total number of buckets including the top bucket
+ InlineBucketN int // total number on inlined buckets
+ InlineBucketInuse int // bytes used for inlined buckets (also accounted for in LeafInuse)
+}
+
+func (s *BucketStats) Add(other BucketStats) {
+ s.BranchPageN += other.BranchPageN
+ s.BranchOverflowN += other.BranchOverflowN
+ s.LeafPageN += other.LeafPageN
+ s.LeafOverflowN += other.LeafOverflowN
+ s.KeyN += other.KeyN
+ if s.Depth < other.Depth {
+ s.Depth = other.Depth
+ }
+ s.BranchAlloc += other.BranchAlloc
+ s.BranchInuse += other.BranchInuse
+ s.LeafAlloc += other.LeafAlloc
+ s.LeafInuse += other.LeafInuse
+
+ s.BucketN += other.BucketN
+ s.InlineBucketN += other.InlineBucketN
+ s.InlineBucketInuse += other.InlineBucketInuse
+}
+
+// cloneBytes returns a copy of a given slice.
+func cloneBytes(v []byte) []byte {
+ var clone = make([]byte, len(v))
+ copy(clone, v)
+ return clone
+}
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/bucket_test.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/bucket_test.go
new file mode 100644
index 0000000..cddbe27
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/bucket_test.go
@@ -0,0 +1,1909 @@
+package bolt_test
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "log"
+ "math/rand"
+ "os"
+ "strconv"
+ "strings"
+ "testing"
+ "testing/quick"
+
+ "github.com/boltdb/bolt"
+)
+
+// Ensure that a bucket that gets a non-existent key returns nil.
+func TestBucket_Get_NonExistent(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if v := b.Get([]byte("foo")); v != nil {
+ t.Fatal("expected nil value")
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a bucket can read a value that is not flushed yet.
+func TestBucket_Get_FromNode(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
+ t.Fatal(err)
+ }
+ if v := b.Get([]byte("foo")); !bytes.Equal(v, []byte("bar")) {
+ t.Fatalf("unexpected value: %v", v)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a bucket retrieved via Get() returns a nil.
+func TestBucket_Get_IncompatibleValue(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ _, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if _, err := tx.Bucket([]byte("widgets")).CreateBucket([]byte("foo")); err != nil {
+ t.Fatal(err)
+ }
+
+ if tx.Bucket([]byte("widgets")).Get([]byte("foo")) != nil {
+ t.Fatal("expected nil value")
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a slice returned from a bucket has a capacity equal to its length.
+// This also allows slices to be appended to since it will require a realloc by Go.
+//
+// https://github.com/boltdb/bolt/issues/544
+func TestBucket_Get_Capacity(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ // Write key to a bucket.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("bucket"))
+ if err != nil {
+ return err
+ }
+ return b.Put([]byte("key"), []byte("val"))
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ // Retrieve value and attempt to append to it.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ k, v := tx.Bucket([]byte("bucket")).Cursor().First()
+
+ // Verify capacity.
+ if len(k) != cap(k) {
+ t.Fatalf("unexpected key slice capacity: %d", cap(k))
+ } else if len(v) != cap(v) {
+ t.Fatalf("unexpected value slice capacity: %d", cap(v))
+ }
+
+ // Ensure slice can be appended to without a segfault.
+ k = append(k, []byte("123")...)
+ v = append(v, []byte("123")...)
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a bucket can write a key/value.
+func TestBucket_Put(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
+ t.Fatal(err)
+ }
+
+ v := tx.Bucket([]byte("widgets")).Get([]byte("foo"))
+ if !bytes.Equal([]byte("bar"), v) {
+ t.Fatalf("unexpected value: %v", v)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a bucket can rewrite a key in the same transaction.
+func TestBucket_Put_Repeat(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("foo"), []byte("baz")); err != nil {
+ t.Fatal(err)
+ }
+
+ value := tx.Bucket([]byte("widgets")).Get([]byte("foo"))
+ if !bytes.Equal([]byte("baz"), value) {
+ t.Fatalf("unexpected value: %v", value)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a bucket can write a bunch of large values.
+func TestBucket_Put_Large(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ count, factor := 100, 200
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ for i := 1; i < count; i++ {
+ if err := b.Put([]byte(strings.Repeat("0", i*factor)), []byte(strings.Repeat("X", (count-i)*factor))); err != nil {
+ t.Fatal(err)
+ }
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.View(func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("widgets"))
+ for i := 1; i < count; i++ {
+ value := b.Get([]byte(strings.Repeat("0", i*factor)))
+ if !bytes.Equal(value, []byte(strings.Repeat("X", (count-i)*factor))) {
+ t.Fatalf("unexpected value: %v", value)
+ }
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a database can perform multiple large appends safely.
+func TestDB_Put_VeryLarge(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping test in short mode.")
+ }
+
+ n, batchN := 400000, 200000
+ ksize, vsize := 8, 500
+
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ for i := 0; i < n; i += batchN {
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucketIfNotExists([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ for j := 0; j < batchN; j++ {
+ k, v := make([]byte, ksize), make([]byte, vsize)
+ binary.BigEndian.PutUint32(k, uint32(i+j))
+ if err := b.Put(k, v); err != nil {
+ t.Fatal(err)
+ }
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+ }
+}
+
+// Ensure that a setting a value on a key with a bucket value returns an error.
+func TestBucket_Put_IncompatibleValue(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b0, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if _, err := tx.Bucket([]byte("widgets")).CreateBucket([]byte("foo")); err != nil {
+ t.Fatal(err)
+ }
+ if err := b0.Put([]byte("foo"), []byte("bar")); err != bolt.ErrIncompatibleValue {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a setting a value while the transaction is closed returns an error.
+func TestBucket_Put_Closed(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ tx, err := db.Begin(true)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if err := tx.Rollback(); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := b.Put([]byte("foo"), []byte("bar")); err != bolt.ErrTxClosed {
+ t.Fatalf("unexpected error: %s", err)
+ }
+}
+
+// Ensure that setting a value on a read-only bucket returns an error.
+func TestBucket_Put_ReadOnly(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if _, err := tx.CreateBucket([]byte("widgets")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.View(func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("widgets"))
+ if err := b.Put([]byte("foo"), []byte("bar")); err != bolt.ErrTxNotWritable {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a bucket can delete an existing key.
+func TestBucket_Delete(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Delete([]byte("foo")); err != nil {
+ t.Fatal(err)
+ }
+ if v := b.Get([]byte("foo")); v != nil {
+ t.Fatalf("unexpected value: %v", v)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that deleting a large set of keys will work correctly.
+func TestBucket_Delete_Large(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ for i := 0; i < 100; i++ {
+ if err := b.Put([]byte(strconv.Itoa(i)), []byte(strings.Repeat("*", 1024))); err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("widgets"))
+ for i := 0; i < 100; i++ {
+ if err := b.Delete([]byte(strconv.Itoa(i))); err != nil {
+ t.Fatal(err)
+ }
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.View(func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("widgets"))
+ for i := 0; i < 100; i++ {
+ if v := b.Get([]byte(strconv.Itoa(i))); v != nil {
+ t.Fatalf("unexpected value: %v, i=%d", v, i)
+ }
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Deleting a very large list of keys will cause the freelist to use overflow.
+func TestBucket_Delete_FreelistOverflow(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping test in short mode.")
+ }
+
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ k := make([]byte, 16)
+ for i := uint64(0); i < 10000; i++ {
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucketIfNotExists([]byte("0"))
+ if err != nil {
+ t.Fatalf("bucket error: %s", err)
+ }
+
+ for j := uint64(0); j < 1000; j++ {
+ binary.BigEndian.PutUint64(k[:8], i)
+ binary.BigEndian.PutUint64(k[8:], j)
+ if err := b.Put(k, nil); err != nil {
+ t.Fatalf("put error: %s", err)
+ }
+ }
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ // Delete all of them in one large transaction
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("0"))
+ c := b.Cursor()
+ for k, _ := c.First(); k != nil; k, _ = c.Next() {
+ if err := c.Delete(); err != nil {
+ t.Fatal(err)
+ }
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that accessing and updating nested buckets is ok across transactions.
+func TestBucket_Nested(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ // Create a widgets bucket.
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Create a widgets/foo bucket.
+ _, err = b.CreateBucket([]byte("foo"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Create a widgets/bar key.
+ if err := b.Put([]byte("bar"), []byte("0000")); err != nil {
+ t.Fatal(err)
+ }
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+ db.MustCheck()
+
+ // Update widgets/bar.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("widgets"))
+ if err := b.Put([]byte("bar"), []byte("xxxx")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+ db.MustCheck()
+
+ // Cause a split.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ var b = tx.Bucket([]byte("widgets"))
+ for i := 0; i < 10000; i++ {
+ if err := b.Put([]byte(strconv.Itoa(i)), []byte(strconv.Itoa(i))); err != nil {
+ t.Fatal(err)
+ }
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+ db.MustCheck()
+
+ // Insert into widgets/foo/baz.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ var b = tx.Bucket([]byte("widgets"))
+ if err := b.Bucket([]byte("foo")).Put([]byte("baz"), []byte("yyyy")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+ db.MustCheck()
+
+ // Verify.
+ if err := db.View(func(tx *bolt.Tx) error {
+ var b = tx.Bucket([]byte("widgets"))
+ if v := b.Bucket([]byte("foo")).Get([]byte("baz")); !bytes.Equal(v, []byte("yyyy")) {
+ t.Fatalf("unexpected value: %v", v)
+ }
+ if v := b.Get([]byte("bar")); !bytes.Equal(v, []byte("xxxx")) {
+ t.Fatalf("unexpected value: %v", v)
+ }
+ for i := 0; i < 10000; i++ {
+ if v := b.Get([]byte(strconv.Itoa(i))); !bytes.Equal(v, []byte(strconv.Itoa(i))) {
+ t.Fatalf("unexpected value: %v", v)
+ }
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that deleting a bucket using Delete() returns an error.
+func TestBucket_Delete_Bucket(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if _, err := b.CreateBucket([]byte("foo")); err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Delete([]byte("foo")); err != bolt.ErrIncompatibleValue {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that deleting a key on a read-only bucket returns an error.
+func TestBucket_Delete_ReadOnly(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if _, err := tx.CreateBucket([]byte("widgets")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.View(func(tx *bolt.Tx) error {
+ if err := tx.Bucket([]byte("widgets")).Delete([]byte("foo")); err != bolt.ErrTxNotWritable {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a deleting value while the transaction is closed returns an error.
+func TestBucket_Delete_Closed(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ tx, err := db.Begin(true)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if err := tx.Rollback(); err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Delete([]byte("foo")); err != bolt.ErrTxClosed {
+ t.Fatalf("unexpected error: %s", err)
+ }
+}
+
+// Ensure that deleting a bucket causes nested buckets to be deleted.
+func TestBucket_DeleteBucket_Nested(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ widgets, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ foo, err := widgets.CreateBucket([]byte("foo"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ bar, err := foo.CreateBucket([]byte("bar"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := bar.Put([]byte("baz"), []byte("bat")); err != nil {
+ t.Fatal(err)
+ }
+ if err := tx.Bucket([]byte("widgets")).DeleteBucket([]byte("foo")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that deleting a bucket causes nested buckets to be deleted after they have been committed.
+func TestBucket_DeleteBucket_Nested2(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ widgets, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ foo, err := widgets.CreateBucket([]byte("foo"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ bar, err := foo.CreateBucket([]byte("bar"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if err := bar.Put([]byte("baz"), []byte("bat")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ widgets := tx.Bucket([]byte("widgets"))
+ if widgets == nil {
+ t.Fatal("expected widgets bucket")
+ }
+
+ foo := widgets.Bucket([]byte("foo"))
+ if foo == nil {
+ t.Fatal("expected foo bucket")
+ }
+
+ bar := foo.Bucket([]byte("bar"))
+ if bar == nil {
+ t.Fatal("expected bar bucket")
+ }
+
+ if v := bar.Get([]byte("baz")); !bytes.Equal(v, []byte("bat")) {
+ t.Fatalf("unexpected value: %v", v)
+ }
+ if err := tx.DeleteBucket([]byte("widgets")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.View(func(tx *bolt.Tx) error {
+ if tx.Bucket([]byte("widgets")) != nil {
+ t.Fatal("expected bucket to be deleted")
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that deleting a child bucket with multiple pages causes all pages to get collected.
+// NOTE: Consistency check in bolt_test.DB.Close() will panic if pages not freed properly.
+func TestBucket_DeleteBucket_Large(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ widgets, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ foo, err := widgets.CreateBucket([]byte("foo"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ for i := 0; i < 1000; i++ {
+ if err := foo.Put([]byte(fmt.Sprintf("%d", i)), []byte(fmt.Sprintf("%0100d", i))); err != nil {
+ t.Fatal(err)
+ }
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if err := tx.DeleteBucket([]byte("widgets")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a simple value retrieved via Bucket() returns a nil.
+func TestBucket_Bucket_IncompatibleValue(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ widgets, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if err := widgets.Put([]byte("foo"), []byte("bar")); err != nil {
+ t.Fatal(err)
+ }
+ if b := tx.Bucket([]byte("widgets")).Bucket([]byte("foo")); b != nil {
+ t.Fatal("expected nil bucket")
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that creating a bucket on an existing non-bucket key returns an error.
+func TestBucket_CreateBucket_IncompatibleValue(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ widgets, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if err := widgets.Put([]byte("foo"), []byte("bar")); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := widgets.CreateBucket([]byte("foo")); err != bolt.ErrIncompatibleValue {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that deleting a bucket on an existing non-bucket key returns an error.
+func TestBucket_DeleteBucket_IncompatibleValue(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ widgets, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := widgets.Put([]byte("foo"), []byte("bar")); err != nil {
+ t.Fatal(err)
+ }
+ if err := tx.Bucket([]byte("widgets")).DeleteBucket([]byte("foo")); err != bolt.ErrIncompatibleValue {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure bucket can set and update its sequence number.
+func TestBucket_Sequence(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ bkt, err := tx.CreateBucket([]byte("0"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Retrieve sequence.
+ if v := bkt.Sequence(); v != 0 {
+ t.Fatalf("unexpected sequence: %d", v)
+ }
+
+ // Update sequence.
+ if err := bkt.SetSequence(1000); err != nil {
+ t.Fatal(err)
+ }
+
+ // Read sequence again.
+ if v := bkt.Sequence(); v != 1000 {
+ t.Fatalf("unexpected sequence: %d", v)
+ }
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ // Verify sequence in separate transaction.
+ if err := db.View(func(tx *bolt.Tx) error {
+ if v := tx.Bucket([]byte("0")).Sequence(); v != 1000 {
+ t.Fatalf("unexpected sequence: %d", v)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a bucket can return an autoincrementing sequence.
+func TestBucket_NextSequence(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ widgets, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ woojits, err := tx.CreateBucket([]byte("woojits"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Make sure sequence increments.
+ if seq, err := widgets.NextSequence(); err != nil {
+ t.Fatal(err)
+ } else if seq != 1 {
+ t.Fatalf("unexpecte sequence: %d", seq)
+ }
+
+ if seq, err := widgets.NextSequence(); err != nil {
+ t.Fatal(err)
+ } else if seq != 2 {
+ t.Fatalf("unexpected sequence: %d", seq)
+ }
+
+ // Buckets should be separate.
+ if seq, err := woojits.NextSequence(); err != nil {
+ t.Fatal(err)
+ } else if seq != 1 {
+ t.Fatalf("unexpected sequence: %d", 1)
+ }
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a bucket will persist an autoincrementing sequence even if its
+// the only thing updated on the bucket.
+// https://github.com/boltdb/bolt/issues/296
+func TestBucket_NextSequence_Persist(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if _, err := tx.CreateBucket([]byte("widgets")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if _, err := tx.Bucket([]byte("widgets")).NextSequence(); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ seq, err := tx.Bucket([]byte("widgets")).NextSequence()
+ if err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ } else if seq != 2 {
+ t.Fatalf("unexpected sequence: %d", seq)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that retrieving the next sequence on a read-only bucket returns an error.
+func TestBucket_NextSequence_ReadOnly(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if _, err := tx.CreateBucket([]byte("widgets")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.View(func(tx *bolt.Tx) error {
+ _, err := tx.Bucket([]byte("widgets")).NextSequence()
+ if err != bolt.ErrTxNotWritable {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that retrieving the next sequence for a bucket on a closed database return an error.
+func TestBucket_NextSequence_Closed(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ tx, err := db.Begin(true)
+ if err != nil {
+ t.Fatal(err)
+ }
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := tx.Rollback(); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := b.NextSequence(); err != bolt.ErrTxClosed {
+ t.Fatal(err)
+ }
+}
+
+// Ensure a user can loop over all key/value pairs in a bucket.
+func TestBucket_ForEach(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("foo"), []byte("0000")); err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("baz"), []byte("0001")); err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("bar"), []byte("0002")); err != nil {
+ t.Fatal(err)
+ }
+
+ var index int
+ if err := b.ForEach(func(k, v []byte) error {
+ switch index {
+ case 0:
+ if !bytes.Equal(k, []byte("bar")) {
+ t.Fatalf("unexpected key: %v", k)
+ } else if !bytes.Equal(v, []byte("0002")) {
+ t.Fatalf("unexpected value: %v", v)
+ }
+ case 1:
+ if !bytes.Equal(k, []byte("baz")) {
+ t.Fatalf("unexpected key: %v", k)
+ } else if !bytes.Equal(v, []byte("0001")) {
+ t.Fatalf("unexpected value: %v", v)
+ }
+ case 2:
+ if !bytes.Equal(k, []byte("foo")) {
+ t.Fatalf("unexpected key: %v", k)
+ } else if !bytes.Equal(v, []byte("0000")) {
+ t.Fatalf("unexpected value: %v", v)
+ }
+ }
+ index++
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if index != 3 {
+ t.Fatalf("unexpected index: %d", index)
+ }
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure a database can stop iteration early.
+func TestBucket_ForEach_ShortCircuit(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("bar"), []byte("0000")); err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("baz"), []byte("0000")); err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("foo"), []byte("0000")); err != nil {
+ t.Fatal(err)
+ }
+
+ var index int
+ if err := tx.Bucket([]byte("widgets")).ForEach(func(k, v []byte) error {
+ index++
+ if bytes.Equal(k, []byte("baz")) {
+ return errors.New("marker")
+ }
+ return nil
+ }); err == nil || err.Error() != "marker" {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ if index != 2 {
+ t.Fatalf("unexpected index: %d", index)
+ }
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that looping over a bucket on a closed database returns an error.
+func TestBucket_ForEach_Closed(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ tx, err := db.Begin(true)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if err := tx.Rollback(); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := b.ForEach(func(k, v []byte) error { return nil }); err != bolt.ErrTxClosed {
+ t.Fatalf("unexpected error: %s", err)
+ }
+}
+
+// Ensure that an error is returned when inserting with an empty key.
+func TestBucket_Put_EmptyKey(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte(""), []byte("bar")); err != bolt.ErrKeyRequired {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ if err := b.Put(nil, []byte("bar")); err != bolt.ErrKeyRequired {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that an error is returned when inserting with a key that's too large.
+func TestBucket_Put_KeyTooLarge(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put(make([]byte, 32769), []byte("bar")); err != bolt.ErrKeyTooLarge {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that an error is returned when inserting a value that's too large.
+func TestBucket_Put_ValueTooLarge(t *testing.T) {
+ // Skip this test on DroneCI because the machine is resource constrained.
+ if os.Getenv("DRONE") == "true" {
+ t.Skip("not enough RAM for test")
+ }
+
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("foo"), make([]byte, bolt.MaxValueSize+1)); err != bolt.ErrValueTooLarge {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure a bucket can calculate stats.
+func TestBucket_Stats(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ // Add bucket with fewer keys but one big value.
+ bigKey := []byte("really-big-value")
+ for i := 0; i < 500; i++ {
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucketIfNotExists([]byte("woojits"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if err := b.Put([]byte(fmt.Sprintf("%03d", i)), []byte(strconv.Itoa(i))); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+ }
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if err := tx.Bucket([]byte("woojits")).Put(bigKey, []byte(strings.Repeat("*", 10000))); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ db.MustCheck()
+
+ if err := db.View(func(tx *bolt.Tx) error {
+ stats := tx.Bucket([]byte("woojits")).Stats()
+ if stats.BranchPageN != 1 {
+ t.Fatalf("unexpected BranchPageN: %d", stats.BranchPageN)
+ } else if stats.BranchOverflowN != 0 {
+ t.Fatalf("unexpected BranchOverflowN: %d", stats.BranchOverflowN)
+ } else if stats.LeafPageN != 7 {
+ t.Fatalf("unexpected LeafPageN: %d", stats.LeafPageN)
+ } else if stats.LeafOverflowN != 2 {
+ t.Fatalf("unexpected LeafOverflowN: %d", stats.LeafOverflowN)
+ } else if stats.KeyN != 501 {
+ t.Fatalf("unexpected KeyN: %d", stats.KeyN)
+ } else if stats.Depth != 2 {
+ t.Fatalf("unexpected Depth: %d", stats.Depth)
+ }
+
+ branchInuse := 16 // branch page header
+ branchInuse += 7 * 16 // branch elements
+ branchInuse += 7 * 3 // branch keys (6 3-byte keys)
+ if stats.BranchInuse != branchInuse {
+ t.Fatalf("unexpected BranchInuse: %d", stats.BranchInuse)
+ }
+
+ leafInuse := 7 * 16 // leaf page header
+ leafInuse += 501 * 16 // leaf elements
+ leafInuse += 500*3 + len(bigKey) // leaf keys
+ leafInuse += 1*10 + 2*90 + 3*400 + 10000 // leaf values
+ if stats.LeafInuse != leafInuse {
+ t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse)
+ }
+
+ // Only check allocations for 4KB pages.
+ if os.Getpagesize() == 4096 {
+ if stats.BranchAlloc != 4096 {
+ t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc)
+ } else if stats.LeafAlloc != 36864 {
+ t.Fatalf("unexpected LeafAlloc: %d", stats.LeafAlloc)
+ }
+ }
+
+ if stats.BucketN != 1 {
+ t.Fatalf("unexpected BucketN: %d", stats.BucketN)
+ } else if stats.InlineBucketN != 0 {
+ t.Fatalf("unexpected InlineBucketN: %d", stats.InlineBucketN)
+ } else if stats.InlineBucketInuse != 0 {
+ t.Fatalf("unexpected InlineBucketInuse: %d", stats.InlineBucketInuse)
+ }
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure a bucket with random insertion utilizes fill percentage correctly.
+func TestBucket_Stats_RandomFill(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping test in short mode.")
+ } else if os.Getpagesize() != 4096 {
+ t.Skip("invalid page size for test")
+ }
+
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ // Add a set of values in random order. It will be the same random
+ // order so we can maintain consistency between test runs.
+ var count int
+ rand := rand.New(rand.NewSource(42))
+ for _, i := range rand.Perm(1000) {
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucketIfNotExists([]byte("woojits"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ b.FillPercent = 0.9
+ for _, j := range rand.Perm(100) {
+ index := (j * 10000) + i
+ if err := b.Put([]byte(fmt.Sprintf("%d000000000000000", index)), []byte("0000000000")); err != nil {
+ t.Fatal(err)
+ }
+ count++
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ db.MustCheck()
+
+ if err := db.View(func(tx *bolt.Tx) error {
+ stats := tx.Bucket([]byte("woojits")).Stats()
+ if stats.KeyN != 100000 {
+ t.Fatalf("unexpected KeyN: %d", stats.KeyN)
+ }
+
+ if stats.BranchPageN != 98 {
+ t.Fatalf("unexpected BranchPageN: %d", stats.BranchPageN)
+ } else if stats.BranchOverflowN != 0 {
+ t.Fatalf("unexpected BranchOverflowN: %d", stats.BranchOverflowN)
+ } else if stats.BranchInuse != 130984 {
+ t.Fatalf("unexpected BranchInuse: %d", stats.BranchInuse)
+ } else if stats.BranchAlloc != 401408 {
+ t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc)
+ }
+
+ if stats.LeafPageN != 3412 {
+ t.Fatalf("unexpected LeafPageN: %d", stats.LeafPageN)
+ } else if stats.LeafOverflowN != 0 {
+ t.Fatalf("unexpected LeafOverflowN: %d", stats.LeafOverflowN)
+ } else if stats.LeafInuse != 4742482 {
+ t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse)
+ } else if stats.LeafAlloc != 13975552 {
+ t.Fatalf("unexpected LeafAlloc: %d", stats.LeafAlloc)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure a bucket can calculate stats.
+func TestBucket_Stats_Small(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ // Add a bucket that fits on a single root leaf.
+ b, err := tx.CreateBucket([]byte("whozawhats"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
+ t.Fatal(err)
+ }
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ db.MustCheck()
+
+ if err := db.View(func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("whozawhats"))
+ stats := b.Stats()
+ if stats.BranchPageN != 0 {
+ t.Fatalf("unexpected BranchPageN: %d", stats.BranchPageN)
+ } else if stats.BranchOverflowN != 0 {
+ t.Fatalf("unexpected BranchOverflowN: %d", stats.BranchOverflowN)
+ } else if stats.LeafPageN != 0 {
+ t.Fatalf("unexpected LeafPageN: %d", stats.LeafPageN)
+ } else if stats.LeafOverflowN != 0 {
+ t.Fatalf("unexpected LeafOverflowN: %d", stats.LeafOverflowN)
+ } else if stats.KeyN != 1 {
+ t.Fatalf("unexpected KeyN: %d", stats.KeyN)
+ } else if stats.Depth != 1 {
+ t.Fatalf("unexpected Depth: %d", stats.Depth)
+ } else if stats.BranchInuse != 0 {
+ t.Fatalf("unexpected BranchInuse: %d", stats.BranchInuse)
+ } else if stats.LeafInuse != 0 {
+ t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse)
+ }
+
+ if os.Getpagesize() == 4096 {
+ if stats.BranchAlloc != 0 {
+ t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc)
+ } else if stats.LeafAlloc != 0 {
+ t.Fatalf("unexpected LeafAlloc: %d", stats.LeafAlloc)
+ }
+ }
+
+ if stats.BucketN != 1 {
+ t.Fatalf("unexpected BucketN: %d", stats.BucketN)
+ } else if stats.InlineBucketN != 1 {
+ t.Fatalf("unexpected InlineBucketN: %d", stats.InlineBucketN)
+ } else if stats.InlineBucketInuse != 16+16+6 {
+ t.Fatalf("unexpected InlineBucketInuse: %d", stats.InlineBucketInuse)
+ }
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestBucket_Stats_EmptyBucket(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ // Add a bucket that fits on a single root leaf.
+ if _, err := tx.CreateBucket([]byte("whozawhats")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ db.MustCheck()
+
+ if err := db.View(func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("whozawhats"))
+ stats := b.Stats()
+ if stats.BranchPageN != 0 {
+ t.Fatalf("unexpected BranchPageN: %d", stats.BranchPageN)
+ } else if stats.BranchOverflowN != 0 {
+ t.Fatalf("unexpected BranchOverflowN: %d", stats.BranchOverflowN)
+ } else if stats.LeafPageN != 0 {
+ t.Fatalf("unexpected LeafPageN: %d", stats.LeafPageN)
+ } else if stats.LeafOverflowN != 0 {
+ t.Fatalf("unexpected LeafOverflowN: %d", stats.LeafOverflowN)
+ } else if stats.KeyN != 0 {
+ t.Fatalf("unexpected KeyN: %d", stats.KeyN)
+ } else if stats.Depth != 1 {
+ t.Fatalf("unexpected Depth: %d", stats.Depth)
+ } else if stats.BranchInuse != 0 {
+ t.Fatalf("unexpected BranchInuse: %d", stats.BranchInuse)
+ } else if stats.LeafInuse != 0 {
+ t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse)
+ }
+
+ if os.Getpagesize() == 4096 {
+ if stats.BranchAlloc != 0 {
+ t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc)
+ } else if stats.LeafAlloc != 0 {
+ t.Fatalf("unexpected LeafAlloc: %d", stats.LeafAlloc)
+ }
+ }
+
+ if stats.BucketN != 1 {
+ t.Fatalf("unexpected BucketN: %d", stats.BucketN)
+ } else if stats.InlineBucketN != 1 {
+ t.Fatalf("unexpected InlineBucketN: %d", stats.InlineBucketN)
+ } else if stats.InlineBucketInuse != 16 {
+ t.Fatalf("unexpected InlineBucketInuse: %d", stats.InlineBucketInuse)
+ }
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure a bucket can calculate stats.
+func TestBucket_Stats_Nested(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("foo"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ for i := 0; i < 100; i++ {
+ if err := b.Put([]byte(fmt.Sprintf("%02d", i)), []byte(fmt.Sprintf("%02d", i))); err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ bar, err := b.CreateBucket([]byte("bar"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ for i := 0; i < 10; i++ {
+ if err := bar.Put([]byte(strconv.Itoa(i)), []byte(strconv.Itoa(i))); err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ baz, err := bar.CreateBucket([]byte("baz"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ for i := 0; i < 10; i++ {
+ if err := baz.Put([]byte(strconv.Itoa(i)), []byte(strconv.Itoa(i))); err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ db.MustCheck()
+
+ if err := db.View(func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("foo"))
+ stats := b.Stats()
+ if stats.BranchPageN != 0 {
+ t.Fatalf("unexpected BranchPageN: %d", stats.BranchPageN)
+ } else if stats.BranchOverflowN != 0 {
+ t.Fatalf("unexpected BranchOverflowN: %d", stats.BranchOverflowN)
+ } else if stats.LeafPageN != 2 {
+ t.Fatalf("unexpected LeafPageN: %d", stats.LeafPageN)
+ } else if stats.LeafOverflowN != 0 {
+ t.Fatalf("unexpected LeafOverflowN: %d", stats.LeafOverflowN)
+ } else if stats.KeyN != 122 {
+ t.Fatalf("unexpected KeyN: %d", stats.KeyN)
+ } else if stats.Depth != 3 {
+ t.Fatalf("unexpected Depth: %d", stats.Depth)
+ } else if stats.BranchInuse != 0 {
+ t.Fatalf("unexpected BranchInuse: %d", stats.BranchInuse)
+ }
+
+ foo := 16 // foo (pghdr)
+ foo += 101 * 16 // foo leaf elements
+ foo += 100*2 + 100*2 // foo leaf key/values
+ foo += 3 + 16 // foo -> bar key/value
+
+ bar := 16 // bar (pghdr)
+ bar += 11 * 16 // bar leaf elements
+ bar += 10 + 10 // bar leaf key/values
+ bar += 3 + 16 // bar -> baz key/value
+
+ baz := 16 // baz (inline) (pghdr)
+ baz += 10 * 16 // baz leaf elements
+ baz += 10 + 10 // baz leaf key/values
+
+ if stats.LeafInuse != foo+bar+baz {
+ t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse)
+ }
+
+ if os.Getpagesize() == 4096 {
+ if stats.BranchAlloc != 0 {
+ t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc)
+ } else if stats.LeafAlloc != 8192 {
+ t.Fatalf("unexpected LeafAlloc: %d", stats.LeafAlloc)
+ }
+ }
+
+ if stats.BucketN != 3 {
+ t.Fatalf("unexpected BucketN: %d", stats.BucketN)
+ } else if stats.InlineBucketN != 1 {
+ t.Fatalf("unexpected InlineBucketN: %d", stats.InlineBucketN)
+ } else if stats.InlineBucketInuse != baz {
+ t.Fatalf("unexpected InlineBucketInuse: %d", stats.InlineBucketInuse)
+ }
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure a large bucket can calculate stats.
+func TestBucket_Stats_Large(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping test in short mode.")
+ }
+
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ var index int
+ for i := 0; i < 100; i++ {
+ // Add bucket with lots of keys.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucketIfNotExists([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ for i := 0; i < 1000; i++ {
+ if err := b.Put([]byte(strconv.Itoa(index)), []byte(strconv.Itoa(index))); err != nil {
+ t.Fatal(err)
+ }
+ index++
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ db.MustCheck()
+
+ if err := db.View(func(tx *bolt.Tx) error {
+ stats := tx.Bucket([]byte("widgets")).Stats()
+ if stats.BranchPageN != 13 {
+ t.Fatalf("unexpected BranchPageN: %d", stats.BranchPageN)
+ } else if stats.BranchOverflowN != 0 {
+ t.Fatalf("unexpected BranchOverflowN: %d", stats.BranchOverflowN)
+ } else if stats.LeafPageN != 1196 {
+ t.Fatalf("unexpected LeafPageN: %d", stats.LeafPageN)
+ } else if stats.LeafOverflowN != 0 {
+ t.Fatalf("unexpected LeafOverflowN: %d", stats.LeafOverflowN)
+ } else if stats.KeyN != 100000 {
+ t.Fatalf("unexpected KeyN: %d", stats.KeyN)
+ } else if stats.Depth != 3 {
+ t.Fatalf("unexpected Depth: %d", stats.Depth)
+ } else if stats.BranchInuse != 25257 {
+ t.Fatalf("unexpected BranchInuse: %d", stats.BranchInuse)
+ } else if stats.LeafInuse != 2596916 {
+ t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse)
+ }
+
+ if os.Getpagesize() == 4096 {
+ if stats.BranchAlloc != 53248 {
+ t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc)
+ } else if stats.LeafAlloc != 4898816 {
+ t.Fatalf("unexpected LeafAlloc: %d", stats.LeafAlloc)
+ }
+ }
+
+ if stats.BucketN != 1 {
+ t.Fatalf("unexpected BucketN: %d", stats.BucketN)
+ } else if stats.InlineBucketN != 0 {
+ t.Fatalf("unexpected InlineBucketN: %d", stats.InlineBucketN)
+ } else if stats.InlineBucketInuse != 0 {
+ t.Fatalf("unexpected InlineBucketInuse: %d", stats.InlineBucketInuse)
+ }
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a bucket can write random keys and values across multiple transactions.
+func TestBucket_Put_Single(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping test in short mode.")
+ }
+
+ index := 0
+ if err := quick.Check(func(items testdata) bool {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ m := make(map[string][]byte)
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if _, err := tx.CreateBucket([]byte("widgets")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ for _, item := range items {
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if err := tx.Bucket([]byte("widgets")).Put(item.Key, item.Value); err != nil {
+ panic("put error: " + err.Error())
+ }
+ m[string(item.Key)] = item.Value
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ // Verify all key/values so far.
+ if err := db.View(func(tx *bolt.Tx) error {
+ i := 0
+ for k, v := range m {
+ value := tx.Bucket([]byte("widgets")).Get([]byte(k))
+ if !bytes.Equal(value, v) {
+ t.Logf("value mismatch [run %d] (%d of %d):\nkey: %x\ngot: %x\nexp: %x", index, i, len(m), []byte(k), value, v)
+ db.CopyTempFile()
+ t.FailNow()
+ }
+ i++
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ index++
+ return true
+ }, nil); err != nil {
+ t.Error(err)
+ }
+}
+
+// Ensure that a transaction can insert multiple key/value pairs at once.
+func TestBucket_Put_Multiple(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping test in short mode.")
+ }
+
+ if err := quick.Check(func(items testdata) bool {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ // Bulk insert all values.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if _, err := tx.CreateBucket([]byte("widgets")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("widgets"))
+ for _, item := range items {
+ if err := b.Put(item.Key, item.Value); err != nil {
+ t.Fatal(err)
+ }
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ // Verify all items exist.
+ if err := db.View(func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("widgets"))
+ for _, item := range items {
+ value := b.Get(item.Key)
+ if !bytes.Equal(item.Value, value) {
+ db.CopyTempFile()
+ t.Fatalf("exp=%x; got=%x", item.Value, value)
+ }
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ return true
+ }, qconfig()); err != nil {
+ t.Error(err)
+ }
+}
+
+// Ensure that a transaction can delete all key/value pairs and return to a single leaf page.
+func TestBucket_Delete_Quick(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping test in short mode.")
+ }
+
+ if err := quick.Check(func(items testdata) bool {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ // Bulk insert all values.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if _, err := tx.CreateBucket([]byte("widgets")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("widgets"))
+ for _, item := range items {
+ if err := b.Put(item.Key, item.Value); err != nil {
+ t.Fatal(err)
+ }
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ // Remove items one at a time and check consistency.
+ for _, item := range items {
+ if err := db.Update(func(tx *bolt.Tx) error {
+ return tx.Bucket([]byte("widgets")).Delete(item.Key)
+ }); err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ // Anything before our deletion index should be nil.
+ if err := db.View(func(tx *bolt.Tx) error {
+ if err := tx.Bucket([]byte("widgets")).ForEach(func(k, v []byte) error {
+ t.Fatalf("bucket should be empty; found: %06x", trunc(k, 3))
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ return true
+ }, qconfig()); err != nil {
+ t.Error(err)
+ }
+}
+
+func ExampleBucket_Put() {
+ // Open the database.
+ db, err := bolt.Open(tempfile(), 0666, nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer os.Remove(db.Path())
+
+ // Start a write transaction.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ // Create a bucket.
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ return err
+ }
+
+ // Set the value "bar" for the key "foo".
+ if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
+ return err
+ }
+ return nil
+ }); err != nil {
+ log.Fatal(err)
+ }
+
+ // Read value back in a different read-only transaction.
+ if err := db.View(func(tx *bolt.Tx) error {
+ value := tx.Bucket([]byte("widgets")).Get([]byte("foo"))
+ fmt.Printf("The value of 'foo' is: %s\n", value)
+ return nil
+ }); err != nil {
+ log.Fatal(err)
+ }
+
+ // Close database to release file lock.
+ if err := db.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ // Output:
+ // The value of 'foo' is: bar
+}
+
+func ExampleBucket_Delete() {
+ // Open the database.
+ db, err := bolt.Open(tempfile(), 0666, nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer os.Remove(db.Path())
+
+ // Start a write transaction.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ // Create a bucket.
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ return err
+ }
+
+ // Set the value "bar" for the key "foo".
+ if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
+ return err
+ }
+
+ // Retrieve the key back from the database and verify it.
+ value := b.Get([]byte("foo"))
+ fmt.Printf("The value of 'foo' was: %s\n", value)
+
+ return nil
+ }); err != nil {
+ log.Fatal(err)
+ }
+
+ // Delete the key in a different write transaction.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ return tx.Bucket([]byte("widgets")).Delete([]byte("foo"))
+ }); err != nil {
+ log.Fatal(err)
+ }
+
+ // Retrieve the key again.
+ if err := db.View(func(tx *bolt.Tx) error {
+ value := tx.Bucket([]byte("widgets")).Get([]byte("foo"))
+ if value == nil {
+ fmt.Printf("The value of 'foo' is now: nil\n")
+ }
+ return nil
+ }); err != nil {
+ log.Fatal(err)
+ }
+
+ // Close database to release file lock.
+ if err := db.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ // Output:
+ // The value of 'foo' was: bar
+ // The value of 'foo' is now: nil
+}
+
+func ExampleBucket_ForEach() {
+ // Open the database.
+ db, err := bolt.Open(tempfile(), 0666, nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer os.Remove(db.Path())
+
+ // Insert data into a bucket.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("animals"))
+ if err != nil {
+ return err
+ }
+
+ if err := b.Put([]byte("dog"), []byte("fun")); err != nil {
+ return err
+ }
+ if err := b.Put([]byte("cat"), []byte("lame")); err != nil {
+ return err
+ }
+ if err := b.Put([]byte("liger"), []byte("awesome")); err != nil {
+ return err
+ }
+
+ // Iterate over items in sorted key order.
+ if err := b.ForEach(func(k, v []byte) error {
+ fmt.Printf("A %s is %s.\n", k, v)
+ return nil
+ }); err != nil {
+ return err
+ }
+
+ return nil
+ }); err != nil {
+ log.Fatal(err)
+ }
+
+ // Close database to release file lock.
+ if err := db.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ // Output:
+ // A cat is lame.
+ // A dog is fun.
+ // A liger is awesome.
+}
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/cmd/bolt/main.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/cmd/bolt/main.go
new file mode 100644
index 0000000..29e393f
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/cmd/bolt/main.go
@@ -0,0 +1,1740 @@
+package main
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+ "flag"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "math/rand"
+ "os"
+ "runtime"
+ "runtime/pprof"
+ "strconv"
+ "strings"
+ "time"
+ "unicode"
+ "unicode/utf8"
+ "unsafe"
+
+ "github.com/boltdb/bolt"
+)
+
+var (
+ // ErrUsage is returned when a usage message was printed and the process
+ // should simply exit with an error.
+ ErrUsage = errors.New("usage")
+
+ // ErrUnknownCommand is returned when a CLI command is not specified.
+ ErrUnknownCommand = errors.New("unknown command")
+
+ // ErrPathRequired is returned when the path to a Bolt database is not specified.
+ ErrPathRequired = errors.New("path required")
+
+ // ErrFileNotFound is returned when a Bolt database does not exist.
+ ErrFileNotFound = errors.New("file not found")
+
+ // ErrInvalidValue is returned when a benchmark reads an unexpected value.
+ ErrInvalidValue = errors.New("invalid value")
+
+ // ErrCorrupt is returned when a checking a data file finds errors.
+ ErrCorrupt = errors.New("invalid value")
+
+ // ErrNonDivisibleBatchSize is returned when the batch size can't be evenly
+ // divided by the iteration count.
+ ErrNonDivisibleBatchSize = errors.New("number of iterations must be divisible by the batch size")
+
+ // ErrPageIDRequired is returned when a required page id is not specified.
+ ErrPageIDRequired = errors.New("page id required")
+
+ // ErrPageNotFound is returned when specifying a page above the high water mark.
+ ErrPageNotFound = errors.New("page not found")
+
+ // ErrPageFreed is returned when reading a page that has already been freed.
+ ErrPageFreed = errors.New("page freed")
+)
+
+// PageHeaderSize represents the size of the bolt.page header.
+const PageHeaderSize = 16
+
+func main() {
+ m := NewMain()
+ if err := m.Run(os.Args[1:]...); err == ErrUsage {
+ os.Exit(2)
+ } else if err != nil {
+ fmt.Println(err.Error())
+ os.Exit(1)
+ }
+}
+
+// Main represents the main program execution.
+type Main struct {
+ Stdin io.Reader
+ Stdout io.Writer
+ Stderr io.Writer
+}
+
+// NewMain returns a new instance of Main connect to the standard input/output.
+func NewMain() *Main {
+ return &Main{
+ Stdin: os.Stdin,
+ Stdout: os.Stdout,
+ Stderr: os.Stderr,
+ }
+}
+
+// Run executes the program.
+func (m *Main) Run(args ...string) error {
+ // Require a command at the beginning.
+ if len(args) == 0 || strings.HasPrefix(args[0], "-") {
+ fmt.Fprintln(m.Stderr, m.Usage())
+ return ErrUsage
+ }
+
+ // Execute command.
+ switch args[0] {
+ case "help":
+ fmt.Fprintln(m.Stderr, m.Usage())
+ return ErrUsage
+ case "bench":
+ return newBenchCommand(m).Run(args[1:]...)
+ case "check":
+ return newCheckCommand(m).Run(args[1:]...)
+ case "compact":
+ return newCompactCommand(m).Run(args[1:]...)
+ case "dump":
+ return newDumpCommand(m).Run(args[1:]...)
+ case "info":
+ return newInfoCommand(m).Run(args[1:]...)
+ case "page":
+ return newPageCommand(m).Run(args[1:]...)
+ case "pages":
+ return newPagesCommand(m).Run(args[1:]...)
+ case "stats":
+ return newStatsCommand(m).Run(args[1:]...)
+ default:
+ return ErrUnknownCommand
+ }
+}
+
+// Usage returns the help message.
+func (m *Main) Usage() string {
+ return strings.TrimLeft(`
+Bolt is a tool for inspecting bolt databases.
+
+Usage:
+
+ bolt command [arguments]
+
+The commands are:
+
+ bench run synthetic benchmark against bolt
+ check verifies integrity of bolt database
+ compact copies a bolt database, compacting it in the process
+ info print basic info
+ help print this screen
+ pages print list of pages with their types
+ stats iterate over all pages and generate usage stats
+
+Use "bolt [command] -h" for more information about a command.
+`, "\n")
+}
+
+// CheckCommand represents the "check" command execution.
+type CheckCommand struct {
+ Stdin io.Reader
+ Stdout io.Writer
+ Stderr io.Writer
+}
+
+// NewCheckCommand returns a CheckCommand.
+func newCheckCommand(m *Main) *CheckCommand {
+ return &CheckCommand{
+ Stdin: m.Stdin,
+ Stdout: m.Stdout,
+ Stderr: m.Stderr,
+ }
+}
+
+// Run executes the command.
+func (cmd *CheckCommand) Run(args ...string) error {
+ // Parse flags.
+ fs := flag.NewFlagSet("", flag.ContinueOnError)
+ help := fs.Bool("h", false, "")
+ if err := fs.Parse(args); err != nil {
+ return err
+ } else if *help {
+ fmt.Fprintln(cmd.Stderr, cmd.Usage())
+ return ErrUsage
+ }
+
+ // Require database path.
+ path := fs.Arg(0)
+ if path == "" {
+ return ErrPathRequired
+ } else if _, err := os.Stat(path); os.IsNotExist(err) {
+ return ErrFileNotFound
+ }
+
+ // Open database.
+ db, err := bolt.Open(path, 0666, nil)
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ // Perform consistency check.
+ return db.View(func(tx *bolt.Tx) error {
+ var count int
+ ch := tx.Check()
+ loop:
+ for {
+ select {
+ case err, ok := <-ch:
+ if !ok {
+ break loop
+ }
+ fmt.Fprintln(cmd.Stdout, err)
+ count++
+ }
+ }
+
+ // Print summary of errors.
+ if count > 0 {
+ fmt.Fprintf(cmd.Stdout, "%d errors found\n", count)
+ return ErrCorrupt
+ }
+
+ // Notify user that database is valid.
+ fmt.Fprintln(cmd.Stdout, "OK")
+ return nil
+ })
+}
+
+// Usage returns the help message.
+func (cmd *CheckCommand) Usage() string {
+ return strings.TrimLeft(`
+usage: bolt check PATH
+
+Check opens a database at PATH and runs an exhaustive check to verify that
+all pages are accessible or are marked as freed. It also verifies that no
+pages are double referenced.
+
+Verification errors will stream out as they are found and the process will
+return after all pages have been checked.
+`, "\n")
+}
+
+// InfoCommand represents the "info" command execution.
+type InfoCommand struct {
+ Stdin io.Reader
+ Stdout io.Writer
+ Stderr io.Writer
+}
+
+// NewInfoCommand returns a InfoCommand.
+func newInfoCommand(m *Main) *InfoCommand {
+ return &InfoCommand{
+ Stdin: m.Stdin,
+ Stdout: m.Stdout,
+ Stderr: m.Stderr,
+ }
+}
+
+// Run executes the command.
+func (cmd *InfoCommand) Run(args ...string) error {
+ // Parse flags.
+ fs := flag.NewFlagSet("", flag.ContinueOnError)
+ help := fs.Bool("h", false, "")
+ if err := fs.Parse(args); err != nil {
+ return err
+ } else if *help {
+ fmt.Fprintln(cmd.Stderr, cmd.Usage())
+ return ErrUsage
+ }
+
+ // Require database path.
+ path := fs.Arg(0)
+ if path == "" {
+ return ErrPathRequired
+ } else if _, err := os.Stat(path); os.IsNotExist(err) {
+ return ErrFileNotFound
+ }
+
+ // Open the database.
+ db, err := bolt.Open(path, 0666, nil)
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ // Print basic database info.
+ info := db.Info()
+ fmt.Fprintf(cmd.Stdout, "Page Size: %d\n", info.PageSize)
+
+ return nil
+}
+
+// Usage returns the help message.
+func (cmd *InfoCommand) Usage() string {
+ return strings.TrimLeft(`
+usage: bolt info PATH
+
+Info prints basic information about the Bolt database at PATH.
+`, "\n")
+}
+
+// DumpCommand represents the "dump" command execution.
+type DumpCommand struct {
+ Stdin io.Reader
+ Stdout io.Writer
+ Stderr io.Writer
+}
+
+// newDumpCommand returns a DumpCommand.
+func newDumpCommand(m *Main) *DumpCommand {
+ return &DumpCommand{
+ Stdin: m.Stdin,
+ Stdout: m.Stdout,
+ Stderr: m.Stderr,
+ }
+}
+
+// Run executes the command.
+func (cmd *DumpCommand) Run(args ...string) error {
+ // Parse flags.
+ fs := flag.NewFlagSet("", flag.ContinueOnError)
+ help := fs.Bool("h", false, "")
+ if err := fs.Parse(args); err != nil {
+ return err
+ } else if *help {
+ fmt.Fprintln(cmd.Stderr, cmd.Usage())
+ return ErrUsage
+ }
+
+ // Require database path and page id.
+ path := fs.Arg(0)
+ if path == "" {
+ return ErrPathRequired
+ } else if _, err := os.Stat(path); os.IsNotExist(err) {
+ return ErrFileNotFound
+ }
+
+ // Read page ids.
+ pageIDs, err := atois(fs.Args()[1:])
+ if err != nil {
+ return err
+ } else if len(pageIDs) == 0 {
+ return ErrPageIDRequired
+ }
+
+ // Open database to retrieve page size.
+ pageSize, err := ReadPageSize(path)
+ if err != nil {
+ return err
+ }
+
+ // Open database file handler.
+ f, err := os.Open(path)
+ if err != nil {
+ return err
+ }
+ defer func() { _ = f.Close() }()
+
+ // Print each page listed.
+ for i, pageID := range pageIDs {
+ // Print a separator.
+ if i > 0 {
+ fmt.Fprintln(cmd.Stdout, "===============================================")
+ }
+
+ // Print page to stdout.
+ if err := cmd.PrintPage(cmd.Stdout, f, pageID, pageSize); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// PrintPage prints a given page as hexidecimal.
+func (cmd *DumpCommand) PrintPage(w io.Writer, r io.ReaderAt, pageID int, pageSize int) error {
+ const bytesPerLineN = 16
+
+ // Read page into buffer.
+ buf := make([]byte, pageSize)
+ addr := pageID * pageSize
+ if n, err := r.ReadAt(buf, int64(addr)); err != nil {
+ return err
+ } else if n != pageSize {
+ return io.ErrUnexpectedEOF
+ }
+
+ // Write out to writer in 16-byte lines.
+ var prev []byte
+ var skipped bool
+ for offset := 0; offset < pageSize; offset += bytesPerLineN {
+ // Retrieve current 16-byte line.
+ line := buf[offset : offset+bytesPerLineN]
+ isLastLine := (offset == (pageSize - bytesPerLineN))
+
+ // If it's the same as the previous line then print a skip.
+ if bytes.Equal(line, prev) && !isLastLine {
+ if !skipped {
+ fmt.Fprintf(w, "%07x *\n", addr+offset)
+ skipped = true
+ }
+ } else {
+ // Print line as hexadecimal in 2-byte groups.
+ fmt.Fprintf(w, "%07x %04x %04x %04x %04x %04x %04x %04x %04x\n", addr+offset,
+ line[0:2], line[2:4], line[4:6], line[6:8],
+ line[8:10], line[10:12], line[12:14], line[14:16],
+ )
+
+ skipped = false
+ }
+
+ // Save the previous line.
+ prev = line
+ }
+ fmt.Fprint(w, "\n")
+
+ return nil
+}
+
+// Usage returns the help message.
+func (cmd *DumpCommand) Usage() string {
+ return strings.TrimLeft(`
+usage: bolt dump -page PAGEID PATH
+
+Dump prints a hexidecimal dump of a single page.
+`, "\n")
+}
+
+// PageCommand represents the "page" command execution.
+type PageCommand struct {
+ Stdin io.Reader
+ Stdout io.Writer
+ Stderr io.Writer
+}
+
+// newPageCommand returns a PageCommand.
+func newPageCommand(m *Main) *PageCommand {
+ return &PageCommand{
+ Stdin: m.Stdin,
+ Stdout: m.Stdout,
+ Stderr: m.Stderr,
+ }
+}
+
+// Run executes the command.
+func (cmd *PageCommand) Run(args ...string) error {
+ // Parse flags.
+ fs := flag.NewFlagSet("", flag.ContinueOnError)
+ help := fs.Bool("h", false, "")
+ if err := fs.Parse(args); err != nil {
+ return err
+ } else if *help {
+ fmt.Fprintln(cmd.Stderr, cmd.Usage())
+ return ErrUsage
+ }
+
+ // Require database path and page id.
+ path := fs.Arg(0)
+ if path == "" {
+ return ErrPathRequired
+ } else if _, err := os.Stat(path); os.IsNotExist(err) {
+ return ErrFileNotFound
+ }
+
+ // Read page ids.
+ pageIDs, err := atois(fs.Args()[1:])
+ if err != nil {
+ return err
+ } else if len(pageIDs) == 0 {
+ return ErrPageIDRequired
+ }
+
+ // Open database file handler.
+ f, err := os.Open(path)
+ if err != nil {
+ return err
+ }
+ defer func() { _ = f.Close() }()
+
+ // Print each page listed.
+ for i, pageID := range pageIDs {
+ // Print a separator.
+ if i > 0 {
+ fmt.Fprintln(cmd.Stdout, "===============================================")
+ }
+
+ // Retrieve page info and page size.
+ p, buf, err := ReadPage(path, pageID)
+ if err != nil {
+ return err
+ }
+
+ // Print basic page info.
+ fmt.Fprintf(cmd.Stdout, "Page ID: %d\n", p.id)
+ fmt.Fprintf(cmd.Stdout, "Page Type: %s\n", p.Type())
+ fmt.Fprintf(cmd.Stdout, "Total Size: %d bytes\n", len(buf))
+
+ // Print type-specific data.
+ switch p.Type() {
+ case "meta":
+ err = cmd.PrintMeta(cmd.Stdout, buf)
+ case "leaf":
+ err = cmd.PrintLeaf(cmd.Stdout, buf)
+ case "branch":
+ err = cmd.PrintBranch(cmd.Stdout, buf)
+ case "freelist":
+ err = cmd.PrintFreelist(cmd.Stdout, buf)
+ }
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// PrintMeta prints the data from the meta page.
+func (cmd *PageCommand) PrintMeta(w io.Writer, buf []byte) error {
+ m := (*meta)(unsafe.Pointer(&buf[PageHeaderSize]))
+ fmt.Fprintf(w, "Version: %d\n", m.version)
+ fmt.Fprintf(w, "Page Size: %d bytes\n", m.pageSize)
+ fmt.Fprintf(w, "Flags: %08x\n", m.flags)
+ fmt.Fprintf(w, "Root: <pgid=%d>\n", m.root.root)
+ fmt.Fprintf(w, "Freelist: <pgid=%d>\n", m.freelist)
+ fmt.Fprintf(w, "HWM: <pgid=%d>\n", m.pgid)
+ fmt.Fprintf(w, "Txn ID: %d\n", m.txid)
+ fmt.Fprintf(w, "Checksum: %016x\n", m.checksum)
+ fmt.Fprintf(w, "\n")
+ return nil
+}
+
+// PrintLeaf prints the data for a leaf page.
+func (cmd *PageCommand) PrintLeaf(w io.Writer, buf []byte) error {
+ p := (*page)(unsafe.Pointer(&buf[0]))
+
+ // Print number of items.
+ fmt.Fprintf(w, "Item Count: %d\n", p.count)
+ fmt.Fprintf(w, "\n")
+
+ // Print each key/value.
+ for i := uint16(0); i < p.count; i++ {
+ e := p.leafPageElement(i)
+
+ // Format key as string.
+ var k string
+ if isPrintable(string(e.key())) {
+ k = fmt.Sprintf("%q", string(e.key()))
+ } else {
+ k = fmt.Sprintf("%x", string(e.key()))
+ }
+
+ // Format value as string.
+ var v string
+ if (e.flags & uint32(bucketLeafFlag)) != 0 {
+ b := (*bucket)(unsafe.Pointer(&e.value()[0]))
+ v = fmt.Sprintf("<pgid=%d,seq=%d>", b.root, b.sequence)
+ } else if isPrintable(string(e.value())) {
+ v = fmt.Sprintf("%q", string(e.value()))
+ } else {
+ v = fmt.Sprintf("%x", string(e.value()))
+ }
+
+ fmt.Fprintf(w, "%s: %s\n", k, v)
+ }
+ fmt.Fprintf(w, "\n")
+ return nil
+}
+
+// PrintBranch prints the data for a leaf page.
+func (cmd *PageCommand) PrintBranch(w io.Writer, buf []byte) error {
+ p := (*page)(unsafe.Pointer(&buf[0]))
+
+ // Print number of items.
+ fmt.Fprintf(w, "Item Count: %d\n", p.count)
+ fmt.Fprintf(w, "\n")
+
+ // Print each key/value.
+ for i := uint16(0); i < p.count; i++ {
+ e := p.branchPageElement(i)
+
+ // Format key as string.
+ var k string
+ if isPrintable(string(e.key())) {
+ k = fmt.Sprintf("%q", string(e.key()))
+ } else {
+ k = fmt.Sprintf("%x", string(e.key()))
+ }
+
+ fmt.Fprintf(w, "%s: <pgid=%d>\n", k, e.pgid)
+ }
+ fmt.Fprintf(w, "\n")
+ return nil
+}
+
+// PrintFreelist prints the data for a freelist page.
+func (cmd *PageCommand) PrintFreelist(w io.Writer, buf []byte) error {
+ p := (*page)(unsafe.Pointer(&buf[0]))
+
+ // Print number of items.
+ fmt.Fprintf(w, "Item Count: %d\n", p.count)
+ fmt.Fprintf(w, "\n")
+
+ // Print each page in the freelist.
+ ids := (*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr))
+ for i := uint16(0); i < p.count; i++ {
+ fmt.Fprintf(w, "%d\n", ids[i])
+ }
+ fmt.Fprintf(w, "\n")
+ return nil
+}
+
+// PrintPage prints a given page as hexidecimal.
+func (cmd *PageCommand) PrintPage(w io.Writer, r io.ReaderAt, pageID int, pageSize int) error {
+ const bytesPerLineN = 16
+
+ // Read page into buffer.
+ buf := make([]byte, pageSize)
+ addr := pageID * pageSize
+ if n, err := r.ReadAt(buf, int64(addr)); err != nil {
+ return err
+ } else if n != pageSize {
+ return io.ErrUnexpectedEOF
+ }
+
+ // Write out to writer in 16-byte lines.
+ var prev []byte
+ var skipped bool
+ for offset := 0; offset < pageSize; offset += bytesPerLineN {
+ // Retrieve current 16-byte line.
+ line := buf[offset : offset+bytesPerLineN]
+ isLastLine := (offset == (pageSize - bytesPerLineN))
+
+ // If it's the same as the previous line then print a skip.
+ if bytes.Equal(line, prev) && !isLastLine {
+ if !skipped {
+ fmt.Fprintf(w, "%07x *\n", addr+offset)
+ skipped = true
+ }
+ } else {
+ // Print line as hexadecimal in 2-byte groups.
+ fmt.Fprintf(w, "%07x %04x %04x %04x %04x %04x %04x %04x %04x\n", addr+offset,
+ line[0:2], line[2:4], line[4:6], line[6:8],
+ line[8:10], line[10:12], line[12:14], line[14:16],
+ )
+
+ skipped = false
+ }
+
+ // Save the previous line.
+ prev = line
+ }
+ fmt.Fprint(w, "\n")
+
+ return nil
+}
+
+// Usage returns the help message.
+func (cmd *PageCommand) Usage() string {
+ return strings.TrimLeft(`
+usage: bolt page -page PATH pageid [pageid...]
+
+Page prints one or more pages in human readable format.
+`, "\n")
+}
+
+// PagesCommand represents the "pages" command execution.
+type PagesCommand struct {
+ Stdin io.Reader
+ Stdout io.Writer
+ Stderr io.Writer
+}
+
+// NewPagesCommand returns a PagesCommand.
+func newPagesCommand(m *Main) *PagesCommand {
+ return &PagesCommand{
+ Stdin: m.Stdin,
+ Stdout: m.Stdout,
+ Stderr: m.Stderr,
+ }
+}
+
+// Run executes the command.
+func (cmd *PagesCommand) Run(args ...string) error {
+ // Parse flags.
+ fs := flag.NewFlagSet("", flag.ContinueOnError)
+ help := fs.Bool("h", false, "")
+ if err := fs.Parse(args); err != nil {
+ return err
+ } else if *help {
+ fmt.Fprintln(cmd.Stderr, cmd.Usage())
+ return ErrUsage
+ }
+
+ // Require database path.
+ path := fs.Arg(0)
+ if path == "" {
+ return ErrPathRequired
+ } else if _, err := os.Stat(path); os.IsNotExist(err) {
+ return ErrFileNotFound
+ }
+
+ // Open database.
+ db, err := bolt.Open(path, 0666, nil)
+ if err != nil {
+ return err
+ }
+ defer func() { _ = db.Close() }()
+
+ // Write header.
+ fmt.Fprintln(cmd.Stdout, "ID TYPE ITEMS OVRFLW")
+ fmt.Fprintln(cmd.Stdout, "======== ========== ====== ======")
+
+ return db.Update(func(tx *bolt.Tx) error {
+ var id int
+ for {
+ p, err := tx.Page(id)
+ if err != nil {
+ return &PageError{ID: id, Err: err}
+ } else if p == nil {
+ break
+ }
+
+ // Only display count and overflow if this is a non-free page.
+ var count, overflow string
+ if p.Type != "free" {
+ count = strconv.Itoa(p.Count)
+ if p.OverflowCount > 0 {
+ overflow = strconv.Itoa(p.OverflowCount)
+ }
+ }
+
+ // Print table row.
+ fmt.Fprintf(cmd.Stdout, "%-8d %-10s %-6s %-6s\n", p.ID, p.Type, count, overflow)
+
+ // Move to the next non-overflow page.
+ id += 1
+ if p.Type != "free" {
+ id += p.OverflowCount
+ }
+ }
+ return nil
+ })
+}
+
+// Usage returns the help message.
+func (cmd *PagesCommand) Usage() string {
+ return strings.TrimLeft(`
+usage: bolt pages PATH
+
+Pages prints a table of pages with their type (meta, leaf, branch, freelist).
+Leaf and branch pages will show a key count in the "items" column while the
+freelist will show the number of free pages in the "items" column.
+
+The "overflow" column shows the number of blocks that the page spills over
+into. Normally there is no overflow but large keys and values can cause
+a single page to take up multiple blocks.
+`, "\n")
+}
+
+// StatsCommand represents the "stats" command execution.
+type StatsCommand struct {
+ Stdin io.Reader
+ Stdout io.Writer
+ Stderr io.Writer
+}
+
+// NewStatsCommand returns a StatsCommand.
+func newStatsCommand(m *Main) *StatsCommand {
+ return &StatsCommand{
+ Stdin: m.Stdin,
+ Stdout: m.Stdout,
+ Stderr: m.Stderr,
+ }
+}
+
+// Run executes the command.
+func (cmd *StatsCommand) Run(args ...string) error {
+ // Parse flags.
+ fs := flag.NewFlagSet("", flag.ContinueOnError)
+ help := fs.Bool("h", false, "")
+ if err := fs.Parse(args); err != nil {
+ return err
+ } else if *help {
+ fmt.Fprintln(cmd.Stderr, cmd.Usage())
+ return ErrUsage
+ }
+
+ // Require database path.
+ path, prefix := fs.Arg(0), fs.Arg(1)
+ if path == "" {
+ return ErrPathRequired
+ } else if _, err := os.Stat(path); os.IsNotExist(err) {
+ return ErrFileNotFound
+ }
+
+ // Open database.
+ db, err := bolt.Open(path, 0666, nil)
+ if err != nil {
+ return err
+ }
+ defer db.Close()
+
+ return db.View(func(tx *bolt.Tx) error {
+ var s bolt.BucketStats
+ var count int
+ if err := tx.ForEach(func(name []byte, b *bolt.Bucket) error {
+ if bytes.HasPrefix(name, []byte(prefix)) {
+ s.Add(b.Stats())
+ count += 1
+ }
+ return nil
+ }); err != nil {
+ return err
+ }
+
+ fmt.Fprintf(cmd.Stdout, "Aggregate statistics for %d buckets\n\n", count)
+
+ fmt.Fprintln(cmd.Stdout, "Page count statistics")
+ fmt.Fprintf(cmd.Stdout, "\tNumber of logical branch pages: %d\n", s.BranchPageN)
+ fmt.Fprintf(cmd.Stdout, "\tNumber of physical branch overflow pages: %d\n", s.BranchOverflowN)
+ fmt.Fprintf(cmd.Stdout, "\tNumber of logical leaf pages: %d\n", s.LeafPageN)
+ fmt.Fprintf(cmd.Stdout, "\tNumber of physical leaf overflow pages: %d\n", s.LeafOverflowN)
+
+ fmt.Fprintln(cmd.Stdout, "Tree statistics")
+ fmt.Fprintf(cmd.Stdout, "\tNumber of keys/value pairs: %d\n", s.KeyN)
+ fmt.Fprintf(cmd.Stdout, "\tNumber of levels in B+tree: %d\n", s.Depth)
+
+ fmt.Fprintln(cmd.Stdout, "Page size utilization")
+ fmt.Fprintf(cmd.Stdout, "\tBytes allocated for physical branch pages: %d\n", s.BranchAlloc)
+ var percentage int
+ if s.BranchAlloc != 0 {
+ percentage = int(float32(s.BranchInuse) * 100.0 / float32(s.BranchAlloc))
+ }
+ fmt.Fprintf(cmd.Stdout, "\tBytes actually used for branch data: %d (%d%%)\n", s.BranchInuse, percentage)
+ fmt.Fprintf(cmd.Stdout, "\tBytes allocated for physical leaf pages: %d\n", s.LeafAlloc)
+ percentage = 0
+ if s.LeafAlloc != 0 {
+ percentage = int(float32(s.LeafInuse) * 100.0 / float32(s.LeafAlloc))
+ }
+ fmt.Fprintf(cmd.Stdout, "\tBytes actually used for leaf data: %d (%d%%)\n", s.LeafInuse, percentage)
+
+ fmt.Fprintln(cmd.Stdout, "Bucket statistics")
+ fmt.Fprintf(cmd.Stdout, "\tTotal number of buckets: %d\n", s.BucketN)
+ percentage = 0
+ if s.BucketN != 0 {
+ percentage = int(float32(s.InlineBucketN) * 100.0 / float32(s.BucketN))
+ }
+ fmt.Fprintf(cmd.Stdout, "\tTotal number on inlined buckets: %d (%d%%)\n", s.InlineBucketN, percentage)
+ percentage = 0
+ if s.LeafInuse != 0 {
+ percentage = int(float32(s.InlineBucketInuse) * 100.0 / float32(s.LeafInuse))
+ }
+ fmt.Fprintf(cmd.Stdout, "\tBytes used for inlined buckets: %d (%d%%)\n", s.InlineBucketInuse, percentage)
+
+ return nil
+ })
+}
+
+// Usage returns the help message.
+func (cmd *StatsCommand) Usage() string {
+ return strings.TrimLeft(`
+usage: bolt stats PATH
+
+Stats performs an extensive search of the database to track every page
+reference. It starts at the current meta page and recursively iterates
+through every accessible bucket.
+
+The following errors can be reported:
+
+ already freed
+ The page is referenced more than once in the freelist.
+
+ unreachable unfreed
+ The page is not referenced by a bucket or in the freelist.
+
+ reachable freed
+ The page is referenced by a bucket but is also in the freelist.
+
+ out of bounds
+ A page is referenced that is above the high water mark.
+
+ multiple references
+ A page is referenced by more than one other page.
+
+ invalid type
+ The page type is not "meta", "leaf", "branch", or "freelist".
+
+No errors should occur in your database. However, if for some reason you
+experience corruption, please submit a ticket to the Bolt project page:
+
+ https://github.com/boltdb/bolt/issues
+`, "\n")
+}
+
+var benchBucketName = []byte("bench")
+
+// BenchCommand represents the "bench" command execution.
+type BenchCommand struct {
+ Stdin io.Reader
+ Stdout io.Writer
+ Stderr io.Writer
+}
+
+// NewBenchCommand returns a BenchCommand using the
+func newBenchCommand(m *Main) *BenchCommand {
+ return &BenchCommand{
+ Stdin: m.Stdin,
+ Stdout: m.Stdout,
+ Stderr: m.Stderr,
+ }
+}
+
+// Run executes the "bench" command.
+func (cmd *BenchCommand) Run(args ...string) error {
+ // Parse CLI arguments.
+ options, err := cmd.ParseFlags(args)
+ if err != nil {
+ return err
+ }
+
+ // Remove path if "-work" is not set. Otherwise keep path.
+ if options.Work {
+ fmt.Fprintf(cmd.Stdout, "work: %s\n", options.Path)
+ } else {
+ defer os.Remove(options.Path)
+ }
+
+ // Create database.
+ db, err := bolt.Open(options.Path, 0666, nil)
+ if err != nil {
+ return err
+ }
+ db.NoSync = options.NoSync
+ defer db.Close()
+
+ // Write to the database.
+ var results BenchResults
+ if err := cmd.runWrites(db, options, &results); err != nil {
+ return fmt.Errorf("write: %v", err)
+ }
+
+ // Read from the database.
+ if err := cmd.runReads(db, options, &results); err != nil {
+ return fmt.Errorf("bench: read: %s", err)
+ }
+
+ // Print results.
+ fmt.Fprintf(os.Stderr, "# Write\t%v\t(%v/op)\t(%v op/sec)\n", results.WriteDuration, results.WriteOpDuration(), results.WriteOpsPerSecond())
+ fmt.Fprintf(os.Stderr, "# Read\t%v\t(%v/op)\t(%v op/sec)\n", results.ReadDuration, results.ReadOpDuration(), results.ReadOpsPerSecond())
+ fmt.Fprintln(os.Stderr, "")
+ return nil
+}
+
+// ParseFlags parses the command line flags.
+func (cmd *BenchCommand) ParseFlags(args []string) (*BenchOptions, error) {
+ var options BenchOptions
+
+ // Parse flagset.
+ fs := flag.NewFlagSet("", flag.ContinueOnError)
+ fs.StringVar(&options.ProfileMode, "profile-mode", "rw", "")
+ fs.StringVar(&options.WriteMode, "write-mode", "seq", "")
+ fs.StringVar(&options.ReadMode, "read-mode", "seq", "")
+ fs.IntVar(&options.Iterations, "count", 1000, "")
+ fs.IntVar(&options.BatchSize, "batch-size", 0, "")
+ fs.IntVar(&options.KeySize, "key-size", 8, "")
+ fs.IntVar(&options.ValueSize, "value-size", 32, "")
+ fs.StringVar(&options.CPUProfile, "cpuprofile", "", "")
+ fs.StringVar(&options.MemProfile, "memprofile", "", "")
+ fs.StringVar(&options.BlockProfile, "blockprofile", "", "")
+ fs.Float64Var(&options.FillPercent, "fill-percent", bolt.DefaultFillPercent, "")
+ fs.BoolVar(&options.NoSync, "no-sync", false, "")
+ fs.BoolVar(&options.Work, "work", false, "")
+ fs.StringVar(&options.Path, "path", "", "")
+ fs.SetOutput(cmd.Stderr)
+ if err := fs.Parse(args); err != nil {
+ return nil, err
+ }
+
+ // Set batch size to iteration size if not set.
+ // Require that batch size can be evenly divided by the iteration count.
+ if options.BatchSize == 0 {
+ options.BatchSize = options.Iterations
+ } else if options.Iterations%options.BatchSize != 0 {
+ return nil, ErrNonDivisibleBatchSize
+ }
+
+ // Generate temp path if one is not passed in.
+ if options.Path == "" {
+ f, err := ioutil.TempFile("", "bolt-bench-")
+ if err != nil {
+ return nil, fmt.Errorf("temp file: %s", err)
+ }
+ f.Close()
+ os.Remove(f.Name())
+ options.Path = f.Name()
+ }
+
+ return &options, nil
+}
+
+// Writes to the database.
+func (cmd *BenchCommand) runWrites(db *bolt.DB, options *BenchOptions, results *BenchResults) error {
+ // Start profiling for writes.
+ if options.ProfileMode == "rw" || options.ProfileMode == "w" {
+ cmd.startProfiling(options)
+ }
+
+ t := time.Now()
+
+ var err error
+ switch options.WriteMode {
+ case "seq":
+ err = cmd.runWritesSequential(db, options, results)
+ case "rnd":
+ err = cmd.runWritesRandom(db, options, results)
+ case "seq-nest":
+ err = cmd.runWritesSequentialNested(db, options, results)
+ case "rnd-nest":
+ err = cmd.runWritesRandomNested(db, options, results)
+ default:
+ return fmt.Errorf("invalid write mode: %s", options.WriteMode)
+ }
+
+ // Save time to write.
+ results.WriteDuration = time.Since(t)
+
+ // Stop profiling for writes only.
+ if options.ProfileMode == "w" {
+ cmd.stopProfiling()
+ }
+
+ return err
+}
+
+func (cmd *BenchCommand) runWritesSequential(db *bolt.DB, options *BenchOptions, results *BenchResults) error {
+ var i = uint32(0)
+ return cmd.runWritesWithSource(db, options, results, func() uint32 { i++; return i })
+}
+
+func (cmd *BenchCommand) runWritesRandom(db *bolt.DB, options *BenchOptions, results *BenchResults) error {
+ r := rand.New(rand.NewSource(time.Now().UnixNano()))
+ return cmd.runWritesWithSource(db, options, results, func() uint32 { return r.Uint32() })
+}
+
+func (cmd *BenchCommand) runWritesSequentialNested(db *bolt.DB, options *BenchOptions, results *BenchResults) error {
+ var i = uint32(0)
+ return cmd.runWritesWithSource(db, options, results, func() uint32 { i++; return i })
+}
+
+func (cmd *BenchCommand) runWritesRandomNested(db *bolt.DB, options *BenchOptions, results *BenchResults) error {
+ r := rand.New(rand.NewSource(time.Now().UnixNano()))
+ return cmd.runWritesWithSource(db, options, results, func() uint32 { return r.Uint32() })
+}
+
+func (cmd *BenchCommand) runWritesWithSource(db *bolt.DB, options *BenchOptions, results *BenchResults, keySource func() uint32) error {
+ results.WriteOps = options.Iterations
+
+ for i := 0; i < options.Iterations; i += options.BatchSize {
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, _ := tx.CreateBucketIfNotExists(benchBucketName)
+ b.FillPercent = options.FillPercent
+
+ for j := 0; j < options.BatchSize; j++ {
+ key := make([]byte, options.KeySize)
+ value := make([]byte, options.ValueSize)
+
+ // Write key as uint32.
+ binary.BigEndian.PutUint32(key, keySource())
+
+ // Insert key/value.
+ if err := b.Put(key, value); err != nil {
+ return err
+ }
+ }
+
+ return nil
+ }); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (cmd *BenchCommand) runWritesNestedWithSource(db *bolt.DB, options *BenchOptions, results *BenchResults, keySource func() uint32) error {
+ results.WriteOps = options.Iterations
+
+ for i := 0; i < options.Iterations; i += options.BatchSize {
+ if err := db.Update(func(tx *bolt.Tx) error {
+ top, err := tx.CreateBucketIfNotExists(benchBucketName)
+ if err != nil {
+ return err
+ }
+ top.FillPercent = options.FillPercent
+
+ // Create bucket key.
+ name := make([]byte, options.KeySize)
+ binary.BigEndian.PutUint32(name, keySource())
+
+ // Create bucket.
+ b, err := top.CreateBucketIfNotExists(name)
+ if err != nil {
+ return err
+ }
+ b.FillPercent = options.FillPercent
+
+ for j := 0; j < options.BatchSize; j++ {
+ var key = make([]byte, options.KeySize)
+ var value = make([]byte, options.ValueSize)
+
+ // Generate key as uint32.
+ binary.BigEndian.PutUint32(key, keySource())
+
+ // Insert value into subbucket.
+ if err := b.Put(key, value); err != nil {
+ return err
+ }
+ }
+
+ return nil
+ }); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// Reads from the database.
+func (cmd *BenchCommand) runReads(db *bolt.DB, options *BenchOptions, results *BenchResults) error {
+ // Start profiling for reads.
+ if options.ProfileMode == "r" {
+ cmd.startProfiling(options)
+ }
+
+ t := time.Now()
+
+ var err error
+ switch options.ReadMode {
+ case "seq":
+ switch options.WriteMode {
+ case "seq-nest", "rnd-nest":
+ err = cmd.runReadsSequentialNested(db, options, results)
+ default:
+ err = cmd.runReadsSequential(db, options, results)
+ }
+ default:
+ return fmt.Errorf("invalid read mode: %s", options.ReadMode)
+ }
+
+ // Save read time.
+ results.ReadDuration = time.Since(t)
+
+ // Stop profiling for reads.
+ if options.ProfileMode == "rw" || options.ProfileMode == "r" {
+ cmd.stopProfiling()
+ }
+
+ return err
+}
+
+func (cmd *BenchCommand) runReadsSequential(db *bolt.DB, options *BenchOptions, results *BenchResults) error {
+ return db.View(func(tx *bolt.Tx) error {
+ t := time.Now()
+
+ for {
+ var count int
+
+ c := tx.Bucket(benchBucketName).Cursor()
+ for k, v := c.First(); k != nil; k, v = c.Next() {
+ if v == nil {
+ return errors.New("invalid value")
+ }
+ count++
+ }
+
+ if options.WriteMode == "seq" && count != options.Iterations {
+ return fmt.Errorf("read seq: iter mismatch: expected %d, got %d", options.Iterations, count)
+ }
+
+ results.ReadOps += count
+
+ // Make sure we do this for at least a second.
+ if time.Since(t) >= time.Second {
+ break
+ }
+ }
+
+ return nil
+ })
+}
+
+func (cmd *BenchCommand) runReadsSequentialNested(db *bolt.DB, options *BenchOptions, results *BenchResults) error {
+ return db.View(func(tx *bolt.Tx) error {
+ t := time.Now()
+
+ for {
+ var count int
+ var top = tx.Bucket(benchBucketName)
+ if err := top.ForEach(func(name, _ []byte) error {
+ c := top.Bucket(name).Cursor()
+ for k, v := c.First(); k != nil; k, v = c.Next() {
+ if v == nil {
+ return ErrInvalidValue
+ }
+ count++
+ }
+ return nil
+ }); err != nil {
+ return err
+ }
+
+ if options.WriteMode == "seq-nest" && count != options.Iterations {
+ return fmt.Errorf("read seq-nest: iter mismatch: expected %d, got %d", options.Iterations, count)
+ }
+
+ results.ReadOps += count
+
+ // Make sure we do this for at least a second.
+ if time.Since(t) >= time.Second {
+ break
+ }
+ }
+
+ return nil
+ })
+}
+
+// File handlers for the various profiles.
+var cpuprofile, memprofile, blockprofile *os.File
+
+// Starts all profiles set on the options.
+func (cmd *BenchCommand) startProfiling(options *BenchOptions) {
+ var err error
+
+ // Start CPU profiling.
+ if options.CPUProfile != "" {
+ cpuprofile, err = os.Create(options.CPUProfile)
+ if err != nil {
+ fmt.Fprintf(cmd.Stderr, "bench: could not create cpu profile %q: %v\n", options.CPUProfile, err)
+ os.Exit(1)
+ }
+ pprof.StartCPUProfile(cpuprofile)
+ }
+
+ // Start memory profiling.
+ if options.MemProfile != "" {
+ memprofile, err = os.Create(options.MemProfile)
+ if err != nil {
+ fmt.Fprintf(cmd.Stderr, "bench: could not create memory profile %q: %v\n", options.MemProfile, err)
+ os.Exit(1)
+ }
+ runtime.MemProfileRate = 4096
+ }
+
+ // Start fatal profiling.
+ if options.BlockProfile != "" {
+ blockprofile, err = os.Create(options.BlockProfile)
+ if err != nil {
+ fmt.Fprintf(cmd.Stderr, "bench: could not create block profile %q: %v\n", options.BlockProfile, err)
+ os.Exit(1)
+ }
+ runtime.SetBlockProfileRate(1)
+ }
+}
+
+// Stops all profiles.
+func (cmd *BenchCommand) stopProfiling() {
+ if cpuprofile != nil {
+ pprof.StopCPUProfile()
+ cpuprofile.Close()
+ cpuprofile = nil
+ }
+
+ if memprofile != nil {
+ pprof.Lookup("heap").WriteTo(memprofile, 0)
+ memprofile.Close()
+ memprofile = nil
+ }
+
+ if blockprofile != nil {
+ pprof.Lookup("block").WriteTo(blockprofile, 0)
+ blockprofile.Close()
+ blockprofile = nil
+ runtime.SetBlockProfileRate(0)
+ }
+}
+
+// BenchOptions represents the set of options that can be passed to "bolt bench".
+type BenchOptions struct {
+ ProfileMode string
+ WriteMode string
+ ReadMode string
+ Iterations int
+ BatchSize int
+ KeySize int
+ ValueSize int
+ CPUProfile string
+ MemProfile string
+ BlockProfile string
+ StatsInterval time.Duration
+ FillPercent float64
+ NoSync bool
+ Work bool
+ Path string
+}
+
+// BenchResults represents the performance results of the benchmark.
+type BenchResults struct {
+ WriteOps int
+ WriteDuration time.Duration
+ ReadOps int
+ ReadDuration time.Duration
+}
+
+// Returns the duration for a single write operation.
+func (r *BenchResults) WriteOpDuration() time.Duration {
+ if r.WriteOps == 0 {
+ return 0
+ }
+ return r.WriteDuration / time.Duration(r.WriteOps)
+}
+
+// Returns average number of write operations that can be performed per second.
+func (r *BenchResults) WriteOpsPerSecond() int {
+ var op = r.WriteOpDuration()
+ if op == 0 {
+ return 0
+ }
+ return int(time.Second) / int(op)
+}
+
+// Returns the duration for a single read operation.
+func (r *BenchResults) ReadOpDuration() time.Duration {
+ if r.ReadOps == 0 {
+ return 0
+ }
+ return r.ReadDuration / time.Duration(r.ReadOps)
+}
+
+// Returns average number of read operations that can be performed per second.
+func (r *BenchResults) ReadOpsPerSecond() int {
+ var op = r.ReadOpDuration()
+ if op == 0 {
+ return 0
+ }
+ return int(time.Second) / int(op)
+}
+
+type PageError struct {
+ ID int
+ Err error
+}
+
+func (e *PageError) Error() string {
+ return fmt.Sprintf("page error: id=%d, err=%s", e.ID, e.Err)
+}
+
+// isPrintable returns true if the string is valid unicode and contains only printable runes.
+func isPrintable(s string) bool {
+ if !utf8.ValidString(s) {
+ return false
+ }
+ for _, ch := range s {
+ if !unicode.IsPrint(ch) {
+ return false
+ }
+ }
+ return true
+}
+
+// ReadPage reads page info & full page data from a path.
+// This is not transactionally safe.
+func ReadPage(path string, pageID int) (*page, []byte, error) {
+ // Find page size.
+ pageSize, err := ReadPageSize(path)
+ if err != nil {
+ return nil, nil, fmt.Errorf("read page size: %s", err)
+ }
+
+ // Open database file.
+ f, err := os.Open(path)
+ if err != nil {
+ return nil, nil, err
+ }
+ defer f.Close()
+
+ // Read one block into buffer.
+ buf := make([]byte, pageSize)
+ if n, err := f.ReadAt(buf, int64(pageID*pageSize)); err != nil {
+ return nil, nil, err
+ } else if n != len(buf) {
+ return nil, nil, io.ErrUnexpectedEOF
+ }
+
+ // Determine total number of blocks.
+ p := (*page)(unsafe.Pointer(&buf[0]))
+ overflowN := p.overflow
+
+ // Re-read entire page (with overflow) into buffer.
+ buf = make([]byte, (int(overflowN)+1)*pageSize)
+ if n, err := f.ReadAt(buf, int64(pageID*pageSize)); err != nil {
+ return nil, nil, err
+ } else if n != len(buf) {
+ return nil, nil, io.ErrUnexpectedEOF
+ }
+ p = (*page)(unsafe.Pointer(&buf[0]))
+
+ return p, buf, nil
+}
+
+// ReadPageSize reads page size a path.
+// This is not transactionally safe.
+func ReadPageSize(path string) (int, error) {
+ // Open database file.
+ f, err := os.Open(path)
+ if err != nil {
+ return 0, err
+ }
+ defer f.Close()
+
+ // Read 4KB chunk.
+ buf := make([]byte, 4096)
+ if _, err := io.ReadFull(f, buf); err != nil {
+ return 0, err
+ }
+
+ // Read page size from metadata.
+ m := (*meta)(unsafe.Pointer(&buf[PageHeaderSize]))
+ return int(m.pageSize), nil
+}
+
+// atois parses a slice of strings into integers.
+func atois(strs []string) ([]int, error) {
+ var a []int
+ for _, str := range strs {
+ i, err := strconv.Atoi(str)
+ if err != nil {
+ return nil, err
+ }
+ a = append(a, i)
+ }
+ return a, nil
+}
+
+// DO NOT EDIT. Copied from the "bolt" package.
+const maxAllocSize = 0xFFFFFFF
+
+// DO NOT EDIT. Copied from the "bolt" package.
+const (
+ branchPageFlag = 0x01
+ leafPageFlag = 0x02
+ metaPageFlag = 0x04
+ freelistPageFlag = 0x10
+)
+
+// DO NOT EDIT. Copied from the "bolt" package.
+const bucketLeafFlag = 0x01
+
+// DO NOT EDIT. Copied from the "bolt" package.
+type pgid uint64
+
+// DO NOT EDIT. Copied from the "bolt" package.
+type txid uint64
+
+// DO NOT EDIT. Copied from the "bolt" package.
+type meta struct {
+ magic uint32
+ version uint32
+ pageSize uint32
+ flags uint32
+ root bucket
+ freelist pgid
+ pgid pgid
+ txid txid
+ checksum uint64
+}
+
+// DO NOT EDIT. Copied from the "bolt" package.
+type bucket struct {
+ root pgid
+ sequence uint64
+}
+
+// DO NOT EDIT. Copied from the "bolt" package.
+type page struct {
+ id pgid
+ flags uint16
+ count uint16
+ overflow uint32
+ ptr uintptr
+}
+
+// DO NOT EDIT. Copied from the "bolt" package.
+func (p *page) Type() string {
+ if (p.flags & branchPageFlag) != 0 {
+ return "branch"
+ } else if (p.flags & leafPageFlag) != 0 {
+ return "leaf"
+ } else if (p.flags & metaPageFlag) != 0 {
+ return "meta"
+ } else if (p.flags & freelistPageFlag) != 0 {
+ return "freelist"
+ }
+ return fmt.Sprintf("unknown<%02x>", p.flags)
+}
+
+// DO NOT EDIT. Copied from the "bolt" package.
+func (p *page) leafPageElement(index uint16) *leafPageElement {
+ n := &((*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr)))[index]
+ return n
+}
+
+// DO NOT EDIT. Copied from the "bolt" package.
+func (p *page) branchPageElement(index uint16) *branchPageElement {
+ return &((*[0x7FFFFFF]branchPageElement)(unsafe.Pointer(&p.ptr)))[index]
+}
+
+// DO NOT EDIT. Copied from the "bolt" package.
+type branchPageElement struct {
+ pos uint32
+ ksize uint32
+ pgid pgid
+}
+
+// DO NOT EDIT. Copied from the "bolt" package.
+func (n *branchPageElement) key() []byte {
+ buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
+ return buf[n.pos : n.pos+n.ksize]
+}
+
+// DO NOT EDIT. Copied from the "bolt" package.
+type leafPageElement struct {
+ flags uint32
+ pos uint32
+ ksize uint32
+ vsize uint32
+}
+
+// DO NOT EDIT. Copied from the "bolt" package.
+func (n *leafPageElement) key() []byte {
+ buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
+ return buf[n.pos : n.pos+n.ksize]
+}
+
+// DO NOT EDIT. Copied from the "bolt" package.
+func (n *leafPageElement) value() []byte {
+ buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
+ return buf[n.pos+n.ksize : n.pos+n.ksize+n.vsize]
+}
+
+// CompactCommand represents the "compact" command execution.
+type CompactCommand struct {
+ Stdin io.Reader
+ Stdout io.Writer
+ Stderr io.Writer
+
+ SrcPath string
+ DstPath string
+ TxMaxSize int64
+}
+
+// newCompactCommand returns a CompactCommand.
+func newCompactCommand(m *Main) *CompactCommand {
+ return &CompactCommand{
+ Stdin: m.Stdin,
+ Stdout: m.Stdout,
+ Stderr: m.Stderr,
+ }
+}
+
+// Run executes the command.
+func (cmd *CompactCommand) Run(args ...string) (err error) {
+ // Parse flags.
+ fs := flag.NewFlagSet("", flag.ContinueOnError)
+ fs.SetOutput(ioutil.Discard)
+ fs.StringVar(&cmd.DstPath, "o", "", "")
+ fs.Int64Var(&cmd.TxMaxSize, "tx-max-size", 65536, "")
+ if err := fs.Parse(args); err == flag.ErrHelp {
+ fmt.Fprintln(cmd.Stderr, cmd.Usage())
+ return ErrUsage
+ } else if err != nil {
+ return err
+ } else if cmd.DstPath == "" {
+ return fmt.Errorf("output file required")
+ }
+
+ // Require database paths.
+ cmd.SrcPath = fs.Arg(0)
+ if cmd.SrcPath == "" {
+ return ErrPathRequired
+ }
+
+ // Ensure source file exists.
+ fi, err := os.Stat(cmd.SrcPath)
+ if os.IsNotExist(err) {
+ return ErrFileNotFound
+ } else if err != nil {
+ return err
+ }
+ initialSize := fi.Size()
+
+ // Open source database.
+ src, err := bolt.Open(cmd.SrcPath, 0444, nil)
+ if err != nil {
+ return err
+ }
+ defer src.Close()
+
+ // Open destination database.
+ dst, err := bolt.Open(cmd.DstPath, fi.Mode(), nil)
+ if err != nil {
+ return err
+ }
+ defer dst.Close()
+
+ // Run compaction.
+ if err := cmd.compact(dst, src); err != nil {
+ return err
+ }
+
+ // Report stats on new size.
+ fi, err = os.Stat(cmd.DstPath)
+ if err != nil {
+ return err
+ } else if fi.Size() == 0 {
+ return fmt.Errorf("zero db size")
+ }
+ fmt.Fprintf(cmd.Stdout, "%d -> %d bytes (gain=%.2fx)\n", initialSize, fi.Size(), float64(initialSize)/float64(fi.Size()))
+
+ return nil
+}
+
+func (cmd *CompactCommand) compact(dst, src *bolt.DB) error {
+ // commit regularly, or we'll run out of memory for large datasets if using one transaction.
+ var size int64
+ tx, err := dst.Begin(true)
+ if err != nil {
+ return err
+ }
+ defer tx.Rollback()
+
+ if err := cmd.walk(src, func(keys [][]byte, k, v []byte, seq uint64) error {
+ // On each key/value, check if we have exceeded tx size.
+ sz := int64(len(k) + len(v))
+ if size+sz > cmd.TxMaxSize && cmd.TxMaxSize != 0 {
+ // Commit previous transaction.
+ if err := tx.Commit(); err != nil {
+ return err
+ }
+
+ // Start new transaction.
+ tx, err = dst.Begin(true)
+ if err != nil {
+ return err
+ }
+ size = 0
+ }
+ size += sz
+
+ // Create bucket on the root transaction if this is the first level.
+ nk := len(keys)
+ if nk == 0 {
+ bkt, err := tx.CreateBucket(k)
+ if err != nil {
+ return err
+ }
+ if err := bkt.SetSequence(seq); err != nil {
+ return err
+ }
+ return nil
+ }
+
+ // Create buckets on subsequent levels, if necessary.
+ b := tx.Bucket(keys[0])
+ if nk > 1 {
+ for _, k := range keys[1:] {
+ b = b.Bucket(k)
+ }
+ }
+
+ // If there is no value then this is a bucket call.
+ if v == nil {
+ bkt, err := b.CreateBucket(k)
+ if err != nil {
+ return err
+ }
+ if err := bkt.SetSequence(seq); err != nil {
+ return err
+ }
+ return nil
+ }
+
+ // Otherwise treat it as a key/value pair.
+ return b.Put(k, v)
+ }); err != nil {
+ return err
+ }
+
+ return tx.Commit()
+}
+
+// walkFunc is the type of the function called for keys (buckets and "normal"
+// values) discovered by Walk. keys is the list of keys to descend to the bucket
+// owning the discovered key/value pair k/v.
+type walkFunc func(keys [][]byte, k, v []byte, seq uint64) error
+
+// walk walks recursively the bolt database db, calling walkFn for each key it finds.
+func (cmd *CompactCommand) walk(db *bolt.DB, walkFn walkFunc) error {
+ return db.View(func(tx *bolt.Tx) error {
+ return tx.ForEach(func(name []byte, b *bolt.Bucket) error {
+ return cmd.walkBucket(b, nil, name, nil, b.Sequence(), walkFn)
+ })
+ })
+}
+
+func (cmd *CompactCommand) walkBucket(b *bolt.Bucket, keypath [][]byte, k, v []byte, seq uint64, fn walkFunc) error {
+ // Execute callback.
+ if err := fn(keypath, k, v, seq); err != nil {
+ return err
+ }
+
+ // If this is not a bucket then stop.
+ if v != nil {
+ return nil
+ }
+
+ // Iterate over each child key/value.
+ keypath = append(keypath, k)
+ return b.ForEach(func(k, v []byte) error {
+ if v == nil {
+ bkt := b.Bucket(k)
+ return cmd.walkBucket(bkt, keypath, k, nil, bkt.Sequence(), fn)
+ }
+ return cmd.walkBucket(b, keypath, k, v, b.Sequence(), fn)
+ })
+}
+
+// Usage returns the help message.
+func (cmd *CompactCommand) Usage() string {
+ return strings.TrimLeft(`
+usage: bolt compact [options] -o DST SRC
+
+Compact opens a database at SRC path and walks it recursively, copying keys
+as they are found from all buckets, to a newly created database at DST path.
+
+The original database is left untouched.
+
+Additional options include:
+
+ -tx-max-size NUM
+ Specifies the maximum size of individual transactions.
+ Defaults to 64KB.
+`, "\n")
+}
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/cmd/bolt/main_test.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/cmd/bolt/main_test.go
new file mode 100644
index 0000000..0a11ff3
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/cmd/bolt/main_test.go
@@ -0,0 +1,356 @@
+package main_test
+
+import (
+ "bytes"
+ crypto "crypto/rand"
+ "encoding/binary"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "math/rand"
+ "os"
+ "strconv"
+ "testing"
+
+ "github.com/boltdb/bolt"
+ "github.com/boltdb/bolt/cmd/bolt"
+)
+
+// Ensure the "info" command can print information about a database.
+func TestInfoCommand_Run(t *testing.T) {
+ db := MustOpen(0666, nil)
+ db.DB.Close()
+ defer db.Close()
+
+ // Run the info command.
+ m := NewMain()
+ if err := m.Run("info", db.Path); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure the "stats" command executes correctly with an empty database.
+func TestStatsCommand_Run_EmptyDatabase(t *testing.T) {
+ // Ignore
+ if os.Getpagesize() != 4096 {
+ t.Skip("system does not use 4KB page size")
+ }
+
+ db := MustOpen(0666, nil)
+ defer db.Close()
+ db.DB.Close()
+
+ // Generate expected result.
+ exp := "Aggregate statistics for 0 buckets\n\n" +
+ "Page count statistics\n" +
+ "\tNumber of logical branch pages: 0\n" +
+ "\tNumber of physical branch overflow pages: 0\n" +
+ "\tNumber of logical leaf pages: 0\n" +
+ "\tNumber of physical leaf overflow pages: 0\n" +
+ "Tree statistics\n" +
+ "\tNumber of keys/value pairs: 0\n" +
+ "\tNumber of levels in B+tree: 0\n" +
+ "Page size utilization\n" +
+ "\tBytes allocated for physical branch pages: 0\n" +
+ "\tBytes actually used for branch data: 0 (0%)\n" +
+ "\tBytes allocated for physical leaf pages: 0\n" +
+ "\tBytes actually used for leaf data: 0 (0%)\n" +
+ "Bucket statistics\n" +
+ "\tTotal number of buckets: 0\n" +
+ "\tTotal number on inlined buckets: 0 (0%)\n" +
+ "\tBytes used for inlined buckets: 0 (0%)\n"
+
+ // Run the command.
+ m := NewMain()
+ if err := m.Run("stats", db.Path); err != nil {
+ t.Fatal(err)
+ } else if m.Stdout.String() != exp {
+ t.Fatalf("unexpected stdout:\n\n%s", m.Stdout.String())
+ }
+}
+
+// Ensure the "stats" command can execute correctly.
+func TestStatsCommand_Run(t *testing.T) {
+ // Ignore
+ if os.Getpagesize() != 4096 {
+ t.Skip("system does not use 4KB page size")
+ }
+
+ db := MustOpen(0666, nil)
+ defer db.Close()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ // Create "foo" bucket.
+ b, err := tx.CreateBucket([]byte("foo"))
+ if err != nil {
+ return err
+ }
+ for i := 0; i < 10; i++ {
+ if err := b.Put([]byte(strconv.Itoa(i)), []byte(strconv.Itoa(i))); err != nil {
+ return err
+ }
+ }
+
+ // Create "bar" bucket.
+ b, err = tx.CreateBucket([]byte("bar"))
+ if err != nil {
+ return err
+ }
+ for i := 0; i < 100; i++ {
+ if err := b.Put([]byte(strconv.Itoa(i)), []byte(strconv.Itoa(i))); err != nil {
+ return err
+ }
+ }
+
+ // Create "baz" bucket.
+ b, err = tx.CreateBucket([]byte("baz"))
+ if err != nil {
+ return err
+ }
+ if err := b.Put([]byte("key"), []byte("value")); err != nil {
+ return err
+ }
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+ db.DB.Close()
+
+ // Generate expected result.
+ exp := "Aggregate statistics for 3 buckets\n\n" +
+ "Page count statistics\n" +
+ "\tNumber of logical branch pages: 0\n" +
+ "\tNumber of physical branch overflow pages: 0\n" +
+ "\tNumber of logical leaf pages: 1\n" +
+ "\tNumber of physical leaf overflow pages: 0\n" +
+ "Tree statistics\n" +
+ "\tNumber of keys/value pairs: 111\n" +
+ "\tNumber of levels in B+tree: 1\n" +
+ "Page size utilization\n" +
+ "\tBytes allocated for physical branch pages: 0\n" +
+ "\tBytes actually used for branch data: 0 (0%)\n" +
+ "\tBytes allocated for physical leaf pages: 4096\n" +
+ "\tBytes actually used for leaf data: 1996 (48%)\n" +
+ "Bucket statistics\n" +
+ "\tTotal number of buckets: 3\n" +
+ "\tTotal number on inlined buckets: 2 (66%)\n" +
+ "\tBytes used for inlined buckets: 236 (11%)\n"
+
+ // Run the command.
+ m := NewMain()
+ if err := m.Run("stats", db.Path); err != nil {
+ t.Fatal(err)
+ } else if m.Stdout.String() != exp {
+ t.Fatalf("unexpected stdout:\n\n%s", m.Stdout.String())
+ }
+}
+
+// Main represents a test wrapper for main.Main that records output.
+type Main struct {
+ *main.Main
+ Stdin bytes.Buffer
+ Stdout bytes.Buffer
+ Stderr bytes.Buffer
+}
+
+// NewMain returns a new instance of Main.
+func NewMain() *Main {
+ m := &Main{Main: main.NewMain()}
+ m.Main.Stdin = &m.Stdin
+ m.Main.Stdout = &m.Stdout
+ m.Main.Stderr = &m.Stderr
+ return m
+}
+
+// MustOpen creates a Bolt database in a temporary location.
+func MustOpen(mode os.FileMode, options *bolt.Options) *DB {
+ // Create temporary path.
+ f, _ := ioutil.TempFile("", "bolt-")
+ f.Close()
+ os.Remove(f.Name())
+
+ db, err := bolt.Open(f.Name(), mode, options)
+ if err != nil {
+ panic(err.Error())
+ }
+ return &DB{DB: db, Path: f.Name()}
+}
+
+// DB is a test wrapper for bolt.DB.
+type DB struct {
+ *bolt.DB
+ Path string
+}
+
+// Close closes and removes the database.
+func (db *DB) Close() error {
+ defer os.Remove(db.Path)
+ return db.DB.Close()
+}
+
+func TestCompactCommand_Run(t *testing.T) {
+ var s int64
+ if err := binary.Read(crypto.Reader, binary.BigEndian, &s); err != nil {
+ t.Fatal(err)
+ }
+ rand.Seed(s)
+
+ dstdb := MustOpen(0666, nil)
+ dstdb.Close()
+
+ // fill the db
+ db := MustOpen(0666, nil)
+ if err := db.Update(func(tx *bolt.Tx) error {
+ n := 2 + rand.Intn(5)
+ for i := 0; i < n; i++ {
+ k := []byte(fmt.Sprintf("b%d", i))
+ b, err := tx.CreateBucketIfNotExists(k)
+ if err != nil {
+ return err
+ }
+ if err := b.SetSequence(uint64(i)); err != nil {
+ return err
+ }
+ if err := fillBucket(b, append(k, '.')); err != nil {
+ return err
+ }
+ }
+ return nil
+ }); err != nil {
+ db.Close()
+ t.Fatal(err)
+ }
+
+ // make the db grow by adding large values, and delete them.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucketIfNotExists([]byte("large_vals"))
+ if err != nil {
+ return err
+ }
+ n := 5 + rand.Intn(5)
+ for i := 0; i < n; i++ {
+ v := make([]byte, 1000*1000*(1+rand.Intn(5)))
+ _, err := crypto.Read(v)
+ if err != nil {
+ return err
+ }
+ if err := b.Put([]byte(fmt.Sprintf("l%d", i)), v); err != nil {
+ return err
+ }
+ }
+ return nil
+ }); err != nil {
+ db.Close()
+ t.Fatal(err)
+ }
+ if err := db.Update(func(tx *bolt.Tx) error {
+ c := tx.Bucket([]byte("large_vals")).Cursor()
+ for k, _ := c.First(); k != nil; k, _ = c.Next() {
+ if err := c.Delete(); err != nil {
+ return err
+ }
+ }
+ return tx.DeleteBucket([]byte("large_vals"))
+ }); err != nil {
+ db.Close()
+ t.Fatal(err)
+ }
+ db.DB.Close()
+ defer db.Close()
+ defer dstdb.Close()
+
+ dbChk, err := chkdb(db.Path)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ m := NewMain()
+ if err := m.Run("compact", "-o", dstdb.Path, db.Path); err != nil {
+ t.Fatal(err)
+ }
+
+ dbChkAfterCompact, err := chkdb(db.Path)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ dstdbChk, err := chkdb(dstdb.Path)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if !bytes.Equal(dbChk, dbChkAfterCompact) {
+ t.Error("the original db has been touched")
+ }
+ if !bytes.Equal(dbChk, dstdbChk) {
+ t.Error("the compacted db data isn't the same than the original db")
+ }
+}
+
+func fillBucket(b *bolt.Bucket, prefix []byte) error {
+ n := 10 + rand.Intn(50)
+ for i := 0; i < n; i++ {
+ v := make([]byte, 10*(1+rand.Intn(4)))
+ _, err := crypto.Read(v)
+ if err != nil {
+ return err
+ }
+ k := append(prefix, []byte(fmt.Sprintf("k%d", i))...)
+ if err := b.Put(k, v); err != nil {
+ return err
+ }
+ }
+ // limit depth of subbuckets
+ s := 2 + rand.Intn(4)
+ if len(prefix) > (2*s + 1) {
+ return nil
+ }
+ n = 1 + rand.Intn(3)
+ for i := 0; i < n; i++ {
+ k := append(prefix, []byte(fmt.Sprintf("b%d", i))...)
+ sb, err := b.CreateBucket(k)
+ if err != nil {
+ return err
+ }
+ if err := fillBucket(sb, append(k, '.')); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func chkdb(path string) ([]byte, error) {
+ db, err := bolt.Open(path, 0666, nil)
+ if err != nil {
+ return nil, err
+ }
+ defer db.Close()
+ var buf bytes.Buffer
+ err = db.View(func(tx *bolt.Tx) error {
+ return tx.ForEach(func(name []byte, b *bolt.Bucket) error {
+ return walkBucket(b, name, nil, &buf)
+ })
+ })
+ if err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}
+
+func walkBucket(parent *bolt.Bucket, k []byte, v []byte, w io.Writer) error {
+ if _, err := fmt.Fprintf(w, "%d:%x=%x\n", parent.Sequence(), k, v); err != nil {
+ return err
+ }
+
+ // not a bucket, exit.
+ if v != nil {
+ return nil
+ }
+ return parent.ForEach(func(k, v []byte) error {
+ if v == nil {
+ return walkBucket(parent.Bucket(k), k, nil, w)
+ }
+ return walkBucket(parent, k, v, w)
+ })
+}
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/cursor.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/cursor.go
new file mode 100644
index 0000000..1be9f35
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/cursor.go
@@ -0,0 +1,400 @@
+package bolt
+
+import (
+ "bytes"
+ "fmt"
+ "sort"
+)
+
+// Cursor represents an iterator that can traverse over all key/value pairs in a bucket in sorted order.
+// Cursors see nested buckets with value == nil.
+// Cursors can be obtained from a transaction and are valid as long as the transaction is open.
+//
+// Keys and values returned from the cursor are only valid for the life of the transaction.
+//
+// Changing data while traversing with a cursor may cause it to be invalidated
+// and return unexpected keys and/or values. You must reposition your cursor
+// after mutating data.
+type Cursor struct {
+ bucket *Bucket
+ stack []elemRef
+}
+
+// Bucket returns the bucket that this cursor was created from.
+func (c *Cursor) Bucket() *Bucket {
+ return c.bucket
+}
+
+// First moves the cursor to the first item in the bucket and returns its key and value.
+// If the bucket is empty then a nil key and value are returned.
+// The returned key and value are only valid for the life of the transaction.
+func (c *Cursor) First() (key []byte, value []byte) {
+ _assert(c.bucket.tx.db != nil, "tx closed")
+ c.stack = c.stack[:0]
+ p, n := c.bucket.pageNode(c.bucket.root)
+ c.stack = append(c.stack, elemRef{page: p, node: n, index: 0})
+ c.first()
+
+ // If we land on an empty page then move to the next value.
+ // https://github.com/boltdb/bolt/issues/450
+ if c.stack[len(c.stack)-1].count() == 0 {
+ c.next()
+ }
+
+ k, v, flags := c.keyValue()
+ if (flags & uint32(bucketLeafFlag)) != 0 {
+ return k, nil
+ }
+ return k, v
+
+}
+
+// Last moves the cursor to the last item in the bucket and returns its key and value.
+// If the bucket is empty then a nil key and value are returned.
+// The returned key and value are only valid for the life of the transaction.
+func (c *Cursor) Last() (key []byte, value []byte) {
+ _assert(c.bucket.tx.db != nil, "tx closed")
+ c.stack = c.stack[:0]
+ p, n := c.bucket.pageNode(c.bucket.root)
+ ref := elemRef{page: p, node: n}
+ ref.index = ref.count() - 1
+ c.stack = append(c.stack, ref)
+ c.last()
+ k, v, flags := c.keyValue()
+ if (flags & uint32(bucketLeafFlag)) != 0 {
+ return k, nil
+ }
+ return k, v
+}
+
+// Next moves the cursor to the next item in the bucket and returns its key and value.
+// If the cursor is at the end of the bucket then a nil key and value are returned.
+// The returned key and value are only valid for the life of the transaction.
+func (c *Cursor) Next() (key []byte, value []byte) {
+ _assert(c.bucket.tx.db != nil, "tx closed")
+ k, v, flags := c.next()
+ if (flags & uint32(bucketLeafFlag)) != 0 {
+ return k, nil
+ }
+ return k, v
+}
+
+// Prev moves the cursor to the previous item in the bucket and returns its key and value.
+// If the cursor is at the beginning of the bucket then a nil key and value are returned.
+// The returned key and value are only valid for the life of the transaction.
+func (c *Cursor) Prev() (key []byte, value []byte) {
+ _assert(c.bucket.tx.db != nil, "tx closed")
+
+ // Attempt to move back one element until we're successful.
+ // Move up the stack as we hit the beginning of each page in our stack.
+ for i := len(c.stack) - 1; i >= 0; i-- {
+ elem := &c.stack[i]
+ if elem.index > 0 {
+ elem.index--
+ break
+ }
+ c.stack = c.stack[:i]
+ }
+
+ // If we've hit the end then return nil.
+ if len(c.stack) == 0 {
+ return nil, nil
+ }
+
+ // Move down the stack to find the last element of the last leaf under this branch.
+ c.last()
+ k, v, flags := c.keyValue()
+ if (flags & uint32(bucketLeafFlag)) != 0 {
+ return k, nil
+ }
+ return k, v
+}
+
+// Seek moves the cursor to a given key and returns it.
+// If the key does not exist then the next key is used. If no keys
+// follow, a nil key is returned.
+// The returned key and value are only valid for the life of the transaction.
+func (c *Cursor) Seek(seek []byte) (key []byte, value []byte) {
+ k, v, flags := c.seek(seek)
+
+ // If we ended up after the last element of a page then move to the next one.
+ if ref := &c.stack[len(c.stack)-1]; ref.index >= ref.count() {
+ k, v, flags = c.next()
+ }
+
+ if k == nil {
+ return nil, nil
+ } else if (flags & uint32(bucketLeafFlag)) != 0 {
+ return k, nil
+ }
+ return k, v
+}
+
+// Delete removes the current key/value under the cursor from the bucket.
+// Delete fails if current key/value is a bucket or if the transaction is not writable.
+func (c *Cursor) Delete() error {
+ if c.bucket.tx.db == nil {
+ return ErrTxClosed
+ } else if !c.bucket.Writable() {
+ return ErrTxNotWritable
+ }
+
+ key, _, flags := c.keyValue()
+ // Return an error if current value is a bucket.
+ if (flags & bucketLeafFlag) != 0 {
+ return ErrIncompatibleValue
+ }
+ c.node().del(key)
+
+ return nil
+}
+
+// seek moves the cursor to a given key and returns it.
+// If the key does not exist then the next key is used.
+func (c *Cursor) seek(seek []byte) (key []byte, value []byte, flags uint32) {
+ _assert(c.bucket.tx.db != nil, "tx closed")
+
+ // Start from root page/node and traverse to correct page.
+ c.stack = c.stack[:0]
+ c.search(seek, c.bucket.root)
+ ref := &c.stack[len(c.stack)-1]
+
+ // If the cursor is pointing to the end of page/node then return nil.
+ if ref.index >= ref.count() {
+ return nil, nil, 0
+ }
+
+ // If this is a bucket then return a nil value.
+ return c.keyValue()
+}
+
+// first moves the cursor to the first leaf element under the last page in the stack.
+func (c *Cursor) first() {
+ for {
+ // Exit when we hit a leaf page.
+ var ref = &c.stack[len(c.stack)-1]
+ if ref.isLeaf() {
+ break
+ }
+
+ // Keep adding pages pointing to the first element to the stack.
+ var pgid pgid
+ if ref.node != nil {
+ pgid = ref.node.inodes[ref.index].pgid
+ } else {
+ pgid = ref.page.branchPageElement(uint16(ref.index)).pgid
+ }
+ p, n := c.bucket.pageNode(pgid)
+ c.stack = append(c.stack, elemRef{page: p, node: n, index: 0})
+ }
+}
+
+// last moves the cursor to the last leaf element under the last page in the stack.
+func (c *Cursor) last() {
+ for {
+ // Exit when we hit a leaf page.
+ ref := &c.stack[len(c.stack)-1]
+ if ref.isLeaf() {
+ break
+ }
+
+ // Keep adding pages pointing to the last element in the stack.
+ var pgid pgid
+ if ref.node != nil {
+ pgid = ref.node.inodes[ref.index].pgid
+ } else {
+ pgid = ref.page.branchPageElement(uint16(ref.index)).pgid
+ }
+ p, n := c.bucket.pageNode(pgid)
+
+ var nextRef = elemRef{page: p, node: n}
+ nextRef.index = nextRef.count() - 1
+ c.stack = append(c.stack, nextRef)
+ }
+}
+
+// next moves to the next leaf element and returns the key and value.
+// If the cursor is at the last leaf element then it stays there and returns nil.
+func (c *Cursor) next() (key []byte, value []byte, flags uint32) {
+ for {
+ // Attempt to move over one element until we're successful.
+ // Move up the stack as we hit the end of each page in our stack.
+ var i int
+ for i = len(c.stack) - 1; i >= 0; i-- {
+ elem := &c.stack[i]
+ if elem.index < elem.count()-1 {
+ elem.index++
+ break
+ }
+ }
+
+ // If we've hit the root page then stop and return. This will leave the
+ // cursor on the last element of the last page.
+ if i == -1 {
+ return nil, nil, 0
+ }
+
+ // Otherwise start from where we left off in the stack and find the
+ // first element of the first leaf page.
+ c.stack = c.stack[:i+1]
+ c.first()
+
+ // If this is an empty page then restart and move back up the stack.
+ // https://github.com/boltdb/bolt/issues/450
+ if c.stack[len(c.stack)-1].count() == 0 {
+ continue
+ }
+
+ return c.keyValue()
+ }
+}
+
+// search recursively performs a binary search against a given page/node until it finds a given key.
+func (c *Cursor) search(key []byte, pgid pgid) {
+ p, n := c.bucket.pageNode(pgid)
+ if p != nil && (p.flags&(branchPageFlag|leafPageFlag)) == 0 {
+ panic(fmt.Sprintf("invalid page type: %d: %x", p.id, p.flags))
+ }
+ e := elemRef{page: p, node: n}
+ c.stack = append(c.stack, e)
+
+ // If we're on a leaf page/node then find the specific node.
+ if e.isLeaf() {
+ c.nsearch(key)
+ return
+ }
+
+ if n != nil {
+ c.searchNode(key, n)
+ return
+ }
+ c.searchPage(key, p)
+}
+
+func (c *Cursor) searchNode(key []byte, n *node) {
+ var exact bool
+ index := sort.Search(len(n.inodes), func(i int) bool {
+ // TODO(benbjohnson): Optimize this range search. It's a bit hacky right now.
+ // sort.Search() finds the lowest index where f() != -1 but we need the highest index.
+ ret := bytes.Compare(n.inodes[i].key, key)
+ if ret == 0 {
+ exact = true
+ }
+ return ret != -1
+ })
+ if !exact && index > 0 {
+ index--
+ }
+ c.stack[len(c.stack)-1].index = index
+
+ // Recursively search to the next page.
+ c.search(key, n.inodes[index].pgid)
+}
+
+func (c *Cursor) searchPage(key []byte, p *page) {
+ // Binary search for the correct range.
+ inodes := p.branchPageElements()
+
+ var exact bool
+ index := sort.Search(int(p.count), func(i int) bool {
+ // TODO(benbjohnson): Optimize this range search. It's a bit hacky right now.
+ // sort.Search() finds the lowest index where f() != -1 but we need the highest index.
+ ret := bytes.Compare(inodes[i].key(), key)
+ if ret == 0 {
+ exact = true
+ }
+ return ret != -1
+ })
+ if !exact && index > 0 {
+ index--
+ }
+ c.stack[len(c.stack)-1].index = index
+
+ // Recursively search to the next page.
+ c.search(key, inodes[index].pgid)
+}
+
+// nsearch searches the leaf node on the top of the stack for a key.
+func (c *Cursor) nsearch(key []byte) {
+ e := &c.stack[len(c.stack)-1]
+ p, n := e.page, e.node
+
+ // If we have a node then search its inodes.
+ if n != nil {
+ index := sort.Search(len(n.inodes), func(i int) bool {
+ return bytes.Compare(n.inodes[i].key, key) != -1
+ })
+ e.index = index
+ return
+ }
+
+ // If we have a page then search its leaf elements.
+ inodes := p.leafPageElements()
+ index := sort.Search(int(p.count), func(i int) bool {
+ return bytes.Compare(inodes[i].key(), key) != -1
+ })
+ e.index = index
+}
+
+// keyValue returns the key and value of the current leaf element.
+func (c *Cursor) keyValue() ([]byte, []byte, uint32) {
+ ref := &c.stack[len(c.stack)-1]
+ if ref.count() == 0 || ref.index >= ref.count() {
+ return nil, nil, 0
+ }
+
+ // Retrieve value from node.
+ if ref.node != nil {
+ inode := &ref.node.inodes[ref.index]
+ return inode.key, inode.value, inode.flags
+ }
+
+ // Or retrieve value from page.
+ elem := ref.page.leafPageElement(uint16(ref.index))
+ return elem.key(), elem.value(), elem.flags
+}
+
+// node returns the node that the cursor is currently positioned on.
+func (c *Cursor) node() *node {
+ _assert(len(c.stack) > 0, "accessing a node with a zero-length cursor stack")
+
+ // If the top of the stack is a leaf node then just return it.
+ if ref := &c.stack[len(c.stack)-1]; ref.node != nil && ref.isLeaf() {
+ return ref.node
+ }
+
+ // Start from root and traverse down the hierarchy.
+ var n = c.stack[0].node
+ if n == nil {
+ n = c.bucket.node(c.stack[0].page.id, nil)
+ }
+ for _, ref := range c.stack[:len(c.stack)-1] {
+ _assert(!n.isLeaf, "expected branch node")
+ n = n.childAt(int(ref.index))
+ }
+ _assert(n.isLeaf, "expected leaf node")
+ return n
+}
+
+// elemRef represents a reference to an element on a given page/node.
+type elemRef struct {
+ page *page
+ node *node
+ index int
+}
+
+// isLeaf returns whether the ref is pointing at a leaf page/node.
+func (r *elemRef) isLeaf() bool {
+ if r.node != nil {
+ return r.node.isLeaf
+ }
+ return (r.page.flags & leafPageFlag) != 0
+}
+
+// count returns the number of inodes or page elements.
+func (r *elemRef) count() int {
+ if r.node != nil {
+ return len(r.node.inodes)
+ }
+ return int(r.page.count)
+}
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/cursor_test.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/cursor_test.go
new file mode 100644
index 0000000..562d60f
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/cursor_test.go
@@ -0,0 +1,817 @@
+package bolt_test
+
+import (
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "log"
+ "os"
+ "reflect"
+ "sort"
+ "testing"
+ "testing/quick"
+
+ "github.com/boltdb/bolt"
+)
+
+// Ensure that a cursor can return a reference to the bucket that created it.
+func TestCursor_Bucket(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if cb := b.Cursor().Bucket(); !reflect.DeepEqual(cb, b) {
+ t.Fatal("cursor bucket mismatch")
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a Tx cursor can seek to the appropriate keys.
+func TestCursor_Seek(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("foo"), []byte("0001")); err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("bar"), []byte("0002")); err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("baz"), []byte("0003")); err != nil {
+ t.Fatal(err)
+ }
+
+ if _, err := b.CreateBucket([]byte("bkt")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.View(func(tx *bolt.Tx) error {
+ c := tx.Bucket([]byte("widgets")).Cursor()
+
+ // Exact match should go to the key.
+ if k, v := c.Seek([]byte("bar")); !bytes.Equal(k, []byte("bar")) {
+ t.Fatalf("unexpected key: %v", k)
+ } else if !bytes.Equal(v, []byte("0002")) {
+ t.Fatalf("unexpected value: %v", v)
+ }
+
+ // Inexact match should go to the next key.
+ if k, v := c.Seek([]byte("bas")); !bytes.Equal(k, []byte("baz")) {
+ t.Fatalf("unexpected key: %v", k)
+ } else if !bytes.Equal(v, []byte("0003")) {
+ t.Fatalf("unexpected value: %v", v)
+ }
+
+ // Low key should go to the first key.
+ if k, v := c.Seek([]byte("")); !bytes.Equal(k, []byte("bar")) {
+ t.Fatalf("unexpected key: %v", k)
+ } else if !bytes.Equal(v, []byte("0002")) {
+ t.Fatalf("unexpected value: %v", v)
+ }
+
+ // High key should return no key.
+ if k, v := c.Seek([]byte("zzz")); k != nil {
+ t.Fatalf("expected nil key: %v", k)
+ } else if v != nil {
+ t.Fatalf("expected nil value: %v", v)
+ }
+
+ // Buckets should return their key but no value.
+ if k, v := c.Seek([]byte("bkt")); !bytes.Equal(k, []byte("bkt")) {
+ t.Fatalf("unexpected key: %v", k)
+ } else if v != nil {
+ t.Fatalf("expected nil value: %v", v)
+ }
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestCursor_Delete(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ const count = 1000
+
+ // Insert every other key between 0 and $count.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ for i := 0; i < count; i += 1 {
+ k := make([]byte, 8)
+ binary.BigEndian.PutUint64(k, uint64(i))
+ if err := b.Put(k, make([]byte, 100)); err != nil {
+ t.Fatal(err)
+ }
+ }
+ if _, err := b.CreateBucket([]byte("sub")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ c := tx.Bucket([]byte("widgets")).Cursor()
+ bound := make([]byte, 8)
+ binary.BigEndian.PutUint64(bound, uint64(count/2))
+ for key, _ := c.First(); bytes.Compare(key, bound) < 0; key, _ = c.Next() {
+ if err := c.Delete(); err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ c.Seek([]byte("sub"))
+ if err := c.Delete(); err != bolt.ErrIncompatibleValue {
+ t.Fatalf("unexpected error: %s", err)
+ }
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.View(func(tx *bolt.Tx) error {
+ stats := tx.Bucket([]byte("widgets")).Stats()
+ if stats.KeyN != count/2+1 {
+ t.Fatalf("unexpected KeyN: %d", stats.KeyN)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a Tx cursor can seek to the appropriate keys when there are a
+// large number of keys. This test also checks that seek will always move
+// forward to the next key.
+//
+// Related: https://github.com/boltdb/bolt/pull/187
+func TestCursor_Seek_Large(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ var count = 10000
+
+ // Insert every other key between 0 and $count.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ for i := 0; i < count; i += 100 {
+ for j := i; j < i+100; j += 2 {
+ k := make([]byte, 8)
+ binary.BigEndian.PutUint64(k, uint64(j))
+ if err := b.Put(k, make([]byte, 100)); err != nil {
+ t.Fatal(err)
+ }
+ }
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.View(func(tx *bolt.Tx) error {
+ c := tx.Bucket([]byte("widgets")).Cursor()
+ for i := 0; i < count; i++ {
+ seek := make([]byte, 8)
+ binary.BigEndian.PutUint64(seek, uint64(i))
+
+ k, _ := c.Seek(seek)
+
+ // The last seek is beyond the end of the the range so
+ // it should return nil.
+ if i == count-1 {
+ if k != nil {
+ t.Fatal("expected nil key")
+ }
+ continue
+ }
+
+ // Otherwise we should seek to the exact key or the next key.
+ num := binary.BigEndian.Uint64(k)
+ if i%2 == 0 {
+ if num != uint64(i) {
+ t.Fatalf("unexpected num: %d", num)
+ }
+ } else {
+ if num != uint64(i+1) {
+ t.Fatalf("unexpected num: %d", num)
+ }
+ }
+ }
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a cursor can iterate over an empty bucket without error.
+func TestCursor_EmptyBucket(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ _, err := tx.CreateBucket([]byte("widgets"))
+ return err
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.View(func(tx *bolt.Tx) error {
+ c := tx.Bucket([]byte("widgets")).Cursor()
+ k, v := c.First()
+ if k != nil {
+ t.Fatalf("unexpected key: %v", k)
+ } else if v != nil {
+ t.Fatalf("unexpected value: %v", v)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a Tx cursor can reverse iterate over an empty bucket without error.
+func TestCursor_EmptyBucketReverse(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ _, err := tx.CreateBucket([]byte("widgets"))
+ return err
+ }); err != nil {
+ t.Fatal(err)
+ }
+ if err := db.View(func(tx *bolt.Tx) error {
+ c := tx.Bucket([]byte("widgets")).Cursor()
+ k, v := c.Last()
+ if k != nil {
+ t.Fatalf("unexpected key: %v", k)
+ } else if v != nil {
+ t.Fatalf("unexpected value: %v", v)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a Tx cursor can iterate over a single root with a couple elements.
+func TestCursor_Iterate_Leaf(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("baz"), []byte{}); err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("foo"), []byte{0}); err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("bar"), []byte{1}); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+ tx, err := db.Begin(false)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer func() { _ = tx.Rollback() }()
+
+ c := tx.Bucket([]byte("widgets")).Cursor()
+
+ k, v := c.First()
+ if !bytes.Equal(k, []byte("bar")) {
+ t.Fatalf("unexpected key: %v", k)
+ } else if !bytes.Equal(v, []byte{1}) {
+ t.Fatalf("unexpected value: %v", v)
+ }
+
+ k, v = c.Next()
+ if !bytes.Equal(k, []byte("baz")) {
+ t.Fatalf("unexpected key: %v", k)
+ } else if !bytes.Equal(v, []byte{}) {
+ t.Fatalf("unexpected value: %v", v)
+ }
+
+ k, v = c.Next()
+ if !bytes.Equal(k, []byte("foo")) {
+ t.Fatalf("unexpected key: %v", k)
+ } else if !bytes.Equal(v, []byte{0}) {
+ t.Fatalf("unexpected value: %v", v)
+ }
+
+ k, v = c.Next()
+ if k != nil {
+ t.Fatalf("expected nil key: %v", k)
+ } else if v != nil {
+ t.Fatalf("expected nil value: %v", v)
+ }
+
+ k, v = c.Next()
+ if k != nil {
+ t.Fatalf("expected nil key: %v", k)
+ } else if v != nil {
+ t.Fatalf("expected nil value: %v", v)
+ }
+
+ if err := tx.Rollback(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a Tx cursor can iterate in reverse over a single root with a couple elements.
+func TestCursor_LeafRootReverse(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("baz"), []byte{}); err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("foo"), []byte{0}); err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("bar"), []byte{1}); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+ tx, err := db.Begin(false)
+ if err != nil {
+ t.Fatal(err)
+ }
+ c := tx.Bucket([]byte("widgets")).Cursor()
+
+ if k, v := c.Last(); !bytes.Equal(k, []byte("foo")) {
+ t.Fatalf("unexpected key: %v", k)
+ } else if !bytes.Equal(v, []byte{0}) {
+ t.Fatalf("unexpected value: %v", v)
+ }
+
+ if k, v := c.Prev(); !bytes.Equal(k, []byte("baz")) {
+ t.Fatalf("unexpected key: %v", k)
+ } else if !bytes.Equal(v, []byte{}) {
+ t.Fatalf("unexpected value: %v", v)
+ }
+
+ if k, v := c.Prev(); !bytes.Equal(k, []byte("bar")) {
+ t.Fatalf("unexpected key: %v", k)
+ } else if !bytes.Equal(v, []byte{1}) {
+ t.Fatalf("unexpected value: %v", v)
+ }
+
+ if k, v := c.Prev(); k != nil {
+ t.Fatalf("expected nil key: %v", k)
+ } else if v != nil {
+ t.Fatalf("expected nil value: %v", v)
+ }
+
+ if k, v := c.Prev(); k != nil {
+ t.Fatalf("expected nil key: %v", k)
+ } else if v != nil {
+ t.Fatalf("expected nil value: %v", v)
+ }
+
+ if err := tx.Rollback(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a Tx cursor can restart from the beginning.
+func TestCursor_Restart(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("bar"), []byte{}); err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("foo"), []byte{}); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ tx, err := db.Begin(false)
+ if err != nil {
+ t.Fatal(err)
+ }
+ c := tx.Bucket([]byte("widgets")).Cursor()
+
+ if k, _ := c.First(); !bytes.Equal(k, []byte("bar")) {
+ t.Fatalf("unexpected key: %v", k)
+ }
+ if k, _ := c.Next(); !bytes.Equal(k, []byte("foo")) {
+ t.Fatalf("unexpected key: %v", k)
+ }
+
+ if k, _ := c.First(); !bytes.Equal(k, []byte("bar")) {
+ t.Fatalf("unexpected key: %v", k)
+ }
+ if k, _ := c.Next(); !bytes.Equal(k, []byte("foo")) {
+ t.Fatalf("unexpected key: %v", k)
+ }
+
+ if err := tx.Rollback(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a cursor can skip over empty pages that have been deleted.
+func TestCursor_First_EmptyPages(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ // Create 1000 keys in the "widgets" bucket.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ for i := 0; i < 1000; i++ {
+ if err := b.Put(u64tob(uint64(i)), []byte{}); err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ // Delete half the keys and then try to iterate.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("widgets"))
+ for i := 0; i < 600; i++ {
+ if err := b.Delete(u64tob(uint64(i))); err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ c := b.Cursor()
+ var n int
+ for k, _ := c.First(); k != nil; k, _ = c.Next() {
+ n++
+ }
+ if n != 400 {
+ t.Fatalf("unexpected key count: %d", n)
+ }
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a Tx can iterate over all elements in a bucket.
+func TestCursor_QuickCheck(t *testing.T) {
+ f := func(items testdata) bool {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ // Bulk insert all values.
+ tx, err := db.Begin(true)
+ if err != nil {
+ t.Fatal(err)
+ }
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, item := range items {
+ if err := b.Put(item.Key, item.Value); err != nil {
+ t.Fatal(err)
+ }
+ }
+ if err := tx.Commit(); err != nil {
+ t.Fatal(err)
+ }
+
+ // Sort test data.
+ sort.Sort(items)
+
+ // Iterate over all items and check consistency.
+ var index = 0
+ tx, err = db.Begin(false)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ c := tx.Bucket([]byte("widgets")).Cursor()
+ for k, v := c.First(); k != nil && index < len(items); k, v = c.Next() {
+ if !bytes.Equal(k, items[index].Key) {
+ t.Fatalf("unexpected key: %v", k)
+ } else if !bytes.Equal(v, items[index].Value) {
+ t.Fatalf("unexpected value: %v", v)
+ }
+ index++
+ }
+ if len(items) != index {
+ t.Fatalf("unexpected item count: %v, expected %v", len(items), index)
+ }
+
+ if err := tx.Rollback(); err != nil {
+ t.Fatal(err)
+ }
+
+ return true
+ }
+ if err := quick.Check(f, qconfig()); err != nil {
+ t.Error(err)
+ }
+}
+
+// Ensure that a transaction can iterate over all elements in a bucket in reverse.
+func TestCursor_QuickCheck_Reverse(t *testing.T) {
+ f := func(items testdata) bool {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ // Bulk insert all values.
+ tx, err := db.Begin(true)
+ if err != nil {
+ t.Fatal(err)
+ }
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, item := range items {
+ if err := b.Put(item.Key, item.Value); err != nil {
+ t.Fatal(err)
+ }
+ }
+ if err := tx.Commit(); err != nil {
+ t.Fatal(err)
+ }
+
+ // Sort test data.
+ sort.Sort(revtestdata(items))
+
+ // Iterate over all items and check consistency.
+ var index = 0
+ tx, err = db.Begin(false)
+ if err != nil {
+ t.Fatal(err)
+ }
+ c := tx.Bucket([]byte("widgets")).Cursor()
+ for k, v := c.Last(); k != nil && index < len(items); k, v = c.Prev() {
+ if !bytes.Equal(k, items[index].Key) {
+ t.Fatalf("unexpected key: %v", k)
+ } else if !bytes.Equal(v, items[index].Value) {
+ t.Fatalf("unexpected value: %v", v)
+ }
+ index++
+ }
+ if len(items) != index {
+ t.Fatalf("unexpected item count: %v, expected %v", len(items), index)
+ }
+
+ if err := tx.Rollback(); err != nil {
+ t.Fatal(err)
+ }
+
+ return true
+ }
+ if err := quick.Check(f, qconfig()); err != nil {
+ t.Error(err)
+ }
+}
+
+// Ensure that a Tx cursor can iterate over subbuckets.
+func TestCursor_QuickCheck_BucketsOnly(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if _, err := b.CreateBucket([]byte("foo")); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := b.CreateBucket([]byte("bar")); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := b.CreateBucket([]byte("baz")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.View(func(tx *bolt.Tx) error {
+ var names []string
+ c := tx.Bucket([]byte("widgets")).Cursor()
+ for k, v := c.First(); k != nil; k, v = c.Next() {
+ names = append(names, string(k))
+ if v != nil {
+ t.Fatalf("unexpected value: %v", v)
+ }
+ }
+ if !reflect.DeepEqual(names, []string{"bar", "baz", "foo"}) {
+ t.Fatalf("unexpected names: %+v", names)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a Tx cursor can reverse iterate over subbuckets.
+func TestCursor_QuickCheck_BucketsOnly_Reverse(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if _, err := b.CreateBucket([]byte("foo")); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := b.CreateBucket([]byte("bar")); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := b.CreateBucket([]byte("baz")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.View(func(tx *bolt.Tx) error {
+ var names []string
+ c := tx.Bucket([]byte("widgets")).Cursor()
+ for k, v := c.Last(); k != nil; k, v = c.Prev() {
+ names = append(names, string(k))
+ if v != nil {
+ t.Fatalf("unexpected value: %v", v)
+ }
+ }
+ if !reflect.DeepEqual(names, []string{"foo", "baz", "bar"}) {
+ t.Fatalf("unexpected names: %+v", names)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func ExampleCursor() {
+ // Open the database.
+ db, err := bolt.Open(tempfile(), 0666, nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer os.Remove(db.Path())
+
+ // Start a read-write transaction.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ // Create a new bucket.
+ b, err := tx.CreateBucket([]byte("animals"))
+ if err != nil {
+ return err
+ }
+
+ // Insert data into a bucket.
+ if err := b.Put([]byte("dog"), []byte("fun")); err != nil {
+ log.Fatal(err)
+ }
+ if err := b.Put([]byte("cat"), []byte("lame")); err != nil {
+ log.Fatal(err)
+ }
+ if err := b.Put([]byte("liger"), []byte("awesome")); err != nil {
+ log.Fatal(err)
+ }
+
+ // Create a cursor for iteration.
+ c := b.Cursor()
+
+ // Iterate over items in sorted key order. This starts from the
+ // first key/value pair and updates the k/v variables to the
+ // next key/value on each iteration.
+ //
+ // The loop finishes at the end of the cursor when a nil key is returned.
+ for k, v := c.First(); k != nil; k, v = c.Next() {
+ fmt.Printf("A %s is %s.\n", k, v)
+ }
+
+ return nil
+ }); err != nil {
+ log.Fatal(err)
+ }
+
+ if err := db.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ // Output:
+ // A cat is lame.
+ // A dog is fun.
+ // A liger is awesome.
+}
+
+func ExampleCursor_reverse() {
+ // Open the database.
+ db, err := bolt.Open(tempfile(), 0666, nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer os.Remove(db.Path())
+
+ // Start a read-write transaction.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ // Create a new bucket.
+ b, err := tx.CreateBucket([]byte("animals"))
+ if err != nil {
+ return err
+ }
+
+ // Insert data into a bucket.
+ if err := b.Put([]byte("dog"), []byte("fun")); err != nil {
+ log.Fatal(err)
+ }
+ if err := b.Put([]byte("cat"), []byte("lame")); err != nil {
+ log.Fatal(err)
+ }
+ if err := b.Put([]byte("liger"), []byte("awesome")); err != nil {
+ log.Fatal(err)
+ }
+
+ // Create a cursor for iteration.
+ c := b.Cursor()
+
+ // Iterate over items in reverse sorted key order. This starts
+ // from the last key/value pair and updates the k/v variables to
+ // the previous key/value on each iteration.
+ //
+ // The loop finishes at the beginning of the cursor when a nil key
+ // is returned.
+ for k, v := c.Last(); k != nil; k, v = c.Prev() {
+ fmt.Printf("A %s is %s.\n", k, v)
+ }
+
+ return nil
+ }); err != nil {
+ log.Fatal(err)
+ }
+
+ // Close the database to release the file lock.
+ if err := db.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ // Output:
+ // A liger is awesome.
+ // A dog is fun.
+ // A cat is lame.
+}
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/db.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/db.go
new file mode 100644
index 0000000..48da059
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/db.go
@@ -0,0 +1,1036 @@
+package bolt
+
+import (
+ "errors"
+ "fmt"
+ "hash/fnv"
+ "log"
+ "os"
+ "runtime"
+ "runtime/debug"
+ "strings"
+ "sync"
+ "time"
+ "unsafe"
+)
+
+// The largest step that can be taken when remapping the mmap.
+const maxMmapStep = 1 << 30 // 1GB
+
+// The data file format version.
+const version = 2
+
+// Represents a marker value to indicate that a file is a Bolt DB.
+const magic uint32 = 0xED0CDAED
+
+// IgnoreNoSync specifies whether the NoSync field of a DB is ignored when
+// syncing changes to a file. This is required as some operating systems,
+// such as OpenBSD, do not have a unified buffer cache (UBC) and writes
+// must be synchronized using the msync(2) syscall.
+const IgnoreNoSync = runtime.GOOS == "openbsd"
+
+// Default values if not set in a DB instance.
+const (
+ DefaultMaxBatchSize int = 1000
+ DefaultMaxBatchDelay = 10 * time.Millisecond
+ DefaultAllocSize = 16 * 1024 * 1024
+)
+
+// default page size for db is set to the OS page size.
+var defaultPageSize = os.Getpagesize()
+
+// DB represents a collection of buckets persisted to a file on disk.
+// All data access is performed through transactions which can be obtained through the DB.
+// All the functions on DB will return a ErrDatabaseNotOpen if accessed before Open() is called.
+type DB struct {
+ // When enabled, the database will perform a Check() after every commit.
+ // A panic is issued if the database is in an inconsistent state. This
+ // flag has a large performance impact so it should only be used for
+ // debugging purposes.
+ StrictMode bool
+
+ // Setting the NoSync flag will cause the database to skip fsync()
+ // calls after each commit. This can be useful when bulk loading data
+ // into a database and you can restart the bulk load in the event of
+ // a system failure or database corruption. Do not set this flag for
+ // normal use.
+ //
+ // If the package global IgnoreNoSync constant is true, this value is
+ // ignored. See the comment on that constant for more details.
+ //
+ // THIS IS UNSAFE. PLEASE USE WITH CAUTION.
+ NoSync bool
+
+ // When true, skips the truncate call when growing the database.
+ // Setting this to true is only safe on non-ext3/ext4 systems.
+ // Skipping truncation avoids preallocation of hard drive space and
+ // bypasses a truncate() and fsync() syscall on remapping.
+ //
+ // https://github.com/boltdb/bolt/issues/284
+ NoGrowSync bool
+
+ // If you want to read the entire database fast, you can set MmapFlag to
+ // syscall.MAP_POPULATE on Linux 2.6.23+ for sequential read-ahead.
+ MmapFlags int
+
+ // MaxBatchSize is the maximum size of a batch. Default value is
+ // copied from DefaultMaxBatchSize in Open.
+ //
+ // If <=0, disables batching.
+ //
+ // Do not change concurrently with calls to Batch.
+ MaxBatchSize int
+
+ // MaxBatchDelay is the maximum delay before a batch starts.
+ // Default value is copied from DefaultMaxBatchDelay in Open.
+ //
+ // If <=0, effectively disables batching.
+ //
+ // Do not change concurrently with calls to Batch.
+ MaxBatchDelay time.Duration
+
+ // AllocSize is the amount of space allocated when the database
+ // needs to create new pages. This is done to amortize the cost
+ // of truncate() and fsync() when growing the data file.
+ AllocSize int
+
+ path string
+ file *os.File
+ lockfile *os.File // windows only
+ dataref []byte // mmap'ed readonly, write throws SEGV
+ data *[maxMapSize]byte
+ datasz int
+ filesz int // current on disk file size
+ meta0 *meta
+ meta1 *meta
+ pageSize int
+ opened bool
+ rwtx *Tx
+ txs []*Tx
+ freelist *freelist
+ stats Stats
+
+ pagePool sync.Pool
+
+ batchMu sync.Mutex
+ batch *batch
+
+ rwlock sync.Mutex // Allows only one writer at a time.
+ metalock sync.Mutex // Protects meta page access.
+ mmaplock sync.RWMutex // Protects mmap access during remapping.
+ statlock sync.RWMutex // Protects stats access.
+
+ ops struct {
+ writeAt func(b []byte, off int64) (n int, err error)
+ }
+
+ // Read only mode.
+ // When true, Update() and Begin(true) return ErrDatabaseReadOnly immediately.
+ readOnly bool
+}
+
+// Path returns the path to currently open database file.
+func (db *DB) Path() string {
+ return db.path
+}
+
+// GoString returns the Go string representation of the database.
+func (db *DB) GoString() string {
+ return fmt.Sprintf("bolt.DB{path:%q}", db.path)
+}
+
+// String returns the string representation of the database.
+func (db *DB) String() string {
+ return fmt.Sprintf("DB<%q>", db.path)
+}
+
+// Open creates and opens a database at the given path.
+// If the file does not exist then it will be created automatically.
+// Passing in nil options will cause Bolt to open the database with the default options.
+func Open(path string, mode os.FileMode, options *Options) (*DB, error) {
+ var db = &DB{opened: true}
+
+ // Set default options if no options are provided.
+ if options == nil {
+ options = DefaultOptions
+ }
+ db.NoGrowSync = options.NoGrowSync
+ db.MmapFlags = options.MmapFlags
+
+ // Set default values for later DB operations.
+ db.MaxBatchSize = DefaultMaxBatchSize
+ db.MaxBatchDelay = DefaultMaxBatchDelay
+ db.AllocSize = DefaultAllocSize
+
+ flag := os.O_RDWR
+ if options.ReadOnly {
+ flag = os.O_RDONLY
+ db.readOnly = true
+ }
+
+ // Open data file and separate sync handler for metadata writes.
+ db.path = path
+ var err error
+ if db.file, err = os.OpenFile(db.path, flag|os.O_CREATE, mode); err != nil {
+ _ = db.close()
+ return nil, err
+ }
+
+ // Lock file so that other processes using Bolt in read-write mode cannot
+ // use the database at the same time. This would cause corruption since
+ // the two processes would write meta pages and free pages separately.
+ // The database file is locked exclusively (only one process can grab the lock)
+ // if !options.ReadOnly.
+ // The database file is locked using the shared lock (more than one process may
+ // hold a lock at the same time) otherwise (options.ReadOnly is set).
+ if err := flock(db, mode, !db.readOnly, options.Timeout); err != nil {
+ _ = db.close()
+ return nil, err
+ }
+
+ // Default values for test hooks
+ db.ops.writeAt = db.file.WriteAt
+
+ // Initialize the database if it doesn't exist.
+ if info, err := db.file.Stat(); err != nil {
+ return nil, err
+ } else if info.Size() == 0 {
+ // Initialize new files with meta pages.
+ if err := db.init(); err != nil {
+ return nil, err
+ }
+ } else {
+ // Read the first meta page to determine the page size.
+ var buf [0x1000]byte
+ if _, err := db.file.ReadAt(buf[:], 0); err == nil {
+ m := db.pageInBuffer(buf[:], 0).meta()
+ if err := m.validate(); err != nil {
+ // If we can't read the page size, we can assume it's the same
+ // as the OS -- since that's how the page size was chosen in the
+ // first place.
+ //
+ // If the first page is invalid and this OS uses a different
+ // page size than what the database was created with then we
+ // are out of luck and cannot access the database.
+ db.pageSize = os.Getpagesize()
+ } else {
+ db.pageSize = int(m.pageSize)
+ }
+ }
+ }
+
+ // Initialize page pool.
+ db.pagePool = sync.Pool{
+ New: func() interface{} {
+ return make([]byte, db.pageSize)
+ },
+ }
+
+ // Memory map the data file.
+ if err := db.mmap(options.InitialMmapSize); err != nil {
+ _ = db.close()
+ return nil, err
+ }
+
+ // Read in the freelist.
+ db.freelist = newFreelist()
+ db.freelist.read(db.page(db.meta().freelist))
+
+ // Mark the database as opened and return.
+ return db, nil
+}
+
+// mmap opens the underlying memory-mapped file and initializes the meta references.
+// minsz is the minimum size that the new mmap can be.
+func (db *DB) mmap(minsz int) error {
+ db.mmaplock.Lock()
+ defer db.mmaplock.Unlock()
+
+ info, err := db.file.Stat()
+ if err != nil {
+ return fmt.Errorf("mmap stat error: %s", err)
+ } else if int(info.Size()) < db.pageSize*2 {
+ return fmt.Errorf("file size too small")
+ }
+
+ // Ensure the size is at least the minimum size.
+ var size = int(info.Size())
+ if size < minsz {
+ size = minsz
+ }
+ size, err = db.mmapSize(size)
+ if err != nil {
+ return err
+ }
+
+ // Dereference all mmap references before unmapping.
+ if db.rwtx != nil {
+ db.rwtx.root.dereference()
+ }
+
+ // Unmap existing data before continuing.
+ if err := db.munmap(); err != nil {
+ return err
+ }
+
+ // Memory-map the data file as a byte slice.
+ if err := mmap(db, size); err != nil {
+ return err
+ }
+
+ // Save references to the meta pages.
+ db.meta0 = db.page(0).meta()
+ db.meta1 = db.page(1).meta()
+
+ // Validate the meta pages. We only return an error if both meta pages fail
+ // validation, since meta0 failing validation means that it wasn't saved
+ // properly -- but we can recover using meta1. And vice-versa.
+ err0 := db.meta0.validate()
+ err1 := db.meta1.validate()
+ if err0 != nil && err1 != nil {
+ return err0
+ }
+
+ return nil
+}
+
+// munmap unmaps the data file from memory.
+func (db *DB) munmap() error {
+ if err := munmap(db); err != nil {
+ return fmt.Errorf("unmap error: " + err.Error())
+ }
+ return nil
+}
+
+// mmapSize determines the appropriate size for the mmap given the current size
+// of the database. The minimum size is 32KB and doubles until it reaches 1GB.
+// Returns an error if the new mmap size is greater than the max allowed.
+func (db *DB) mmapSize(size int) (int, error) {
+ // Double the size from 32KB until 1GB.
+ for i := uint(15); i <= 30; i++ {
+ if size <= 1<<i {
+ return 1 << i, nil
+ }
+ }
+
+ // Verify the requested size is not above the maximum allowed.
+ if size > maxMapSize {
+ return 0, fmt.Errorf("mmap too large")
+ }
+
+ // If larger than 1GB then grow by 1GB at a time.
+ sz := int64(size)
+ if remainder := sz % int64(maxMmapStep); remainder > 0 {
+ sz += int64(maxMmapStep) - remainder
+ }
+
+ // Ensure that the mmap size is a multiple of the page size.
+ // This should always be true since we're incrementing in MBs.
+ pageSize := int64(db.pageSize)
+ if (sz % pageSize) != 0 {
+ sz = ((sz / pageSize) + 1) * pageSize
+ }
+
+ // If we've exceeded the max size then only grow up to the max size.
+ if sz > maxMapSize {
+ sz = maxMapSize
+ }
+
+ return int(sz), nil
+}
+
+// init creates a new database file and initializes its meta pages.
+func (db *DB) init() error {
+ // Set the page size to the OS page size.
+ db.pageSize = os.Getpagesize()
+
+ // Create two meta pages on a buffer.
+ buf := make([]byte, db.pageSize*4)
+ for i := 0; i < 2; i++ {
+ p := db.pageInBuffer(buf[:], pgid(i))
+ p.id = pgid(i)
+ p.flags = metaPageFlag
+
+ // Initialize the meta page.
+ m := p.meta()
+ m.magic = magic
+ m.version = version
+ m.pageSize = uint32(db.pageSize)
+ m.freelist = 2
+ m.root = bucket{root: 3}
+ m.pgid = 4
+ m.txid = txid(i)
+ m.checksum = m.sum64()
+ }
+
+ // Write an empty freelist at page 3.
+ p := db.pageInBuffer(buf[:], pgid(2))
+ p.id = pgid(2)
+ p.flags = freelistPageFlag
+ p.count = 0
+
+ // Write an empty leaf page at page 4.
+ p = db.pageInBuffer(buf[:], pgid(3))
+ p.id = pgid(3)
+ p.flags = leafPageFlag
+ p.count = 0
+
+ // Write the buffer to our data file.
+ if _, err := db.ops.writeAt(buf, 0); err != nil {
+ return err
+ }
+ if err := fdatasync(db); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// Close releases all database resources.
+// All transactions must be closed before closing the database.
+func (db *DB) Close() error {
+ db.rwlock.Lock()
+ defer db.rwlock.Unlock()
+
+ db.metalock.Lock()
+ defer db.metalock.Unlock()
+
+ db.mmaplock.RLock()
+ defer db.mmaplock.RUnlock()
+
+ return db.close()
+}
+
+func (db *DB) close() error {
+ if !db.opened {
+ return nil
+ }
+
+ db.opened = false
+
+ db.freelist = nil
+
+ // Clear ops.
+ db.ops.writeAt = nil
+
+ // Close the mmap.
+ if err := db.munmap(); err != nil {
+ return err
+ }
+
+ // Close file handles.
+ if db.file != nil {
+ // No need to unlock read-only file.
+ if !db.readOnly {
+ // Unlock the file.
+ if err := funlock(db); err != nil {
+ log.Printf("bolt.Close(): funlock error: %s", err)
+ }
+ }
+
+ // Close the file descriptor.
+ if err := db.file.Close(); err != nil {
+ return fmt.Errorf("db file close: %s", err)
+ }
+ db.file = nil
+ }
+
+ db.path = ""
+ return nil
+}
+
+// Begin starts a new transaction.
+// Multiple read-only transactions can be used concurrently but only one
+// write transaction can be used at a time. Starting multiple write transactions
+// will cause the calls to block and be serialized until the current write
+// transaction finishes.
+//
+// Transactions should not be dependent on one another. Opening a read
+// transaction and a write transaction in the same goroutine can cause the
+// writer to deadlock because the database periodically needs to re-mmap itself
+// as it grows and it cannot do that while a read transaction is open.
+//
+// If a long running read transaction (for example, a snapshot transaction) is
+// needed, you might want to set DB.InitialMmapSize to a large enough value
+// to avoid potential blocking of write transaction.
+//
+// IMPORTANT: You must close read-only transactions after you are finished or
+// else the database will not reclaim old pages.
+func (db *DB) Begin(writable bool) (*Tx, error) {
+ if writable {
+ return db.beginRWTx()
+ }
+ return db.beginTx()
+}
+
+func (db *DB) beginTx() (*Tx, error) {
+ // Lock the meta pages while we initialize the transaction. We obtain
+ // the meta lock before the mmap lock because that's the order that the
+ // write transaction will obtain them.
+ db.metalock.Lock()
+
+ // Obtain a read-only lock on the mmap. When the mmap is remapped it will
+ // obtain a write lock so all transactions must finish before it can be
+ // remapped.
+ db.mmaplock.RLock()
+
+ // Exit if the database is not open yet.
+ if !db.opened {
+ db.mmaplock.RUnlock()
+ db.metalock.Unlock()
+ return nil, ErrDatabaseNotOpen
+ }
+
+ // Create a transaction associated with the database.
+ t := &Tx{}
+ t.init(db)
+
+ // Keep track of transaction until it closes.
+ db.txs = append(db.txs, t)
+ n := len(db.txs)
+
+ // Unlock the meta pages.
+ db.metalock.Unlock()
+
+ // Update the transaction stats.
+ db.statlock.Lock()
+ db.stats.TxN++
+ db.stats.OpenTxN = n
+ db.statlock.Unlock()
+
+ return t, nil
+}
+
+func (db *DB) beginRWTx() (*Tx, error) {
+ // If the database was opened with Options.ReadOnly, return an error.
+ if db.readOnly {
+ return nil, ErrDatabaseReadOnly
+ }
+
+ // Obtain writer lock. This is released by the transaction when it closes.
+ // This enforces only one writer transaction at a time.
+ db.rwlock.Lock()
+
+ // Once we have the writer lock then we can lock the meta pages so that
+ // we can set up the transaction.
+ db.metalock.Lock()
+ defer db.metalock.Unlock()
+
+ // Exit if the database is not open yet.
+ if !db.opened {
+ db.rwlock.Unlock()
+ return nil, ErrDatabaseNotOpen
+ }
+
+ // Create a transaction associated with the database.
+ t := &Tx{writable: true}
+ t.init(db)
+ db.rwtx = t
+
+ // Free any pages associated with closed read-only transactions.
+ var minid txid = 0xFFFFFFFFFFFFFFFF
+ for _, t := range db.txs {
+ if t.meta.txid < minid {
+ minid = t.meta.txid
+ }
+ }
+ if minid > 0 {
+ db.freelist.release(minid - 1)
+ }
+
+ return t, nil
+}
+
+// removeTx removes a transaction from the database.
+func (db *DB) removeTx(tx *Tx) {
+ // Release the read lock on the mmap.
+ db.mmaplock.RUnlock()
+
+ // Use the meta lock to restrict access to the DB object.
+ db.metalock.Lock()
+
+ // Remove the transaction.
+ for i, t := range db.txs {
+ if t == tx {
+ db.txs = append(db.txs[:i], db.txs[i+1:]...)
+ break
+ }
+ }
+ n := len(db.txs)
+
+ // Unlock the meta pages.
+ db.metalock.Unlock()
+
+ // Merge statistics.
+ db.statlock.Lock()
+ db.stats.OpenTxN = n
+ db.stats.TxStats.add(&tx.stats)
+ db.statlock.Unlock()
+}
+
+// Update executes a function within the context of a read-write managed transaction.
+// If no error is returned from the function then the transaction is committed.
+// If an error is returned then the entire transaction is rolled back.
+// Any error that is returned from the function or returned from the commit is
+// returned from the Update() method.
+//
+// Attempting to manually commit or rollback within the function will cause a panic.
+func (db *DB) Update(fn func(*Tx) error) error {
+ t, err := db.Begin(true)
+ if err != nil {
+ return err
+ }
+
+ // Make sure the transaction rolls back in the event of a panic.
+ defer func() {
+ if t.db != nil {
+ t.rollback()
+ }
+ }()
+
+ // Mark as a managed tx so that the inner function cannot manually commit.
+ t.managed = true
+
+ // If an error is returned from the function then rollback and return error.
+ err = fn(t)
+ t.managed = false
+ if err != nil {
+ _ = t.Rollback()
+ return err
+ }
+
+ return t.Commit()
+}
+
+// View executes a function within the context of a managed read-only transaction.
+// Any error that is returned from the function is returned from the View() method.
+//
+// Attempting to manually rollback within the function will cause a panic.
+func (db *DB) View(fn func(*Tx) error) error {
+ t, err := db.Begin(false)
+ if err != nil {
+ return err
+ }
+
+ // Make sure the transaction rolls back in the event of a panic.
+ defer func() {
+ if t.db != nil {
+ t.rollback()
+ }
+ }()
+
+ // Mark as a managed tx so that the inner function cannot manually rollback.
+ t.managed = true
+
+ // If an error is returned from the function then pass it through.
+ err = fn(t)
+ t.managed = false
+ if err != nil {
+ _ = t.Rollback()
+ return err
+ }
+
+ if err := t.Rollback(); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// Batch calls fn as part of a batch. It behaves similar to Update,
+// except:
+//
+// 1. concurrent Batch calls can be combined into a single Bolt
+// transaction.
+//
+// 2. the function passed to Batch may be called multiple times,
+// regardless of whether it returns error or not.
+//
+// This means that Batch function side effects must be idempotent and
+// take permanent effect only after a successful return is seen in
+// caller.
+//
+// The maximum batch size and delay can be adjusted with DB.MaxBatchSize
+// and DB.MaxBatchDelay, respectively.
+//
+// Batch is only useful when there are multiple goroutines calling it.
+func (db *DB) Batch(fn func(*Tx) error) error {
+ errCh := make(chan error, 1)
+
+ db.batchMu.Lock()
+ if (db.batch == nil) || (db.batch != nil && len(db.batch.calls) >= db.MaxBatchSize) {
+ // There is no existing batch, or the existing batch is full; start a new one.
+ db.batch = &batch{
+ db: db,
+ }
+ db.batch.timer = time.AfterFunc(db.MaxBatchDelay, db.batch.trigger)
+ }
+ db.batch.calls = append(db.batch.calls, call{fn: fn, err: errCh})
+ if len(db.batch.calls) >= db.MaxBatchSize {
+ // wake up batch, it's ready to run
+ go db.batch.trigger()
+ }
+ db.batchMu.Unlock()
+
+ err := <-errCh
+ if err == trySolo {
+ err = db.Update(fn)
+ }
+ return err
+}
+
+type call struct {
+ fn func(*Tx) error
+ err chan<- error
+}
+
+type batch struct {
+ db *DB
+ timer *time.Timer
+ start sync.Once
+ calls []call
+}
+
+// trigger runs the batch if it hasn't already been run.
+func (b *batch) trigger() {
+ b.start.Do(b.run)
+}
+
+// run performs the transactions in the batch and communicates results
+// back to DB.Batch.
+func (b *batch) run() {
+ b.db.batchMu.Lock()
+ b.timer.Stop()
+ // Make sure no new work is added to this batch, but don't break
+ // other batches.
+ if b.db.batch == b {
+ b.db.batch = nil
+ }
+ b.db.batchMu.Unlock()
+
+retry:
+ for len(b.calls) > 0 {
+ var failIdx = -1
+ err := b.db.Update(func(tx *Tx) error {
+ for i, c := range b.calls {
+ if err := safelyCall(c.fn, tx); err != nil {
+ failIdx = i
+ return err
+ }
+ }
+ return nil
+ })
+
+ if failIdx >= 0 {
+ // take the failing transaction out of the batch. it's
+ // safe to shorten b.calls here because db.batch no longer
+ // points to us, and we hold the mutex anyway.
+ c := b.calls[failIdx]
+ b.calls[failIdx], b.calls = b.calls[len(b.calls)-1], b.calls[:len(b.calls)-1]
+ // tell the submitter re-run it solo, continue with the rest of the batch
+ c.err <- trySolo
+ continue retry
+ }
+
+ // pass success, or bolt internal errors, to all callers
+ for _, c := range b.calls {
+ if c.err != nil {
+ c.err <- err
+ }
+ }
+ break retry
+ }
+}
+
+// trySolo is a special sentinel error value used for signaling that a
+// transaction function should be re-run. It should never be seen by
+// callers.
+var trySolo = errors.New("batch function returned an error and should be re-run solo")
+
+type panicked struct {
+ reason interface{}
+}
+
+func (p panicked) Error() string {
+ if err, ok := p.reason.(error); ok {
+ return err.Error()
+ }
+ return fmt.Sprintf("panic: %v", p.reason)
+}
+
+func safelyCall(fn func(*Tx) error, tx *Tx) (err error) {
+ defer func() {
+ if p := recover(); p != nil {
+ err = panicked{p}
+ }
+ }()
+ return fn(tx)
+}
+
+// Sync executes fdatasync() against the database file handle.
+//
+// This is not necessary under normal operation, however, if you use NoSync
+// then it allows you to force the database file to sync against the disk.
+func (db *DB) Sync() error { return fdatasync(db) }
+
+// Stats retrieves ongoing performance stats for the database.
+// This is only updated when a transaction closes.
+func (db *DB) Stats() Stats {
+ db.statlock.RLock()
+ defer db.statlock.RUnlock()
+ return db.stats
+}
+
+// This is for internal access to the raw data bytes from the C cursor, use
+// carefully, or not at all.
+func (db *DB) Info() *Info {
+ return &Info{uintptr(unsafe.Pointer(&db.data[0])), db.pageSize}
+}
+
+// page retrieves a page reference from the mmap based on the current page size.
+func (db *DB) page(id pgid) *page {
+ pos := id * pgid(db.pageSize)
+ return (*page)(unsafe.Pointer(&db.data[pos]))
+}
+
+// pageInBuffer retrieves a page reference from a given byte array based on the current page size.
+func (db *DB) pageInBuffer(b []byte, id pgid) *page {
+ return (*page)(unsafe.Pointer(&b[id*pgid(db.pageSize)]))
+}
+
+// meta retrieves the current meta page reference.
+func (db *DB) meta() *meta {
+ // We have to return the meta with the highest txid which doesn't fail
+ // validation. Otherwise, we can cause errors when in fact the database is
+ // in a consistent state. metaA is the one with the higher txid.
+ metaA := db.meta0
+ metaB := db.meta1
+ if db.meta1.txid > db.meta0.txid {
+ metaA = db.meta1
+ metaB = db.meta0
+ }
+
+ // Use higher meta page if valid. Otherwise fallback to previous, if valid.
+ if err := metaA.validate(); err == nil {
+ return metaA
+ } else if err := metaB.validate(); err == nil {
+ return metaB
+ }
+
+ // This should never be reached, because both meta1 and meta0 were validated
+ // on mmap() and we do fsync() on every write.
+ panic("bolt.DB.meta(): invalid meta pages")
+}
+
+// allocate returns a contiguous block of memory starting at a given page.
+func (db *DB) allocate(count int) (*page, error) {
+ // Allocate a temporary buffer for the page.
+ var buf []byte
+ if count == 1 {
+ buf = db.pagePool.Get().([]byte)
+ } else {
+ buf = make([]byte, count*db.pageSize)
+ }
+ p := (*page)(unsafe.Pointer(&buf[0]))
+ p.overflow = uint32(count - 1)
+
+ // Use pages from the freelist if they are available.
+ if p.id = db.freelist.allocate(count); p.id != 0 {
+ return p, nil
+ }
+
+ // Resize mmap() if we're at the end.
+ p.id = db.rwtx.meta.pgid
+ var minsz = int((p.id+pgid(count))+1) * db.pageSize
+ if minsz >= db.datasz {
+ if err := db.mmap(minsz); err != nil {
+ return nil, fmt.Errorf("mmap allocate error: %s", err)
+ }
+ }
+
+ // Move the page id high water mark.
+ db.rwtx.meta.pgid += pgid(count)
+
+ return p, nil
+}
+
+// grow grows the size of the database to the given sz.
+func (db *DB) grow(sz int) error {
+ // Ignore if the new size is less than available file size.
+ if sz <= db.filesz {
+ return nil
+ }
+
+ // If the data is smaller than the alloc size then only allocate what's needed.
+ // Once it goes over the allocation size then allocate in chunks.
+ if db.datasz < db.AllocSize {
+ sz = db.datasz
+ } else {
+ sz += db.AllocSize
+ }
+
+ // Truncate and fsync to ensure file size metadata is flushed.
+ // https://github.com/boltdb/bolt/issues/284
+ if !db.NoGrowSync && !db.readOnly {
+ if runtime.GOOS != "windows" {
+ if err := db.file.Truncate(int64(sz)); err != nil {
+ return fmt.Errorf("file resize error: %s", err)
+ }
+ }
+ if err := db.file.Sync(); err != nil {
+ return fmt.Errorf("file sync error: %s", err)
+ }
+ }
+
+ db.filesz = sz
+ return nil
+}
+
+func (db *DB) IsReadOnly() bool {
+ return db.readOnly
+}
+
+// Options represents the options that can be set when opening a database.
+type Options struct {
+ // Timeout is the amount of time to wait to obtain a file lock.
+ // When set to zero it will wait indefinitely. This option is only
+ // available on Darwin and Linux.
+ Timeout time.Duration
+
+ // Sets the DB.NoGrowSync flag before memory mapping the file.
+ NoGrowSync bool
+
+ // Open database in read-only mode. Uses flock(..., LOCK_SH |LOCK_NB) to
+ // grab a shared lock (UNIX).
+ ReadOnly bool
+
+ // Sets the DB.MmapFlags flag before memory mapping the file.
+ MmapFlags int
+
+ // InitialMmapSize is the initial mmap size of the database
+ // in bytes. Read transactions won't block write transaction
+ // if the InitialMmapSize is large enough to hold database mmap
+ // size. (See DB.Begin for more information)
+ //
+ // If <=0, the initial map size is 0.
+ // If initialMmapSize is smaller than the previous database size,
+ // it takes no effect.
+ InitialMmapSize int
+}
+
+// DefaultOptions represent the options used if nil options are passed into Open().
+// No timeout is used which will cause Bolt to wait indefinitely for a lock.
+var DefaultOptions = &Options{
+ Timeout: 0,
+ NoGrowSync: false,
+}
+
+// Stats represents statistics about the database.
+type Stats struct {
+ // Freelist stats
+ FreePageN int // total number of free pages on the freelist
+ PendingPageN int // total number of pending pages on the freelist
+ FreeAlloc int // total bytes allocated in free pages
+ FreelistInuse int // total bytes used by the freelist
+
+ // Transaction stats
+ TxN int // total number of started read transactions
+ OpenTxN int // number of currently open read transactions
+
+ TxStats TxStats // global, ongoing stats.
+}
+
+// Sub calculates and returns the difference between two sets of database stats.
+// This is useful when obtaining stats at two different points and time and
+// you need the performance counters that occurred within that time span.
+func (s *Stats) Sub(other *Stats) Stats {
+ if other == nil {
+ return *s
+ }
+ var diff Stats
+ diff.FreePageN = s.FreePageN
+ diff.PendingPageN = s.PendingPageN
+ diff.FreeAlloc = s.FreeAlloc
+ diff.FreelistInuse = s.FreelistInuse
+ diff.TxN = s.TxN - other.TxN
+ diff.TxStats = s.TxStats.Sub(&other.TxStats)
+ return diff
+}
+
+func (s *Stats) add(other *Stats) {
+ s.TxStats.add(&other.TxStats)
+}
+
+type Info struct {
+ Data uintptr
+ PageSize int
+}
+
+type meta struct {
+ magic uint32
+ version uint32
+ pageSize uint32
+ flags uint32
+ root bucket
+ freelist pgid
+ pgid pgid
+ txid txid
+ checksum uint64
+}
+
+// validate checks the marker bytes and version of the meta page to ensure it matches this binary.
+func (m *meta) validate() error {
+ if m.magic != magic {
+ return ErrInvalid
+ } else if m.version != version {
+ return ErrVersionMismatch
+ } else if m.checksum != 0 && m.checksum != m.sum64() {
+ return ErrChecksum
+ }
+ return nil
+}
+
+// copy copies one meta object to another.
+func (m *meta) copy(dest *meta) {
+ *dest = *m
+}
+
+// write writes the meta onto a page.
+func (m *meta) write(p *page) {
+ if m.root.root >= m.pgid {
+ panic(fmt.Sprintf("root bucket pgid (%d) above high water mark (%d)", m.root.root, m.pgid))
+ } else if m.freelist >= m.pgid {
+ panic(fmt.Sprintf("freelist pgid (%d) above high water mark (%d)", m.freelist, m.pgid))
+ }
+
+ // Page id is either going to be 0 or 1 which we can determine by the transaction ID.
+ p.id = pgid(m.txid % 2)
+ p.flags |= metaPageFlag
+
+ // Calculate the checksum.
+ m.checksum = m.sum64()
+
+ m.copy(p.meta())
+}
+
+// generates the checksum for the meta.
+func (m *meta) sum64() uint64 {
+ var h = fnv.New64a()
+ _, _ = h.Write((*[unsafe.Offsetof(meta{}.checksum)]byte)(unsafe.Pointer(m))[:])
+ return h.Sum64()
+}
+
+// _assert will panic with a given formatted message if the given condition is false.
+func _assert(condition bool, msg string, v ...interface{}) {
+ if !condition {
+ panic(fmt.Sprintf("assertion failed: "+msg, v...))
+ }
+}
+
+func warn(v ...interface{}) { fmt.Fprintln(os.Stderr, v...) }
+func warnf(msg string, v ...interface{}) { fmt.Fprintf(os.Stderr, msg+"\n", v...) }
+
+func printstack() {
+ stack := strings.Join(strings.Split(string(debug.Stack()), "\n")[2:], "\n")
+ fmt.Fprintln(os.Stderr, stack)
+}
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/db_test.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/db_test.go
new file mode 100644
index 0000000..74ff93a
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/db_test.go
@@ -0,0 +1,1706 @@
+package bolt_test
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+ "flag"
+ "fmt"
+ "hash/fnv"
+ "io/ioutil"
+ "log"
+ "os"
+ "path/filepath"
+ "regexp"
+ "runtime"
+ "sort"
+ "strings"
+ "sync"
+ "testing"
+ "time"
+ "unsafe"
+
+ "github.com/boltdb/bolt"
+)
+
+var statsFlag = flag.Bool("stats", false, "show performance stats")
+
+// version is the data file format version.
+const version = 2
+
+// magic is the marker value to indicate that a file is a Bolt DB.
+const magic uint32 = 0xED0CDAED
+
+// pageSize is the size of one page in the data file.
+const pageSize = 4096
+
+// pageHeaderSize is the size of a page header.
+const pageHeaderSize = 16
+
+// meta represents a simplified version of a database meta page for testing.
+type meta struct {
+ magic uint32
+ version uint32
+ _ uint32
+ _ uint32
+ _ [16]byte
+ _ uint64
+ pgid uint64
+ _ uint64
+ checksum uint64
+}
+
+// Ensure that a database can be opened without error.
+func TestOpen(t *testing.T) {
+ path := tempfile()
+ db, err := bolt.Open(path, 0666, nil)
+ if err != nil {
+ t.Fatal(err)
+ } else if db == nil {
+ t.Fatal("expected db")
+ }
+
+ if s := db.Path(); s != path {
+ t.Fatalf("unexpected path: %s", s)
+ }
+
+ if err := db.Close(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that opening a database with a blank path returns an error.
+func TestOpen_ErrPathRequired(t *testing.T) {
+ _, err := bolt.Open("", 0666, nil)
+ if err == nil {
+ t.Fatalf("expected error")
+ }
+}
+
+// Ensure that opening a database with a bad path returns an error.
+func TestOpen_ErrNotExists(t *testing.T) {
+ _, err := bolt.Open(filepath.Join(tempfile(), "bad-path"), 0666, nil)
+ if err == nil {
+ t.Fatal("expected error")
+ }
+}
+
+// Ensure that opening a file that is not a Bolt database returns ErrInvalid.
+func TestOpen_ErrInvalid(t *testing.T) {
+ path := tempfile()
+
+ f, err := os.Create(path)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if _, err := fmt.Fprintln(f, "this is not a bolt database"); err != nil {
+ t.Fatal(err)
+ }
+ if err := f.Close(); err != nil {
+ t.Fatal(err)
+ }
+ defer os.Remove(path)
+
+ if _, err := bolt.Open(path, 0666, nil); err != bolt.ErrInvalid {
+ t.Fatalf("unexpected error: %s", err)
+ }
+}
+
+// Ensure that opening a file with two invalid versions returns ErrVersionMismatch.
+func TestOpen_ErrVersionMismatch(t *testing.T) {
+ if pageSize != os.Getpagesize() {
+ t.Skip("page size mismatch")
+ }
+
+ // Create empty database.
+ db := MustOpenDB()
+ path := db.Path()
+ defer db.MustClose()
+
+ // Close database.
+ if err := db.DB.Close(); err != nil {
+ t.Fatal(err)
+ }
+
+ // Read data file.
+ buf, err := ioutil.ReadFile(path)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Rewrite meta pages.
+ meta0 := (*meta)(unsafe.Pointer(&buf[pageHeaderSize]))
+ meta0.version++
+ meta1 := (*meta)(unsafe.Pointer(&buf[pageSize+pageHeaderSize]))
+ meta1.version++
+ if err := ioutil.WriteFile(path, buf, 0666); err != nil {
+ t.Fatal(err)
+ }
+
+ // Reopen data file.
+ if _, err := bolt.Open(path, 0666, nil); err != bolt.ErrVersionMismatch {
+ t.Fatalf("unexpected error: %s", err)
+ }
+}
+
+// Ensure that opening a file with two invalid checksums returns ErrChecksum.
+func TestOpen_ErrChecksum(t *testing.T) {
+ if pageSize != os.Getpagesize() {
+ t.Skip("page size mismatch")
+ }
+
+ // Create empty database.
+ db := MustOpenDB()
+ path := db.Path()
+ defer db.MustClose()
+
+ // Close database.
+ if err := db.DB.Close(); err != nil {
+ t.Fatal(err)
+ }
+
+ // Read data file.
+ buf, err := ioutil.ReadFile(path)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Rewrite meta pages.
+ meta0 := (*meta)(unsafe.Pointer(&buf[pageHeaderSize]))
+ meta0.pgid++
+ meta1 := (*meta)(unsafe.Pointer(&buf[pageSize+pageHeaderSize]))
+ meta1.pgid++
+ if err := ioutil.WriteFile(path, buf, 0666); err != nil {
+ t.Fatal(err)
+ }
+
+ // Reopen data file.
+ if _, err := bolt.Open(path, 0666, nil); err != bolt.ErrChecksum {
+ t.Fatalf("unexpected error: %s", err)
+ }
+}
+
+// Ensure that opening an already open database file will timeout.
+func TestOpen_Timeout(t *testing.T) {
+ if runtime.GOOS == "solaris" {
+ t.Skip("solaris fcntl locks don't support intra-process locking")
+ }
+
+ path := tempfile()
+
+ // Open a data file.
+ db0, err := bolt.Open(path, 0666, nil)
+ if err != nil {
+ t.Fatal(err)
+ } else if db0 == nil {
+ t.Fatal("expected database")
+ }
+
+ // Attempt to open the database again.
+ start := time.Now()
+ db1, err := bolt.Open(path, 0666, &bolt.Options{Timeout: 100 * time.Millisecond})
+ if err != bolt.ErrTimeout {
+ t.Fatalf("unexpected timeout: %s", err)
+ } else if db1 != nil {
+ t.Fatal("unexpected database")
+ } else if time.Since(start) <= 100*time.Millisecond {
+ t.Fatal("expected to wait at least timeout duration")
+ }
+
+ if err := db0.Close(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that opening an already open database file will wait until its closed.
+func TestOpen_Wait(t *testing.T) {
+ if runtime.GOOS == "solaris" {
+ t.Skip("solaris fcntl locks don't support intra-process locking")
+ }
+
+ path := tempfile()
+
+ // Open a data file.
+ db0, err := bolt.Open(path, 0666, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Close it in just a bit.
+ time.AfterFunc(100*time.Millisecond, func() { _ = db0.Close() })
+
+ // Attempt to open the database again.
+ start := time.Now()
+ db1, err := bolt.Open(path, 0666, &bolt.Options{Timeout: 200 * time.Millisecond})
+ if err != nil {
+ t.Fatal(err)
+ } else if time.Since(start) <= 100*time.Millisecond {
+ t.Fatal("expected to wait at least timeout duration")
+ }
+
+ if err := db1.Close(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that opening a database does not increase its size.
+// https://github.com/boltdb/bolt/issues/291
+func TestOpen_Size(t *testing.T) {
+ // Open a data file.
+ db := MustOpenDB()
+ path := db.Path()
+ defer db.MustClose()
+
+ pagesize := db.Info().PageSize
+
+ // Insert until we get above the minimum 4MB size.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, _ := tx.CreateBucketIfNotExists([]byte("data"))
+ for i := 0; i < 10000; i++ {
+ if err := b.Put([]byte(fmt.Sprintf("%04d", i)), make([]byte, 1000)); err != nil {
+ t.Fatal(err)
+ }
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ // Close database and grab the size.
+ if err := db.DB.Close(); err != nil {
+ t.Fatal(err)
+ }
+ sz := fileSize(path)
+ if sz == 0 {
+ t.Fatalf("unexpected new file size: %d", sz)
+ }
+
+ // Reopen database, update, and check size again.
+ db0, err := bolt.Open(path, 0666, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := db0.Update(func(tx *bolt.Tx) error {
+ if err := tx.Bucket([]byte("data")).Put([]byte{0}, []byte{0}); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+ if err := db0.Close(); err != nil {
+ t.Fatal(err)
+ }
+ newSz := fileSize(path)
+ if newSz == 0 {
+ t.Fatalf("unexpected new file size: %d", newSz)
+ }
+
+ // Compare the original size with the new size.
+ // db size might increase by a few page sizes due to the new small update.
+ if sz < newSz-5*int64(pagesize) {
+ t.Fatalf("unexpected file growth: %d => %d", sz, newSz)
+ }
+}
+
+// Ensure that opening a database beyond the max step size does not increase its size.
+// https://github.com/boltdb/bolt/issues/303
+func TestOpen_Size_Large(t *testing.T) {
+ if testing.Short() {
+ t.Skip("short mode")
+ }
+
+ // Open a data file.
+ db := MustOpenDB()
+ path := db.Path()
+ defer db.MustClose()
+
+ pagesize := db.Info().PageSize
+
+ // Insert until we get above the minimum 4MB size.
+ var index uint64
+ for i := 0; i < 10000; i++ {
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, _ := tx.CreateBucketIfNotExists([]byte("data"))
+ for j := 0; j < 1000; j++ {
+ if err := b.Put(u64tob(index), make([]byte, 50)); err != nil {
+ t.Fatal(err)
+ }
+ index++
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ // Close database and grab the size.
+ if err := db.DB.Close(); err != nil {
+ t.Fatal(err)
+ }
+ sz := fileSize(path)
+ if sz == 0 {
+ t.Fatalf("unexpected new file size: %d", sz)
+ } else if sz < (1 << 30) {
+ t.Fatalf("expected larger initial size: %d", sz)
+ }
+
+ // Reopen database, update, and check size again.
+ db0, err := bolt.Open(path, 0666, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := db0.Update(func(tx *bolt.Tx) error {
+ return tx.Bucket([]byte("data")).Put([]byte{0}, []byte{0})
+ }); err != nil {
+ t.Fatal(err)
+ }
+ if err := db0.Close(); err != nil {
+ t.Fatal(err)
+ }
+
+ newSz := fileSize(path)
+ if newSz == 0 {
+ t.Fatalf("unexpected new file size: %d", newSz)
+ }
+
+ // Compare the original size with the new size.
+ // db size might increase by a few page sizes due to the new small update.
+ if sz < newSz-5*int64(pagesize) {
+ t.Fatalf("unexpected file growth: %d => %d", sz, newSz)
+ }
+}
+
+// Ensure that a re-opened database is consistent.
+func TestOpen_Check(t *testing.T) {
+ path := tempfile()
+
+ db, err := bolt.Open(path, 0666, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := db.View(func(tx *bolt.Tx) error { return <-tx.Check() }); err != nil {
+ t.Fatal(err)
+ }
+ if err := db.Close(); err != nil {
+ t.Fatal(err)
+ }
+
+ db, err = bolt.Open(path, 0666, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := db.View(func(tx *bolt.Tx) error { return <-tx.Check() }); err != nil {
+ t.Fatal(err)
+ }
+ if err := db.Close(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that write errors to the meta file handler during initialization are returned.
+func TestOpen_MetaInitWriteError(t *testing.T) {
+ t.Skip("pending")
+}
+
+// Ensure that a database that is too small returns an error.
+func TestOpen_FileTooSmall(t *testing.T) {
+ path := tempfile()
+
+ db, err := bolt.Open(path, 0666, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := db.Close(); err != nil {
+ t.Fatal(err)
+ }
+
+ // corrupt the database
+ if err := os.Truncate(path, int64(os.Getpagesize())); err != nil {
+ t.Fatal(err)
+ }
+
+ db, err = bolt.Open(path, 0666, nil)
+ if err == nil || err.Error() != "file size too small" {
+ t.Fatalf("unexpected error: %s", err)
+ }
+}
+
+// Ensure that a database can be opened in read-only mode by multiple processes
+// and that a database can not be opened in read-write mode and in read-only
+// mode at the same time.
+func TestOpen_ReadOnly(t *testing.T) {
+ if runtime.GOOS == "solaris" {
+ t.Skip("solaris fcntl locks don't support intra-process locking")
+ }
+
+ bucket, key, value := []byte(`bucket`), []byte(`key`), []byte(`value`)
+
+ path := tempfile()
+
+ // Open in read-write mode.
+ db, err := bolt.Open(path, 0666, nil)
+ if err != nil {
+ t.Fatal(err)
+ } else if db.IsReadOnly() {
+ t.Fatal("db should not be in read only mode")
+ }
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket(bucket)
+ if err != nil {
+ return err
+ }
+ if err := b.Put(key, value); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+ if err := db.Close(); err != nil {
+ t.Fatal(err)
+ }
+
+ // Open in read-only mode.
+ db0, err := bolt.Open(path, 0666, &bolt.Options{ReadOnly: true})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Opening in read-write mode should return an error.
+ if _, err = bolt.Open(path, 0666, &bolt.Options{Timeout: time.Millisecond * 100}); err == nil {
+ t.Fatal("expected error")
+ }
+
+ // And again (in read-only mode).
+ db1, err := bolt.Open(path, 0666, &bolt.Options{ReadOnly: true})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Verify both read-only databases are accessible.
+ for _, db := range []*bolt.DB{db0, db1} {
+ // Verify is is in read only mode indeed.
+ if !db.IsReadOnly() {
+ t.Fatal("expected read only mode")
+ }
+
+ // Read-only databases should not allow updates.
+ if err := db.Update(func(*bolt.Tx) error {
+ panic(`should never get here`)
+ }); err != bolt.ErrDatabaseReadOnly {
+ t.Fatalf("unexpected error: %s", err)
+ }
+
+ // Read-only databases should not allow beginning writable txns.
+ if _, err := db.Begin(true); err != bolt.ErrDatabaseReadOnly {
+ t.Fatalf("unexpected error: %s", err)
+ }
+
+ // Verify the data.
+ if err := db.View(func(tx *bolt.Tx) error {
+ b := tx.Bucket(bucket)
+ if b == nil {
+ return fmt.Errorf("expected bucket `%s`", string(bucket))
+ }
+
+ got := string(b.Get(key))
+ expected := string(value)
+ if got != expected {
+ return fmt.Errorf("expected `%s`, got `%s`", expected, got)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ if err := db0.Close(); err != nil {
+ t.Fatal(err)
+ }
+ if err := db1.Close(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// TestDB_Open_InitialMmapSize tests if having InitialMmapSize large enough
+// to hold data from concurrent write transaction resolves the issue that
+// read transaction blocks the write transaction and causes deadlock.
+// This is a very hacky test since the mmap size is not exposed.
+func TestDB_Open_InitialMmapSize(t *testing.T) {
+ path := tempfile()
+ defer os.Remove(path)
+
+ initMmapSize := 1 << 31 // 2GB
+ testWriteSize := 1 << 27 // 134MB
+
+ db, err := bolt.Open(path, 0666, &bolt.Options{InitialMmapSize: initMmapSize})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // create a long-running read transaction
+ // that never gets closed while writing
+ rtx, err := db.Begin(false)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // create a write transaction
+ wtx, err := db.Begin(true)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ b, err := wtx.CreateBucket([]byte("test"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // and commit a large write
+ err = b.Put([]byte("foo"), make([]byte, testWriteSize))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ done := make(chan struct{})
+
+ go func() {
+ if err := wtx.Commit(); err != nil {
+ t.Fatal(err)
+ }
+ done <- struct{}{}
+ }()
+
+ select {
+ case <-time.After(5 * time.Second):
+ t.Errorf("unexpected that the reader blocks writer")
+ case <-done:
+ }
+
+ if err := rtx.Rollback(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a database cannot open a transaction when it's not open.
+func TestDB_Begin_ErrDatabaseNotOpen(t *testing.T) {
+ var db bolt.DB
+ if _, err := db.Begin(false); err != bolt.ErrDatabaseNotOpen {
+ t.Fatalf("unexpected error: %s", err)
+ }
+}
+
+// Ensure that a read-write transaction can be retrieved.
+func TestDB_BeginRW(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ tx, err := db.Begin(true)
+ if err != nil {
+ t.Fatal(err)
+ } else if tx == nil {
+ t.Fatal("expected tx")
+ }
+
+ if tx.DB() != db.DB {
+ t.Fatal("unexpected tx database")
+ } else if !tx.Writable() {
+ t.Fatal("expected writable tx")
+ }
+
+ if err := tx.Commit(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that opening a transaction while the DB is closed returns an error.
+func TestDB_BeginRW_Closed(t *testing.T) {
+ var db bolt.DB
+ if _, err := db.Begin(true); err != bolt.ErrDatabaseNotOpen {
+ t.Fatalf("unexpected error: %s", err)
+ }
+}
+
+func TestDB_Close_PendingTx_RW(t *testing.T) { testDB_Close_PendingTx(t, true) }
+func TestDB_Close_PendingTx_RO(t *testing.T) { testDB_Close_PendingTx(t, false) }
+
+// Ensure that a database cannot close while transactions are open.
+func testDB_Close_PendingTx(t *testing.T, writable bool) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ // Start transaction.
+ tx, err := db.Begin(true)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Open update in separate goroutine.
+ done := make(chan struct{})
+ go func() {
+ if err := db.Close(); err != nil {
+ t.Fatal(err)
+ }
+ close(done)
+ }()
+
+ // Ensure database hasn't closed.
+ time.Sleep(100 * time.Millisecond)
+ select {
+ case <-done:
+ t.Fatal("database closed too early")
+ default:
+ }
+
+ // Commit transaction.
+ if err := tx.Commit(); err != nil {
+ t.Fatal(err)
+ }
+
+ // Ensure database closed now.
+ time.Sleep(100 * time.Millisecond)
+ select {
+ case <-done:
+ default:
+ t.Fatal("database did not close")
+ }
+}
+
+// Ensure a database can provide a transactional block.
+func TestDB_Update(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("baz"), []byte("bat")); err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Delete([]byte("foo")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+ if err := db.View(func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("widgets"))
+ if v := b.Get([]byte("foo")); v != nil {
+ t.Fatalf("expected nil value, got: %v", v)
+ }
+ if v := b.Get([]byte("baz")); !bytes.Equal(v, []byte("bat")) {
+ t.Fatalf("unexpected value: %v", v)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure a closed database returns an error while running a transaction block
+func TestDB_Update_Closed(t *testing.T) {
+ var db bolt.DB
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if _, err := tx.CreateBucket([]byte("widgets")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != bolt.ErrDatabaseNotOpen {
+ t.Fatalf("unexpected error: %s", err)
+ }
+}
+
+// Ensure a panic occurs while trying to commit a managed transaction.
+func TestDB_Update_ManualCommit(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ var panicked bool
+ if err := db.Update(func(tx *bolt.Tx) error {
+ func() {
+ defer func() {
+ if r := recover(); r != nil {
+ panicked = true
+ }
+ }()
+
+ if err := tx.Commit(); err != nil {
+ t.Fatal(err)
+ }
+ }()
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ } else if !panicked {
+ t.Fatal("expected panic")
+ }
+}
+
+// Ensure a panic occurs while trying to rollback a managed transaction.
+func TestDB_Update_ManualRollback(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ var panicked bool
+ if err := db.Update(func(tx *bolt.Tx) error {
+ func() {
+ defer func() {
+ if r := recover(); r != nil {
+ panicked = true
+ }
+ }()
+
+ if err := tx.Rollback(); err != nil {
+ t.Fatal(err)
+ }
+ }()
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ } else if !panicked {
+ t.Fatal("expected panic")
+ }
+}
+
+// Ensure a panic occurs while trying to commit a managed transaction.
+func TestDB_View_ManualCommit(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ var panicked bool
+ if err := db.View(func(tx *bolt.Tx) error {
+ func() {
+ defer func() {
+ if r := recover(); r != nil {
+ panicked = true
+ }
+ }()
+
+ if err := tx.Commit(); err != nil {
+ t.Fatal(err)
+ }
+ }()
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ } else if !panicked {
+ t.Fatal("expected panic")
+ }
+}
+
+// Ensure a panic occurs while trying to rollback a managed transaction.
+func TestDB_View_ManualRollback(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ var panicked bool
+ if err := db.View(func(tx *bolt.Tx) error {
+ func() {
+ defer func() {
+ if r := recover(); r != nil {
+ panicked = true
+ }
+ }()
+
+ if err := tx.Rollback(); err != nil {
+ t.Fatal(err)
+ }
+ }()
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ } else if !panicked {
+ t.Fatal("expected panic")
+ }
+}
+
+// Ensure a write transaction that panics does not hold open locks.
+func TestDB_Update_Panic(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ // Panic during update but recover.
+ func() {
+ defer func() {
+ if r := recover(); r != nil {
+ t.Log("recover: update", r)
+ }
+ }()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if _, err := tx.CreateBucket([]byte("widgets")); err != nil {
+ t.Fatal(err)
+ }
+ panic("omg")
+ }); err != nil {
+ t.Fatal(err)
+ }
+ }()
+
+ // Verify we can update again.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if _, err := tx.CreateBucket([]byte("widgets")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ // Verify that our change persisted.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if tx.Bucket([]byte("widgets")) == nil {
+ t.Fatal("expected bucket")
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure a database can return an error through a read-only transactional block.
+func TestDB_View_Error(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.View(func(tx *bolt.Tx) error {
+ return errors.New("xxx")
+ }); err == nil || err.Error() != "xxx" {
+ t.Fatalf("unexpected error: %s", err)
+ }
+}
+
+// Ensure a read transaction that panics does not hold open locks.
+func TestDB_View_Panic(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if _, err := tx.CreateBucket([]byte("widgets")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ // Panic during view transaction but recover.
+ func() {
+ defer func() {
+ if r := recover(); r != nil {
+ t.Log("recover: view", r)
+ }
+ }()
+
+ if err := db.View(func(tx *bolt.Tx) error {
+ if tx.Bucket([]byte("widgets")) == nil {
+ t.Fatal("expected bucket")
+ }
+ panic("omg")
+ }); err != nil {
+ t.Fatal(err)
+ }
+ }()
+
+ // Verify that we can still use read transactions.
+ if err := db.View(func(tx *bolt.Tx) error {
+ if tx.Bucket([]byte("widgets")) == nil {
+ t.Fatal("expected bucket")
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that DB stats can be returned.
+func TestDB_Stats(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ _, err := tx.CreateBucket([]byte("widgets"))
+ return err
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ stats := db.Stats()
+ if stats.TxStats.PageCount != 2 {
+ t.Fatalf("unexpected TxStats.PageCount: %d", stats.TxStats.PageCount)
+ } else if stats.FreePageN != 0 {
+ t.Fatalf("unexpected FreePageN != 0: %d", stats.FreePageN)
+ } else if stats.PendingPageN != 2 {
+ t.Fatalf("unexpected PendingPageN != 2: %d", stats.PendingPageN)
+ }
+}
+
+// Ensure that database pages are in expected order and type.
+func TestDB_Consistency(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ _, err := tx.CreateBucket([]byte("widgets"))
+ return err
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ for i := 0; i < 10; i++ {
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if err := tx.Bucket([]byte("widgets")).Put([]byte("foo"), []byte("bar")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if p, _ := tx.Page(0); p == nil {
+ t.Fatal("expected page")
+ } else if p.Type != "meta" {
+ t.Fatalf("unexpected page type: %s", p.Type)
+ }
+
+ if p, _ := tx.Page(1); p == nil {
+ t.Fatal("expected page")
+ } else if p.Type != "meta" {
+ t.Fatalf("unexpected page type: %s", p.Type)
+ }
+
+ if p, _ := tx.Page(2); p == nil {
+ t.Fatal("expected page")
+ } else if p.Type != "free" {
+ t.Fatalf("unexpected page type: %s", p.Type)
+ }
+
+ if p, _ := tx.Page(3); p == nil {
+ t.Fatal("expected page")
+ } else if p.Type != "free" {
+ t.Fatalf("unexpected page type: %s", p.Type)
+ }
+
+ if p, _ := tx.Page(4); p == nil {
+ t.Fatal("expected page")
+ } else if p.Type != "leaf" {
+ t.Fatalf("unexpected page type: %s", p.Type)
+ }
+
+ if p, _ := tx.Page(5); p == nil {
+ t.Fatal("expected page")
+ } else if p.Type != "freelist" {
+ t.Fatalf("unexpected page type: %s", p.Type)
+ }
+
+ if p, _ := tx.Page(6); p != nil {
+ t.Fatal("unexpected page")
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that DB stats can be subtracted from one another.
+func TestDBStats_Sub(t *testing.T) {
+ var a, b bolt.Stats
+ a.TxStats.PageCount = 3
+ a.FreePageN = 4
+ b.TxStats.PageCount = 10
+ b.FreePageN = 14
+ diff := b.Sub(&a)
+ if diff.TxStats.PageCount != 7 {
+ t.Fatalf("unexpected TxStats.PageCount: %d", diff.TxStats.PageCount)
+ }
+
+ // free page stats are copied from the receiver and not subtracted
+ if diff.FreePageN != 14 {
+ t.Fatalf("unexpected FreePageN: %d", diff.FreePageN)
+ }
+}
+
+// Ensure two functions can perform updates in a single batch.
+func TestDB_Batch(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if _, err := tx.CreateBucket([]byte("widgets")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ // Iterate over multiple updates in separate goroutines.
+ n := 2
+ ch := make(chan error)
+ for i := 0; i < n; i++ {
+ go func(i int) {
+ ch <- db.Batch(func(tx *bolt.Tx) error {
+ return tx.Bucket([]byte("widgets")).Put(u64tob(uint64(i)), []byte{})
+ })
+ }(i)
+ }
+
+ // Check all responses to make sure there's no error.
+ for i := 0; i < n; i++ {
+ if err := <-ch; err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ // Ensure data is correct.
+ if err := db.View(func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("widgets"))
+ for i := 0; i < n; i++ {
+ if v := b.Get(u64tob(uint64(i))); v == nil {
+ t.Errorf("key not found: %d", i)
+ }
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestDB_Batch_Panic(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ var sentinel int
+ var bork = &sentinel
+ var problem interface{}
+ var err error
+
+ // Execute a function inside a batch that panics.
+ func() {
+ defer func() {
+ if p := recover(); p != nil {
+ problem = p
+ }
+ }()
+ err = db.Batch(func(tx *bolt.Tx) error {
+ panic(bork)
+ })
+ }()
+
+ // Verify there is no error.
+ if g, e := err, error(nil); g != e {
+ t.Fatalf("wrong error: %v != %v", g, e)
+ }
+ // Verify the panic was captured.
+ if g, e := problem, bork; g != e {
+ t.Fatalf("wrong error: %v != %v", g, e)
+ }
+}
+
+func TestDB_BatchFull(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ _, err := tx.CreateBucket([]byte("widgets"))
+ return err
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ const size = 3
+ // buffered so we never leak goroutines
+ ch := make(chan error, size)
+ put := func(i int) {
+ ch <- db.Batch(func(tx *bolt.Tx) error {
+ return tx.Bucket([]byte("widgets")).Put(u64tob(uint64(i)), []byte{})
+ })
+ }
+
+ db.MaxBatchSize = size
+ // high enough to never trigger here
+ db.MaxBatchDelay = 1 * time.Hour
+
+ go put(1)
+ go put(2)
+
+ // Give the batch a chance to exhibit bugs.
+ time.Sleep(10 * time.Millisecond)
+
+ // not triggered yet
+ select {
+ case <-ch:
+ t.Fatalf("batch triggered too early")
+ default:
+ }
+
+ go put(3)
+
+ // Check all responses to make sure there's no error.
+ for i := 0; i < size; i++ {
+ if err := <-ch; err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ // Ensure data is correct.
+ if err := db.View(func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("widgets"))
+ for i := 1; i <= size; i++ {
+ if v := b.Get(u64tob(uint64(i))); v == nil {
+ t.Errorf("key not found: %d", i)
+ }
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestDB_BatchTime(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ _, err := tx.CreateBucket([]byte("widgets"))
+ return err
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ const size = 1
+ // buffered so we never leak goroutines
+ ch := make(chan error, size)
+ put := func(i int) {
+ ch <- db.Batch(func(tx *bolt.Tx) error {
+ return tx.Bucket([]byte("widgets")).Put(u64tob(uint64(i)), []byte{})
+ })
+ }
+
+ db.MaxBatchSize = 1000
+ db.MaxBatchDelay = 0
+
+ go put(1)
+
+ // Batch must trigger by time alone.
+
+ // Check all responses to make sure there's no error.
+ for i := 0; i < size; i++ {
+ if err := <-ch; err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ // Ensure data is correct.
+ if err := db.View(func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("widgets"))
+ for i := 1; i <= size; i++ {
+ if v := b.Get(u64tob(uint64(i))); v == nil {
+ t.Errorf("key not found: %d", i)
+ }
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func ExampleDB_Update() {
+ // Open the database.
+ db, err := bolt.Open(tempfile(), 0666, nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer os.Remove(db.Path())
+
+ // Execute several commands within a read-write transaction.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ return err
+ }
+ if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
+ return err
+ }
+ return nil
+ }); err != nil {
+ log.Fatal(err)
+ }
+
+ // Read the value back from a separate read-only transaction.
+ if err := db.View(func(tx *bolt.Tx) error {
+ value := tx.Bucket([]byte("widgets")).Get([]byte("foo"))
+ fmt.Printf("The value of 'foo' is: %s\n", value)
+ return nil
+ }); err != nil {
+ log.Fatal(err)
+ }
+
+ // Close database to release the file lock.
+ if err := db.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ // Output:
+ // The value of 'foo' is: bar
+}
+
+func ExampleDB_View() {
+ // Open the database.
+ db, err := bolt.Open(tempfile(), 0666, nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer os.Remove(db.Path())
+
+ // Insert data into a bucket.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("people"))
+ if err != nil {
+ return err
+ }
+ if err := b.Put([]byte("john"), []byte("doe")); err != nil {
+ return err
+ }
+ if err := b.Put([]byte("susy"), []byte("que")); err != nil {
+ return err
+ }
+ return nil
+ }); err != nil {
+ log.Fatal(err)
+ }
+
+ // Access data from within a read-only transactional block.
+ if err := db.View(func(tx *bolt.Tx) error {
+ v := tx.Bucket([]byte("people")).Get([]byte("john"))
+ fmt.Printf("John's last name is %s.\n", v)
+ return nil
+ }); err != nil {
+ log.Fatal(err)
+ }
+
+ // Close database to release the file lock.
+ if err := db.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ // Output:
+ // John's last name is doe.
+}
+
+func ExampleDB_Begin_ReadOnly() {
+ // Open the database.
+ db, err := bolt.Open(tempfile(), 0666, nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer os.Remove(db.Path())
+
+ // Create a bucket using a read-write transaction.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ _, err := tx.CreateBucket([]byte("widgets"))
+ return err
+ }); err != nil {
+ log.Fatal(err)
+ }
+
+ // Create several keys in a transaction.
+ tx, err := db.Begin(true)
+ if err != nil {
+ log.Fatal(err)
+ }
+ b := tx.Bucket([]byte("widgets"))
+ if err := b.Put([]byte("john"), []byte("blue")); err != nil {
+ log.Fatal(err)
+ }
+ if err := b.Put([]byte("abby"), []byte("red")); err != nil {
+ log.Fatal(err)
+ }
+ if err := b.Put([]byte("zephyr"), []byte("purple")); err != nil {
+ log.Fatal(err)
+ }
+ if err := tx.Commit(); err != nil {
+ log.Fatal(err)
+ }
+
+ // Iterate over the values in sorted key order.
+ tx, err = db.Begin(false)
+ if err != nil {
+ log.Fatal(err)
+ }
+ c := tx.Bucket([]byte("widgets")).Cursor()
+ for k, v := c.First(); k != nil; k, v = c.Next() {
+ fmt.Printf("%s likes %s\n", k, v)
+ }
+
+ if err := tx.Rollback(); err != nil {
+ log.Fatal(err)
+ }
+
+ if err := db.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ // Output:
+ // abby likes red
+ // john likes blue
+ // zephyr likes purple
+}
+
+func BenchmarkDBBatchAutomatic(b *testing.B) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ _, err := tx.CreateBucket([]byte("bench"))
+ return err
+ }); err != nil {
+ b.Fatal(err)
+ }
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ start := make(chan struct{})
+ var wg sync.WaitGroup
+
+ for round := 0; round < 1000; round++ {
+ wg.Add(1)
+
+ go func(id uint32) {
+ defer wg.Done()
+ <-start
+
+ h := fnv.New32a()
+ buf := make([]byte, 4)
+ binary.LittleEndian.PutUint32(buf, id)
+ _, _ = h.Write(buf[:])
+ k := h.Sum(nil)
+ insert := func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("bench"))
+ return b.Put(k, []byte("filler"))
+ }
+ if err := db.Batch(insert); err != nil {
+ b.Error(err)
+ return
+ }
+ }(uint32(round))
+ }
+ close(start)
+ wg.Wait()
+ }
+
+ b.StopTimer()
+ validateBatchBench(b, db)
+}
+
+func BenchmarkDBBatchSingle(b *testing.B) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ _, err := tx.CreateBucket([]byte("bench"))
+ return err
+ }); err != nil {
+ b.Fatal(err)
+ }
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ start := make(chan struct{})
+ var wg sync.WaitGroup
+
+ for round := 0; round < 1000; round++ {
+ wg.Add(1)
+ go func(id uint32) {
+ defer wg.Done()
+ <-start
+
+ h := fnv.New32a()
+ buf := make([]byte, 4)
+ binary.LittleEndian.PutUint32(buf, id)
+ _, _ = h.Write(buf[:])
+ k := h.Sum(nil)
+ insert := func(tx *bolt.Tx) error {
+ b := tx.Bucket([]byte("bench"))
+ return b.Put(k, []byte("filler"))
+ }
+ if err := db.Update(insert); err != nil {
+ b.Error(err)
+ return
+ }
+ }(uint32(round))
+ }
+ close(start)
+ wg.Wait()
+ }
+
+ b.StopTimer()
+ validateBatchBench(b, db)
+}
+
+func BenchmarkDBBatchManual10x100(b *testing.B) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ _, err := tx.CreateBucket([]byte("bench"))
+ return err
+ }); err != nil {
+ b.Fatal(err)
+ }
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ start := make(chan struct{})
+ var wg sync.WaitGroup
+
+ for major := 0; major < 10; major++ {
+ wg.Add(1)
+ go func(id uint32) {
+ defer wg.Done()
+ <-start
+
+ insert100 := func(tx *bolt.Tx) error {
+ h := fnv.New32a()
+ buf := make([]byte, 4)
+ for minor := uint32(0); minor < 100; minor++ {
+ binary.LittleEndian.PutUint32(buf, uint32(id*100+minor))
+ h.Reset()
+ _, _ = h.Write(buf[:])
+ k := h.Sum(nil)
+ b := tx.Bucket([]byte("bench"))
+ if err := b.Put(k, []byte("filler")); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+ if err := db.Update(insert100); err != nil {
+ b.Fatal(err)
+ }
+ }(uint32(major))
+ }
+ close(start)
+ wg.Wait()
+ }
+
+ b.StopTimer()
+ validateBatchBench(b, db)
+}
+
+func validateBatchBench(b *testing.B, db *DB) {
+ var rollback = errors.New("sentinel error to cause rollback")
+ validate := func(tx *bolt.Tx) error {
+ bucket := tx.Bucket([]byte("bench"))
+ h := fnv.New32a()
+ buf := make([]byte, 4)
+ for id := uint32(0); id < 1000; id++ {
+ binary.LittleEndian.PutUint32(buf, id)
+ h.Reset()
+ _, _ = h.Write(buf[:])
+ k := h.Sum(nil)
+ v := bucket.Get(k)
+ if v == nil {
+ b.Errorf("not found id=%d key=%x", id, k)
+ continue
+ }
+ if g, e := v, []byte("filler"); !bytes.Equal(g, e) {
+ b.Errorf("bad value for id=%d key=%x: %s != %q", id, k, g, e)
+ }
+ if err := bucket.Delete(k); err != nil {
+ return err
+ }
+ }
+ // should be empty now
+ c := bucket.Cursor()
+ for k, v := c.First(); k != nil; k, v = c.Next() {
+ b.Errorf("unexpected key: %x = %q", k, v)
+ }
+ return rollback
+ }
+ if err := db.Update(validate); err != nil && err != rollback {
+ b.Error(err)
+ }
+}
+
+// DB is a test wrapper for bolt.DB.
+type DB struct {
+ *bolt.DB
+}
+
+// MustOpenDB returns a new, open DB at a temporary location.
+func MustOpenDB() *DB {
+ db, err := bolt.Open(tempfile(), 0666, nil)
+ if err != nil {
+ panic(err)
+ }
+ return &DB{db}
+}
+
+// Close closes the database and deletes the underlying file.
+func (db *DB) Close() error {
+ // Log statistics.
+ if *statsFlag {
+ db.PrintStats()
+ }
+
+ // Check database consistency after every test.
+ db.MustCheck()
+
+ // Close database and remove file.
+ defer os.Remove(db.Path())
+ return db.DB.Close()
+}
+
+// MustClose closes the database and deletes the underlying file. Panic on error.
+func (db *DB) MustClose() {
+ if err := db.Close(); err != nil {
+ panic(err)
+ }
+}
+
+// PrintStats prints the database stats
+func (db *DB) PrintStats() {
+ var stats = db.Stats()
+ fmt.Printf("[db] %-20s %-20s %-20s\n",
+ fmt.Sprintf("pg(%d/%d)", stats.TxStats.PageCount, stats.TxStats.PageAlloc),
+ fmt.Sprintf("cur(%d)", stats.TxStats.CursorCount),
+ fmt.Sprintf("node(%d/%d)", stats.TxStats.NodeCount, stats.TxStats.NodeDeref),
+ )
+ fmt.Printf(" %-20s %-20s %-20s\n",
+ fmt.Sprintf("rebal(%d/%v)", stats.TxStats.Rebalance, truncDuration(stats.TxStats.RebalanceTime)),
+ fmt.Sprintf("spill(%d/%v)", stats.TxStats.Spill, truncDuration(stats.TxStats.SpillTime)),
+ fmt.Sprintf("w(%d/%v)", stats.TxStats.Write, truncDuration(stats.TxStats.WriteTime)),
+ )
+}
+
+// MustCheck runs a consistency check on the database and panics if any errors are found.
+func (db *DB) MustCheck() {
+ if err := db.Update(func(tx *bolt.Tx) error {
+ // Collect all the errors.
+ var errors []error
+ for err := range tx.Check() {
+ errors = append(errors, err)
+ if len(errors) > 10 {
+ break
+ }
+ }
+
+ // If errors occurred, copy the DB and print the errors.
+ if len(errors) > 0 {
+ var path = tempfile()
+ if err := tx.CopyFile(path, 0600); err != nil {
+ panic(err)
+ }
+
+ // Print errors.
+ fmt.Print("\n\n")
+ fmt.Printf("consistency check failed (%d errors)\n", len(errors))
+ for _, err := range errors {
+ fmt.Println(err)
+ }
+ fmt.Println("")
+ fmt.Println("db saved to:")
+ fmt.Println(path)
+ fmt.Print("\n\n")
+ os.Exit(-1)
+ }
+
+ return nil
+ }); err != nil && err != bolt.ErrDatabaseNotOpen {
+ panic(err)
+ }
+}
+
+// CopyTempFile copies a database to a temporary file.
+func (db *DB) CopyTempFile() {
+ path := tempfile()
+ if err := db.View(func(tx *bolt.Tx) error {
+ return tx.CopyFile(path, 0600)
+ }); err != nil {
+ panic(err)
+ }
+ fmt.Println("db copied to: ", path)
+}
+
+// tempfile returns a temporary file path.
+func tempfile() string {
+ f, err := ioutil.TempFile("", "bolt-")
+ if err != nil {
+ panic(err)
+ }
+ if err := f.Close(); err != nil {
+ panic(err)
+ }
+ if err := os.Remove(f.Name()); err != nil {
+ panic(err)
+ }
+ return f.Name()
+}
+
+// mustContainKeys checks that a bucket contains a given set of keys.
+func mustContainKeys(b *bolt.Bucket, m map[string]string) {
+ found := make(map[string]string)
+ if err := b.ForEach(func(k, _ []byte) error {
+ found[string(k)] = ""
+ return nil
+ }); err != nil {
+ panic(err)
+ }
+
+ // Check for keys found in bucket that shouldn't be there.
+ var keys []string
+ for k, _ := range found {
+ if _, ok := m[string(k)]; !ok {
+ keys = append(keys, k)
+ }
+ }
+ if len(keys) > 0 {
+ sort.Strings(keys)
+ panic(fmt.Sprintf("keys found(%d): %s", len(keys), strings.Join(keys, ",")))
+ }
+
+ // Check for keys not found in bucket that should be there.
+ for k, _ := range m {
+ if _, ok := found[string(k)]; !ok {
+ keys = append(keys, k)
+ }
+ }
+ if len(keys) > 0 {
+ sort.Strings(keys)
+ panic(fmt.Sprintf("keys not found(%d): %s", len(keys), strings.Join(keys, ",")))
+ }
+}
+
+func trunc(b []byte, length int) []byte {
+ if length < len(b) {
+ return b[:length]
+ }
+ return b
+}
+
+func truncDuration(d time.Duration) string {
+ return regexp.MustCompile(`^(\d+)(\.\d+)`).ReplaceAllString(d.String(), "$1")
+}
+
+func fileSize(path string) int64 {
+ fi, err := os.Stat(path)
+ if err != nil {
+ return 0
+ }
+ return fi.Size()
+}
+
+func warn(v ...interface{}) { fmt.Fprintln(os.Stderr, v...) }
+func warnf(msg string, v ...interface{}) { fmt.Fprintf(os.Stderr, msg+"\n", v...) }
+
+// u64tob converts a uint64 into an 8-byte slice.
+func u64tob(v uint64) []byte {
+ b := make([]byte, 8)
+ binary.BigEndian.PutUint64(b, v)
+ return b
+}
+
+// btou64 converts an 8-byte slice into an uint64.
+func btou64(b []byte) uint64 { return binary.BigEndian.Uint64(b) }
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/doc.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/doc.go
new file mode 100644
index 0000000..cc93784
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/doc.go
@@ -0,0 +1,44 @@
+/*
+Package bolt implements a low-level key/value store in pure Go. It supports
+fully serializable transactions, ACID semantics, and lock-free MVCC with
+multiple readers and a single writer. Bolt can be used for projects that
+want a simple data store without the need to add large dependencies such as
+Postgres or MySQL.
+
+Bolt is a single-level, zero-copy, B+tree data store. This means that Bolt is
+optimized for fast read access and does not require recovery in the event of a
+system crash. Transactions which have not finished committing will simply be
+rolled back in the event of a crash.
+
+The design of Bolt is based on Howard Chu's LMDB database project.
+
+Bolt currently works on Windows, Mac OS X, and Linux.
+
+
+Basics
+
+There are only a few types in Bolt: DB, Bucket, Tx, and Cursor. The DB is
+a collection of buckets and is represented by a single file on disk. A bucket is
+a collection of unique keys that are associated with values.
+
+Transactions provide either read-only or read-write access to the database.
+Read-only transactions can retrieve key/value pairs and can use Cursors to
+iterate over the dataset sequentially. Read-write transactions can create and
+delete buckets and can insert and remove keys. Only one read-write transaction
+is allowed at a time.
+
+
+Caveats
+
+The database uses a read-only, memory-mapped data file to ensure that
+applications cannot corrupt the database, however, this means that keys and
+values returned from Bolt cannot be changed. Writing to a read-only byte slice
+will cause Go to panic.
+
+Keys and values retrieved from the database are only valid for the life of
+the transaction. When used outside the transaction, these byte slices can
+point to different data or can point to invalid memory which will cause a panic.
+
+
+*/
+package bolt
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/errors.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/errors.go
new file mode 100644
index 0000000..a3620a3
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/errors.go
@@ -0,0 +1,71 @@
+package bolt
+
+import "errors"
+
+// These errors can be returned when opening or calling methods on a DB.
+var (
+ // ErrDatabaseNotOpen is returned when a DB instance is accessed before it
+ // is opened or after it is closed.
+ ErrDatabaseNotOpen = errors.New("database not open")
+
+ // ErrDatabaseOpen is returned when opening a database that is
+ // already open.
+ ErrDatabaseOpen = errors.New("database already open")
+
+ // ErrInvalid is returned when both meta pages on a database are invalid.
+ // This typically occurs when a file is not a bolt database.
+ ErrInvalid = errors.New("invalid database")
+
+ // ErrVersionMismatch is returned when the data file was created with a
+ // different version of Bolt.
+ ErrVersionMismatch = errors.New("version mismatch")
+
+ // ErrChecksum is returned when either meta page checksum does not match.
+ ErrChecksum = errors.New("checksum error")
+
+ // ErrTimeout is returned when a database cannot obtain an exclusive lock
+ // on the data file after the timeout passed to Open().
+ ErrTimeout = errors.New("timeout")
+)
+
+// These errors can occur when beginning or committing a Tx.
+var (
+ // ErrTxNotWritable is returned when performing a write operation on a
+ // read-only transaction.
+ ErrTxNotWritable = errors.New("tx not writable")
+
+ // ErrTxClosed is returned when committing or rolling back a transaction
+ // that has already been committed or rolled back.
+ ErrTxClosed = errors.New("tx closed")
+
+ // ErrDatabaseReadOnly is returned when a mutating transaction is started on a
+ // read-only database.
+ ErrDatabaseReadOnly = errors.New("database is in read-only mode")
+)
+
+// These errors can occur when putting or deleting a value or a bucket.
+var (
+ // ErrBucketNotFound is returned when trying to access a bucket that has
+ // not been created yet.
+ ErrBucketNotFound = errors.New("bucket not found")
+
+ // ErrBucketExists is returned when creating a bucket that already exists.
+ ErrBucketExists = errors.New("bucket already exists")
+
+ // ErrBucketNameRequired is returned when creating a bucket with a blank name.
+ ErrBucketNameRequired = errors.New("bucket name required")
+
+ // ErrKeyRequired is returned when inserting a zero-length key.
+ ErrKeyRequired = errors.New("key required")
+
+ // ErrKeyTooLarge is returned when inserting a key that is larger than MaxKeySize.
+ ErrKeyTooLarge = errors.New("key too large")
+
+ // ErrValueTooLarge is returned when inserting a value that is larger than MaxValueSize.
+ ErrValueTooLarge = errors.New("value too large")
+
+ // ErrIncompatibleValue is returned when trying create or delete a bucket
+ // on an existing non-bucket key or when trying to create or delete a
+ // non-bucket key on an existing bucket key.
+ ErrIncompatibleValue = errors.New("incompatible value")
+)
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/freelist.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/freelist.go
new file mode 100644
index 0000000..d32f6cd
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/freelist.go
@@ -0,0 +1,248 @@
+package bolt
+
+import (
+ "fmt"
+ "sort"
+ "unsafe"
+)
+
+// freelist represents a list of all pages that are available for allocation.
+// It also tracks pages that have been freed but are still in use by open transactions.
+type freelist struct {
+ ids []pgid // all free and available free page ids.
+ pending map[txid][]pgid // mapping of soon-to-be free page ids by tx.
+ cache map[pgid]bool // fast lookup of all free and pending page ids.
+}
+
+// newFreelist returns an empty, initialized freelist.
+func newFreelist() *freelist {
+ return &freelist{
+ pending: make(map[txid][]pgid),
+ cache: make(map[pgid]bool),
+ }
+}
+
+// size returns the size of the page after serialization.
+func (f *freelist) size() int {
+ return pageHeaderSize + (int(unsafe.Sizeof(pgid(0))) * f.count())
+}
+
+// count returns count of pages on the freelist
+func (f *freelist) count() int {
+ return f.free_count() + f.pending_count()
+}
+
+// free_count returns count of free pages
+func (f *freelist) free_count() int {
+ return len(f.ids)
+}
+
+// pending_count returns count of pending pages
+func (f *freelist) pending_count() int {
+ var count int
+ for _, list := range f.pending {
+ count += len(list)
+ }
+ return count
+}
+
+// all returns a list of all free ids and all pending ids in one sorted list.
+func (f *freelist) all() []pgid {
+ m := make(pgids, 0)
+
+ for _, list := range f.pending {
+ m = append(m, list...)
+ }
+
+ sort.Sort(m)
+ return pgids(f.ids).merge(m)
+}
+
+// allocate returns the starting page id of a contiguous list of pages of a given size.
+// If a contiguous block cannot be found then 0 is returned.
+func (f *freelist) allocate(n int) pgid {
+ if len(f.ids) == 0 {
+ return 0
+ }
+
+ var initial, previd pgid
+ for i, id := range f.ids {
+ if id <= 1 {
+ panic(fmt.Sprintf("invalid page allocation: %d", id))
+ }
+
+ // Reset initial page if this is not contiguous.
+ if previd == 0 || id-previd != 1 {
+ initial = id
+ }
+
+ // If we found a contiguous block then remove it and return it.
+ if (id-initial)+1 == pgid(n) {
+ // If we're allocating off the beginning then take the fast path
+ // and just adjust the existing slice. This will use extra memory
+ // temporarily but the append() in free() will realloc the slice
+ // as is necessary.
+ if (i + 1) == n {
+ f.ids = f.ids[i+1:]
+ } else {
+ copy(f.ids[i-n+1:], f.ids[i+1:])
+ f.ids = f.ids[:len(f.ids)-n]
+ }
+
+ // Remove from the free cache.
+ for i := pgid(0); i < pgid(n); i++ {
+ delete(f.cache, initial+i)
+ }
+
+ return initial
+ }
+
+ previd = id
+ }
+ return 0
+}
+
+// free releases a page and its overflow for a given transaction id.
+// If the page is already free then a panic will occur.
+func (f *freelist) free(txid txid, p *page) {
+ if p.id <= 1 {
+ panic(fmt.Sprintf("cannot free page 0 or 1: %d", p.id))
+ }
+
+ // Free page and all its overflow pages.
+ var ids = f.pending[txid]
+ for id := p.id; id <= p.id+pgid(p.overflow); id++ {
+ // Verify that page is not already free.
+ if f.cache[id] {
+ panic(fmt.Sprintf("page %d already freed", id))
+ }
+
+ // Add to the freelist and cache.
+ ids = append(ids, id)
+ f.cache[id] = true
+ }
+ f.pending[txid] = ids
+}
+
+// release moves all page ids for a transaction id (or older) to the freelist.
+func (f *freelist) release(txid txid) {
+ m := make(pgids, 0)
+ for tid, ids := range f.pending {
+ if tid <= txid {
+ // Move transaction's pending pages to the available freelist.
+ // Don't remove from the cache since the page is still free.
+ m = append(m, ids...)
+ delete(f.pending, tid)
+ }
+ }
+ sort.Sort(m)
+ f.ids = pgids(f.ids).merge(m)
+}
+
+// rollback removes the pages from a given pending tx.
+func (f *freelist) rollback(txid txid) {
+ // Remove page ids from cache.
+ for _, id := range f.pending[txid] {
+ delete(f.cache, id)
+ }
+
+ // Remove pages from pending list.
+ delete(f.pending, txid)
+}
+
+// freed returns whether a given page is in the free list.
+func (f *freelist) freed(pgid pgid) bool {
+ return f.cache[pgid]
+}
+
+// read initializes the freelist from a freelist page.
+func (f *freelist) read(p *page) {
+ // If the page.count is at the max uint16 value (64k) then it's considered
+ // an overflow and the size of the freelist is stored as the first element.
+ idx, count := 0, int(p.count)
+ if count == 0xFFFF {
+ idx = 1
+ count = int(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[0])
+ }
+
+ // Copy the list of page ids from the freelist.
+ if count == 0 {
+ f.ids = nil
+ } else {
+ ids := ((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[idx:count]
+ f.ids = make([]pgid, len(ids))
+ copy(f.ids, ids)
+
+ // Make sure they're sorted.
+ sort.Sort(pgids(f.ids))
+ }
+
+ // Rebuild the page cache.
+ f.reindex()
+}
+
+// write writes the page ids onto a freelist page. All free and pending ids are
+// saved to disk since in the event of a program crash, all pending ids will
+// become free.
+func (f *freelist) write(p *page) error {
+ // Combine the old free pgids and pgids waiting on an open transaction.
+ ids := f.all()
+
+ // Update the header flag.
+ p.flags |= freelistPageFlag
+
+ // The page.count can only hold up to 64k elements so if we overflow that
+ // number then we handle it by putting the size in the first element.
+ if len(ids) == 0 {
+ p.count = uint16(len(ids))
+ } else if len(ids) < 0xFFFF {
+ p.count = uint16(len(ids))
+ copy(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[:], ids)
+ } else {
+ p.count = 0xFFFF
+ ((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[0] = pgid(len(ids))
+ copy(((*[maxAllocSize]pgid)(unsafe.Pointer(&p.ptr)))[1:], ids)
+ }
+
+ return nil
+}
+
+// reload reads the freelist from a page and filters out pending items.
+func (f *freelist) reload(p *page) {
+ f.read(p)
+
+ // Build a cache of only pending pages.
+ pcache := make(map[pgid]bool)
+ for _, pendingIDs := range f.pending {
+ for _, pendingID := range pendingIDs {
+ pcache[pendingID] = true
+ }
+ }
+
+ // Check each page in the freelist and build a new available freelist
+ // with any pages not in the pending lists.
+ var a []pgid
+ for _, id := range f.ids {
+ if !pcache[id] {
+ a = append(a, id)
+ }
+ }
+ f.ids = a
+
+ // Once the available list is rebuilt then rebuild the free cache so that
+ // it includes the available and pending free pages.
+ f.reindex()
+}
+
+// reindex rebuilds the free cache based on available and pending free lists.
+func (f *freelist) reindex() {
+ f.cache = make(map[pgid]bool, len(f.ids))
+ for _, id := range f.ids {
+ f.cache[id] = true
+ }
+ for _, pendingIDs := range f.pending {
+ for _, pendingID := range pendingIDs {
+ f.cache[pendingID] = true
+ }
+ }
+}
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/freelist_test.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/freelist_test.go
new file mode 100644
index 0000000..4e9b3a8
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/freelist_test.go
@@ -0,0 +1,158 @@
+package bolt
+
+import (
+ "math/rand"
+ "reflect"
+ "sort"
+ "testing"
+ "unsafe"
+)
+
+// Ensure that a page is added to a transaction's freelist.
+func TestFreelist_free(t *testing.T) {
+ f := newFreelist()
+ f.free(100, &page{id: 12})
+ if !reflect.DeepEqual([]pgid{12}, f.pending[100]) {
+ t.Fatalf("exp=%v; got=%v", []pgid{12}, f.pending[100])
+ }
+}
+
+// Ensure that a page and its overflow is added to a transaction's freelist.
+func TestFreelist_free_overflow(t *testing.T) {
+ f := newFreelist()
+ f.free(100, &page{id: 12, overflow: 3})
+ if exp := []pgid{12, 13, 14, 15}; !reflect.DeepEqual(exp, f.pending[100]) {
+ t.Fatalf("exp=%v; got=%v", exp, f.pending[100])
+ }
+}
+
+// Ensure that a transaction's free pages can be released.
+func TestFreelist_release(t *testing.T) {
+ f := newFreelist()
+ f.free(100, &page{id: 12, overflow: 1})
+ f.free(100, &page{id: 9})
+ f.free(102, &page{id: 39})
+ f.release(100)
+ f.release(101)
+ if exp := []pgid{9, 12, 13}; !reflect.DeepEqual(exp, f.ids) {
+ t.Fatalf("exp=%v; got=%v", exp, f.ids)
+ }
+
+ f.release(102)
+ if exp := []pgid{9, 12, 13, 39}; !reflect.DeepEqual(exp, f.ids) {
+ t.Fatalf("exp=%v; got=%v", exp, f.ids)
+ }
+}
+
+// Ensure that a freelist can find contiguous blocks of pages.
+func TestFreelist_allocate(t *testing.T) {
+ f := &freelist{ids: []pgid{3, 4, 5, 6, 7, 9, 12, 13, 18}}
+ if id := int(f.allocate(3)); id != 3 {
+ t.Fatalf("exp=3; got=%v", id)
+ }
+ if id := int(f.allocate(1)); id != 6 {
+ t.Fatalf("exp=6; got=%v", id)
+ }
+ if id := int(f.allocate(3)); id != 0 {
+ t.Fatalf("exp=0; got=%v", id)
+ }
+ if id := int(f.allocate(2)); id != 12 {
+ t.Fatalf("exp=12; got=%v", id)
+ }
+ if id := int(f.allocate(1)); id != 7 {
+ t.Fatalf("exp=7; got=%v", id)
+ }
+ if id := int(f.allocate(0)); id != 0 {
+ t.Fatalf("exp=0; got=%v", id)
+ }
+ if id := int(f.allocate(0)); id != 0 {
+ t.Fatalf("exp=0; got=%v", id)
+ }
+ if exp := []pgid{9, 18}; !reflect.DeepEqual(exp, f.ids) {
+ t.Fatalf("exp=%v; got=%v", exp, f.ids)
+ }
+
+ if id := int(f.allocate(1)); id != 9 {
+ t.Fatalf("exp=9; got=%v", id)
+ }
+ if id := int(f.allocate(1)); id != 18 {
+ t.Fatalf("exp=18; got=%v", id)
+ }
+ if id := int(f.allocate(1)); id != 0 {
+ t.Fatalf("exp=0; got=%v", id)
+ }
+ if exp := []pgid{}; !reflect.DeepEqual(exp, f.ids) {
+ t.Fatalf("exp=%v; got=%v", exp, f.ids)
+ }
+}
+
+// Ensure that a freelist can deserialize from a freelist page.
+func TestFreelist_read(t *testing.T) {
+ // Create a page.
+ var buf [4096]byte
+ page := (*page)(unsafe.Pointer(&buf[0]))
+ page.flags = freelistPageFlag
+ page.count = 2
+
+ // Insert 2 page ids.
+ ids := (*[3]pgid)(unsafe.Pointer(&page.ptr))
+ ids[0] = 23
+ ids[1] = 50
+
+ // Deserialize page into a freelist.
+ f := newFreelist()
+ f.read(page)
+
+ // Ensure that there are two page ids in the freelist.
+ if exp := []pgid{23, 50}; !reflect.DeepEqual(exp, f.ids) {
+ t.Fatalf("exp=%v; got=%v", exp, f.ids)
+ }
+}
+
+// Ensure that a freelist can serialize into a freelist page.
+func TestFreelist_write(t *testing.T) {
+ // Create a freelist and write it to a page.
+ var buf [4096]byte
+ f := &freelist{ids: []pgid{12, 39}, pending: make(map[txid][]pgid)}
+ f.pending[100] = []pgid{28, 11}
+ f.pending[101] = []pgid{3}
+ p := (*page)(unsafe.Pointer(&buf[0]))
+ if err := f.write(p); err != nil {
+ t.Fatal(err)
+ }
+
+ // Read the page back out.
+ f2 := newFreelist()
+ f2.read(p)
+
+ // Ensure that the freelist is correct.
+ // All pages should be present and in reverse order.
+ if exp := []pgid{3, 11, 12, 28, 39}; !reflect.DeepEqual(exp, f2.ids) {
+ t.Fatalf("exp=%v; got=%v", exp, f2.ids)
+ }
+}
+
+func Benchmark_FreelistRelease10K(b *testing.B) { benchmark_FreelistRelease(b, 10000) }
+func Benchmark_FreelistRelease100K(b *testing.B) { benchmark_FreelistRelease(b, 100000) }
+func Benchmark_FreelistRelease1000K(b *testing.B) { benchmark_FreelistRelease(b, 1000000) }
+func Benchmark_FreelistRelease10000K(b *testing.B) { benchmark_FreelistRelease(b, 10000000) }
+
+func benchmark_FreelistRelease(b *testing.B, size int) {
+ ids := randomPgids(size)
+ pending := randomPgids(len(ids) / 400)
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ f := &freelist{ids: ids, pending: map[txid][]pgid{1: pending}}
+ f.release(1)
+ }
+}
+
+func randomPgids(n int) []pgid {
+ rand.Seed(42)
+ pgids := make(pgids, n)
+ for i := range pgids {
+ pgids[i] = pgid(rand.Int63())
+ }
+ sort.Sort(pgids)
+ return pgids
+}
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/node.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/node.go
new file mode 100644
index 0000000..159318b
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/node.go
@@ -0,0 +1,604 @@
+package bolt
+
+import (
+ "bytes"
+ "fmt"
+ "sort"
+ "unsafe"
+)
+
+// node represents an in-memory, deserialized page.
+type node struct {
+ bucket *Bucket
+ isLeaf bool
+ unbalanced bool
+ spilled bool
+ key []byte
+ pgid pgid
+ parent *node
+ children nodes
+ inodes inodes
+}
+
+// root returns the top-level node this node is attached to.
+func (n *node) root() *node {
+ if n.parent == nil {
+ return n
+ }
+ return n.parent.root()
+}
+
+// minKeys returns the minimum number of inodes this node should have.
+func (n *node) minKeys() int {
+ if n.isLeaf {
+ return 1
+ }
+ return 2
+}
+
+// size returns the size of the node after serialization.
+func (n *node) size() int {
+ sz, elsz := pageHeaderSize, n.pageElementSize()
+ for i := 0; i < len(n.inodes); i++ {
+ item := &n.inodes[i]
+ sz += elsz + len(item.key) + len(item.value)
+ }
+ return sz
+}
+
+// sizeLessThan returns true if the node is less than a given size.
+// This is an optimization to avoid calculating a large node when we only need
+// to know if it fits inside a certain page size.
+func (n *node) sizeLessThan(v int) bool {
+ sz, elsz := pageHeaderSize, n.pageElementSize()
+ for i := 0; i < len(n.inodes); i++ {
+ item := &n.inodes[i]
+ sz += elsz + len(item.key) + len(item.value)
+ if sz >= v {
+ return false
+ }
+ }
+ return true
+}
+
+// pageElementSize returns the size of each page element based on the type of node.
+func (n *node) pageElementSize() int {
+ if n.isLeaf {
+ return leafPageElementSize
+ }
+ return branchPageElementSize
+}
+
+// childAt returns the child node at a given index.
+func (n *node) childAt(index int) *node {
+ if n.isLeaf {
+ panic(fmt.Sprintf("invalid childAt(%d) on a leaf node", index))
+ }
+ return n.bucket.node(n.inodes[index].pgid, n)
+}
+
+// childIndex returns the index of a given child node.
+func (n *node) childIndex(child *node) int {
+ index := sort.Search(len(n.inodes), func(i int) bool { return bytes.Compare(n.inodes[i].key, child.key) != -1 })
+ return index
+}
+
+// numChildren returns the number of children.
+func (n *node) numChildren() int {
+ return len(n.inodes)
+}
+
+// nextSibling returns the next node with the same parent.
+func (n *node) nextSibling() *node {
+ if n.parent == nil {
+ return nil
+ }
+ index := n.parent.childIndex(n)
+ if index >= n.parent.numChildren()-1 {
+ return nil
+ }
+ return n.parent.childAt(index + 1)
+}
+
+// prevSibling returns the previous node with the same parent.
+func (n *node) prevSibling() *node {
+ if n.parent == nil {
+ return nil
+ }
+ index := n.parent.childIndex(n)
+ if index == 0 {
+ return nil
+ }
+ return n.parent.childAt(index - 1)
+}
+
+// put inserts a key/value.
+func (n *node) put(oldKey, newKey, value []byte, pgid pgid, flags uint32) {
+ if pgid >= n.bucket.tx.meta.pgid {
+ panic(fmt.Sprintf("pgid (%d) above high water mark (%d)", pgid, n.bucket.tx.meta.pgid))
+ } else if len(oldKey) <= 0 {
+ panic("put: zero-length old key")
+ } else if len(newKey) <= 0 {
+ panic("put: zero-length new key")
+ }
+
+ // Find insertion index.
+ index := sort.Search(len(n.inodes), func(i int) bool { return bytes.Compare(n.inodes[i].key, oldKey) != -1 })
+
+ // Add capacity and shift nodes if we don't have an exact match and need to insert.
+ exact := (len(n.inodes) > 0 && index < len(n.inodes) && bytes.Equal(n.inodes[index].key, oldKey))
+ if !exact {
+ n.inodes = append(n.inodes, inode{})
+ copy(n.inodes[index+1:], n.inodes[index:])
+ }
+
+ inode := &n.inodes[index]
+ inode.flags = flags
+ inode.key = newKey
+ inode.value = value
+ inode.pgid = pgid
+ _assert(len(inode.key) > 0, "put: zero-length inode key")
+}
+
+// del removes a key from the node.
+func (n *node) del(key []byte) {
+ // Find index of key.
+ index := sort.Search(len(n.inodes), func(i int) bool { return bytes.Compare(n.inodes[i].key, key) != -1 })
+
+ // Exit if the key isn't found.
+ if index >= len(n.inodes) || !bytes.Equal(n.inodes[index].key, key) {
+ return
+ }
+
+ // Delete inode from the node.
+ n.inodes = append(n.inodes[:index], n.inodes[index+1:]...)
+
+ // Mark the node as needing rebalancing.
+ n.unbalanced = true
+}
+
+// read initializes the node from a page.
+func (n *node) read(p *page) {
+ n.pgid = p.id
+ n.isLeaf = ((p.flags & leafPageFlag) != 0)
+ n.inodes = make(inodes, int(p.count))
+
+ for i := 0; i < int(p.count); i++ {
+ inode := &n.inodes[i]
+ if n.isLeaf {
+ elem := p.leafPageElement(uint16(i))
+ inode.flags = elem.flags
+ inode.key = elem.key()
+ inode.value = elem.value()
+ } else {
+ elem := p.branchPageElement(uint16(i))
+ inode.pgid = elem.pgid
+ inode.key = elem.key()
+ }
+ _assert(len(inode.key) > 0, "read: zero-length inode key")
+ }
+
+ // Save first key so we can find the node in the parent when we spill.
+ if len(n.inodes) > 0 {
+ n.key = n.inodes[0].key
+ _assert(len(n.key) > 0, "read: zero-length node key")
+ } else {
+ n.key = nil
+ }
+}
+
+// write writes the items onto one or more pages.
+func (n *node) write(p *page) {
+ // Initialize page.
+ if n.isLeaf {
+ p.flags |= leafPageFlag
+ } else {
+ p.flags |= branchPageFlag
+ }
+
+ if len(n.inodes) >= 0xFFFF {
+ panic(fmt.Sprintf("inode overflow: %d (pgid=%d)", len(n.inodes), p.id))
+ }
+ p.count = uint16(len(n.inodes))
+
+ // Stop here if there are no items to write.
+ if p.count == 0 {
+ return
+ }
+
+ // Loop over each item and write it to the page.
+ b := (*[maxAllocSize]byte)(unsafe.Pointer(&p.ptr))[n.pageElementSize()*len(n.inodes):]
+ for i, item := range n.inodes {
+ _assert(len(item.key) > 0, "write: zero-length inode key")
+
+ // Write the page element.
+ if n.isLeaf {
+ elem := p.leafPageElement(uint16(i))
+ elem.pos = uint32(uintptr(unsafe.Pointer(&b[0])) - uintptr(unsafe.Pointer(elem)))
+ elem.flags = item.flags
+ elem.ksize = uint32(len(item.key))
+ elem.vsize = uint32(len(item.value))
+ } else {
+ elem := p.branchPageElement(uint16(i))
+ elem.pos = uint32(uintptr(unsafe.Pointer(&b[0])) - uintptr(unsafe.Pointer(elem)))
+ elem.ksize = uint32(len(item.key))
+ elem.pgid = item.pgid
+ _assert(elem.pgid != p.id, "write: circular dependency occurred")
+ }
+
+ // If the length of key+value is larger than the max allocation size
+ // then we need to reallocate the byte array pointer.
+ //
+ // See: https://github.com/boltdb/bolt/pull/335
+ klen, vlen := len(item.key), len(item.value)
+ if len(b) < klen+vlen {
+ b = (*[maxAllocSize]byte)(unsafe.Pointer(&b[0]))[:]
+ }
+
+ // Write data for the element to the end of the page.
+ copy(b[0:], item.key)
+ b = b[klen:]
+ copy(b[0:], item.value)
+ b = b[vlen:]
+ }
+
+ // DEBUG ONLY: n.dump()
+}
+
+// split breaks up a node into multiple smaller nodes, if appropriate.
+// This should only be called from the spill() function.
+func (n *node) split(pageSize int) []*node {
+ var nodes []*node
+
+ node := n
+ for {
+ // Split node into two.
+ a, b := node.splitTwo(pageSize)
+ nodes = append(nodes, a)
+
+ // If we can't split then exit the loop.
+ if b == nil {
+ break
+ }
+
+ // Set node to b so it gets split on the next iteration.
+ node = b
+ }
+
+ return nodes
+}
+
+// splitTwo breaks up a node into two smaller nodes, if appropriate.
+// This should only be called from the split() function.
+func (n *node) splitTwo(pageSize int) (*node, *node) {
+ // Ignore the split if the page doesn't have at least enough nodes for
+ // two pages or if the nodes can fit in a single page.
+ if len(n.inodes) <= (minKeysPerPage*2) || n.sizeLessThan(pageSize) {
+ return n, nil
+ }
+
+ // Determine the threshold before starting a new node.
+ var fillPercent = n.bucket.FillPercent
+ if fillPercent < minFillPercent {
+ fillPercent = minFillPercent
+ } else if fillPercent > maxFillPercent {
+ fillPercent = maxFillPercent
+ }
+ threshold := int(float64(pageSize) * fillPercent)
+
+ // Determine split position and sizes of the two pages.
+ splitIndex, _ := n.splitIndex(threshold)
+
+ // Split node into two separate nodes.
+ // If there's no parent then we'll need to create one.
+ if n.parent == nil {
+ n.parent = &node{bucket: n.bucket, children: []*node{n}}
+ }
+
+ // Create a new node and add it to the parent.
+ next := &node{bucket: n.bucket, isLeaf: n.isLeaf, parent: n.parent}
+ n.parent.children = append(n.parent.children, next)
+
+ // Split inodes across two nodes.
+ next.inodes = n.inodes[splitIndex:]
+ n.inodes = n.inodes[:splitIndex]
+
+ // Update the statistics.
+ n.bucket.tx.stats.Split++
+
+ return n, next
+}
+
+// splitIndex finds the position where a page will fill a given threshold.
+// It returns the index as well as the size of the first page.
+// This is only be called from split().
+func (n *node) splitIndex(threshold int) (index, sz int) {
+ sz = pageHeaderSize
+
+ // Loop until we only have the minimum number of keys required for the second page.
+ for i := 0; i < len(n.inodes)-minKeysPerPage; i++ {
+ index = i
+ inode := n.inodes[i]
+ elsize := n.pageElementSize() + len(inode.key) + len(inode.value)
+
+ // If we have at least the minimum number of keys and adding another
+ // node would put us over the threshold then exit and return.
+ if i >= minKeysPerPage && sz+elsize > threshold {
+ break
+ }
+
+ // Add the element size to the total size.
+ sz += elsize
+ }
+
+ return
+}
+
+// spill writes the nodes to dirty pages and splits nodes as it goes.
+// Returns an error if dirty pages cannot be allocated.
+func (n *node) spill() error {
+ var tx = n.bucket.tx
+ if n.spilled {
+ return nil
+ }
+
+ // Spill child nodes first. Child nodes can materialize sibling nodes in
+ // the case of split-merge so we cannot use a range loop. We have to check
+ // the children size on every loop iteration.
+ sort.Sort(n.children)
+ for i := 0; i < len(n.children); i++ {
+ if err := n.children[i].spill(); err != nil {
+ return err
+ }
+ }
+
+ // We no longer need the child list because it's only used for spill tracking.
+ n.children = nil
+
+ // Split nodes into appropriate sizes. The first node will always be n.
+ var nodes = n.split(tx.db.pageSize)
+ for _, node := range nodes {
+ // Add node's page to the freelist if it's not new.
+ if node.pgid > 0 {
+ tx.db.freelist.free(tx.meta.txid, tx.page(node.pgid))
+ node.pgid = 0
+ }
+
+ // Allocate contiguous space for the node.
+ p, err := tx.allocate((node.size() / tx.db.pageSize) + 1)
+ if err != nil {
+ return err
+ }
+
+ // Write the node.
+ if p.id >= tx.meta.pgid {
+ panic(fmt.Sprintf("pgid (%d) above high water mark (%d)", p.id, tx.meta.pgid))
+ }
+ node.pgid = p.id
+ node.write(p)
+ node.spilled = true
+
+ // Insert into parent inodes.
+ if node.parent != nil {
+ var key = node.key
+ if key == nil {
+ key = node.inodes[0].key
+ }
+
+ node.parent.put(key, node.inodes[0].key, nil, node.pgid, 0)
+ node.key = node.inodes[0].key
+ _assert(len(node.key) > 0, "spill: zero-length node key")
+ }
+
+ // Update the statistics.
+ tx.stats.Spill++
+ }
+
+ // If the root node split and created a new root then we need to spill that
+ // as well. We'll clear out the children to make sure it doesn't try to respill.
+ if n.parent != nil && n.parent.pgid == 0 {
+ n.children = nil
+ return n.parent.spill()
+ }
+
+ return nil
+}
+
+// rebalance attempts to combine the node with sibling nodes if the node fill
+// size is below a threshold or if there are not enough keys.
+func (n *node) rebalance() {
+ if !n.unbalanced {
+ return
+ }
+ n.unbalanced = false
+
+ // Update statistics.
+ n.bucket.tx.stats.Rebalance++
+
+ // Ignore if node is above threshold (25%) and has enough keys.
+ var threshold = n.bucket.tx.db.pageSize / 4
+ if n.size() > threshold && len(n.inodes) > n.minKeys() {
+ return
+ }
+
+ // Root node has special handling.
+ if n.parent == nil {
+ // If root node is a branch and only has one node then collapse it.
+ if !n.isLeaf && len(n.inodes) == 1 {
+ // Move root's child up.
+ child := n.bucket.node(n.inodes[0].pgid, n)
+ n.isLeaf = child.isLeaf
+ n.inodes = child.inodes[:]
+ n.children = child.children
+
+ // Reparent all child nodes being moved.
+ for _, inode := range n.inodes {
+ if child, ok := n.bucket.nodes[inode.pgid]; ok {
+ child.parent = n
+ }
+ }
+
+ // Remove old child.
+ child.parent = nil
+ delete(n.bucket.nodes, child.pgid)
+ child.free()
+ }
+
+ return
+ }
+
+ // If node has no keys then just remove it.
+ if n.numChildren() == 0 {
+ n.parent.del(n.key)
+ n.parent.removeChild(n)
+ delete(n.bucket.nodes, n.pgid)
+ n.free()
+ n.parent.rebalance()
+ return
+ }
+
+ _assert(n.parent.numChildren() > 1, "parent must have at least 2 children")
+
+ // Destination node is right sibling if idx == 0, otherwise left sibling.
+ var target *node
+ var useNextSibling = (n.parent.childIndex(n) == 0)
+ if useNextSibling {
+ target = n.nextSibling()
+ } else {
+ target = n.prevSibling()
+ }
+
+ // If both this node and the target node are too small then merge them.
+ if useNextSibling {
+ // Reparent all child nodes being moved.
+ for _, inode := range target.inodes {
+ if child, ok := n.bucket.nodes[inode.pgid]; ok {
+ child.parent.removeChild(child)
+ child.parent = n
+ child.parent.children = append(child.parent.children, child)
+ }
+ }
+
+ // Copy over inodes from target and remove target.
+ n.inodes = append(n.inodes, target.inodes...)
+ n.parent.del(target.key)
+ n.parent.removeChild(target)
+ delete(n.bucket.nodes, target.pgid)
+ target.free()
+ } else {
+ // Reparent all child nodes being moved.
+ for _, inode := range n.inodes {
+ if child, ok := n.bucket.nodes[inode.pgid]; ok {
+ child.parent.removeChild(child)
+ child.parent = target
+ child.parent.children = append(child.parent.children, child)
+ }
+ }
+
+ // Copy over inodes to target and remove node.
+ target.inodes = append(target.inodes, n.inodes...)
+ n.parent.del(n.key)
+ n.parent.removeChild(n)
+ delete(n.bucket.nodes, n.pgid)
+ n.free()
+ }
+
+ // Either this node or the target node was deleted from the parent so rebalance it.
+ n.parent.rebalance()
+}
+
+// removes a node from the list of in-memory children.
+// This does not affect the inodes.
+func (n *node) removeChild(target *node) {
+ for i, child := range n.children {
+ if child == target {
+ n.children = append(n.children[:i], n.children[i+1:]...)
+ return
+ }
+ }
+}
+
+// dereference causes the node to copy all its inode key/value references to heap memory.
+// This is required when the mmap is reallocated so inodes are not pointing to stale data.
+func (n *node) dereference() {
+ if n.key != nil {
+ key := make([]byte, len(n.key))
+ copy(key, n.key)
+ n.key = key
+ _assert(n.pgid == 0 || len(n.key) > 0, "dereference: zero-length node key on existing node")
+ }
+
+ for i := range n.inodes {
+ inode := &n.inodes[i]
+
+ key := make([]byte, len(inode.key))
+ copy(key, inode.key)
+ inode.key = key
+ _assert(len(inode.key) > 0, "dereference: zero-length inode key")
+
+ value := make([]byte, len(inode.value))
+ copy(value, inode.value)
+ inode.value = value
+ }
+
+ // Recursively dereference children.
+ for _, child := range n.children {
+ child.dereference()
+ }
+
+ // Update statistics.
+ n.bucket.tx.stats.NodeDeref++
+}
+
+// free adds the node's underlying page to the freelist.
+func (n *node) free() {
+ if n.pgid != 0 {
+ n.bucket.tx.db.freelist.free(n.bucket.tx.meta.txid, n.bucket.tx.page(n.pgid))
+ n.pgid = 0
+ }
+}
+
+// dump writes the contents of the node to STDERR for debugging purposes.
+/*
+func (n *node) dump() {
+ // Write node header.
+ var typ = "branch"
+ if n.isLeaf {
+ typ = "leaf"
+ }
+ warnf("[NODE %d {type=%s count=%d}]", n.pgid, typ, len(n.inodes))
+
+ // Write out abbreviated version of each item.
+ for _, item := range n.inodes {
+ if n.isLeaf {
+ if item.flags&bucketLeafFlag != 0 {
+ bucket := (*bucket)(unsafe.Pointer(&item.value[0]))
+ warnf("+L %08x -> (bucket root=%d)", trunc(item.key, 4), bucket.root)
+ } else {
+ warnf("+L %08x -> %08x", trunc(item.key, 4), trunc(item.value, 4))
+ }
+ } else {
+ warnf("+B %08x -> pgid=%d", trunc(item.key, 4), item.pgid)
+ }
+ }
+ warn("")
+}
+*/
+
+type nodes []*node
+
+func (s nodes) Len() int { return len(s) }
+func (s nodes) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+func (s nodes) Less(i, j int) bool { return bytes.Compare(s[i].inodes[0].key, s[j].inodes[0].key) == -1 }
+
+// inode represents an internal node inside of a node.
+// It can be used to point to elements in a page or point
+// to an element which hasn't been added to a page yet.
+type inode struct {
+ flags uint32
+ pgid pgid
+ key []byte
+ value []byte
+}
+
+type inodes []inode
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/node_test.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/node_test.go
new file mode 100644
index 0000000..fa5d10f
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/node_test.go
@@ -0,0 +1,156 @@
+package bolt
+
+import (
+ "testing"
+ "unsafe"
+)
+
+// Ensure that a node can insert a key/value.
+func TestNode_put(t *testing.T) {
+ n := &node{inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{meta: &meta{pgid: 1}}}}
+ n.put([]byte("baz"), []byte("baz"), []byte("2"), 0, 0)
+ n.put([]byte("foo"), []byte("foo"), []byte("0"), 0, 0)
+ n.put([]byte("bar"), []byte("bar"), []byte("1"), 0, 0)
+ n.put([]byte("foo"), []byte("foo"), []byte("3"), 0, leafPageFlag)
+
+ if len(n.inodes) != 3 {
+ t.Fatalf("exp=3; got=%d", len(n.inodes))
+ }
+ if k, v := n.inodes[0].key, n.inodes[0].value; string(k) != "bar" || string(v) != "1" {
+ t.Fatalf("exp=<bar,1>; got=<%s,%s>", k, v)
+ }
+ if k, v := n.inodes[1].key, n.inodes[1].value; string(k) != "baz" || string(v) != "2" {
+ t.Fatalf("exp=<baz,2>; got=<%s,%s>", k, v)
+ }
+ if k, v := n.inodes[2].key, n.inodes[2].value; string(k) != "foo" || string(v) != "3" {
+ t.Fatalf("exp=<foo,3>; got=<%s,%s>", k, v)
+ }
+ if n.inodes[2].flags != uint32(leafPageFlag) {
+ t.Fatalf("not a leaf: %d", n.inodes[2].flags)
+ }
+}
+
+// Ensure that a node can deserialize from a leaf page.
+func TestNode_read_LeafPage(t *testing.T) {
+ // Create a page.
+ var buf [4096]byte
+ page := (*page)(unsafe.Pointer(&buf[0]))
+ page.flags = leafPageFlag
+ page.count = 2
+
+ // Insert 2 elements at the beginning. sizeof(leafPageElement) == 16
+ nodes := (*[3]leafPageElement)(unsafe.Pointer(&page.ptr))
+ nodes[0] = leafPageElement{flags: 0, pos: 32, ksize: 3, vsize: 4} // pos = sizeof(leafPageElement) * 2
+ nodes[1] = leafPageElement{flags: 0, pos: 23, ksize: 10, vsize: 3} // pos = sizeof(leafPageElement) + 3 + 4
+
+ // Write data for the nodes at the end.
+ data := (*[4096]byte)(unsafe.Pointer(&nodes[2]))
+ copy(data[:], []byte("barfooz"))
+ copy(data[7:], []byte("helloworldbye"))
+
+ // Deserialize page into a leaf.
+ n := &node{}
+ n.read(page)
+
+ // Check that there are two inodes with correct data.
+ if !n.isLeaf {
+ t.Fatal("expected leaf")
+ }
+ if len(n.inodes) != 2 {
+ t.Fatalf("exp=2; got=%d", len(n.inodes))
+ }
+ if k, v := n.inodes[0].key, n.inodes[0].value; string(k) != "bar" || string(v) != "fooz" {
+ t.Fatalf("exp=<bar,fooz>; got=<%s,%s>", k, v)
+ }
+ if k, v := n.inodes[1].key, n.inodes[1].value; string(k) != "helloworld" || string(v) != "bye" {
+ t.Fatalf("exp=<helloworld,bye>; got=<%s,%s>", k, v)
+ }
+}
+
+// Ensure that a node can serialize into a leaf page.
+func TestNode_write_LeafPage(t *testing.T) {
+ // Create a node.
+ n := &node{isLeaf: true, inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{db: &DB{}, meta: &meta{pgid: 1}}}}
+ n.put([]byte("susy"), []byte("susy"), []byte("que"), 0, 0)
+ n.put([]byte("ricki"), []byte("ricki"), []byte("lake"), 0, 0)
+ n.put([]byte("john"), []byte("john"), []byte("johnson"), 0, 0)
+
+ // Write it to a page.
+ var buf [4096]byte
+ p := (*page)(unsafe.Pointer(&buf[0]))
+ n.write(p)
+
+ // Read the page back in.
+ n2 := &node{}
+ n2.read(p)
+
+ // Check that the two pages are the same.
+ if len(n2.inodes) != 3 {
+ t.Fatalf("exp=3; got=%d", len(n2.inodes))
+ }
+ if k, v := n2.inodes[0].key, n2.inodes[0].value; string(k) != "john" || string(v) != "johnson" {
+ t.Fatalf("exp=<john,johnson>; got=<%s,%s>", k, v)
+ }
+ if k, v := n2.inodes[1].key, n2.inodes[1].value; string(k) != "ricki" || string(v) != "lake" {
+ t.Fatalf("exp=<ricki,lake>; got=<%s,%s>", k, v)
+ }
+ if k, v := n2.inodes[2].key, n2.inodes[2].value; string(k) != "susy" || string(v) != "que" {
+ t.Fatalf("exp=<susy,que>; got=<%s,%s>", k, v)
+ }
+}
+
+// Ensure that a node can split into appropriate subgroups.
+func TestNode_split(t *testing.T) {
+ // Create a node.
+ n := &node{inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{db: &DB{}, meta: &meta{pgid: 1}}}}
+ n.put([]byte("00000001"), []byte("00000001"), []byte("0123456701234567"), 0, 0)
+ n.put([]byte("00000002"), []byte("00000002"), []byte("0123456701234567"), 0, 0)
+ n.put([]byte("00000003"), []byte("00000003"), []byte("0123456701234567"), 0, 0)
+ n.put([]byte("00000004"), []byte("00000004"), []byte("0123456701234567"), 0, 0)
+ n.put([]byte("00000005"), []byte("00000005"), []byte("0123456701234567"), 0, 0)
+
+ // Split between 2 & 3.
+ n.split(100)
+
+ var parent = n.parent
+ if len(parent.children) != 2 {
+ t.Fatalf("exp=2; got=%d", len(parent.children))
+ }
+ if len(parent.children[0].inodes) != 2 {
+ t.Fatalf("exp=2; got=%d", len(parent.children[0].inodes))
+ }
+ if len(parent.children[1].inodes) != 3 {
+ t.Fatalf("exp=3; got=%d", len(parent.children[1].inodes))
+ }
+}
+
+// Ensure that a page with the minimum number of inodes just returns a single node.
+func TestNode_split_MinKeys(t *testing.T) {
+ // Create a node.
+ n := &node{inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{db: &DB{}, meta: &meta{pgid: 1}}}}
+ n.put([]byte("00000001"), []byte("00000001"), []byte("0123456701234567"), 0, 0)
+ n.put([]byte("00000002"), []byte("00000002"), []byte("0123456701234567"), 0, 0)
+
+ // Split.
+ n.split(20)
+ if n.parent != nil {
+ t.Fatalf("expected nil parent")
+ }
+}
+
+// Ensure that a node that has keys that all fit on a page just returns one leaf.
+func TestNode_split_SinglePage(t *testing.T) {
+ // Create a node.
+ n := &node{inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{db: &DB{}, meta: &meta{pgid: 1}}}}
+ n.put([]byte("00000001"), []byte("00000001"), []byte("0123456701234567"), 0, 0)
+ n.put([]byte("00000002"), []byte("00000002"), []byte("0123456701234567"), 0, 0)
+ n.put([]byte("00000003"), []byte("00000003"), []byte("0123456701234567"), 0, 0)
+ n.put([]byte("00000004"), []byte("00000004"), []byte("0123456701234567"), 0, 0)
+ n.put([]byte("00000005"), []byte("00000005"), []byte("0123456701234567"), 0, 0)
+
+ // Split.
+ n.split(4096)
+ if n.parent != nil {
+ t.Fatalf("expected nil parent")
+ }
+}
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/page.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/page.go
new file mode 100644
index 0000000..7651a6b
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/page.go
@@ -0,0 +1,178 @@
+package bolt
+
+import (
+ "fmt"
+ "os"
+ "sort"
+ "unsafe"
+)
+
+const pageHeaderSize = int(unsafe.Offsetof(((*page)(nil)).ptr))
+
+const minKeysPerPage = 2
+
+const branchPageElementSize = int(unsafe.Sizeof(branchPageElement{}))
+const leafPageElementSize = int(unsafe.Sizeof(leafPageElement{}))
+
+const (
+ branchPageFlag = 0x01
+ leafPageFlag = 0x02
+ metaPageFlag = 0x04
+ freelistPageFlag = 0x10
+)
+
+const (
+ bucketLeafFlag = 0x01
+)
+
+type pgid uint64
+
+type page struct {
+ id pgid
+ flags uint16
+ count uint16
+ overflow uint32
+ ptr uintptr
+}
+
+// typ returns a human readable page type string used for debugging.
+func (p *page) typ() string {
+ if (p.flags & branchPageFlag) != 0 {
+ return "branch"
+ } else if (p.flags & leafPageFlag) != 0 {
+ return "leaf"
+ } else if (p.flags & metaPageFlag) != 0 {
+ return "meta"
+ } else if (p.flags & freelistPageFlag) != 0 {
+ return "freelist"
+ }
+ return fmt.Sprintf("unknown<%02x>", p.flags)
+}
+
+// meta returns a pointer to the metadata section of the page.
+func (p *page) meta() *meta {
+ return (*meta)(unsafe.Pointer(&p.ptr))
+}
+
+// leafPageElement retrieves the leaf node by index
+func (p *page) leafPageElement(index uint16) *leafPageElement {
+ n := &((*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr)))[index]
+ return n
+}
+
+// leafPageElements retrieves a list of leaf nodes.
+func (p *page) leafPageElements() []leafPageElement {
+ if p.count == 0 {
+ return nil
+ }
+ return ((*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr)))[:]
+}
+
+// branchPageElement retrieves the branch node by index
+func (p *page) branchPageElement(index uint16) *branchPageElement {
+ return &((*[0x7FFFFFF]branchPageElement)(unsafe.Pointer(&p.ptr)))[index]
+}
+
+// branchPageElements retrieves a list of branch nodes.
+func (p *page) branchPageElements() []branchPageElement {
+ if p.count == 0 {
+ return nil
+ }
+ return ((*[0x7FFFFFF]branchPageElement)(unsafe.Pointer(&p.ptr)))[:]
+}
+
+// dump writes n bytes of the page to STDERR as hex output.
+func (p *page) hexdump(n int) {
+ buf := (*[maxAllocSize]byte)(unsafe.Pointer(p))[:n]
+ fmt.Fprintf(os.Stderr, "%x\n", buf)
+}
+
+type pages []*page
+
+func (s pages) Len() int { return len(s) }
+func (s pages) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+func (s pages) Less(i, j int) bool { return s[i].id < s[j].id }
+
+// branchPageElement represents a node on a branch page.
+type branchPageElement struct {
+ pos uint32
+ ksize uint32
+ pgid pgid
+}
+
+// key returns a byte slice of the node key.
+func (n *branchPageElement) key() []byte {
+ buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
+ return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos]))[:n.ksize]
+}
+
+// leafPageElement represents a node on a leaf page.
+type leafPageElement struct {
+ flags uint32
+ pos uint32
+ ksize uint32
+ vsize uint32
+}
+
+// key returns a byte slice of the node key.
+func (n *leafPageElement) key() []byte {
+ buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
+ return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos]))[:n.ksize:n.ksize]
+}
+
+// value returns a byte slice of the node value.
+func (n *leafPageElement) value() []byte {
+ buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
+ return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos+n.ksize]))[:n.vsize:n.vsize]
+}
+
+// PageInfo represents human readable information about a page.
+type PageInfo struct {
+ ID int
+ Type string
+ Count int
+ OverflowCount int
+}
+
+type pgids []pgid
+
+func (s pgids) Len() int { return len(s) }
+func (s pgids) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+func (s pgids) Less(i, j int) bool { return s[i] < s[j] }
+
+// merge returns the sorted union of a and b.
+func (a pgids) merge(b pgids) pgids {
+ // Return the opposite slice if one is nil.
+ if len(a) == 0 {
+ return b
+ } else if len(b) == 0 {
+ return a
+ }
+
+ // Create a list to hold all elements from both lists.
+ merged := make(pgids, 0, len(a)+len(b))
+
+ // Assign lead to the slice with a lower starting value, follow to the higher value.
+ lead, follow := a, b
+ if b[0] < a[0] {
+ lead, follow = b, a
+ }
+
+ // Continue while there are elements in the lead.
+ for len(lead) > 0 {
+ // Merge largest prefix of lead that is ahead of follow[0].
+ n := sort.Search(len(lead), func(i int) bool { return lead[i] > follow[0] })
+ merged = append(merged, lead[:n]...)
+ if n >= len(lead) {
+ break
+ }
+
+ // Swap lead and follow.
+ lead, follow = follow, lead[n:]
+ }
+
+ // Append what's left in follow.
+ merged = append(merged, follow...)
+
+ return merged
+}
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/page_test.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/page_test.go
new file mode 100644
index 0000000..59f4a30
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/page_test.go
@@ -0,0 +1,72 @@
+package bolt
+
+import (
+ "reflect"
+ "sort"
+ "testing"
+ "testing/quick"
+)
+
+// Ensure that the page type can be returned in human readable format.
+func TestPage_typ(t *testing.T) {
+ if typ := (&page{flags: branchPageFlag}).typ(); typ != "branch" {
+ t.Fatalf("exp=branch; got=%v", typ)
+ }
+ if typ := (&page{flags: leafPageFlag}).typ(); typ != "leaf" {
+ t.Fatalf("exp=leaf; got=%v", typ)
+ }
+ if typ := (&page{flags: metaPageFlag}).typ(); typ != "meta" {
+ t.Fatalf("exp=meta; got=%v", typ)
+ }
+ if typ := (&page{flags: freelistPageFlag}).typ(); typ != "freelist" {
+ t.Fatalf("exp=freelist; got=%v", typ)
+ }
+ if typ := (&page{flags: 20000}).typ(); typ != "unknown<4e20>" {
+ t.Fatalf("exp=unknown<4e20>; got=%v", typ)
+ }
+}
+
+// Ensure that the hexdump debugging function doesn't blow up.
+func TestPage_dump(t *testing.T) {
+ (&page{id: 256}).hexdump(16)
+}
+
+func TestPgids_merge(t *testing.T) {
+ a := pgids{4, 5, 6, 10, 11, 12, 13, 27}
+ b := pgids{1, 3, 8, 9, 25, 30}
+ c := a.merge(b)
+ if !reflect.DeepEqual(c, pgids{1, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 25, 27, 30}) {
+ t.Errorf("mismatch: %v", c)
+ }
+
+ a = pgids{4, 5, 6, 10, 11, 12, 13, 27, 35, 36}
+ b = pgids{8, 9, 25, 30}
+ c = a.merge(b)
+ if !reflect.DeepEqual(c, pgids{4, 5, 6, 8, 9, 10, 11, 12, 13, 25, 27, 30, 35, 36}) {
+ t.Errorf("mismatch: %v", c)
+ }
+}
+
+func TestPgids_merge_quick(t *testing.T) {
+ if err := quick.Check(func(a, b pgids) bool {
+ // Sort incoming lists.
+ sort.Sort(a)
+ sort.Sort(b)
+
+ // Merge the two lists together.
+ got := a.merge(b)
+
+ // The expected value should be the two lists combined and sorted.
+ exp := append(a, b...)
+ sort.Sort(exp)
+
+ if !reflect.DeepEqual(exp, got) {
+ t.Errorf("\nexp=%+v\ngot=%+v\n", exp, got)
+ return false
+ }
+
+ return true
+ }, nil); err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/quick_test.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/quick_test.go
new file mode 100644
index 0000000..4da5817
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/quick_test.go
@@ -0,0 +1,79 @@
+package bolt_test
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "math/rand"
+ "os"
+ "reflect"
+ "testing/quick"
+ "time"
+)
+
+// testing/quick defaults to 5 iterations and a random seed.
+// You can override these settings from the command line:
+//
+// -quick.count The number of iterations to perform.
+// -quick.seed The seed to use for randomizing.
+// -quick.maxitems The maximum number of items to insert into a DB.
+// -quick.maxksize The maximum size of a key.
+// -quick.maxvsize The maximum size of a value.
+//
+
+var qcount, qseed, qmaxitems, qmaxksize, qmaxvsize int
+
+func init() {
+ flag.IntVar(&qcount, "quick.count", 5, "")
+ flag.IntVar(&qseed, "quick.seed", int(time.Now().UnixNano())%100000, "")
+ flag.IntVar(&qmaxitems, "quick.maxitems", 1000, "")
+ flag.IntVar(&qmaxksize, "quick.maxksize", 1024, "")
+ flag.IntVar(&qmaxvsize, "quick.maxvsize", 1024, "")
+ flag.Parse()
+ fmt.Fprintln(os.Stderr, "seed:", qseed)
+ fmt.Fprintf(os.Stderr, "quick settings: count=%v, items=%v, ksize=%v, vsize=%v\n", qcount, qmaxitems, qmaxksize, qmaxvsize)
+}
+
+func qconfig() *quick.Config {
+ return &quick.Config{
+ MaxCount: qcount,
+ Rand: rand.New(rand.NewSource(int64(qseed))),
+ }
+}
+
+type testdata []testdataitem
+
+func (t testdata) Len() int { return len(t) }
+func (t testdata) Swap(i, j int) { t[i], t[j] = t[j], t[i] }
+func (t testdata) Less(i, j int) bool { return bytes.Compare(t[i].Key, t[j].Key) == -1 }
+
+func (t testdata) Generate(rand *rand.Rand, size int) reflect.Value {
+ n := rand.Intn(qmaxitems-1) + 1
+ items := make(testdata, n)
+ for i := 0; i < n; i++ {
+ item := &items[i]
+ item.Key = randByteSlice(rand, 1, qmaxksize)
+ item.Value = randByteSlice(rand, 0, qmaxvsize)
+ }
+ return reflect.ValueOf(items)
+}
+
+type revtestdata []testdataitem
+
+func (t revtestdata) Len() int { return len(t) }
+func (t revtestdata) Swap(i, j int) { t[i], t[j] = t[j], t[i] }
+func (t revtestdata) Less(i, j int) bool { return bytes.Compare(t[i].Key, t[j].Key) == 1 }
+
+type testdataitem struct {
+ Key []byte
+ Value []byte
+}
+
+func randByteSlice(rand *rand.Rand, minSize, maxSize int) []byte {
+ n := rand.Intn(maxSize-minSize) + minSize
+ b := make([]byte, n)
+ for i := 0; i < n; i++ {
+ b[i] = byte(rand.Intn(255))
+ }
+ return b
+}
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/simulation_test.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/simulation_test.go
new file mode 100644
index 0000000..3831016
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/simulation_test.go
@@ -0,0 +1,329 @@
+package bolt_test
+
+import (
+ "bytes"
+ "fmt"
+ "math/rand"
+ "sync"
+ "testing"
+
+ "github.com/boltdb/bolt"
+)
+
+func TestSimulate_1op_1p(t *testing.T) { testSimulate(t, 1, 1) }
+func TestSimulate_10op_1p(t *testing.T) { testSimulate(t, 10, 1) }
+func TestSimulate_100op_1p(t *testing.T) { testSimulate(t, 100, 1) }
+func TestSimulate_1000op_1p(t *testing.T) { testSimulate(t, 1000, 1) }
+func TestSimulate_10000op_1p(t *testing.T) { testSimulate(t, 10000, 1) }
+
+func TestSimulate_10op_10p(t *testing.T) { testSimulate(t, 10, 10) }
+func TestSimulate_100op_10p(t *testing.T) { testSimulate(t, 100, 10) }
+func TestSimulate_1000op_10p(t *testing.T) { testSimulate(t, 1000, 10) }
+func TestSimulate_10000op_10p(t *testing.T) { testSimulate(t, 10000, 10) }
+
+func TestSimulate_100op_100p(t *testing.T) { testSimulate(t, 100, 100) }
+func TestSimulate_1000op_100p(t *testing.T) { testSimulate(t, 1000, 100) }
+func TestSimulate_10000op_100p(t *testing.T) { testSimulate(t, 10000, 100) }
+
+func TestSimulate_10000op_1000p(t *testing.T) { testSimulate(t, 10000, 1000) }
+
+// Randomly generate operations on a given database with multiple clients to ensure consistency and thread safety.
+func testSimulate(t *testing.T, threadCount, parallelism int) {
+ if testing.Short() {
+ t.Skip("skipping test in short mode.")
+ }
+
+ rand.Seed(int64(qseed))
+
+ // A list of operations that readers and writers can perform.
+ var readerHandlers = []simulateHandler{simulateGetHandler}
+ var writerHandlers = []simulateHandler{simulateGetHandler, simulatePutHandler}
+
+ var versions = make(map[int]*QuickDB)
+ versions[1] = NewQuickDB()
+
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ var mutex sync.Mutex
+
+ // Run n threads in parallel, each with their own operation.
+ var wg sync.WaitGroup
+ var threads = make(chan bool, parallelism)
+ var i int
+ for {
+ threads <- true
+ wg.Add(1)
+ writable := ((rand.Int() % 100) < 20) // 20% writers
+
+ // Choose an operation to execute.
+ var handler simulateHandler
+ if writable {
+ handler = writerHandlers[rand.Intn(len(writerHandlers))]
+ } else {
+ handler = readerHandlers[rand.Intn(len(readerHandlers))]
+ }
+
+ // Execute a thread for the given operation.
+ go func(writable bool, handler simulateHandler) {
+ defer wg.Done()
+
+ // Start transaction.
+ tx, err := db.Begin(writable)
+ if err != nil {
+ t.Fatal("tx begin: ", err)
+ }
+
+ // Obtain current state of the dataset.
+ mutex.Lock()
+ var qdb = versions[tx.ID()]
+ if writable {
+ qdb = versions[tx.ID()-1].Copy()
+ }
+ mutex.Unlock()
+
+ // Make sure we commit/rollback the tx at the end and update the state.
+ if writable {
+ defer func() {
+ mutex.Lock()
+ versions[tx.ID()] = qdb
+ mutex.Unlock()
+
+ if err := tx.Commit(); err != nil {
+ t.Fatal(err)
+ }
+ }()
+ } else {
+ defer func() { _ = tx.Rollback() }()
+ }
+
+ // Ignore operation if we don't have data yet.
+ if qdb == nil {
+ return
+ }
+
+ // Execute handler.
+ handler(tx, qdb)
+
+ // Release a thread back to the scheduling loop.
+ <-threads
+ }(writable, handler)
+
+ i++
+ if i > threadCount {
+ break
+ }
+ }
+
+ // Wait until all threads are done.
+ wg.Wait()
+}
+
+type simulateHandler func(tx *bolt.Tx, qdb *QuickDB)
+
+// Retrieves a key from the database and verifies that it is what is expected.
+func simulateGetHandler(tx *bolt.Tx, qdb *QuickDB) {
+ // Randomly retrieve an existing exist.
+ keys := qdb.Rand()
+ if len(keys) == 0 {
+ return
+ }
+
+ // Retrieve root bucket.
+ b := tx.Bucket(keys[0])
+ if b == nil {
+ panic(fmt.Sprintf("bucket[0] expected: %08x\n", trunc(keys[0], 4)))
+ }
+
+ // Drill into nested buckets.
+ for _, key := range keys[1 : len(keys)-1] {
+ b = b.Bucket(key)
+ if b == nil {
+ panic(fmt.Sprintf("bucket[n] expected: %v -> %v\n", keys, key))
+ }
+ }
+
+ // Verify key/value on the final bucket.
+ expected := qdb.Get(keys)
+ actual := b.Get(keys[len(keys)-1])
+ if !bytes.Equal(actual, expected) {
+ fmt.Println("=== EXPECTED ===")
+ fmt.Println(expected)
+ fmt.Println("=== ACTUAL ===")
+ fmt.Println(actual)
+ fmt.Println("=== END ===")
+ panic("value mismatch")
+ }
+}
+
+// Inserts a key into the database.
+func simulatePutHandler(tx *bolt.Tx, qdb *QuickDB) {
+ var err error
+ keys, value := randKeys(), randValue()
+
+ // Retrieve root bucket.
+ b := tx.Bucket(keys[0])
+ if b == nil {
+ b, err = tx.CreateBucket(keys[0])
+ if err != nil {
+ panic("create bucket: " + err.Error())
+ }
+ }
+
+ // Create nested buckets, if necessary.
+ for _, key := range keys[1 : len(keys)-1] {
+ child := b.Bucket(key)
+ if child != nil {
+ b = child
+ } else {
+ b, err = b.CreateBucket(key)
+ if err != nil {
+ panic("create bucket: " + err.Error())
+ }
+ }
+ }
+
+ // Insert into database.
+ if err := b.Put(keys[len(keys)-1], value); err != nil {
+ panic("put: " + err.Error())
+ }
+
+ // Insert into in-memory database.
+ qdb.Put(keys, value)
+}
+
+// QuickDB is an in-memory database that replicates the functionality of the
+// Bolt DB type except that it is entirely in-memory. It is meant for testing
+// that the Bolt database is consistent.
+type QuickDB struct {
+ sync.RWMutex
+ m map[string]interface{}
+}
+
+// NewQuickDB returns an instance of QuickDB.
+func NewQuickDB() *QuickDB {
+ return &QuickDB{m: make(map[string]interface{})}
+}
+
+// Get retrieves the value at a key path.
+func (db *QuickDB) Get(keys [][]byte) []byte {
+ db.RLock()
+ defer db.RUnlock()
+
+ m := db.m
+ for _, key := range keys[:len(keys)-1] {
+ value := m[string(key)]
+ if value == nil {
+ return nil
+ }
+ switch value := value.(type) {
+ case map[string]interface{}:
+ m = value
+ case []byte:
+ return nil
+ }
+ }
+
+ // Only return if it's a simple value.
+ if value, ok := m[string(keys[len(keys)-1])].([]byte); ok {
+ return value
+ }
+ return nil
+}
+
+// Put inserts a value into a key path.
+func (db *QuickDB) Put(keys [][]byte, value []byte) {
+ db.Lock()
+ defer db.Unlock()
+
+ // Build buckets all the way down the key path.
+ m := db.m
+ for _, key := range keys[:len(keys)-1] {
+ if _, ok := m[string(key)].([]byte); ok {
+ return // Keypath intersects with a simple value. Do nothing.
+ }
+
+ if m[string(key)] == nil {
+ m[string(key)] = make(map[string]interface{})
+ }
+ m = m[string(key)].(map[string]interface{})
+ }
+
+ // Insert value into the last key.
+ m[string(keys[len(keys)-1])] = value
+}
+
+// Rand returns a random key path that points to a simple value.
+func (db *QuickDB) Rand() [][]byte {
+ db.RLock()
+ defer db.RUnlock()
+ if len(db.m) == 0 {
+ return nil
+ }
+ var keys [][]byte
+ db.rand(db.m, &keys)
+ return keys
+}
+
+func (db *QuickDB) rand(m map[string]interface{}, keys *[][]byte) {
+ i, index := 0, rand.Intn(len(m))
+ for k, v := range m {
+ if i == index {
+ *keys = append(*keys, []byte(k))
+ if v, ok := v.(map[string]interface{}); ok {
+ db.rand(v, keys)
+ }
+ return
+ }
+ i++
+ }
+ panic("quickdb rand: out-of-range")
+}
+
+// Copy copies the entire database.
+func (db *QuickDB) Copy() *QuickDB {
+ db.RLock()
+ defer db.RUnlock()
+ return &QuickDB{m: db.copy(db.m)}
+}
+
+func (db *QuickDB) copy(m map[string]interface{}) map[string]interface{} {
+ clone := make(map[string]interface{}, len(m))
+ for k, v := range m {
+ switch v := v.(type) {
+ case map[string]interface{}:
+ clone[k] = db.copy(v)
+ default:
+ clone[k] = v
+ }
+ }
+ return clone
+}
+
+func randKey() []byte {
+ var min, max = 1, 1024
+ n := rand.Intn(max-min) + min
+ b := make([]byte, n)
+ for i := 0; i < n; i++ {
+ b[i] = byte(rand.Intn(255))
+ }
+ return b
+}
+
+func randKeys() [][]byte {
+ var keys [][]byte
+ var count = rand.Intn(2) + 2
+ for i := 0; i < count; i++ {
+ keys = append(keys, randKey())
+ }
+ return keys
+}
+
+func randValue() []byte {
+ n := rand.Intn(8192)
+ b := make([]byte, n)
+ for i := 0; i < n; i++ {
+ b[i] = byte(rand.Intn(255))
+ }
+ return b
+}
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/tx.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/tx.go
new file mode 100644
index 0000000..1cfb4cd
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/tx.go
@@ -0,0 +1,682 @@
+package bolt
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "sort"
+ "strings"
+ "time"
+ "unsafe"
+)
+
+// txid represents the internal transaction identifier.
+type txid uint64
+
+// Tx represents a read-only or read/write transaction on the database.
+// Read-only transactions can be used for retrieving values for keys and creating cursors.
+// Read/write transactions can create and remove buckets and create and remove keys.
+//
+// IMPORTANT: You must commit or rollback transactions when you are done with
+// them. Pages can not be reclaimed by the writer until no more transactions
+// are using them. A long running read transaction can cause the database to
+// quickly grow.
+type Tx struct {
+ writable bool
+ managed bool
+ db *DB
+ meta *meta
+ root Bucket
+ pages map[pgid]*page
+ stats TxStats
+ commitHandlers []func()
+
+ // WriteFlag specifies the flag for write-related methods like WriteTo().
+ // Tx opens the database file with the specified flag to copy the data.
+ //
+ // By default, the flag is unset, which works well for mostly in-memory
+ // workloads. For databases that are much larger than available RAM,
+ // set the flag to syscall.O_DIRECT to avoid trashing the page cache.
+ WriteFlag int
+}
+
+// init initializes the transaction.
+func (tx *Tx) init(db *DB) {
+ tx.db = db
+ tx.pages = nil
+
+ // Copy the meta page since it can be changed by the writer.
+ tx.meta = &meta{}
+ db.meta().copy(tx.meta)
+
+ // Copy over the root bucket.
+ tx.root = newBucket(tx)
+ tx.root.bucket = &bucket{}
+ *tx.root.bucket = tx.meta.root
+
+ // Increment the transaction id and add a page cache for writable transactions.
+ if tx.writable {
+ tx.pages = make(map[pgid]*page)
+ tx.meta.txid += txid(1)
+ }
+}
+
+// ID returns the transaction id.
+func (tx *Tx) ID() int {
+ return int(tx.meta.txid)
+}
+
+// DB returns a reference to the database that created the transaction.
+func (tx *Tx) DB() *DB {
+ return tx.db
+}
+
+// Size returns current database size in bytes as seen by this transaction.
+func (tx *Tx) Size() int64 {
+ return int64(tx.meta.pgid) * int64(tx.db.pageSize)
+}
+
+// Writable returns whether the transaction can perform write operations.
+func (tx *Tx) Writable() bool {
+ return tx.writable
+}
+
+// Cursor creates a cursor associated with the root bucket.
+// All items in the cursor will return a nil value because all root bucket keys point to buckets.
+// The cursor is only valid as long as the transaction is open.
+// Do not use a cursor after the transaction is closed.
+func (tx *Tx) Cursor() *Cursor {
+ return tx.root.Cursor()
+}
+
+// Stats retrieves a copy of the current transaction statistics.
+func (tx *Tx) Stats() TxStats {
+ return tx.stats
+}
+
+// Bucket retrieves a bucket by name.
+// Returns nil if the bucket does not exist.
+// The bucket instance is only valid for the lifetime of the transaction.
+func (tx *Tx) Bucket(name []byte) *Bucket {
+ return tx.root.Bucket(name)
+}
+
+// CreateBucket creates a new bucket.
+// Returns an error if the bucket already exists, if the bucket name is blank, or if the bucket name is too long.
+// The bucket instance is only valid for the lifetime of the transaction.
+func (tx *Tx) CreateBucket(name []byte) (*Bucket, error) {
+ return tx.root.CreateBucket(name)
+}
+
+// CreateBucketIfNotExists creates a new bucket if it doesn't already exist.
+// Returns an error if the bucket name is blank, or if the bucket name is too long.
+// The bucket instance is only valid for the lifetime of the transaction.
+func (tx *Tx) CreateBucketIfNotExists(name []byte) (*Bucket, error) {
+ return tx.root.CreateBucketIfNotExists(name)
+}
+
+// DeleteBucket deletes a bucket.
+// Returns an error if the bucket cannot be found or if the key represents a non-bucket value.
+func (tx *Tx) DeleteBucket(name []byte) error {
+ return tx.root.DeleteBucket(name)
+}
+
+// ForEach executes a function for each bucket in the root.
+// If the provided function returns an error then the iteration is stopped and
+// the error is returned to the caller.
+func (tx *Tx) ForEach(fn func(name []byte, b *Bucket) error) error {
+ return tx.root.ForEach(func(k, v []byte) error {
+ if err := fn(k, tx.root.Bucket(k)); err != nil {
+ return err
+ }
+ return nil
+ })
+}
+
+// OnCommit adds a handler function to be executed after the transaction successfully commits.
+func (tx *Tx) OnCommit(fn func()) {
+ tx.commitHandlers = append(tx.commitHandlers, fn)
+}
+
+// Commit writes all changes to disk and updates the meta page.
+// Returns an error if a disk write error occurs, or if Commit is
+// called on a read-only transaction.
+func (tx *Tx) Commit() error {
+ _assert(!tx.managed, "managed tx commit not allowed")
+ if tx.db == nil {
+ return ErrTxClosed
+ } else if !tx.writable {
+ return ErrTxNotWritable
+ }
+
+ // TODO(benbjohnson): Use vectorized I/O to write out dirty pages.
+
+ // Rebalance nodes which have had deletions.
+ var startTime = time.Now()
+ tx.root.rebalance()
+ if tx.stats.Rebalance > 0 {
+ tx.stats.RebalanceTime += time.Since(startTime)
+ }
+
+ // spill data onto dirty pages.
+ startTime = time.Now()
+ if err := tx.root.spill(); err != nil {
+ tx.rollback()
+ return err
+ }
+ tx.stats.SpillTime += time.Since(startTime)
+
+ // Free the old root bucket.
+ tx.meta.root.root = tx.root.root
+
+ opgid := tx.meta.pgid
+
+ // Free the freelist and allocate new pages for it. This will overestimate
+ // the size of the freelist but not underestimate the size (which would be bad).
+ tx.db.freelist.free(tx.meta.txid, tx.db.page(tx.meta.freelist))
+ p, err := tx.allocate((tx.db.freelist.size() / tx.db.pageSize) + 1)
+ if err != nil {
+ tx.rollback()
+ return err
+ }
+ if err := tx.db.freelist.write(p); err != nil {
+ tx.rollback()
+ return err
+ }
+ tx.meta.freelist = p.id
+
+ // If the high water mark has moved up then attempt to grow the database.
+ if tx.meta.pgid > opgid {
+ if err := tx.db.grow(int(tx.meta.pgid+1) * tx.db.pageSize); err != nil {
+ tx.rollback()
+ return err
+ }
+ }
+
+ // Write dirty pages to disk.
+ startTime = time.Now()
+ if err := tx.write(); err != nil {
+ tx.rollback()
+ return err
+ }
+
+ // If strict mode is enabled then perform a consistency check.
+ // Only the first consistency error is reported in the panic.
+ if tx.db.StrictMode {
+ ch := tx.Check()
+ var errs []string
+ for {
+ err, ok := <-ch
+ if !ok {
+ break
+ }
+ errs = append(errs, err.Error())
+ }
+ if len(errs) > 0 {
+ panic("check fail: " + strings.Join(errs, "\n"))
+ }
+ }
+
+ // Write meta to disk.
+ if err := tx.writeMeta(); err != nil {
+ tx.rollback()
+ return err
+ }
+ tx.stats.WriteTime += time.Since(startTime)
+
+ // Finalize the transaction.
+ tx.close()
+
+ // Execute commit handlers now that the locks have been removed.
+ for _, fn := range tx.commitHandlers {
+ fn()
+ }
+
+ return nil
+}
+
+// Rollback closes the transaction and ignores all previous updates. Read-only
+// transactions must be rolled back and not committed.
+func (tx *Tx) Rollback() error {
+ _assert(!tx.managed, "managed tx rollback not allowed")
+ if tx.db == nil {
+ return ErrTxClosed
+ }
+ tx.rollback()
+ return nil
+}
+
+func (tx *Tx) rollback() {
+ if tx.db == nil {
+ return
+ }
+ if tx.writable {
+ tx.db.freelist.rollback(tx.meta.txid)
+ tx.db.freelist.reload(tx.db.page(tx.db.meta().freelist))
+ }
+ tx.close()
+}
+
+func (tx *Tx) close() {
+ if tx.db == nil {
+ return
+ }
+ if tx.writable {
+ // Grab freelist stats.
+ var freelistFreeN = tx.db.freelist.free_count()
+ var freelistPendingN = tx.db.freelist.pending_count()
+ var freelistAlloc = tx.db.freelist.size()
+
+ // Remove transaction ref & writer lock.
+ tx.db.rwtx = nil
+ tx.db.rwlock.Unlock()
+
+ // Merge statistics.
+ tx.db.statlock.Lock()
+ tx.db.stats.FreePageN = freelistFreeN
+ tx.db.stats.PendingPageN = freelistPendingN
+ tx.db.stats.FreeAlloc = (freelistFreeN + freelistPendingN) * tx.db.pageSize
+ tx.db.stats.FreelistInuse = freelistAlloc
+ tx.db.stats.TxStats.add(&tx.stats)
+ tx.db.statlock.Unlock()
+ } else {
+ tx.db.removeTx(tx)
+ }
+
+ // Clear all references.
+ tx.db = nil
+ tx.meta = nil
+ tx.root = Bucket{tx: tx}
+ tx.pages = nil
+}
+
+// Copy writes the entire database to a writer.
+// This function exists for backwards compatibility. Use WriteTo() instead.
+func (tx *Tx) Copy(w io.Writer) error {
+ _, err := tx.WriteTo(w)
+ return err
+}
+
+// WriteTo writes the entire database to a writer.
+// If err == nil then exactly tx.Size() bytes will be written into the writer.
+func (tx *Tx) WriteTo(w io.Writer) (n int64, err error) {
+ // Attempt to open reader with WriteFlag
+ f, err := os.OpenFile(tx.db.path, os.O_RDONLY|tx.WriteFlag, 0)
+ if err != nil {
+ return 0, err
+ }
+ defer func() { _ = f.Close() }()
+
+ // Generate a meta page. We use the same page data for both meta pages.
+ buf := make([]byte, tx.db.pageSize)
+ page := (*page)(unsafe.Pointer(&buf[0]))
+ page.flags = metaPageFlag
+ *page.meta() = *tx.meta
+
+ // Write meta 0.
+ page.id = 0
+ page.meta().checksum = page.meta().sum64()
+ nn, err := w.Write(buf)
+ n += int64(nn)
+ if err != nil {
+ return n, fmt.Errorf("meta 0 copy: %s", err)
+ }
+
+ // Write meta 1 with a lower transaction id.
+ page.id = 1
+ page.meta().txid -= 1
+ page.meta().checksum = page.meta().sum64()
+ nn, err = w.Write(buf)
+ n += int64(nn)
+ if err != nil {
+ return n, fmt.Errorf("meta 1 copy: %s", err)
+ }
+
+ // Move past the meta pages in the file.
+ if _, err := f.Seek(int64(tx.db.pageSize*2), os.SEEK_SET); err != nil {
+ return n, fmt.Errorf("seek: %s", err)
+ }
+
+ // Copy data pages.
+ wn, err := io.CopyN(w, f, tx.Size()-int64(tx.db.pageSize*2))
+ n += wn
+ if err != nil {
+ return n, err
+ }
+
+ return n, f.Close()
+}
+
+// CopyFile copies the entire database to file at the given path.
+// A reader transaction is maintained during the copy so it is safe to continue
+// using the database while a copy is in progress.
+func (tx *Tx) CopyFile(path string, mode os.FileMode) error {
+ f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, mode)
+ if err != nil {
+ return err
+ }
+
+ err = tx.Copy(f)
+ if err != nil {
+ _ = f.Close()
+ return err
+ }
+ return f.Close()
+}
+
+// Check performs several consistency checks on the database for this transaction.
+// An error is returned if any inconsistency is found.
+//
+// It can be safely run concurrently on a writable transaction. However, this
+// incurs a high cost for large databases and databases with a lot of subbuckets
+// because of caching. This overhead can be removed if running on a read-only
+// transaction, however, it is not safe to execute other writer transactions at
+// the same time.
+func (tx *Tx) Check() <-chan error {
+ ch := make(chan error)
+ go tx.check(ch)
+ return ch
+}
+
+func (tx *Tx) check(ch chan error) {
+ // Check if any pages are double freed.
+ freed := make(map[pgid]bool)
+ for _, id := range tx.db.freelist.all() {
+ if freed[id] {
+ ch <- fmt.Errorf("page %d: already freed", id)
+ }
+ freed[id] = true
+ }
+
+ // Track every reachable page.
+ reachable := make(map[pgid]*page)
+ reachable[0] = tx.page(0) // meta0
+ reachable[1] = tx.page(1) // meta1
+ for i := uint32(0); i <= tx.page(tx.meta.freelist).overflow; i++ {
+ reachable[tx.meta.freelist+pgid(i)] = tx.page(tx.meta.freelist)
+ }
+
+ // Recursively check buckets.
+ tx.checkBucket(&tx.root, reachable, freed, ch)
+
+ // Ensure all pages below high water mark are either reachable or freed.
+ for i := pgid(0); i < tx.meta.pgid; i++ {
+ _, isReachable := reachable[i]
+ if !isReachable && !freed[i] {
+ ch <- fmt.Errorf("page %d: unreachable unfreed", int(i))
+ }
+ }
+
+ // Close the channel to signal completion.
+ close(ch)
+}
+
+func (tx *Tx) checkBucket(b *Bucket, reachable map[pgid]*page, freed map[pgid]bool, ch chan error) {
+ // Ignore inline buckets.
+ if b.root == 0 {
+ return
+ }
+
+ // Check every page used by this bucket.
+ b.tx.forEachPage(b.root, 0, func(p *page, _ int) {
+ if p.id > tx.meta.pgid {
+ ch <- fmt.Errorf("page %d: out of bounds: %d", int(p.id), int(b.tx.meta.pgid))
+ }
+
+ // Ensure each page is only referenced once.
+ for i := pgid(0); i <= pgid(p.overflow); i++ {
+ var id = p.id + i
+ if _, ok := reachable[id]; ok {
+ ch <- fmt.Errorf("page %d: multiple references", int(id))
+ }
+ reachable[id] = p
+ }
+
+ // We should only encounter un-freed leaf and branch pages.
+ if freed[p.id] {
+ ch <- fmt.Errorf("page %d: reachable freed", int(p.id))
+ } else if (p.flags&branchPageFlag) == 0 && (p.flags&leafPageFlag) == 0 {
+ ch <- fmt.Errorf("page %d: invalid type: %s", int(p.id), p.typ())
+ }
+ })
+
+ // Check each bucket within this bucket.
+ _ = b.ForEach(func(k, v []byte) error {
+ if child := b.Bucket(k); child != nil {
+ tx.checkBucket(child, reachable, freed, ch)
+ }
+ return nil
+ })
+}
+
+// allocate returns a contiguous block of memory starting at a given page.
+func (tx *Tx) allocate(count int) (*page, error) {
+ p, err := tx.db.allocate(count)
+ if err != nil {
+ return nil, err
+ }
+
+ // Save to our page cache.
+ tx.pages[p.id] = p
+
+ // Update statistics.
+ tx.stats.PageCount++
+ tx.stats.PageAlloc += count * tx.db.pageSize
+
+ return p, nil
+}
+
+// write writes any dirty pages to disk.
+func (tx *Tx) write() error {
+ // Sort pages by id.
+ pages := make(pages, 0, len(tx.pages))
+ for _, p := range tx.pages {
+ pages = append(pages, p)
+ }
+ // Clear out page cache early.
+ tx.pages = make(map[pgid]*page)
+ sort.Sort(pages)
+
+ // Write pages to disk in order.
+ for _, p := range pages {
+ size := (int(p.overflow) + 1) * tx.db.pageSize
+ offset := int64(p.id) * int64(tx.db.pageSize)
+
+ // Write out page in "max allocation" sized chunks.
+ ptr := (*[maxAllocSize]byte)(unsafe.Pointer(p))
+ for {
+ // Limit our write to our max allocation size.
+ sz := size
+ if sz > maxAllocSize-1 {
+ sz = maxAllocSize - 1
+ }
+
+ // Write chunk to disk.
+ buf := ptr[:sz]
+ if _, err := tx.db.ops.writeAt(buf, offset); err != nil {
+ return err
+ }
+
+ // Update statistics.
+ tx.stats.Write++
+
+ // Exit inner for loop if we've written all the chunks.
+ size -= sz
+ if size == 0 {
+ break
+ }
+
+ // Otherwise move offset forward and move pointer to next chunk.
+ offset += int64(sz)
+ ptr = (*[maxAllocSize]byte)(unsafe.Pointer(&ptr[sz]))
+ }
+ }
+
+ // Ignore file sync if flag is set on DB.
+ if !tx.db.NoSync || IgnoreNoSync {
+ if err := fdatasync(tx.db); err != nil {
+ return err
+ }
+ }
+
+ // Put small pages back to page pool.
+ for _, p := range pages {
+ // Ignore page sizes over 1 page.
+ // These are allocated using make() instead of the page pool.
+ if int(p.overflow) != 0 {
+ continue
+ }
+
+ buf := (*[maxAllocSize]byte)(unsafe.Pointer(p))[:tx.db.pageSize]
+
+ // See https://go.googlesource.com/go/+/f03c9202c43e0abb130669852082117ca50aa9b1
+ for i := range buf {
+ buf[i] = 0
+ }
+ tx.db.pagePool.Put(buf)
+ }
+
+ return nil
+}
+
+// writeMeta writes the meta to the disk.
+func (tx *Tx) writeMeta() error {
+ // Create a temporary buffer for the meta page.
+ buf := make([]byte, tx.db.pageSize)
+ p := tx.db.pageInBuffer(buf, 0)
+ tx.meta.write(p)
+
+ // Write the meta page to file.
+ if _, err := tx.db.ops.writeAt(buf, int64(p.id)*int64(tx.db.pageSize)); err != nil {
+ return err
+ }
+ if !tx.db.NoSync || IgnoreNoSync {
+ if err := fdatasync(tx.db); err != nil {
+ return err
+ }
+ }
+
+ // Update statistics.
+ tx.stats.Write++
+
+ return nil
+}
+
+// page returns a reference to the page with a given id.
+// If page has been written to then a temporary buffered page is returned.
+func (tx *Tx) page(id pgid) *page {
+ // Check the dirty pages first.
+ if tx.pages != nil {
+ if p, ok := tx.pages[id]; ok {
+ return p
+ }
+ }
+
+ // Otherwise return directly from the mmap.
+ return tx.db.page(id)
+}
+
+// forEachPage iterates over every page within a given page and executes a function.
+func (tx *Tx) forEachPage(pgid pgid, depth int, fn func(*page, int)) {
+ p := tx.page(pgid)
+
+ // Execute function.
+ fn(p, depth)
+
+ // Recursively loop over children.
+ if (p.flags & branchPageFlag) != 0 {
+ for i := 0; i < int(p.count); i++ {
+ elem := p.branchPageElement(uint16(i))
+ tx.forEachPage(elem.pgid, depth+1, fn)
+ }
+ }
+}
+
+// Page returns page information for a given page number.
+// This is only safe for concurrent use when used by a writable transaction.
+func (tx *Tx) Page(id int) (*PageInfo, error) {
+ if tx.db == nil {
+ return nil, ErrTxClosed
+ } else if pgid(id) >= tx.meta.pgid {
+ return nil, nil
+ }
+
+ // Build the page info.
+ p := tx.db.page(pgid(id))
+ info := &PageInfo{
+ ID: id,
+ Count: int(p.count),
+ OverflowCount: int(p.overflow),
+ }
+
+ // Determine the type (or if it's free).
+ if tx.db.freelist.freed(pgid(id)) {
+ info.Type = "free"
+ } else {
+ info.Type = p.typ()
+ }
+
+ return info, nil
+}
+
+// TxStats represents statistics about the actions performed by the transaction.
+type TxStats struct {
+ // Page statistics.
+ PageCount int // number of page allocations
+ PageAlloc int // total bytes allocated
+
+ // Cursor statistics.
+ CursorCount int // number of cursors created
+
+ // Node statistics
+ NodeCount int // number of node allocations
+ NodeDeref int // number of node dereferences
+
+ // Rebalance statistics.
+ Rebalance int // number of node rebalances
+ RebalanceTime time.Duration // total time spent rebalancing
+
+ // Split/Spill statistics.
+ Split int // number of nodes split
+ Spill int // number of nodes spilled
+ SpillTime time.Duration // total time spent spilling
+
+ // Write statistics.
+ Write int // number of writes performed
+ WriteTime time.Duration // total time spent writing to disk
+}
+
+func (s *TxStats) add(other *TxStats) {
+ s.PageCount += other.PageCount
+ s.PageAlloc += other.PageAlloc
+ s.CursorCount += other.CursorCount
+ s.NodeCount += other.NodeCount
+ s.NodeDeref += other.NodeDeref
+ s.Rebalance += other.Rebalance
+ s.RebalanceTime += other.RebalanceTime
+ s.Split += other.Split
+ s.Spill += other.Spill
+ s.SpillTime += other.SpillTime
+ s.Write += other.Write
+ s.WriteTime += other.WriteTime
+}
+
+// Sub calculates and returns the difference between two sets of transaction stats.
+// This is useful when obtaining stats at two different points and time and
+// you need the performance counters that occurred within that time span.
+func (s *TxStats) Sub(other *TxStats) TxStats {
+ var diff TxStats
+ diff.PageCount = s.PageCount - other.PageCount
+ diff.PageAlloc = s.PageAlloc - other.PageAlloc
+ diff.CursorCount = s.CursorCount - other.CursorCount
+ diff.NodeCount = s.NodeCount - other.NodeCount
+ diff.NodeDeref = s.NodeDeref - other.NodeDeref
+ diff.Rebalance = s.Rebalance - other.Rebalance
+ diff.RebalanceTime = s.RebalanceTime - other.RebalanceTime
+ diff.Split = s.Split - other.Split
+ diff.Spill = s.Spill - other.Spill
+ diff.SpillTime = s.SpillTime - other.SpillTime
+ diff.Write = s.Write - other.Write
+ diff.WriteTime = s.WriteTime - other.WriteTime
+ return diff
+}
diff --git a/cmd/ponzu/vendor/github.com/boltdb/bolt/tx_test.go b/cmd/ponzu/vendor/github.com/boltdb/bolt/tx_test.go
new file mode 100644
index 0000000..2201e79
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/boltdb/bolt/tx_test.go
@@ -0,0 +1,716 @@
+package bolt_test
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "log"
+ "os"
+ "testing"
+
+ "github.com/boltdb/bolt"
+)
+
+// Ensure that committing a closed transaction returns an error.
+func TestTx_Commit_ErrTxClosed(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ tx, err := db.Begin(true)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if _, err := tx.CreateBucket([]byte("foo")); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := tx.Commit(); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := tx.Commit(); err != bolt.ErrTxClosed {
+ t.Fatalf("unexpected error: %s", err)
+ }
+}
+
+// Ensure that rolling back a closed transaction returns an error.
+func TestTx_Rollback_ErrTxClosed(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ tx, err := db.Begin(true)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if err := tx.Rollback(); err != nil {
+ t.Fatal(err)
+ }
+ if err := tx.Rollback(); err != bolt.ErrTxClosed {
+ t.Fatalf("unexpected error: %s", err)
+ }
+}
+
+// Ensure that committing a read-only transaction returns an error.
+func TestTx_Commit_ErrTxNotWritable(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ tx, err := db.Begin(false)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := tx.Commit(); err != bolt.ErrTxNotWritable {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a transaction can retrieve a cursor on the root bucket.
+func TestTx_Cursor(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if _, err := tx.CreateBucket([]byte("widgets")); err != nil {
+ t.Fatal(err)
+ }
+
+ if _, err := tx.CreateBucket([]byte("woojits")); err != nil {
+ t.Fatal(err)
+ }
+
+ c := tx.Cursor()
+ if k, v := c.First(); !bytes.Equal(k, []byte("widgets")) {
+ t.Fatalf("unexpected key: %v", k)
+ } else if v != nil {
+ t.Fatalf("unexpected value: %v", v)
+ }
+
+ if k, v := c.Next(); !bytes.Equal(k, []byte("woojits")) {
+ t.Fatalf("unexpected key: %v", k)
+ } else if v != nil {
+ t.Fatalf("unexpected value: %v", v)
+ }
+
+ if k, v := c.Next(); k != nil {
+ t.Fatalf("unexpected key: %v", k)
+ } else if v != nil {
+ t.Fatalf("unexpected value: %v", k)
+ }
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that creating a bucket with a read-only transaction returns an error.
+func TestTx_CreateBucket_ErrTxNotWritable(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.View(func(tx *bolt.Tx) error {
+ _, err := tx.CreateBucket([]byte("foo"))
+ if err != bolt.ErrTxNotWritable {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that creating a bucket on a closed transaction returns an error.
+func TestTx_CreateBucket_ErrTxClosed(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ tx, err := db.Begin(true)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := tx.Commit(); err != nil {
+ t.Fatal(err)
+ }
+
+ if _, err := tx.CreateBucket([]byte("foo")); err != bolt.ErrTxClosed {
+ t.Fatalf("unexpected error: %s", err)
+ }
+}
+
+// Ensure that a Tx can retrieve a bucket.
+func TestTx_Bucket(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if _, err := tx.CreateBucket([]byte("widgets")); err != nil {
+ t.Fatal(err)
+ }
+ if tx.Bucket([]byte("widgets")) == nil {
+ t.Fatal("expected bucket")
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a Tx retrieving a non-existent key returns nil.
+func TestTx_Get_NotFound(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
+ t.Fatal(err)
+ }
+ if b.Get([]byte("no_such_key")) != nil {
+ t.Fatal("expected nil value")
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a bucket can be created and retrieved.
+func TestTx_CreateBucket(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ // Create a bucket.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ } else if b == nil {
+ t.Fatal("expected bucket")
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ // Read the bucket through a separate transaction.
+ if err := db.View(func(tx *bolt.Tx) error {
+ if tx.Bucket([]byte("widgets")) == nil {
+ t.Fatal("expected bucket")
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a bucket can be created if it doesn't already exist.
+func TestTx_CreateBucketIfNotExists(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ // Create bucket.
+ if b, err := tx.CreateBucketIfNotExists([]byte("widgets")); err != nil {
+ t.Fatal(err)
+ } else if b == nil {
+ t.Fatal("expected bucket")
+ }
+
+ // Create bucket again.
+ if b, err := tx.CreateBucketIfNotExists([]byte("widgets")); err != nil {
+ t.Fatal(err)
+ } else if b == nil {
+ t.Fatal("expected bucket")
+ }
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ // Read the bucket through a separate transaction.
+ if err := db.View(func(tx *bolt.Tx) error {
+ if tx.Bucket([]byte("widgets")) == nil {
+ t.Fatal("expected bucket")
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure transaction returns an error if creating an unnamed bucket.
+func TestTx_CreateBucketIfNotExists_ErrBucketNameRequired(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if _, err := tx.CreateBucketIfNotExists([]byte{}); err != bolt.ErrBucketNameRequired {
+ t.Fatalf("unexpected error: %s", err)
+ }
+
+ if _, err := tx.CreateBucketIfNotExists(nil); err != bolt.ErrBucketNameRequired {
+ t.Fatalf("unexpected error: %s", err)
+ }
+
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a bucket cannot be created twice.
+func TestTx_CreateBucket_ErrBucketExists(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ // Create a bucket.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if _, err := tx.CreateBucket([]byte("widgets")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ // Create the same bucket again.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if _, err := tx.CreateBucket([]byte("widgets")); err != bolt.ErrBucketExists {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a bucket is created with a non-blank name.
+func TestTx_CreateBucket_ErrBucketNameRequired(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if _, err := tx.CreateBucket(nil); err != bolt.ErrBucketNameRequired {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that a bucket can be deleted.
+func TestTx_DeleteBucket(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ // Create a bucket and add a value.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ // Delete the bucket and make sure we can't get the value.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if err := tx.DeleteBucket([]byte("widgets")); err != nil {
+ t.Fatal(err)
+ }
+ if tx.Bucket([]byte("widgets")) != nil {
+ t.Fatal("unexpected bucket")
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.Update(func(tx *bolt.Tx) error {
+ // Create the bucket again and make sure there's not a phantom value.
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if v := b.Get([]byte("foo")); v != nil {
+ t.Fatalf("unexpected phantom value: %v", v)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that deleting a bucket on a closed transaction returns an error.
+func TestTx_DeleteBucket_ErrTxClosed(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ tx, err := db.Begin(true)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := tx.Commit(); err != nil {
+ t.Fatal(err)
+ }
+ if err := tx.DeleteBucket([]byte("foo")); err != bolt.ErrTxClosed {
+ t.Fatalf("unexpected error: %s", err)
+ }
+}
+
+// Ensure that deleting a bucket with a read-only transaction returns an error.
+func TestTx_DeleteBucket_ReadOnly(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.View(func(tx *bolt.Tx) error {
+ if err := tx.DeleteBucket([]byte("foo")); err != bolt.ErrTxNotWritable {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that nothing happens when deleting a bucket that doesn't exist.
+func TestTx_DeleteBucket_NotFound(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ if err := tx.DeleteBucket([]byte("widgets")); err != bolt.ErrBucketNotFound {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that no error is returned when a tx.ForEach function does not return
+// an error.
+func TestTx_ForEach_NoError(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := tx.ForEach(func(name []byte, b *bolt.Bucket) error {
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that an error is returned when a tx.ForEach function returns an error.
+func TestTx_ForEach_WithError(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
+ t.Fatal(err)
+ }
+
+ marker := errors.New("marker")
+ if err := tx.ForEach(func(name []byte, b *bolt.Bucket) error {
+ return marker
+ }); err != marker {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+// Ensure that Tx commit handlers are called after a transaction successfully commits.
+func TestTx_OnCommit(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ var x int
+ if err := db.Update(func(tx *bolt.Tx) error {
+ tx.OnCommit(func() { x += 1 })
+ tx.OnCommit(func() { x += 2 })
+ if _, err := tx.CreateBucket([]byte("widgets")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ } else if x != 3 {
+ t.Fatalf("unexpected x: %d", x)
+ }
+}
+
+// Ensure that Tx commit handlers are NOT called after a transaction rolls back.
+func TestTx_OnCommit_Rollback(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ var x int
+ if err := db.Update(func(tx *bolt.Tx) error {
+ tx.OnCommit(func() { x += 1 })
+ tx.OnCommit(func() { x += 2 })
+ if _, err := tx.CreateBucket([]byte("widgets")); err != nil {
+ t.Fatal(err)
+ }
+ return errors.New("rollback this commit")
+ }); err == nil || err.Error() != "rollback this commit" {
+ t.Fatalf("unexpected error: %s", err)
+ } else if x != 0 {
+ t.Fatalf("unexpected x: %d", x)
+ }
+}
+
+// Ensure that the database can be copied to a file path.
+func TestTx_CopyFile(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+
+ path := tempfile()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("baz"), []byte("bat")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.View(func(tx *bolt.Tx) error {
+ return tx.CopyFile(path, 0600)
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ db2, err := bolt.Open(path, 0600, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db2.View(func(tx *bolt.Tx) error {
+ if v := tx.Bucket([]byte("widgets")).Get([]byte("foo")); !bytes.Equal(v, []byte("bar")) {
+ t.Fatalf("unexpected value: %v", v)
+ }
+ if v := tx.Bucket([]byte("widgets")).Get([]byte("baz")); !bytes.Equal(v, []byte("bat")) {
+ t.Fatalf("unexpected value: %v", v)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db2.Close(); err != nil {
+ t.Fatal(err)
+ }
+}
+
+type failWriterError struct{}
+
+func (failWriterError) Error() string {
+ return "error injected for tests"
+}
+
+type failWriter struct {
+ // fail after this many bytes
+ After int
+}
+
+func (f *failWriter) Write(p []byte) (n int, err error) {
+ n = len(p)
+ if n > f.After {
+ n = f.After
+ err = failWriterError{}
+ }
+ f.After -= n
+ return n, err
+}
+
+// Ensure that Copy handles write errors right.
+func TestTx_CopyFile_Error_Meta(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("baz"), []byte("bat")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.View(func(tx *bolt.Tx) error {
+ return tx.Copy(&failWriter{})
+ }); err == nil || err.Error() != "meta 0 copy: error injected for tests" {
+ t.Fatalf("unexpected error: %v", err)
+ }
+}
+
+// Ensure that Copy handles write errors right.
+func TestTx_CopyFile_Error_Normal(t *testing.T) {
+ db := MustOpenDB()
+ defer db.MustClose()
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
+ t.Fatal(err)
+ }
+ if err := b.Put([]byte("baz"), []byte("bat")); err != nil {
+ t.Fatal(err)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.View(func(tx *bolt.Tx) error {
+ return tx.Copy(&failWriter{3 * db.Info().PageSize})
+ }); err == nil || err.Error() != "error injected for tests" {
+ t.Fatalf("unexpected error: %v", err)
+ }
+}
+
+func ExampleTx_Rollback() {
+ // Open the database.
+ db, err := bolt.Open(tempfile(), 0666, nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer os.Remove(db.Path())
+
+ // Create a bucket.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ _, err := tx.CreateBucket([]byte("widgets"))
+ return err
+ }); err != nil {
+ log.Fatal(err)
+ }
+
+ // Set a value for a key.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ return tx.Bucket([]byte("widgets")).Put([]byte("foo"), []byte("bar"))
+ }); err != nil {
+ log.Fatal(err)
+ }
+
+ // Update the key but rollback the transaction so it never saves.
+ tx, err := db.Begin(true)
+ if err != nil {
+ log.Fatal(err)
+ }
+ b := tx.Bucket([]byte("widgets"))
+ if err := b.Put([]byte("foo"), []byte("baz")); err != nil {
+ log.Fatal(err)
+ }
+ if err := tx.Rollback(); err != nil {
+ log.Fatal(err)
+ }
+
+ // Ensure that our original value is still set.
+ if err := db.View(func(tx *bolt.Tx) error {
+ value := tx.Bucket([]byte("widgets")).Get([]byte("foo"))
+ fmt.Printf("The value for 'foo' is still: %s\n", value)
+ return nil
+ }); err != nil {
+ log.Fatal(err)
+ }
+
+ // Close database to release file lock.
+ if err := db.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ // Output:
+ // The value for 'foo' is still: bar
+}
+
+func ExampleTx_CopyFile() {
+ // Open the database.
+ db, err := bolt.Open(tempfile(), 0666, nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer os.Remove(db.Path())
+
+ // Create a bucket and a key.
+ if err := db.Update(func(tx *bolt.Tx) error {
+ b, err := tx.CreateBucket([]byte("widgets"))
+ if err != nil {
+ return err
+ }
+ if err := b.Put([]byte("foo"), []byte("bar")); err != nil {
+ return err
+ }
+ return nil
+ }); err != nil {
+ log.Fatal(err)
+ }
+
+ // Copy the database to another file.
+ toFile := tempfile()
+ if err := db.View(func(tx *bolt.Tx) error {
+ return tx.CopyFile(toFile, 0666)
+ }); err != nil {
+ log.Fatal(err)
+ }
+ defer os.Remove(toFile)
+
+ // Open the cloned database.
+ db2, err := bolt.Open(toFile, 0666, nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // Ensure that the key exists in the copy.
+ if err := db2.View(func(tx *bolt.Tx) error {
+ value := tx.Bucket([]byte("widgets")).Get([]byte("foo"))
+ fmt.Printf("The value for 'foo' in the clone is: %s\n", value)
+ return nil
+ }); err != nil {
+ log.Fatal(err)
+ }
+
+ // Close database to release file lock.
+ if err := db.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ if err := db2.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ // Output:
+ // The value for 'foo' in the clone is: bar
+}
diff --git a/cmd/ponzu/vendor/github.com/gorilla/schema/.travis.yml b/cmd/ponzu/vendor/github.com/gorilla/schema/.travis.yml
new file mode 100644
index 0000000..6f440f1
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/gorilla/schema/.travis.yml
@@ -0,0 +1,19 @@
+language: go
+sudo: false
+
+matrix:
+ include:
+ - go: 1.3
+ - go: 1.4
+ - go: 1.5
+ - go: 1.6
+ - go: 1.7
+ - go: tip
+ allow_failures:
+ - go: tip
+
+script:
+ - go get -t -v ./...
+ - diff -u <(echo -n) <(gofmt -d .)
+ - go vet $(go list ./... | grep -v /vendor/)
+ - go test -v -race ./...
diff --git a/cmd/ponzu/vendor/github.com/gorilla/schema/LICENSE b/cmd/ponzu/vendor/github.com/gorilla/schema/LICENSE
new file mode 100644
index 0000000..0e5fb87
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/gorilla/schema/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/cmd/ponzu/vendor/github.com/gorilla/schema/README.md b/cmd/ponzu/vendor/github.com/gorilla/schema/README.md
new file mode 100644
index 0000000..e9936d9
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/gorilla/schema/README.md
@@ -0,0 +1,66 @@
+schema
+======
+[![GoDoc](https://godoc.org/github.com/gorilla/schema?status.svg)](https://godoc.org/github.com/gorilla/schema) [![Build Status](https://travis-ci.org/gorilla/schema.png?branch=master)](https://travis-ci.org/gorilla/schema)
+
+Package gorilla/schema fills a struct with form values.
+
+## Example
+
+Here's a quick example: we parse POST form values and then decode them into a struct:
+
+```go
+// Set a Decoder instance as a package global, because it caches
+// meta-data about structs, and an instance can be shared safely.
+var decoder = schema.NewDecoder()
+
+type Person struct {
+ Name string
+ Phone string
+}
+
+func MyHandler(w http.ResponseWriter, r *http.Request) {
+ err := r.ParseForm()
+ if err != nil {
+ // Handle error
+ }
+
+ var person Person
+
+ // r.PostForm is a map of our POST form values
+ err := decoder.Decode(&person, r.PostForm)
+ if err != nil {
+ // Handle error
+ }
+
+ // Do something with person.Name or person.Phone
+}
+```
+
+To define custom names for fields, use a struct tag "schema". To not populate certain fields, use a dash for the name and it will be ignored:
+
+```go
+type Person struct {
+ Name string `schema:"name"` // custom name
+ Phone string `schema:"phone"` // custom name
+ Admin bool `schema:"-"` // this field is never set
+}
+```
+
+The supported field types in the destination struct are:
+
+* bool
+* float variants (float32, float64)
+* int variants (int, int8, int16, int32, int64)
+* string
+* uint variants (uint, uint8, uint16, uint32, uint64)
+* struct
+* a pointer to one of the above types
+* a slice or a pointer to a slice of one of the above types
+
+Unsupported types are simply ignored, however custom types can be registered to be converted.
+
+More examples are available on the Gorilla website: http://www.gorillatoolkit.org/pkg/schema
+
+## License
+
+BSD licensed. See the LICENSE file for details.
diff --git a/cmd/ponzu/vendor/github.com/gorilla/schema/cache.go b/cmd/ponzu/vendor/github.com/gorilla/schema/cache.go
new file mode 100644
index 0000000..e0f7566
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/gorilla/schema/cache.go
@@ -0,0 +1,261 @@
+// 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 schema
+
+import (
+ "errors"
+ "reflect"
+ "strconv"
+ "strings"
+ "sync"
+)
+
+var invalidPath = errors.New("schema: invalid path")
+
+// newCache returns a new cache.
+func newCache() *cache {
+ c := cache{
+ m: make(map[reflect.Type]*structInfo),
+ conv: make(map[reflect.Kind]Converter),
+ regconv: make(map[reflect.Type]Converter),
+ tag: "schema",
+ }
+ for k, v := range converters {
+ c.conv[k] = v
+ }
+ return &c
+}
+
+// cache caches meta-data about a struct.
+type cache struct {
+ l sync.RWMutex
+ m map[reflect.Type]*structInfo
+ conv map[reflect.Kind]Converter
+ regconv map[reflect.Type]Converter
+ tag string
+}
+
+// parsePath parses a path in dotted notation verifying that it is a valid
+// path to a struct field.
+//
+// It returns "path parts" which contain indices to fields to be used by
+// reflect.Value.FieldByString(). Multiple parts are required for slices of
+// structs.
+func (c *cache) parsePath(p string, t reflect.Type) ([]pathPart, error) {
+ var struc *structInfo
+ var field *fieldInfo
+ var index64 int64
+ var err error
+ parts := make([]pathPart, 0)
+ path := make([]string, 0)
+ keys := strings.Split(p, ".")
+ for i := 0; i < len(keys); i++ {
+ if t.Kind() != reflect.Struct {
+ return nil, invalidPath
+ }
+ if struc = c.get(t); struc == nil {
+ return nil, invalidPath
+ }
+ if field = struc.get(keys[i]); field == nil {
+ return nil, invalidPath
+ }
+ // Valid field. Append index.
+ path = append(path, field.name)
+ if field.ss {
+ // Parse a special case: slices of structs.
+ // i+1 must be the slice index.
+ //
+ // Now that struct can implements TextUnmarshaler interface,
+ // we don't need to force the struct's fields to appear in the path.
+ // So checking i+2 is not necessary anymore.
+ i++
+ if i+1 > len(keys) {
+ return nil, invalidPath
+ }
+ if index64, err = strconv.ParseInt(keys[i], 10, 0); err != nil {
+ return nil, invalidPath
+ }
+ parts = append(parts, pathPart{
+ path: path,
+ field: field,
+ index: int(index64),
+ })
+ path = make([]string, 0)
+
+ // Get the next struct type, dropping ptrs.
+ if field.typ.Kind() == reflect.Ptr {
+ t = field.typ.Elem()
+ } else {
+ t = field.typ
+ }
+ if t.Kind() == reflect.Slice {
+ t = t.Elem()
+ if t.Kind() == reflect.Ptr {
+ t = t.Elem()
+ }
+ }
+ } else if field.typ.Kind() == reflect.Ptr {
+ t = field.typ.Elem()
+ } else {
+ t = field.typ
+ }
+ }
+ // Add the remaining.
+ parts = append(parts, pathPart{
+ path: path,
+ field: field,
+ index: -1,
+ })
+ return parts, nil
+}
+
+// get returns a cached structInfo, creating it if necessary.
+func (c *cache) get(t reflect.Type) *structInfo {
+ c.l.RLock()
+ info := c.m[t]
+ c.l.RUnlock()
+ if info == nil {
+ info = c.create(t, nil)
+ c.l.Lock()
+ c.m[t] = info
+ c.l.Unlock()
+ }
+ return info
+}
+
+// create creates a structInfo with meta-data about a struct.
+func (c *cache) create(t reflect.Type, info *structInfo) *structInfo {
+ if info == nil {
+ info = &structInfo{fields: []*fieldInfo{}}
+ }
+ for i := 0; i < t.NumField(); i++ {
+ field := t.Field(i)
+ if field.Anonymous {
+ ft := field.Type
+ if ft.Kind() == reflect.Ptr {
+ ft = ft.Elem()
+ }
+ if ft.Kind() == reflect.Struct {
+ c.create(ft, info)
+ }
+ }
+ c.createField(field, info)
+ }
+ return info
+}
+
+// createField creates a fieldInfo for the given field.
+func (c *cache) createField(field reflect.StructField, info *structInfo) {
+ alias, options := fieldAlias(field, c.tag)
+ if alias == "-" {
+ // Ignore this field.
+ return
+ }
+ // Check if the type is supported and don't cache it if not.
+ // First let's get the basic type.
+ isSlice, isStruct := false, false
+ ft := field.Type
+ if ft.Kind() == reflect.Ptr {
+ ft = ft.Elem()
+ }
+ if isSlice = ft.Kind() == reflect.Slice; isSlice {
+ ft = ft.Elem()
+ if ft.Kind() == reflect.Ptr {
+ ft = ft.Elem()
+ }
+ }
+ if ft.Kind() == reflect.Array {
+ ft = ft.Elem()
+ if ft.Kind() == reflect.Ptr {
+ ft = ft.Elem()
+ }
+ }
+ if isStruct = ft.Kind() == reflect.Struct; !isStruct {
+ if conv := c.conv[ft.Kind()]; conv == nil {
+ // Type is not supported.
+ return
+ }
+ }
+
+ info.fields = append(info.fields, &fieldInfo{
+ typ: field.Type,
+ name: field.Name,
+ ss: isSlice && isStruct,
+ alias: alias,
+ required: options.Contains("required"),
+ })
+}
+
+// converter returns the converter for a type.
+func (c *cache) converter(t reflect.Type) Converter {
+ conv := c.regconv[t]
+ if conv == nil {
+ conv = c.conv[t.Kind()]
+ }
+ return conv
+}
+
+// ----------------------------------------------------------------------------
+
+type structInfo struct {
+ fields []*fieldInfo
+}
+
+func (i *structInfo) get(alias string) *fieldInfo {
+ for _, field := range i.fields {
+ if strings.EqualFold(field.alias, alias) {
+ return field
+ }
+ }
+ return nil
+}
+
+type fieldInfo struct {
+ typ reflect.Type
+ name string // field name in the struct.
+ ss bool // true if this is a slice of structs.
+ alias string
+ required bool // tag option
+}
+
+type pathPart struct {
+ field *fieldInfo
+ path []string // path to the field: walks structs using field names.
+ index int // struct index in slices of structs.
+}
+
+// ----------------------------------------------------------------------------
+
+// fieldAlias parses a field tag to get a field alias.
+func fieldAlias(field reflect.StructField, tagName string) (alias string, options tagOptions) {
+ if tag := field.Tag.Get(tagName); tag != "" {
+ alias, options = parseTag(tag)
+ }
+ if alias == "" {
+ alias = field.Name
+ }
+ return alias, options
+}
+
+// tagOptions is the string following a comma in a struct field's tag, or
+// the empty string. It does not include the leading comma.
+type tagOptions []string
+
+// parseTag splits a struct field's url tag into its name and comma-separated
+// options.
+func parseTag(tag string) (string, tagOptions) {
+ s := strings.Split(tag, ",")
+ return s[0], s[1:]
+}
+
+// Contains checks whether the tagOptions contains the specified option.
+func (o tagOptions) Contains(option string) bool {
+ for _, s := range o {
+ if s == option {
+ return true
+ }
+ }
+ return false
+}
diff --git a/cmd/ponzu/vendor/github.com/gorilla/schema/converter.go b/cmd/ponzu/vendor/github.com/gorilla/schema/converter.go
new file mode 100644
index 0000000..b33e942
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/gorilla/schema/converter.go
@@ -0,0 +1,145 @@
+// 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 schema
+
+import (
+ "reflect"
+ "strconv"
+)
+
+type Converter func(string) reflect.Value
+
+var (
+ invalidValue = reflect.Value{}
+ boolType = reflect.Bool
+ float32Type = reflect.Float32
+ float64Type = reflect.Float64
+ intType = reflect.Int
+ int8Type = reflect.Int8
+ int16Type = reflect.Int16
+ int32Type = reflect.Int32
+ int64Type = reflect.Int64
+ stringType = reflect.String
+ uintType = reflect.Uint
+ uint8Type = reflect.Uint8
+ uint16Type = reflect.Uint16
+ uint32Type = reflect.Uint32
+ uint64Type = reflect.Uint64
+)
+
+// Default converters for basic types.
+var converters = map[reflect.Kind]Converter{
+ boolType: convertBool,
+ float32Type: convertFloat32,
+ float64Type: convertFloat64,
+ intType: convertInt,
+ int8Type: convertInt8,
+ int16Type: convertInt16,
+ int32Type: convertInt32,
+ int64Type: convertInt64,
+ stringType: convertString,
+ uintType: convertUint,
+ uint8Type: convertUint8,
+ uint16Type: convertUint16,
+ uint32Type: convertUint32,
+ uint64Type: convertUint64,
+}
+
+func convertBool(value string) reflect.Value {
+ if value == "on" {
+ return reflect.ValueOf(true)
+ } else if v, err := strconv.ParseBool(value); err == nil {
+ return reflect.ValueOf(v)
+ }
+ return invalidValue
+}
+
+func convertFloat32(value string) reflect.Value {
+ if v, err := strconv.ParseFloat(value, 32); err == nil {
+ return reflect.ValueOf(float32(v))
+ }
+ return invalidValue
+}
+
+func convertFloat64(value string) reflect.Value {
+ if v, err := strconv.ParseFloat(value, 64); err == nil {
+ return reflect.ValueOf(v)
+ }
+ return invalidValue
+}
+
+func convertInt(value string) reflect.Value {
+ if v, err := strconv.ParseInt(value, 10, 0); err == nil {
+ return reflect.ValueOf(int(v))
+ }
+ return invalidValue
+}
+
+func convertInt8(value string) reflect.Value {
+ if v, err := strconv.ParseInt(value, 10, 8); err == nil {
+ return reflect.ValueOf(int8(v))
+ }
+ return invalidValue
+}
+
+func convertInt16(value string) reflect.Value {
+ if v, err := strconv.ParseInt(value, 10, 16); err == nil {
+ return reflect.ValueOf(int16(v))
+ }
+ return invalidValue
+}
+
+func convertInt32(value string) reflect.Value {
+ if v, err := strconv.ParseInt(value, 10, 32); err == nil {
+ return reflect.ValueOf(int32(v))
+ }
+ return invalidValue
+}
+
+func convertInt64(value string) reflect.Value {
+ if v, err := strconv.ParseInt(value, 10, 64); err == nil {
+ return reflect.ValueOf(v)
+ }
+ return invalidValue
+}
+
+func convertString(value string) reflect.Value {
+ return reflect.ValueOf(value)
+}
+
+func convertUint(value string) reflect.Value {
+ if v, err := strconv.ParseUint(value, 10, 0); err == nil {
+ return reflect.ValueOf(uint(v))
+ }
+ return invalidValue
+}
+
+func convertUint8(value string) reflect.Value {
+ if v, err := strconv.ParseUint(value, 10, 8); err == nil {
+ return reflect.ValueOf(uint8(v))
+ }
+ return invalidValue
+}
+
+func convertUint16(value string) reflect.Value {
+ if v, err := strconv.ParseUint(value, 10, 16); err == nil {
+ return reflect.ValueOf(uint16(v))
+ }
+ return invalidValue
+}
+
+func convertUint32(value string) reflect.Value {
+ if v, err := strconv.ParseUint(value, 10, 32); err == nil {
+ return reflect.ValueOf(uint32(v))
+ }
+ return invalidValue
+}
+
+func convertUint64(value string) reflect.Value {
+ if v, err := strconv.ParseUint(value, 10, 64); err == nil {
+ return reflect.ValueOf(v)
+ }
+ return invalidValue
+}
diff --git a/cmd/ponzu/vendor/github.com/gorilla/schema/decoder.go b/cmd/ponzu/vendor/github.com/gorilla/schema/decoder.go
new file mode 100644
index 0000000..7ebe1b1
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/gorilla/schema/decoder.go
@@ -0,0 +1,343 @@
+// 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 schema
+
+import (
+ "encoding"
+ "errors"
+ "fmt"
+ "reflect"
+ "strings"
+)
+
+// NewDecoder returns a new Decoder.
+func NewDecoder() *Decoder {
+ return &Decoder{cache: newCache()}
+}
+
+// Decoder decodes values from a map[string][]string to a struct.
+type Decoder struct {
+ cache *cache
+ zeroEmpty bool
+ ignoreUnknownKeys bool
+}
+
+// SetAliasTag changes the tag used to locate custom field aliases.
+// The default tag is "schema".
+func (d *Decoder) SetAliasTag(tag string) {
+ d.cache.tag = tag
+}
+
+// ZeroEmpty controls the behaviour when the decoder encounters empty values
+// in a map.
+// If z is true and a key in the map has the empty string as a value
+// then the corresponding struct field is set to the zero value.
+// If z is false then empty strings are ignored.
+//
+// The default value is false, that is empty values do not change
+// the value of the struct field.
+func (d *Decoder) ZeroEmpty(z bool) {
+ d.zeroEmpty = z
+}
+
+// IgnoreUnknownKeys controls the behaviour when the decoder encounters unknown
+// keys in the map.
+// If i is true and an unknown field is encountered, it is ignored. This is
+// similar to how unknown keys are handled by encoding/json.
+// If i is false then Decode will return an error. Note that any valid keys
+// will still be decoded in to the target struct.
+//
+// To preserve backwards compatibility, the default value is false.
+func (d *Decoder) IgnoreUnknownKeys(i bool) {
+ d.ignoreUnknownKeys = i
+}
+
+// RegisterConverter registers a converter function for a custom type.
+func (d *Decoder) RegisterConverter(value interface{}, converterFunc Converter) {
+ d.cache.regconv[reflect.TypeOf(value)] = converterFunc
+}
+
+// Decode decodes a map[string][]string to a struct.
+//
+// The first parameter must be a pointer to a struct.
+//
+// The second parameter is a map, typically url.Values from an HTTP request.
+// Keys are "paths" in dotted notation to the struct fields and nested structs.
+//
+// See the package documentation for a full explanation of the mechanics.
+func (d *Decoder) Decode(dst interface{}, src map[string][]string) error {
+ v := reflect.ValueOf(dst)
+ if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
+ return errors.New("schema: interface must be a pointer to struct")
+ }
+ v = v.Elem()
+ t := v.Type()
+ errors := MultiError{}
+ for path, values := range src {
+ if parts, err := d.cache.parsePath(path, t); err == nil {
+ if err = d.decode(v, path, parts, values); err != nil {
+ errors[path] = err
+ }
+ } else if !d.ignoreUnknownKeys {
+ errors[path] = fmt.Errorf("schema: invalid path %q", path)
+ }
+ }
+ if len(errors) > 0 {
+ return errors
+ }
+ return d.checkRequired(t, src, "")
+}
+
+// checkRequired checks whether requred field empty
+//
+// check type t recursively if t has struct fields, and prefix is same as parsePath: in dotted notation
+//
+// src is the source map for decoding, we use it here to see if those required fields are included in src
+func (d *Decoder) checkRequired(t reflect.Type, src map[string][]string, prefix string) error {
+ struc := d.cache.get(t)
+ if struc == nil {
+ // unexpect, cache.get never return nil
+ return errors.New("cache fail")
+ }
+
+ for _, f := range struc.fields {
+ if f.typ.Kind() == reflect.Struct {
+ err := d.checkRequired(f.typ, src, prefix+f.alias+".")
+ if err != nil {
+ return err
+ }
+ }
+ if f.required {
+ key := f.alias
+ if prefix != "" {
+ key = prefix + key
+ }
+ if isEmpty(f.typ, src[key]) {
+ return fmt.Errorf("%v is empty", key)
+ }
+ }
+ }
+ return nil
+}
+
+// isEmpty returns true if value is empty for specific type
+func isEmpty(t reflect.Type, value []string) bool {
+ if len(value) == 0 {
+ return true
+ }
+ switch t.Kind() {
+ case boolType, float32Type, float64Type, intType, int8Type, int32Type, int64Type, stringType, uint8Type, uint16Type, uint32Type, uint64Type:
+ return len(value[0]) == 0
+ }
+ return false
+}
+
+// decode fills a struct field using a parsed path.
+func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values []string) error {
+ // Get the field walking the struct fields by index.
+ for _, name := range parts[0].path {
+ if v.Type().Kind() == reflect.Ptr {
+ if v.IsNil() {
+ v.Set(reflect.New(v.Type().Elem()))
+ }
+ v = v.Elem()
+ }
+ v = v.FieldByName(name)
+ }
+
+ // Don't even bother for unexported fields.
+ if !v.CanSet() {
+ return nil
+ }
+
+ // Dereference if needed.
+ t := v.Type()
+ if t.Kind() == reflect.Ptr {
+ t = t.Elem()
+ if v.IsNil() {
+ v.Set(reflect.New(t))
+ }
+ v = v.Elem()
+ }
+
+ // Slice of structs. Let's go recursive.
+ if len(parts) > 1 {
+ idx := parts[0].index
+ if v.IsNil() || v.Len() < idx+1 {
+ value := reflect.MakeSlice(t, idx+1, idx+1)
+ if v.Len() < idx+1 {
+ // Resize it.
+ reflect.Copy(value, v)
+ }
+ v.Set(value)
+ }
+ return d.decode(v.Index(idx), path, parts[1:], values)
+ }
+
+ // Get the converter early in case there is one for a slice type.
+ conv := d.cache.converter(t)
+ if conv == nil && t.Kind() == reflect.Slice {
+ var items []reflect.Value
+ elemT := t.Elem()
+ isPtrElem := elemT.Kind() == reflect.Ptr
+ if isPtrElem {
+ elemT = elemT.Elem()
+ }
+
+ // Try to get a converter for the element type.
+ conv := d.cache.converter(elemT)
+ if conv == nil {
+ // As we are not dealing with slice of structs here, we don't need to check if the type
+ // implements TextUnmarshaler interface
+ return fmt.Errorf("schema: converter not found for %v", elemT)
+ }
+
+ for key, value := range values {
+ if value == "" {
+ if d.zeroEmpty {
+ items = append(items, reflect.Zero(elemT))
+ }
+ } else if item := conv(value); item.IsValid() {
+ if isPtrElem {
+ ptr := reflect.New(elemT)
+ ptr.Elem().Set(item)
+ item = ptr
+ }
+ if item.Type() != elemT && !isPtrElem {
+ item = item.Convert(elemT)
+ }
+ items = append(items, item)
+ } else {
+ if strings.Contains(value, ",") {
+ values := strings.Split(value, ",")
+ for _, value := range values {
+ if value == "" {
+ if d.zeroEmpty {
+ items = append(items, reflect.Zero(elemT))
+ }
+ } else if item := conv(value); item.IsValid() {
+ if isPtrElem {
+ ptr := reflect.New(elemT)
+ ptr.Elem().Set(item)
+ item = ptr
+ }
+ if item.Type() != elemT && !isPtrElem {
+ item = item.Convert(elemT)
+ }
+ items = append(items, item)
+ } else {
+ return ConversionError{
+ Key: path,
+ Type: elemT,
+ Index: key,
+ }
+ }
+ }
+ } else {
+ return ConversionError{
+ Key: path,
+ Type: elemT,
+ Index: key,
+ }
+ }
+ }
+ }
+ value := reflect.Append(reflect.MakeSlice(t, 0, 0), items...)
+ v.Set(value)
+ } else {
+ val := ""
+ // Use the last value provided if any values were provided
+ if len(values) > 0 {
+ val = values[len(values)-1]
+ }
+
+ if val == "" {
+ if d.zeroEmpty {
+ v.Set(reflect.Zero(t))
+ }
+ } else if conv != nil {
+ if value := conv(val); value.IsValid() {
+ v.Set(value.Convert(t))
+ } else {
+ return ConversionError{
+ Key: path,
+ Type: t,
+ Index: -1,
+ }
+ }
+ } else {
+ // When there's no registered conversion for the custom type, we will check if the type
+ // implements the TextUnmarshaler interface. As the UnmarshalText function should be applied
+ // to the pointer of the type, we convert the value to pointer.
+ if v.CanAddr() {
+ v = v.Addr()
+ }
+
+ if u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
+ if err := u.UnmarshalText([]byte(val)); err != nil {
+ return ConversionError{
+ Key: path,
+ Type: t,
+ Index: -1,
+ Err: err,
+ }
+ }
+
+ } else {
+ return fmt.Errorf("schema: converter not found for %v", t)
+ }
+ }
+ }
+ return nil
+}
+
+// Errors ---------------------------------------------------------------------
+
+// ConversionError stores information about a failed conversion.
+type ConversionError struct {
+ Key string // key from the source map.
+ Type reflect.Type // expected type of elem
+ Index int // index for multi-value fields; -1 for single-value fields.
+ Err error // low-level error (when it exists)
+}
+
+func (e ConversionError) Error() string {
+ var output string
+
+ if e.Index < 0 {
+ output = fmt.Sprintf("schema: error converting value for %q", e.Key)
+ } else {
+ output = fmt.Sprintf("schema: error converting value for index %d of %q",
+ e.Index, e.Key)
+ }
+
+ if e.Err != nil {
+ output = fmt.Sprintf("%s. Details: %s", output, e.Err)
+ }
+
+ return output
+}
+
+// MultiError stores multiple decoding errors.
+//
+// Borrowed from the App Engine SDK.
+type MultiError map[string]error
+
+func (e MultiError) Error() string {
+ s := ""
+ for _, err := range e {
+ s = err.Error()
+ break
+ }
+ switch len(e) {
+ 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, len(e)-1)
+}
diff --git a/cmd/ponzu/vendor/github.com/gorilla/schema/decoder_test.go b/cmd/ponzu/vendor/github.com/gorilla/schema/decoder_test.go
new file mode 100644
index 0000000..4593916
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/gorilla/schema/decoder_test.go
@@ -0,0 +1,1460 @@
+// 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 schema
+
+import (
+ "encoding/hex"
+ "errors"
+ "reflect"
+ "strings"
+ "testing"
+ "time"
+)
+
+type IntAlias int
+
+// All cases we want to cover, in a nutshell.
+type S1 struct {
+ F01 int `schema:"f1"`
+ F02 *int `schema:"f2"`
+ F03 []int `schema:"f3"`
+ F04 []*int `schema:"f4"`
+ F05 *[]int `schema:"f5"`
+ F06 *[]*int `schema:"f6"`
+ F07 S2 `schema:"f7"`
+ F08 *S1 `schema:"f8"`
+ F09 int `schema:"-"`
+ F10 []S1 `schema:"f10"`
+ F11 []*S1 `schema:"f11"`
+ F12 *[]S1 `schema:"f12"`
+ F13 *[]*S1 `schema:"f13"`
+ F14 int `schema:"f14"`
+ F15 IntAlias `schema:"f15"`
+ F16 []IntAlias `schema:"f16"`
+ F17 S19 `schema:"f17"`
+}
+
+type S2 struct {
+ F01 *[]*int `schema:"f1"`
+}
+
+type S19 [2]byte
+
+func (id *S19) UnmarshalText(text []byte) error {
+ buf, err := hex.DecodeString(string(text))
+ if err != nil {
+ return err
+ }
+ if len(buf) > len(*id) {
+ return errors.New("out of range")
+ }
+ for i := range buf {
+ (*id)[i] = buf[i]
+ }
+ return nil
+}
+
+func TestAll(t *testing.T) {
+ v := map[string][]string{
+ "f1": {"1"},
+ "f2": {"2"},
+ "f3": {"31", "32"},
+ "f4": {"41", "42"},
+ "f5": {"51", "52"},
+ "f6": {"61", "62"},
+ "f7.f1": {"71", "72"},
+ "f8.f8.f7.f1": {"81", "82"},
+ "f9": {"9"},
+ "f10.0.f10.0.f6": {"101", "102"},
+ "f10.0.f10.1.f6": {"103", "104"},
+ "f11.0.f11.0.f6": {"111", "112"},
+ "f11.0.f11.1.f6": {"113", "114"},
+ "f12.0.f12.0.f6": {"121", "122"},
+ "f12.0.f12.1.f6": {"123", "124"},
+ "f13.0.f13.0.f6": {"131", "132"},
+ "f13.0.f13.1.f6": {"133", "134"},
+ "f14": {},
+ "f15": {"151"},
+ "f16": {"161", "162"},
+ "f17": {"1a2b"},
+ }
+ f2 := 2
+ f41, f42 := 41, 42
+ f61, f62 := 61, 62
+ f71, f72 := 71, 72
+ f81, f82 := 81, 82
+ f101, f102, f103, f104 := 101, 102, 103, 104
+ f111, f112, f113, f114 := 111, 112, 113, 114
+ f121, f122, f123, f124 := 121, 122, 123, 124
+ f131, f132, f133, f134 := 131, 132, 133, 134
+ var f151 IntAlias = 151
+ var f161, f162 IntAlias = 161, 162
+ e := S1{
+ F01: 1,
+ F02: &f2,
+ F03: []int{31, 32},
+ F04: []*int{&f41, &f42},
+ F05: &[]int{51, 52},
+ F06: &[]*int{&f61, &f62},
+ F07: S2{
+ F01: &[]*int{&f71, &f72},
+ },
+ F08: &S1{
+ F08: &S1{
+ F07: S2{
+ F01: &[]*int{&f81, &f82},
+ },
+ },
+ },
+ F09: 0,
+ F10: []S1{
+ S1{
+ F10: []S1{
+ S1{F06: &[]*int{&f101, &f102}},
+ S1{F06: &[]*int{&f103, &f104}},
+ },
+ },
+ },
+ F11: []*S1{
+ &S1{
+ F11: []*S1{
+ &S1{F06: &[]*int{&f111, &f112}},
+ &S1{F06: &[]*int{&f113, &f114}},
+ },
+ },
+ },
+ F12: &[]S1{
+ S1{
+ F12: &[]S1{
+ S1{F06: &[]*int{&f121, &f122}},
+ S1{F06: &[]*int{&f123, &f124}},
+ },
+ },
+ },
+ F13: &[]*S1{
+ &S1{
+ F13: &[]*S1{
+ &S1{F06: &[]*int{&f131, &f132}},
+ &S1{F06: &[]*int{&f133, &f134}},
+ },
+ },
+ },
+ F14: 0,
+ F15: f151,
+ F16: []IntAlias{f161, f162},
+ F17: S19{0x1a, 0x2b},
+ }
+
+ s := &S1{}
+ _ = NewDecoder().Decode(s, v)
+
+ vals := func(values []*int) []int {
+ r := make([]int, len(values))
+ for k, v := range values {
+ r[k] = *v
+ }
+ return r
+ }
+
+ if s.F01 != e.F01 {
+ t.Errorf("f1: expected %v, got %v", e.F01, s.F01)
+ }
+ if s.F02 == nil {
+ t.Errorf("f2: expected %v, got nil", *e.F02)
+ } else if *s.F02 != *e.F02 {
+ t.Errorf("f2: expected %v, got %v", *e.F02, *s.F02)
+ }
+ if s.F03 == nil {
+ t.Errorf("f3: expected %v, got nil", e.F03)
+ } else if len(s.F03) != 2 || s.F03[0] != e.F03[0] || s.F03[1] != e.F03[1] {
+ t.Errorf("f3: expected %v, got %v", e.F03, s.F03)
+ }
+ if s.F04 == nil {
+ t.Errorf("f4: expected %v, got nil", e.F04)
+ } else {
+ if len(s.F04) != 2 || *(s.F04)[0] != *(e.F04)[0] || *(s.F04)[1] != *(e.F04)[1] {
+ t.Errorf("f4: expected %v, got %v", vals(e.F04), vals(s.F04))
+ }
+ }
+ if s.F05 == nil {
+ t.Errorf("f5: expected %v, got nil", e.F05)
+ } else {
+ sF05, eF05 := *s.F05, *e.F05
+ if len(sF05) != 2 || sF05[0] != eF05[0] || sF05[1] != eF05[1] {
+ t.Errorf("f5: expected %v, got %v", eF05, sF05)
+ }
+ }
+ if s.F06 == nil {
+ t.Errorf("f6: expected %v, got nil", vals(*e.F06))
+ } else {
+ sF06, eF06 := *s.F06, *e.F06
+ if len(sF06) != 2 || *(sF06)[0] != *(eF06)[0] || *(sF06)[1] != *(eF06)[1] {
+ t.Errorf("f6: expected %v, got %v", vals(eF06), vals(sF06))
+ }
+ }
+ if s.F07.F01 == nil {
+ t.Errorf("f7.f1: expected %v, got nil", vals(*e.F07.F01))
+ } else {
+ sF07, eF07 := *s.F07.F01, *e.F07.F01
+ if len(sF07) != 2 || *(sF07)[0] != *(eF07)[0] || *(sF07)[1] != *(eF07)[1] {
+ t.Errorf("f7.f1: expected %v, got %v", vals(eF07), vals(sF07))
+ }
+ }
+ if s.F08 == nil {
+ t.Errorf("f8: got nil")
+ } else if s.F08.F08 == nil {
+ t.Errorf("f8.f8: got nil")
+ } else if s.F08.F08.F07.F01 == nil {
+ t.Errorf("f8.f8.f7.f1: expected %v, got nil", vals(*e.F08.F08.F07.F01))
+ } else {
+ sF08, eF08 := *s.F08.F08.F07.F01, *e.F08.F08.F07.F01
+ if len(sF08) != 2 || *(sF08)[0] != *(eF08)[0] || *(sF08)[1] != *(eF08)[1] {
+ t.Errorf("f8.f8.f7.f1: expected %v, got %v", vals(eF08), vals(sF08))
+ }
+ }
+ if s.F09 != e.F09 {
+ t.Errorf("f9: expected %v, got %v", e.F09, s.F09)
+ }
+ if s.F10 == nil {
+ t.Errorf("f10: got nil")
+ } else if len(s.F10) != 1 {
+ t.Errorf("f10: expected 1 element, got %v", s.F10)
+ } else {
+ if len(s.F10[0].F10) != 2 {
+ t.Errorf("f10.0.f10: expected 1 element, got %v", s.F10[0].F10)
+ } else {
+ sF10, eF10 := *s.F10[0].F10[0].F06, *e.F10[0].F10[0].F06
+ if sF10 == nil {
+ t.Errorf("f10.0.f10.0.f6: expected %v, got nil", vals(eF10))
+ } else {
+ if len(sF10) != 2 || *(sF10)[0] != *(eF10)[0] || *(sF10)[1] != *(eF10)[1] {
+ t.Errorf("f10.0.f10.0.f6: expected %v, got %v", vals(eF10), vals(sF10))
+ }
+ }
+ sF10, eF10 = *s.F10[0].F10[1].F06, *e.F10[0].F10[1].F06
+ if sF10 == nil {
+ t.Errorf("f10.0.f10.0.f6: expected %v, got nil", vals(eF10))
+ } else {
+ if len(sF10) != 2 || *(sF10)[0] != *(eF10)[0] || *(sF10)[1] != *(eF10)[1] {
+ t.Errorf("f10.0.f10.0.f6: expected %v, got %v", vals(eF10), vals(sF10))
+ }
+ }
+ }
+ }
+ if s.F11 == nil {
+ t.Errorf("f11: got nil")
+ } else if len(s.F11) != 1 {
+ t.Errorf("f11: expected 1 element, got %v", s.F11)
+ } else {
+ if len(s.F11[0].F11) != 2 {
+ t.Errorf("f11.0.f11: expected 1 element, got %v", s.F11[0].F11)
+ } else {
+ sF11, eF11 := *s.F11[0].F11[0].F06, *e.F11[0].F11[0].F06
+ if sF11 == nil {
+ t.Errorf("f11.0.f11.0.f6: expected %v, got nil", vals(eF11))
+ } else {
+ if len(sF11) != 2 || *(sF11)[0] != *(eF11)[0] || *(sF11)[1] != *(eF11)[1] {
+ t.Errorf("f11.0.f11.0.f6: expected %v, got %v", vals(eF11), vals(sF11))
+ }
+ }
+ sF11, eF11 = *s.F11[0].F11[1].F06, *e.F11[0].F11[1].F06
+ if sF11 == nil {
+ t.Errorf("f11.0.f11.0.f6: expected %v, got nil", vals(eF11))
+ } else {
+ if len(sF11) != 2 || *(sF11)[0] != *(eF11)[0] || *(sF11)[1] != *(eF11)[1] {
+ t.Errorf("f11.0.f11.0.f6: expected %v, got %v", vals(eF11), vals(sF11))
+ }
+ }
+ }
+ }
+ if s.F12 == nil {
+ t.Errorf("f12: got nil")
+ } else if len(*s.F12) != 1 {
+ t.Errorf("f12: expected 1 element, got %v", *s.F12)
+ } else {
+ sF12, eF12 := *(s.F12), *(e.F12)
+ if len(*sF12[0].F12) != 2 {
+ t.Errorf("f12.0.f12: expected 1 element, got %v", *sF12[0].F12)
+ } else {
+ sF122, eF122 := *(*sF12[0].F12)[0].F06, *(*eF12[0].F12)[0].F06
+ if sF122 == nil {
+ t.Errorf("f12.0.f12.0.f6: expected %v, got nil", vals(eF122))
+ } else {
+ if len(sF122) != 2 || *(sF122)[0] != *(eF122)[0] || *(sF122)[1] != *(eF122)[1] {
+ t.Errorf("f12.0.f12.0.f6: expected %v, got %v", vals(eF122), vals(sF122))
+ }
+ }
+ sF122, eF122 = *(*sF12[0].F12)[1].F06, *(*eF12[0].F12)[1].F06
+ if sF122 == nil {
+ t.Errorf("f12.0.f12.0.f6: expected %v, got nil", vals(eF122))
+ } else {
+ if len(sF122) != 2 || *(sF122)[0] != *(eF122)[0] || *(sF122)[1] != *(eF122)[1] {
+ t.Errorf("f12.0.f12.0.f6: expected %v, got %v", vals(eF122), vals(sF122))
+ }
+ }
+ }
+ }
+ if s.F13 == nil {
+ t.Errorf("f13: got nil")
+ } else if len(*s.F13) != 1 {
+ t.Errorf("f13: expected 1 element, got %v", *s.F13)
+ } else {
+ sF13, eF13 := *(s.F13), *(e.F13)
+ if len(*sF13[0].F13) != 2 {
+ t.Errorf("f13.0.f13: expected 1 element, got %v", *sF13[0].F13)
+ } else {
+ sF132, eF132 := *(*sF13[0].F13)[0].F06, *(*eF13[0].F13)[0].F06
+ if sF132 == nil {
+ t.Errorf("f13.0.f13.0.f6: expected %v, got nil", vals(eF132))
+ } else {
+ if len(sF132) != 2 || *(sF132)[0] != *(eF132)[0] || *(sF132)[1] != *(eF132)[1] {
+ t.Errorf("f13.0.f13.0.f6: expected %v, got %v", vals(eF132), vals(sF132))
+ }
+ }
+ sF132, eF132 = *(*sF13[0].F13)[1].F06, *(*eF13[0].F13)[1].F06
+ if sF132 == nil {
+ t.Errorf("f13.0.f13.0.f6: expected %v, got nil", vals(eF132))
+ } else {
+ if len(sF132) != 2 || *(sF132)[0] != *(eF132)[0] || *(sF132)[1] != *(eF132)[1] {
+ t.Errorf("f13.0.f13.0.f6: expected %v, got %v", vals(eF132), vals(sF132))
+ }
+ }
+ }
+ }
+ if s.F14 != e.F14 {
+ t.Errorf("f14: expected %v, got %v", e.F14, s.F14)
+ }
+ if s.F15 != e.F15 {
+ t.Errorf("f15: expected %v, got %v", e.F15, s.F15)
+ }
+ if s.F16 == nil {
+ t.Errorf("f16: nil")
+ } else if len(s.F16) != len(e.F16) {
+ t.Errorf("f16: expected len %d, got %d", len(e.F16), len(s.F16))
+ } else if !reflect.DeepEqual(s.F16, e.F16) {
+ t.Errorf("f16: expected %v, got %v", e.F16, s.F16)
+ }
+ if s.F17 != e.F17 {
+ t.Errorf("f17: expected %v, got %v", e.F17, s.F17)
+ }
+}
+
+func BenchmarkAll(b *testing.B) {
+ v := map[string][]string{
+ "f1": {"1"},
+ "f2": {"2"},
+ "f3": {"31", "32"},
+ "f4": {"41", "42"},
+ "f5": {"51", "52"},
+ "f6": {"61", "62"},
+ "f7.f1": {"71", "72"},
+ "f8.f8.f7.f1": {"81", "82"},
+ "f9": {"9"},
+ "f10.0.f10.0.f6": {"101", "102"},
+ "f10.0.f10.1.f6": {"103", "104"},
+ "f11.0.f11.0.f6": {"111", "112"},
+ "f11.0.f11.1.f6": {"113", "114"},
+ "f12.0.f12.0.f6": {"121", "122"},
+ "f12.0.f12.1.f6": {"123", "124"},
+ "f13.0.f13.0.f6": {"131", "132"},
+ "f13.0.f13.1.f6": {"133", "134"},
+ }
+
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ s := &S1{}
+ _ = NewDecoder().Decode(s, v)
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+type S3 struct {
+ F01 bool
+ F02 float32
+ F03 float64
+ F04 int
+ F05 int8
+ F06 int16
+ F07 int32
+ F08 int64
+ F09 string
+ F10 uint
+ F11 uint8
+ F12 uint16
+ F13 uint32
+ F14 uint64
+}
+
+func TestDefaultConverters(t *testing.T) {
+ v := map[string][]string{
+ "F01": {"true"},
+ "F02": {"4.2"},
+ "F03": {"4.3"},
+ "F04": {"-42"},
+ "F05": {"-43"},
+ "F06": {"-44"},
+ "F07": {"-45"},
+ "F08": {"-46"},
+ "F09": {"foo"},
+ "F10": {"42"},
+ "F11": {"43"},
+ "F12": {"44"},
+ "F13": {"45"},
+ "F14": {"46"},
+ }
+ e := S3{
+ F01: true,
+ F02: 4.2,
+ F03: 4.3,
+ F04: -42,
+ F05: -43,
+ F06: -44,
+ F07: -45,
+ F08: -46,
+ F09: "foo",
+ F10: 42,
+ F11: 43,
+ F12: 44,
+ F13: 45,
+ F14: 46,
+ }
+ s := &S3{}
+ _ = NewDecoder().Decode(s, v)
+ if s.F01 != e.F01 {
+ t.Errorf("F01: expected %v, got %v", e.F01, s.F01)
+ }
+ if s.F02 != e.F02 {
+ t.Errorf("F02: expected %v, got %v", e.F02, s.F02)
+ }
+ if s.F03 != e.F03 {
+ t.Errorf("F03: expected %v, got %v", e.F03, s.F03)
+ }
+ if s.F04 != e.F04 {
+ t.Errorf("F04: expected %v, got %v", e.F04, s.F04)
+ }
+ if s.F05 != e.F05 {
+ t.Errorf("F05: expected %v, got %v", e.F05, s.F05)
+ }
+ if s.F06 != e.F06 {
+ t.Errorf("F06: expected %v, got %v", e.F06, s.F06)
+ }
+ if s.F07 != e.F07 {
+ t.Errorf("F07: expected %v, got %v", e.F07, s.F07)
+ }
+ if s.F08 != e.F08 {
+ t.Errorf("F08: expected %v, got %v", e.F08, s.F08)
+ }
+ if s.F09 != e.F09 {
+ t.Errorf("F09: expected %v, got %v", e.F09, s.F09)
+ }
+ if s.F10 != e.F10 {
+ t.Errorf("F10: expected %v, got %v", e.F10, s.F10)
+ }
+ if s.F11 != e.F11 {
+ t.Errorf("F11: expected %v, got %v", e.F11, s.F11)
+ }
+ if s.F12 != e.F12 {
+ t.Errorf("F12: expected %v, got %v", e.F12, s.F12)
+ }
+ if s.F13 != e.F13 {
+ t.Errorf("F13: expected %v, got %v", e.F13, s.F13)
+ }
+ if s.F14 != e.F14 {
+ t.Errorf("F14: expected %v, got %v", e.F14, s.F14)
+ }
+}
+
+func TestOn(t *testing.T) {
+ v := map[string][]string{
+ "F01": {"on"},
+ }
+ s := S3{}
+ err := NewDecoder().Decode(&s, v)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !s.F01 {
+ t.Fatal("Value was not set to true")
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+func TestInlineStruct(t *testing.T) {
+ s1 := &struct {
+ F01 bool
+ }{}
+ s2 := &struct {
+ F01 int
+ }{}
+ v1 := map[string][]string{
+ "F01": {"true"},
+ }
+ v2 := map[string][]string{
+ "F01": {"42"},
+ }
+ decoder := NewDecoder()
+ _ = decoder.Decode(s1, v1)
+ if s1.F01 != true {
+ t.Errorf("s1: expected %v, got %v", true, s1.F01)
+ }
+ _ = decoder.Decode(s2, v2)
+ if s2.F01 != 42 {
+ t.Errorf("s2: expected %v, got %v", 42, s2.F01)
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+type Foo struct {
+ F01 int
+ F02 Bar
+ Bif []Baz
+}
+
+type Bar struct {
+ F01 string
+ F02 string
+ F03 string
+ F14 string
+ S05 string
+ Str string
+}
+
+type Baz struct {
+ F99 []string
+}
+
+func TestSimpleExample(t *testing.T) {
+ data := map[string][]string{
+ "F01": {"1"},
+ "F02.F01": {"S1"},
+ "F02.F02": {"S2"},
+ "F02.F03": {"S3"},
+ "F02.F14": {"S4"},
+ "F02.S05": {"S5"},
+ "F02.Str": {"Str"},
+ "Bif.0.F99": {"A", "B", "C"},
+ }
+
+ e := &Foo{
+ F01: 1,
+ F02: Bar{
+ F01: "S1",
+ F02: "S2",
+ F03: "S3",
+ F14: "S4",
+ S05: "S5",
+ Str: "Str",
+ },
+ Bif: []Baz{{
+ F99: []string{"A", "B", "C"}},
+ },
+ }
+
+ s := &Foo{}
+ _ = NewDecoder().Decode(s, data)
+
+ if s.F01 != e.F01 {
+ t.Errorf("F01: expected %v, got %v", e.F01, s.F01)
+ }
+ if s.F02.F01 != e.F02.F01 {
+ t.Errorf("F02.F01: expected %v, got %v", e.F02.F01, s.F02.F01)
+ }
+ if s.F02.F02 != e.F02.F02 {
+ t.Errorf("F02.F02: expected %v, got %v", e.F02.F02, s.F02.F02)
+ }
+ if s.F02.F03 != e.F02.F03 {
+ t.Errorf("F02.F03: expected %v, got %v", e.F02.F03, s.F02.F03)
+ }
+ if s.F02.F14 != e.F02.F14 {
+ t.Errorf("F02.F14: expected %v, got %v", e.F02.F14, s.F02.F14)
+ }
+ if s.F02.S05 != e.F02.S05 {
+ t.Errorf("F02.S05: expected %v, got %v", e.F02.S05, s.F02.S05)
+ }
+ if s.F02.Str != e.F02.Str {
+ t.Errorf("F02.Str: expected %v, got %v", e.F02.Str, s.F02.Str)
+ }
+ if len(s.Bif) != len(e.Bif) {
+ t.Errorf("Bif len: expected %d, got %d", len(e.Bif), len(s.Bif))
+ } else {
+ if len(s.Bif[0].F99) != len(e.Bif[0].F99) {
+ t.Errorf("Bif[0].F99 len: expected %d, got %d", len(e.Bif[0].F99), len(s.Bif[0].F99))
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+type S4 struct {
+ F01 int64
+ F02 float64
+ F03 bool
+}
+
+func TestConversionError(t *testing.T) {
+ data := map[string][]string{
+ "F01": {"foo"},
+ "F02": {"bar"},
+ "F03": {"baz"},
+ }
+ s := &S4{}
+ e := NewDecoder().Decode(s, data)
+
+ m := e.(MultiError)
+ if len(m) != 3 {
+ t.Errorf("Expected 3 errors, got %v", m)
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+type S5 struct {
+ F01 []string
+}
+
+func TestEmptyValue(t *testing.T) {
+ data := map[string][]string{
+ "F01": {"", "foo"},
+ }
+ s := &S5{}
+ NewDecoder().Decode(s, data)
+ if len(s.F01) != 1 {
+ t.Errorf("Expected 1 values in F01")
+ }
+}
+
+func TestEmptyValueZeroEmpty(t *testing.T) {
+ data := map[string][]string{
+ "F01": {"", "foo"},
+ }
+ s := S5{}
+ d := NewDecoder()
+ d.ZeroEmpty(true)
+ err := d.Decode(&s, data)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(s.F01) != 2 {
+ t.Errorf("Expected 1 values in F01")
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+type S6 struct {
+ id string
+}
+
+func TestUnexportedField(t *testing.T) {
+ data := map[string][]string{
+ "id": {"identifier"},
+ }
+ s := &S6{}
+ NewDecoder().Decode(s, data)
+ if s.id != "" {
+ t.Errorf("Unexported field expected to be ignored")
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+type S7 struct {
+ ID string
+}
+
+func TestMultipleValues(t *testing.T) {
+ data := map[string][]string{
+ "ID": {"0", "1"},
+ }
+
+ s := S7{}
+ NewDecoder().Decode(&s, data)
+ if s.ID != "1" {
+ t.Errorf("Last defined value must be used when multiple values for same field are provided")
+ }
+}
+
+type S8 struct {
+ ID string `json:"id"`
+}
+
+func TestSetAliasTag(t *testing.T) {
+ data := map[string][]string{
+ "id": {"foo"},
+ }
+
+ s := S8{}
+ dec := NewDecoder()
+ dec.SetAliasTag("json")
+ dec.Decode(&s, data)
+ if s.ID != "foo" {
+ t.Fatalf("Bad value: got %q, want %q", s.ID, "foo")
+ }
+}
+
+func TestZeroEmpty(t *testing.T) {
+ data := map[string][]string{
+ "F01": {""},
+ "F03": {"true"},
+ }
+ s := S4{1, 1, false}
+ d := NewDecoder()
+ d.ZeroEmpty(true)
+
+ err := d.Decode(&s, data)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if s.F01 != 0 {
+ t.Errorf("F01: got %v, want %v", s.F01, 0)
+ }
+ if s.F02 != 1 {
+ t.Errorf("F02: got %v, want %v", s.F02, 1)
+ }
+ if s.F03 != true {
+ t.Errorf("F03: got %v, want %v", s.F03, true)
+ }
+}
+
+func TestNoZeroEmpty(t *testing.T) {
+ data := map[string][]string{
+ "F01": {""},
+ "F03": {"true"},
+ }
+ s := S4{1, 1, false}
+ d := NewDecoder()
+ d.ZeroEmpty(false)
+ err := d.Decode(&s, data)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if s.F01 != 1 {
+ t.Errorf("F01: got %v, want %v", s.F01, 1)
+ }
+ if s.F02 != 1 {
+ t.Errorf("F02: got %v, want %v", s.F02, 1)
+ }
+ if s.F03 != true {
+ t.Errorf("F03: got %v, want %v", s.F03, true)
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+type S9 struct {
+ Id string
+}
+
+type S10 struct {
+ S9
+}
+
+func TestEmbeddedField(t *testing.T) {
+ data := map[string][]string{
+ "Id": {"identifier"},
+ }
+ s := &S10{}
+ NewDecoder().Decode(s, data)
+ if s.Id != "identifier" {
+ t.Errorf("Missing support for embedded fields")
+ }
+}
+
+type S11 struct {
+ S10
+}
+
+func TestMultipleLevelEmbeddedField(t *testing.T) {
+ data := map[string][]string{
+ "Id": {"identifier"},
+ }
+ s := &S11{}
+ err := NewDecoder().Decode(s, data)
+ if s.Id != "identifier" {
+ t.Errorf("Missing support for multiple-level embedded fields (%v)", err)
+ }
+}
+
+func TestInvalidPath(t *testing.T) {
+ data := map[string][]string{
+ "Foo.Bar": {"baz"},
+ }
+ s := S9{}
+ err := NewDecoder().Decode(&s, data)
+ expectedErr := `schema: invalid path "Foo.Bar"`
+ if err.Error() != expectedErr {
+ t.Fatalf("got %q, want %q", err, expectedErr)
+ }
+}
+
+func TestInvalidPathIgnoreUnknownKeys(t *testing.T) {
+ data := map[string][]string{
+ "Foo.Bar": {"baz"},
+ }
+ s := S9{}
+ dec := NewDecoder()
+ dec.IgnoreUnknownKeys(true)
+ err := dec.Decode(&s, data)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+type S1NT struct {
+ F1 int
+ F2 *int
+ F3 []int
+ F4 []*int
+ F5 *[]int
+ F6 *[]*int
+ F7 S2
+ F8 *S1
+ F9 int `schema:"-"`
+ F10 []S1
+ F11 []*S1
+ F12 *[]S1
+ F13 *[]*S1
+}
+
+func TestAllNT(t *testing.T) {
+ v := map[string][]string{
+ "f1": {"1"},
+ "f2": {"2"},
+ "f3": {"31", "32"},
+ "f4": {"41", "42"},
+ "f5": {"51", "52"},
+ "f6": {"61", "62"},
+ "f7.f1": {"71", "72"},
+ "f8.f8.f7.f1": {"81", "82"},
+ "f9": {"9"},
+ "f10.0.f10.0.f6": {"101", "102"},
+ "f10.0.f10.1.f6": {"103", "104"},
+ "f11.0.f11.0.f6": {"111", "112"},
+ "f11.0.f11.1.f6": {"113", "114"},
+ "f12.0.f12.0.f6": {"121", "122"},
+ "f12.0.f12.1.f6": {"123", "124"},
+ "f13.0.f13.0.f6": {"131", "132"},
+ "f13.0.f13.1.f6": {"133", "134"},
+ }
+ f2 := 2
+ f41, f42 := 41, 42
+ f61, f62 := 61, 62
+ f71, f72 := 71, 72
+ f81, f82 := 81, 82
+ f101, f102, f103, f104 := 101, 102, 103, 104
+ f111, f112, f113, f114 := 111, 112, 113, 114
+ f121, f122, f123, f124 := 121, 122, 123, 124
+ f131, f132, f133, f134 := 131, 132, 133, 134
+ e := S1NT{
+ F1: 1,
+ F2: &f2,
+ F3: []int{31, 32},
+ F4: []*int{&f41, &f42},
+ F5: &[]int{51, 52},
+ F6: &[]*int{&f61, &f62},
+ F7: S2{
+ F01: &[]*int{&f71, &f72},
+ },
+ F8: &S1{
+ F08: &S1{
+ F07: S2{
+ F01: &[]*int{&f81, &f82},
+ },
+ },
+ },
+ F9: 0,
+ F10: []S1{
+ S1{
+ F10: []S1{
+ S1{F06: &[]*int{&f101, &f102}},
+ S1{F06: &[]*int{&f103, &f104}},
+ },
+ },
+ },
+ F11: []*S1{
+ &S1{
+ F11: []*S1{
+ &S1{F06: &[]*int{&f111, &f112}},
+ &S1{F06: &[]*int{&f113, &f114}},
+ },
+ },
+ },
+ F12: &[]S1{
+ S1{
+ F12: &[]S1{
+ S1{F06: &[]*int{&f121, &f122}},
+ S1{F06: &[]*int{&f123, &f124}},
+ },
+ },
+ },
+ F13: &[]*S1{
+ &S1{
+ F13: &[]*S1{
+ &S1{F06: &[]*int{&f131, &f132}},
+ &S1{F06: &[]*int{&f133, &f134}},
+ },
+ },
+ },
+ }
+
+ s := &S1NT{}
+ _ = NewDecoder().Decode(s, v)
+
+ vals := func(values []*int) []int {
+ r := make([]int, len(values))
+ for k, v := range values {
+ r[k] = *v
+ }
+ return r
+ }
+
+ if s.F1 != e.F1 {
+ t.Errorf("f1: expected %v, got %v", e.F1, s.F1)
+ }
+ if s.F2 == nil {
+ t.Errorf("f2: expected %v, got nil", *e.F2)
+ } else if *s.F2 != *e.F2 {
+ t.Errorf("f2: expected %v, got %v", *e.F2, *s.F2)
+ }
+ if s.F3 == nil {
+ t.Errorf("f3: expected %v, got nil", e.F3)
+ } else if len(s.F3) != 2 || s.F3[0] != e.F3[0] || s.F3[1] != e.F3[1] {
+ t.Errorf("f3: expected %v, got %v", e.F3, s.F3)
+ }
+ if s.F4 == nil {
+ t.Errorf("f4: expected %v, got nil", e.F4)
+ } else {
+ if len(s.F4) != 2 || *(s.F4)[0] != *(e.F4)[0] || *(s.F4)[1] != *(e.F4)[1] {
+ t.Errorf("f4: expected %v, got %v", vals(e.F4), vals(s.F4))
+ }
+ }
+ if s.F5 == nil {
+ t.Errorf("f5: expected %v, got nil", e.F5)
+ } else {
+ sF5, eF5 := *s.F5, *e.F5
+ if len(sF5) != 2 || sF5[0] != eF5[0] || sF5[1] != eF5[1] {
+ t.Errorf("f5: expected %v, got %v", eF5, sF5)
+ }
+ }
+ if s.F6 == nil {
+ t.Errorf("f6: expected %v, got nil", vals(*e.F6))
+ } else {
+ sF6, eF6 := *s.F6, *e.F6
+ if len(sF6) != 2 || *(sF6)[0] != *(eF6)[0] || *(sF6)[1] != *(eF6)[1] {
+ t.Errorf("f6: expected %v, got %v", vals(eF6), vals(sF6))
+ }
+ }
+ if s.F7.F01 == nil {
+ t.Errorf("f7.f1: expected %v, got nil", vals(*e.F7.F01))
+ } else {
+ sF7, eF7 := *s.F7.F01, *e.F7.F01
+ if len(sF7) != 2 || *(sF7)[0] != *(eF7)[0] || *(sF7)[1] != *(eF7)[1] {
+ t.Errorf("f7.f1: expected %v, got %v", vals(eF7), vals(sF7))
+ }
+ }
+ if s.F8 == nil {
+ t.Errorf("f8: got nil")
+ } else if s.F8.F08 == nil {
+ t.Errorf("f8.f8: got nil")
+ } else if s.F8.F08.F07.F01 == nil {
+ t.Errorf("f8.f8.f7.f1: expected %v, got nil", vals(*e.F8.F08.F07.F01))
+ } else {
+ sF8, eF8 := *s.F8.F08.F07.F01, *e.F8.F08.F07.F01
+ if len(sF8) != 2 || *(sF8)[0] != *(eF8)[0] || *(sF8)[1] != *(eF8)[1] {
+ t.Errorf("f8.f8.f7.f1: expected %v, got %v", vals(eF8), vals(sF8))
+ }
+ }
+ if s.F9 != e.F9 {
+ t.Errorf("f9: expected %v, got %v", e.F9, s.F9)
+ }
+ if s.F10 == nil {
+ t.Errorf("f10: got nil")
+ } else if len(s.F10) != 1 {
+ t.Errorf("f10: expected 1 element, got %v", s.F10)
+ } else {
+ if len(s.F10[0].F10) != 2 {
+ t.Errorf("f10.0.f10: expected 1 element, got %v", s.F10[0].F10)
+ } else {
+ sF10, eF10 := *s.F10[0].F10[0].F06, *e.F10[0].F10[0].F06
+ if sF10 == nil {
+ t.Errorf("f10.0.f10.0.f6: expected %v, got nil", vals(eF10))
+ } else {
+ if len(sF10) != 2 || *(sF10)[0] != *(eF10)[0] || *(sF10)[1] != *(eF10)[1] {
+ t.Errorf("f10.0.f10.0.f6: expected %v, got %v", vals(eF10), vals(sF10))
+ }
+ }
+ sF10, eF10 = *s.F10[0].F10[1].F06, *e.F10[0].F10[1].F06
+ if sF10 == nil {
+ t.Errorf("f10.0.f10.0.f6: expected %v, got nil", vals(eF10))
+ } else {
+ if len(sF10) != 2 || *(sF10)[0] != *(eF10)[0] || *(sF10)[1] != *(eF10)[1] {
+ t.Errorf("f10.0.f10.0.f6: expected %v, got %v", vals(eF10), vals(sF10))
+ }
+ }
+ }
+ }
+ if s.F11 == nil {
+ t.Errorf("f11: got nil")
+ } else if len(s.F11) != 1 {
+ t.Errorf("f11: expected 1 element, got %v", s.F11)
+ } else {
+ if len(s.F11[0].F11) != 2 {
+ t.Errorf("f11.0.f11: expected 1 element, got %v", s.F11[0].F11)
+ } else {
+ sF11, eF11 := *s.F11[0].F11[0].F06, *e.F11[0].F11[0].F06
+ if sF11 == nil {
+ t.Errorf("f11.0.f11.0.f6: expected %v, got nil", vals(eF11))
+ } else {
+ if len(sF11) != 2 || *(sF11)[0] != *(eF11)[0] || *(sF11)[1] != *(eF11)[1] {
+ t.Errorf("f11.0.f11.0.f6: expected %v, got %v", vals(eF11), vals(sF11))
+ }
+ }
+ sF11, eF11 = *s.F11[0].F11[1].F06, *e.F11[0].F11[1].F06
+ if sF11 == nil {
+ t.Errorf("f11.0.f11.0.f6: expected %v, got nil", vals(eF11))
+ } else {
+ if len(sF11) != 2 || *(sF11)[0] != *(eF11)[0] || *(sF11)[1] != *(eF11)[1] {
+ t.Errorf("f11.0.f11.0.f6: expected %v, got %v", vals(eF11), vals(sF11))
+ }
+ }
+ }
+ }
+ if s.F12 == nil {
+ t.Errorf("f12: got nil")
+ } else if len(*s.F12) != 1 {
+ t.Errorf("f12: expected 1 element, got %v", *s.F12)
+ } else {
+ sF12, eF12 := *(s.F12), *(e.F12)
+ if len(*sF12[0].F12) != 2 {
+ t.Errorf("f12.0.f12: expected 1 element, got %v", *sF12[0].F12)
+ } else {
+ sF122, eF122 := *(*sF12[0].F12)[0].F06, *(*eF12[0].F12)[0].F06
+ if sF122 == nil {
+ t.Errorf("f12.0.f12.0.f6: expected %v, got nil", vals(eF122))
+ } else {
+ if len(sF122) != 2 || *(sF122)[0] != *(eF122)[0] || *(sF122)[1] != *(eF122)[1] {
+ t.Errorf("f12.0.f12.0.f6: expected %v, got %v", vals(eF122), vals(sF122))
+ }
+ }
+ sF122, eF122 = *(*sF12[0].F12)[1].F06, *(*eF12[0].F12)[1].F06
+ if sF122 == nil {
+ t.Errorf("f12.0.f12.0.f6: expected %v, got nil", vals(eF122))
+ } else {
+ if len(sF122) != 2 || *(sF122)[0] != *(eF122)[0] || *(sF122)[1] != *(eF122)[1] {
+ t.Errorf("f12.0.f12.0.f6: expected %v, got %v", vals(eF122), vals(sF122))
+ }
+ }
+ }
+ }
+ if s.F13 == nil {
+ t.Errorf("f13: got nil")
+ } else if len(*s.F13) != 1 {
+ t.Errorf("f13: expected 1 element, got %v", *s.F13)
+ } else {
+ sF13, eF13 := *(s.F13), *(e.F13)
+ if len(*sF13[0].F13) != 2 {
+ t.Errorf("f13.0.f13: expected 1 element, got %v", *sF13[0].F13)
+ } else {
+ sF132, eF132 := *(*sF13[0].F13)[0].F06, *(*eF13[0].F13)[0].F06
+ if sF132 == nil {
+ t.Errorf("f13.0.f13.0.f6: expected %v, got nil", vals(eF132))
+ } else {
+ if len(sF132) != 2 || *(sF132)[0] != *(eF132)[0] || *(sF132)[1] != *(eF132)[1] {
+ t.Errorf("f13.0.f13.0.f6: expected %v, got %v", vals(eF132), vals(sF132))
+ }
+ }
+ sF132, eF132 = *(*sF13[0].F13)[1].F06, *(*eF13[0].F13)[1].F06
+ if sF132 == nil {
+ t.Errorf("f13.0.f13.0.f6: expected %v, got nil", vals(eF132))
+ } else {
+ if len(sF132) != 2 || *(sF132)[0] != *(eF132)[0] || *(sF132)[1] != *(eF132)[1] {
+ t.Errorf("f13.0.f13.0.f6: expected %v, got %v", vals(eF132), vals(sF132))
+ }
+ }
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+type S12A struct {
+ ID []int
+}
+
+func TestCSVSlice(t *testing.T) {
+ data := map[string][]string{
+ "ID": {"0,1"},
+ }
+
+ s := S12A{}
+ NewDecoder().Decode(&s, data)
+ if len(s.ID) != 2 {
+ t.Errorf("Expected two values in the result list, got %+v", s.ID)
+ }
+ if s.ID[0] != 0 || s.ID[1] != 1 {
+ t.Errorf("Expected []{0, 1} got %+v", s)
+ }
+}
+
+type S12B struct {
+ ID []string
+}
+
+//Decode should not split on , into a slice for string only
+func TestCSVStringSlice(t *testing.T) {
+ data := map[string][]string{
+ "ID": {"0,1"},
+ }
+
+ s := S12B{}
+ NewDecoder().Decode(&s, data)
+ if len(s.ID) != 1 {
+ t.Errorf("Expected one value in the result list, got %+v", s.ID)
+ }
+ if s.ID[0] != "0,1" {
+ t.Errorf("Expected []{0, 1} got %+v", s)
+ }
+}
+
+//Invalid data provided by client should not panic (github issue 33)
+func TestInvalidDataProvidedByClient(t *testing.T) {
+ defer func() {
+ if r := recover(); r != nil {
+ t.Errorf("Panicked calling decoder.Decode: %v", r)
+ }
+ }()
+
+ type S struct {
+ f string
+ }
+
+ data := map[string][]string{
+ "f.f": {"v"},
+ }
+
+ err := NewDecoder().Decode(new(S), data)
+ if err == nil {
+ t.Errorf("invalid path in decoder.Decode should return an error.")
+ }
+}
+
+// underlying cause of error in issue 33
+func TestInvalidPathInCacheParsePath(t *testing.T) {
+ type S struct {
+ f string
+ }
+
+ typ := reflect.ValueOf(new(S)).Elem().Type()
+ c := newCache()
+ _, err := c.parsePath("f.f", typ)
+ if err == nil {
+ t.Errorf("invalid path in cache.parsePath should return an error.")
+ }
+}
+
+// issue 32
+func TestDecodeToTypedField(t *testing.T) {
+ type Aa bool
+ s1 := &struct{ Aa }{}
+ v1 := map[string][]string{"Aa": {"true"}}
+ NewDecoder().Decode(s1, v1)
+ if s1.Aa != Aa(true) {
+ t.Errorf("s1: expected %v, got %v", true, s1.Aa)
+ }
+}
+
+// issue 37
+func TestRegisterConverter(t *testing.T) {
+ type Aa int
+ type Bb int
+ s1 := &struct {
+ Aa
+ Bb
+ }{}
+ decoder := NewDecoder()
+
+ decoder.RegisterConverter(s1.Aa, func(s string) reflect.Value { return reflect.ValueOf(1) })
+ decoder.RegisterConverter(s1.Bb, func(s string) reflect.Value { return reflect.ValueOf(2) })
+
+ v1 := map[string][]string{"Aa": {"4"}, "Bb": {"5"}}
+ decoder.Decode(s1, v1)
+
+ if s1.Aa != Aa(1) {
+ t.Errorf("s1.Aa: expected %v, got %v", 1, s1.Aa)
+ }
+ if s1.Bb != Bb(2) {
+ t.Errorf("s1.Bb: expected %v, got %v", 2, s1.Bb)
+ }
+}
+
+// Issue #40
+func TestRegisterConverterSlice(t *testing.T) {
+ decoder := NewDecoder()
+ decoder.RegisterConverter([]string{}, func(input string) reflect.Value {
+ return reflect.ValueOf(strings.Split(input, ","))
+ })
+
+ result := struct {
+ Multiple []string `schema:"multiple"`
+ }{}
+
+ expected := []string{"one", "two", "three"}
+ decoder.Decode(&result, map[string][]string{
+ "multiple": []string{"one,two,three"},
+ })
+ for i := range expected {
+ if got, want := expected[i], result.Multiple[i]; got != want {
+ t.Errorf("%d: got %s, want %s", i, got, want)
+ }
+ }
+}
+
+type S13 struct {
+ Value []S14
+}
+
+type S14 struct {
+ F1 string
+ F2 string
+}
+
+func (n *S14) UnmarshalText(text []byte) error {
+ textParts := strings.Split(string(text), " ")
+ if len(textParts) < 2 {
+ return errors.New("Not a valid name!")
+ }
+
+ n.F1, n.F2 = textParts[0], textParts[len(textParts)-1]
+ return nil
+}
+
+type S15 struct {
+ Value []S16
+}
+
+type S16 struct {
+ F1 string
+ F2 string
+}
+
+func TestCustomTypeSlice(t *testing.T) {
+ data := map[string][]string{
+ "Value.0": []string{"Louisa May Alcott"},
+ "Value.1": []string{"Florence Nightingale"},
+ "Value.2": []string{"Clara Barton"},
+ }
+
+ s := S13{}
+ decoder := NewDecoder()
+
+ if err := decoder.Decode(&s, data); err != nil {
+ t.Fatal(err)
+ }
+
+ if len(s.Value) != 3 {
+ t.Fatalf("Expected 3 values in the result list, got %+v", s.Value)
+ }
+ if s.Value[0].F1 != "Louisa" || s.Value[0].F2 != "Alcott" {
+ t.Errorf("Expected S14{'Louisa', 'Alcott'} got %+v", s.Value[0])
+ }
+ if s.Value[1].F1 != "Florence" || s.Value[1].F2 != "Nightingale" {
+ t.Errorf("Expected S14{'Florence', 'Nightingale'} got %+v", s.Value[1])
+ }
+ if s.Value[2].F1 != "Clara" || s.Value[2].F2 != "Barton" {
+ t.Errorf("Expected S14{'Clara', 'Barton'} got %+v", s.Value[2])
+ }
+}
+
+func TestCustomTypeSliceWithError(t *testing.T) {
+ data := map[string][]string{
+ "Value.0": []string{"Louisa May Alcott"},
+ "Value.1": []string{"Florence Nightingale"},
+ "Value.2": []string{"Clara"},
+ }
+
+ s := S13{}
+ decoder := NewDecoder()
+
+ if err := decoder.Decode(&s, data); err == nil {
+ t.Error("Not detecting error in conversion")
+ }
+}
+
+func TestNoTextUnmarshalerTypeSlice(t *testing.T) {
+ data := map[string][]string{
+ "Value.0": []string{"Louisa May Alcott"},
+ "Value.1": []string{"Florence Nightingale"},
+ "Value.2": []string{"Clara Barton"},
+ }
+
+ s := S15{}
+ decoder := NewDecoder()
+
+ if err := decoder.Decode(&s, data); err == nil {
+ t.Error("Not detecting when there's no converter")
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+type S17 struct {
+ Value S14
+}
+
+type S18 struct {
+ Value S16
+}
+
+func TestCustomType(t *testing.T) {
+ data := map[string][]string{
+ "Value": []string{"Louisa May Alcott"},
+ }
+
+ s := S17{}
+ decoder := NewDecoder()
+
+ if err := decoder.Decode(&s, data); err != nil {
+ t.Fatal(err)
+ }
+
+ if s.Value.F1 != "Louisa" || s.Value.F2 != "Alcott" {
+ t.Errorf("Expected S14{'Louisa', 'Alcott'} got %+v", s.Value)
+ }
+}
+
+func TestCustomTypeWithError(t *testing.T) {
+ data := map[string][]string{
+ "Value": []string{"Louisa"},
+ }
+
+ s := S17{}
+ decoder := NewDecoder()
+
+ if err := decoder.Decode(&s, data); err == nil {
+ t.Error("Not detecting error in conversion")
+ }
+}
+
+func TestNoTextUnmarshalerType(t *testing.T) {
+ data := map[string][]string{
+ "Value": []string{"Louisa May Alcott"},
+ }
+
+ s := S18{}
+ decoder := NewDecoder()
+
+ if err := decoder.Decode(&s, data); err == nil {
+ t.Error("Not detecting when there's no converter")
+ }
+}
+
+func TestExpectedType(t *testing.T) {
+ data := map[string][]string{
+ "bools": []string{"1", "a"},
+ "date": []string{"invalid"},
+ "Foo.Bar": []string{"a", "b"},
+ }
+
+ type B struct {
+ Bar *int
+ }
+ type A struct {
+ Bools []bool `schema:"bools"`
+ Date time.Time `schema:"date"`
+ Foo B
+ }
+
+ a := A{}
+
+ err := NewDecoder().Decode(&a, data)
+
+ e := err.(MultiError)["bools"].(ConversionError)
+ if e.Type != reflect.TypeOf(false) && e.Index == 1 {
+ t.Errorf("Expected bool, index: 1 got %+v, index: %d", e.Type, e.Index)
+ }
+ e = err.(MultiError)["date"].(ConversionError)
+ if e.Type != reflect.TypeOf(time.Time{}) {
+ t.Errorf("Expected time.Time got %+v", e.Type)
+ }
+ e = err.(MultiError)["Foo.Bar"].(ConversionError)
+ if e.Type != reflect.TypeOf(0) {
+ t.Errorf("Expected int got %+v", e.Type)
+ }
+}
+
+type R1 struct {
+ A string `schema:"a,required"`
+ B struct {
+ C int `schema:"c,required"`
+ D float64 `schema:"d"`
+ E string `schema:"e,required"`
+ } `schema:"b"`
+ F []string `schema:"f,required"`
+ G []int `schema:"g,othertag"`
+ H bool `schema:"h,required"`
+}
+
+func TestRequiredField(t *testing.T) {
+ var a R1
+ v := map[string][]string{
+ "a": []string{"bbb"},
+ "b.c": []string{"88"},
+ "b.d": []string{"9"},
+ "f": []string{""},
+ "h": []string{"true"},
+ }
+ err := NewDecoder().Decode(&a, v)
+ if err == nil {
+ t.Errorf("error nil, b.e is empty expect")
+ return
+ }
+ // b.e empty
+ v["b.e"] = []string{""} // empty string
+ err = NewDecoder().Decode(&a, v)
+ if err == nil {
+ t.Errorf("error nil, b.e is empty expect")
+ return
+ }
+
+ // all fields ok
+ v["b.e"] = []string{"nonempty"}
+ err = NewDecoder().Decode(&a, v)
+ if err != nil {
+ t.Errorf("error: %v", err)
+ return
+ }
+
+ // set f empty
+ v["f"] = []string{}
+ err = NewDecoder().Decode(&a, v)
+ if err == nil {
+ t.Errorf("error nil, f is empty expect")
+ return
+ }
+ v["f"] = []string{"nonempty"}
+
+ // b.c type int with empty string
+ v["b.c"] = []string{""}
+ err = NewDecoder().Decode(&a, v)
+ if err == nil {
+ t.Errorf("error nil, b.c is empty expect")
+ return
+ }
+ v["b.c"] = []string{"3"}
+
+ // h type bool with empty string
+ v["h"] = []string{""}
+ err = NewDecoder().Decode(&a, v)
+ if err == nil {
+ t.Errorf("error nil, h is empty expect")
+ return
+ }
+}
diff --git a/cmd/ponzu/vendor/github.com/gorilla/schema/doc.go b/cmd/ponzu/vendor/github.com/gorilla/schema/doc.go
new file mode 100644
index 0000000..a95e87b
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/gorilla/schema/doc.go
@@ -0,0 +1,148 @@
+// 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/schema fills a struct with form values.
+
+The basic usage is really simple. Given this struct:
+
+ type Person struct {
+ Name string
+ Phone string
+ }
+
+...we can fill it passing a map to the Decode() function:
+
+ values := map[string][]string{
+ "Name": {"John"},
+ "Phone": {"999-999-999"},
+ }
+ person := new(Person)
+ decoder := schema.NewDecoder()
+ decoder.Decode(person, values)
+
+This is just a simple example and it doesn't make a lot of sense to create
+the map manually. Typically it will come from a http.Request object and
+will be of type url.Values: http.Request.Form or http.Request.MultipartForm:
+
+ func MyHandler(w http.ResponseWriter, r *http.Request) {
+ err := r.ParseForm()
+
+ if err != nil {
+ // Handle error
+ }
+
+ decoder := schema.NewDecoder()
+ // r.PostForm is a map of our POST form values
+ err := decoder.Decode(person, r.PostForm)
+
+ if err != nil {
+ // Handle error
+ }
+
+ // Do something with person.Name or person.Phone
+ }
+
+Note: it is a good idea to set a Decoder instance as a package global,
+because it caches meta-data about structs, and a instance can be shared safely:
+
+ var decoder = schema.NewDecoder()
+
+To define custom names for fields, use a struct tag "schema". To not populate
+certain fields, use a dash for the name and it will be ignored:
+
+ type Person struct {
+ Name string `schema:"name"` // custom name
+ Phone string `schema:"phone"` // custom name
+ Admin bool `schema:"-"` // this field is never set
+ }
+
+The supported field types in the destination struct are:
+
+ * bool
+ * float variants (float32, float64)
+ * int variants (int, int8, int16, int32, int64)
+ * string
+ * uint variants (uint, uint8, uint16, uint32, uint64)
+ * struct
+ * a pointer to one of the above types
+ * a slice or a pointer to a slice of one of the above types
+
+Non-supported types are simply ignored, however custom types can be registered
+to be converted.
+
+To fill nested structs, keys must use a dotted notation as the "path" for the
+field. So for example, to fill the struct Person below:
+
+ type Phone struct {
+ Label string
+ Number string
+ }
+
+ type Person struct {
+ Name string
+ Phone Phone
+ }
+
+...the source map must have the keys "Name", "Phone.Label" and "Phone.Number".
+This means that an HTML form to fill a Person struct must look like this:
+
+ <form>
+ <input type="text" name="Name">
+ <input type="text" name="Phone.Label">
+ <input type="text" name="Phone.Number">
+ </form>
+
+Single values are filled using the first value for a key from the source map.
+Slices are filled using all values for a key from the source map. So to fill
+a Person with multiple Phone values, like:
+
+ type Person struct {
+ Name string
+ Phones []Phone
+ }
+
+...an HTML form that accepts three Phone values would look like this:
+
+ <form>
+ <input type="text" name="Name">
+ <input type="text" name="Phones.0.Label">
+ <input type="text" name="Phones.0.Number">
+ <input type="text" name="Phones.1.Label">
+ <input type="text" name="Phones.1.Number">
+ <input type="text" name="Phones.2.Label">
+ <input type="text" name="Phones.2.Number">
+ </form>
+
+Notice that only for slices of structs the slice index is required.
+This is needed for disambiguation: if the nested struct also had a slice
+field, we could not translate multiple values to it if we did not use an
+index for the parent struct.
+
+There's also the possibility to create a custom type that implements the
+TextUnmarshaler interface, and in this case there's no need to registry
+a converter, like:
+
+ type Person struct {
+ Emails []Email
+ }
+
+ type Email struct {
+ *mail.Address
+ }
+
+ func (e *Email) UnmarshalText(text []byte) (err error) {
+ e.Address, err = mail.ParseAddress(string(text))
+ return
+ }
+
+...an HTML form that accepts three Email values would look like this:
+
+ <form>
+ <input type="email" name="Emails.0">
+ <input type="email" name="Emails.1">
+ <input type="email" name="Emails.2">
+ </form>
+*/
+package schema
diff --git a/cmd/ponzu/vendor/github.com/nilslice/jwt/LICENSE b/cmd/ponzu/vendor/github.com/nilslice/jwt/LICENSE
new file mode 100644
index 0000000..f67119e
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/nilslice/jwt/LICENSE
@@ -0,0 +1,19 @@
+Copyright (C) 2015 Steve Manuel <stevenhmanuel@gmail.com>
+
+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/cmd/ponzu/vendor/github.com/nilslice/jwt/README.md b/cmd/ponzu/vendor/github.com/nilslice/jwt/README.md
new file mode 100644
index 0000000..a384dd1
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/nilslice/jwt/README.md
@@ -0,0 +1,43 @@
+# JWT
+
+### Usage
+ $ go get github.com/nilslice/jwt
+
+package jwt provides methods to create and check JSON Web Tokens. It only implements HMAC 256 encryption and has a very small footprint, ideal for simple usage when authorizing clients
+
+```go
+ package main
+
+ import (
+ auth "github.com/nilslice/jwt"
+ "fmt"
+ "net/http"
+ "strings"
+ )
+
+ func main() {
+ http.HandleFunc("/auth/new", func(res http.ResponseWriter, req *http.Request) {
+ claims := map[string]interface{}{"exp": time.Now().Add(time.Hour * 24).Unix()}
+ token, err := auth.New(claims)
+ if err != nil {
+ http.Error(res, "Error", 500)
+ return
+ }
+ res.Header().Add("Authorization", "Bearer "+token)
+
+ res.WriteHeader(http.StatusOK)
+ })
+
+ http.HandleFunc("/auth", func(res http.ResponseWriter, req *http.Request) {
+ userToken := strings.Split(req.Header.Get("Authorization"), " ")[1]
+
+ if auth.Passes(userToken) {
+ fmt.Println("ok")
+ } else {
+ fmt.Println("no")
+ }
+ })
+
+ http.ListenAndServe(":8080", nil)
+ }
+```
diff --git a/cmd/ponzu/vendor/github.com/nilslice/jwt/doc.go b/cmd/ponzu/vendor/github.com/nilslice/jwt/doc.go
new file mode 100644
index 0000000..aa9a5c8
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/nilslice/jwt/doc.go
@@ -0,0 +1,40 @@
+// Package jwt provides methods to create and check JSON Web Tokens (JWT). It only implements HMAC 256 encryption and has a very small footprint, ideal for simple usage when authorizing clients
+/*
+
+ package main
+
+ import (
+ auth "github.com/nilslice/jwt"
+ "fmt"
+ "net/http"
+ "strings"
+ "time"
+ )
+
+ func main() {
+ http.HandleFunc("/auth/new", func(res http.ResponseWriter, req *http.Request) {
+ claims := map[string]interface{}{"exp": time.Now().Add(time.Hour * 24).Unix()}
+ token, err := auth.New(claims)
+ if err != nil {
+ http.Error(res, "Error", 500)
+ return
+ }
+ res.Header().Add("Authorization", "Bearer "+token)
+
+ res.WriteHeader(http.StatusOK)
+ })
+
+ http.HandleFunc("/auth", func(res http.ResponseWriter, req *http.Request) {
+ userToken := strings.Split(req.Header.Get("Authorization"), " ")[1]
+
+ if auth.Passes(userToken) {
+ fmt.Println("ok")
+ } else {
+ fmt.Println("no")
+ }
+ })
+
+ http.ListenAndServe(":8080", nil)
+ }
+*/
+package jwt
diff --git a/cmd/ponzu/vendor/github.com/nilslice/jwt/jwt.go b/cmd/ponzu/vendor/github.com/nilslice/jwt/jwt.go
new file mode 100644
index 0000000..6d7eaa3
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/nilslice/jwt/jwt.go
@@ -0,0 +1,204 @@
+package jwt
+
+import (
+ "crypto/hmac"
+ "crypto/sha256"
+ "encoding/base64"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "strings"
+)
+
+var (
+ privateKey = []byte("")
+ defaultHeader = header{Typ: "JWT", Alg: "HS256"}
+ registeredClaims = []string{"iss", "sub", "aud", "exp", "nbf", "iat", "jti"}
+)
+
+type header struct {
+ Typ string `json:"typ"`
+ Alg string `json:"alg"`
+}
+
+type payload map[string]interface{}
+
+type encoded struct {
+ token string
+}
+type decoded struct {
+ header string
+ payload string
+}
+
+type signedDecoded struct {
+ decoded
+ signature string
+}
+
+func newEncoded(claims map[string]interface{}) (encoded, error) {
+ header, err := json.Marshal(defaultHeader)
+ if err != nil {
+ return encoded{}, err
+ }
+
+ for _, claim := range registeredClaims {
+ if _, ok := claims[claim]; !ok {
+ claims[claim] = nil
+ }
+ }
+
+ payload, err := json.Marshal(claims)
+ if err != nil {
+ return encoded{}, err
+ }
+
+ d := decoded{header: string(header), payload: string(payload)}
+
+ d.encodeInternal()
+ signed, err := d.sign()
+ if err != nil {
+ return encoded{}, err
+ }
+
+ token := signed.token()
+ e := encoded{token: token}
+ return e, nil
+}
+
+func newDecoded(token string) (decoded, error) {
+ e := encoded{token: token}
+ d, err := e.parseToken()
+ if err != nil {
+ return d, nil
+ }
+
+ return d, nil
+}
+
+func encodeToString(src []byte) string {
+ return base64.RawURLEncoding.EncodeToString(src)
+}
+
+func (d decoded) getHeader() []byte {
+ return []byte(d.header)
+}
+
+func (d decoded) getPayload() []byte {
+ return []byte(d.payload)
+}
+
+func (sd signedDecoded) getSignature() []byte {
+ return []byte(sd.signature)
+}
+
+func (d *decoded) encodeInternal() {
+ d.header = encodeToString(d.getHeader())
+ d.payload = encodeToString(d.getPayload())
+}
+
+func (d decoded) dot(internals ...string) string {
+ return strings.Join(internals, ".")
+}
+
+func (d *decoded) sign() (signedDecoded, error) {
+ if d.header == "" || d.payload == "" {
+ return signedDecoded{}, errors.New("Missing header or payload on Decoded")
+ }
+
+ unsigned := d.dot(d.header, d.payload)
+
+ hash := hmac.New(sha256.New, privateKey)
+ _, err := hash.Write([]byte(unsigned))
+ if err != nil {
+ return signedDecoded{}, err
+ }
+
+ signed := signedDecoded{decoded: *d}
+ signed.signature = encodeToString(hash.Sum(nil))
+
+ return signed, nil
+}
+
+func (sd signedDecoded) token() string {
+ return fmt.Sprintf("%s.%s.%s", sd.getHeader(), sd.getPayload(), sd.getSignature())
+}
+
+func (sd signedDecoded) verify(enc encoded) bool {
+ if sd.token() == enc.token {
+ return true
+ }
+ return false
+}
+
+func (e encoded) parseToken() (decoded, error) {
+ parts := strings.Split(e.token, ".")
+ if len(parts) != 3 {
+ return decoded{}, errors.New("Error: incorrect # of results from string parsing")
+ }
+
+ d := decoded{
+ header: parts[0],
+ payload: parts[1],
+ }
+
+ return d, nil
+}
+
+// New returns a token (string) and error. The token is a fully qualified JWT to be sent to a client via HTTP Header or other method. Error returned will be from the newEncoded unexported function.
+func New(claims map[string]interface{}) (string, error) {
+ enc, err := newEncoded(claims)
+ if err != nil {
+ return "", err
+ }
+
+ return enc.token, nil
+}
+
+// Passes returns a bool indicating whether a token (string) provided has been signed by our server. If true, the client is authenticated and may proceed.
+func Passes(token string) bool {
+ dec, err := newDecoded(token)
+ if err != nil {
+ // may want to log some error here so we have visibility
+ // intentionally simplifying return type to bool for ease
+ // of use in API. Caller should only do `if auth.Passes(str) {}`
+ return false
+ }
+ signed, err := dec.sign()
+ if err != nil {
+ return false
+ }
+
+ return signed.verify(encoded{token: token})
+}
+
+// GetClaims() returns a token's claims, allowing
+// you to check the values to make sure they match
+func GetClaims(token string) map[string]interface{} {
+ // decode the token
+ dec, err := newDecoded(token)
+ if err != nil {
+ return nil
+ }
+
+ // base64 decode payload
+ payload, err := base64.RawURLEncoding.DecodeString(dec.payload)
+ if err != nil {
+ return nil
+ }
+
+ dst := map[string]interface{}{}
+ err = json.Unmarshal(payload, &dst)
+ if err != nil {
+ return nil
+ }
+
+ return dst
+
+}
+
+// Secret is a helper function to set the unexported privateKey variable used when signing and verifying tokens.
+// Its argument is type []byte since we expect users to read this value from a file which can be excluded from source code.
+func Secret(key []byte) {
+ privateKey = key
+}
diff --git a/cmd/ponzu/vendor/github.com/nilslice/rand/README.md b/cmd/ponzu/vendor/github.com/nilslice/rand/README.md
new file mode 100644
index 0000000..89cc36d
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/nilslice/rand/README.md
@@ -0,0 +1,2 @@
+rand provides a convenient package to use crypto/rand as default
+but falls back to math/rand if necessary \ No newline at end of file
diff --git a/cmd/ponzu/vendor/github.com/nilslice/rand/rand.go b/cmd/ponzu/vendor/github.com/nilslice/rand/rand.go
new file mode 100644
index 0000000..cbff54a
--- /dev/null
+++ b/cmd/ponzu/vendor/github.com/nilslice/rand/rand.go
@@ -0,0 +1,38 @@
+// rand provides a convenient package to use crypto/rand as default
+// but falls back to math/rand if necessary
+package rand
+
+import (
+ crand "crypto/rand"
+ mrand "math/rand"
+ "time"
+)
+
+var g_mathRand = mrand.New(mrand.NewSource(time.Now().Unix()))
+
+// Read fills the slice with random bytes
+func Read(xs []byte) {
+ length := len(xs)
+ n, err := crand.Read(xs)
+ if n != length || err != nil {
+ for length > 0 {
+ length--
+ xs[length] = byte(g_mathRand.Int31n(256))
+ }
+ }
+}
+
+// Int63 returns a non-negative 63-bit integer as an int64
+func Int63() int64 {
+ xs := make([]byte, 8)
+ var n int64
+
+ Read(xs)
+ xs[0] &= 0x7F
+ for _, x := range xs {
+ n <<= 4
+ n |= int64(x)
+ }
+
+ return n
+}
diff --git a/cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/base64.go b/cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/base64.go
new file mode 100644
index 0000000..fc31160
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/base64.go
@@ -0,0 +1,35 @@
+// 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 bcrypt
+
+import "encoding/base64"
+
+const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+
+var bcEncoding = base64.NewEncoding(alphabet)
+
+func base64Encode(src []byte) []byte {
+ n := bcEncoding.EncodedLen(len(src))
+ dst := make([]byte, n)
+ bcEncoding.Encode(dst, src)
+ for dst[n-1] == '=' {
+ n--
+ }
+ return dst[:n]
+}
+
+func base64Decode(src []byte) ([]byte, error) {
+ numOfEquals := 4 - (len(src) % 4)
+ for i := 0; i < numOfEquals; i++ {
+ src = append(src, '=')
+ }
+
+ dst := make([]byte, bcEncoding.DecodedLen(len(src)))
+ n, err := bcEncoding.Decode(dst, src)
+ if err != nil {
+ return nil, err
+ }
+ return dst[:n], nil
+}
diff --git a/cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/bcrypt.go b/cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/bcrypt.go
new file mode 100644
index 0000000..f8b807f
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/bcrypt.go
@@ -0,0 +1,294 @@
+// 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 bcrypt implements Provos and Mazières's bcrypt adaptive hashing
+// algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf
+package bcrypt // import "golang.org/x/crypto/bcrypt"
+
+// The code is a port of Provos and Mazières's C implementation.
+import (
+ "crypto/rand"
+ "crypto/subtle"
+ "errors"
+ "fmt"
+ "golang.org/x/crypto/blowfish"
+ "io"
+ "strconv"
+)
+
+const (
+ MinCost int = 4 // the minimum allowable cost as passed in to GenerateFromPassword
+ MaxCost int = 31 // the maximum allowable cost as passed in to GenerateFromPassword
+ DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword
+)
+
+// The error returned from CompareHashAndPassword when a password and hash do
+// not match.
+var ErrMismatchedHashAndPassword = errors.New("crypto/bcrypt: hashedPassword is not the hash of the given password")
+
+// The error returned from CompareHashAndPassword when a hash is too short to
+// be a bcrypt hash.
+var ErrHashTooShort = errors.New("crypto/bcrypt: hashedSecret too short to be a bcrypted password")
+
+// The error returned from CompareHashAndPassword when a hash was created with
+// a bcrypt algorithm newer than this implementation.
+type HashVersionTooNewError byte
+
+func (hv HashVersionTooNewError) Error() string {
+ return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion)
+}
+
+// The error returned from CompareHashAndPassword when a hash starts with something other than '$'
+type InvalidHashPrefixError byte
+
+func (ih InvalidHashPrefixError) Error() string {
+ return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih))
+}
+
+type InvalidCostError int
+
+func (ic InvalidCostError) Error() string {
+ return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost))
+}
+
+const (
+ majorVersion = '2'
+ minorVersion = 'a'
+ maxSaltSize = 16
+ maxCryptedHashSize = 23
+ encodedSaltSize = 22
+ encodedHashSize = 31
+ minHashSize = 59
+)
+
+// magicCipherData is an IV for the 64 Blowfish encryption calls in
+// bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes.
+var magicCipherData = []byte{
+ 0x4f, 0x72, 0x70, 0x68,
+ 0x65, 0x61, 0x6e, 0x42,
+ 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x65, 0x72, 0x53,
+ 0x63, 0x72, 0x79, 0x44,
+ 0x6f, 0x75, 0x62, 0x74,
+}
+
+type hashed struct {
+ hash []byte
+ salt []byte
+ cost int // allowed range is MinCost to MaxCost
+ major byte
+ minor byte
+}
+
+// GenerateFromPassword returns the bcrypt hash of the password at the given
+// cost. If the cost given is less than MinCost, the cost will be set to
+// DefaultCost, instead. Use CompareHashAndPassword, as defined in this package,
+// to compare the returned hashed password with its cleartext version.
+func GenerateFromPassword(password []byte, cost int) ([]byte, error) {
+ p, err := newFromPassword(password, cost)
+ if err != nil {
+ return nil, err
+ }
+ return p.Hash(), nil
+}
+
+// CompareHashAndPassword compares a bcrypt hashed password with its possible
+// plaintext equivalent. Returns nil on success, or an error on failure.
+func CompareHashAndPassword(hashedPassword, password []byte) error {
+ p, err := newFromHash(hashedPassword)
+ if err != nil {
+ return err
+ }
+
+ otherHash, err := bcrypt(password, p.cost, p.salt)
+ if err != nil {
+ return err
+ }
+
+ otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor}
+ if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 {
+ return nil
+ }
+
+ return ErrMismatchedHashAndPassword
+}
+
+// Cost returns the hashing cost used to create the given hashed
+// password. When, in the future, the hashing cost of a password system needs
+// to be increased in order to adjust for greater computational power, this
+// function allows one to establish which passwords need to be updated.
+func Cost(hashedPassword []byte) (int, error) {
+ p, err := newFromHash(hashedPassword)
+ if err != nil {
+ return 0, err
+ }
+ return p.cost, nil
+}
+
+func newFromPassword(password []byte, cost int) (*hashed, error) {
+ if cost < MinCost {
+ cost = DefaultCost
+ }
+ p := new(hashed)
+ p.major = majorVersion
+ p.minor = minorVersion
+
+ err := checkCost(cost)
+ if err != nil {
+ return nil, err
+ }
+ p.cost = cost
+
+ unencodedSalt := make([]byte, maxSaltSize)
+ _, err = io.ReadFull(rand.Reader, unencodedSalt)
+ if err != nil {
+ return nil, err
+ }
+
+ p.salt = base64Encode(unencodedSalt)
+ hash, err := bcrypt(password, p.cost, p.salt)
+ if err != nil {
+ return nil, err
+ }
+ p.hash = hash
+ return p, err
+}
+
+func newFromHash(hashedSecret []byte) (*hashed, error) {
+ if len(hashedSecret) < minHashSize {
+ return nil, ErrHashTooShort
+ }
+ p := new(hashed)
+ n, err := p.decodeVersion(hashedSecret)
+ if err != nil {
+ return nil, err
+ }
+ hashedSecret = hashedSecret[n:]
+ n, err = p.decodeCost(hashedSecret)
+ if err != nil {
+ return nil, err
+ }
+ hashedSecret = hashedSecret[n:]
+
+ // The "+2" is here because we'll have to append at most 2 '=' to the salt
+ // when base64 decoding it in expensiveBlowfishSetup().
+ p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2)
+ copy(p.salt, hashedSecret[:encodedSaltSize])
+
+ hashedSecret = hashedSecret[encodedSaltSize:]
+ p.hash = make([]byte, len(hashedSecret))
+ copy(p.hash, hashedSecret)
+
+ return p, nil
+}
+
+func bcrypt(password []byte, cost int, salt []byte) ([]byte, error) {
+ cipherData := make([]byte, len(magicCipherData))
+ copy(cipherData, magicCipherData)
+
+ c, err := expensiveBlowfishSetup(password, uint32(cost), salt)
+ if err != nil {
+ return nil, err
+ }
+
+ for i := 0; i < 24; i += 8 {
+ for j := 0; j < 64; j++ {
+ c.Encrypt(cipherData[i:i+8], cipherData[i:i+8])
+ }
+ }
+
+ // Bug compatibility with C bcrypt implementations. We only encode 23 of
+ // the 24 bytes encrypted.
+ hsh := base64Encode(cipherData[:maxCryptedHashSize])
+ return hsh, nil
+}
+
+func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) {
+
+ csalt, err := base64Decode(salt)
+ if err != nil {
+ return nil, err
+ }
+
+ // Bug compatibility with C bcrypt implementations. They use the trailing
+ // NULL in the key string during expansion.
+ ckey := append(key, 0)
+
+ c, err := blowfish.NewSaltedCipher(ckey, csalt)
+ if err != nil {
+ return nil, err
+ }
+
+ var i, rounds uint64
+ rounds = 1 << cost
+ for i = 0; i < rounds; i++ {
+ blowfish.ExpandKey(ckey, c)
+ blowfish.ExpandKey(csalt, c)
+ }
+
+ return c, nil
+}
+
+func (p *hashed) Hash() []byte {
+ arr := make([]byte, 60)
+ arr[0] = '$'
+ arr[1] = p.major
+ n := 2
+ if p.minor != 0 {
+ arr[2] = p.minor
+ n = 3
+ }
+ arr[n] = '$'
+ n += 1
+ copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost)))
+ n += 2
+ arr[n] = '$'
+ n += 1
+ copy(arr[n:], p.salt)
+ n += encodedSaltSize
+ copy(arr[n:], p.hash)
+ n += encodedHashSize
+ return arr[:n]
+}
+
+func (p *hashed) decodeVersion(sbytes []byte) (int, error) {
+ if sbytes[0] != '$' {
+ return -1, InvalidHashPrefixError(sbytes[0])
+ }
+ if sbytes[1] > majorVersion {
+ return -1, HashVersionTooNewError(sbytes[1])
+ }
+ p.major = sbytes[1]
+ n := 3
+ if sbytes[2] != '$' {
+ p.minor = sbytes[2]
+ n++
+ }
+ return n, nil
+}
+
+// sbytes should begin where decodeVersion left off.
+func (p *hashed) decodeCost(sbytes []byte) (int, error) {
+ cost, err := strconv.Atoi(string(sbytes[0:2]))
+ if err != nil {
+ return -1, err
+ }
+ err = checkCost(cost)
+ if err != nil {
+ return -1, err
+ }
+ p.cost = cost
+ return 3, nil
+}
+
+func (p *hashed) String() string {
+ return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor)
+}
+
+func checkCost(cost int) error {
+ if cost < MinCost || cost > MaxCost {
+ return InvalidCostError(cost)
+ }
+ return nil
+}
diff --git a/cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go b/cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go
new file mode 100644
index 0000000..f08a6f5
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/crypto/bcrypt/bcrypt_test.go
@@ -0,0 +1,226 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bcrypt
+
+import (
+ "bytes"
+ "fmt"
+ "testing"
+)
+
+func TestBcryptingIsEasy(t *testing.T) {
+ pass := []byte("mypassword")
+ hp, err := GenerateFromPassword(pass, 0)
+ if err != nil {
+ t.Fatalf("GenerateFromPassword error: %s", err)
+ }
+
+ if CompareHashAndPassword(hp, pass) != nil {
+ t.Errorf("%v should hash %s correctly", hp, pass)
+ }
+
+ notPass := "notthepass"
+ err = CompareHashAndPassword(hp, []byte(notPass))
+ if err != ErrMismatchedHashAndPassword {
+ t.Errorf("%v and %s should be mismatched", hp, notPass)
+ }
+}
+
+func TestBcryptingIsCorrect(t *testing.T) {
+ pass := []byte("allmine")
+ salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
+ expectedHash := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
+
+ hash, err := bcrypt(pass, 10, salt)
+ if err != nil {
+ t.Fatalf("bcrypt blew up: %v", err)
+ }
+ if !bytes.HasSuffix(expectedHash, hash) {
+ t.Errorf("%v should be the suffix of %v", hash, expectedHash)
+ }
+
+ h, err := newFromHash(expectedHash)
+ if err != nil {
+ t.Errorf("Unable to parse %s: %v", string(expectedHash), err)
+ }
+
+ // This is not the safe way to compare these hashes. We do this only for
+ // testing clarity. Use bcrypt.CompareHashAndPassword()
+ if err == nil && !bytes.Equal(expectedHash, h.Hash()) {
+ t.Errorf("Parsed hash %v should equal %v", h.Hash(), expectedHash)
+ }
+}
+
+func TestVeryShortPasswords(t *testing.T) {
+ key := []byte("k")
+ salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
+ _, err := bcrypt(key, 10, salt)
+ if err != nil {
+ t.Errorf("One byte key resulted in error: %s", err)
+ }
+}
+
+func TestTooLongPasswordsWork(t *testing.T) {
+ salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
+ // One byte over the usual 56 byte limit that blowfish has
+ tooLongPass := []byte("012345678901234567890123456789012345678901234567890123456")
+ tooLongExpected := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C")
+ hash, err := bcrypt(tooLongPass, 10, salt)
+ if err != nil {
+ t.Fatalf("bcrypt blew up on long password: %v", err)
+ }
+ if !bytes.HasSuffix(tooLongExpected, hash) {
+ t.Errorf("%v should be the suffix of %v", hash, tooLongExpected)
+ }
+}
+
+type InvalidHashTest struct {
+ err error
+ hash []byte
+}
+
+var invalidTests = []InvalidHashTest{
+ {ErrHashTooShort, []byte("$2a$10$fooo")},
+ {ErrHashTooShort, []byte("$2a")},
+ {HashVersionTooNewError('3'), []byte("$3a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
+ {InvalidHashPrefixError('%'), []byte("%2a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
+ {InvalidCostError(32), []byte("$2a$32$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
+}
+
+func TestInvalidHashErrors(t *testing.T) {
+ check := func(name string, expected, err error) {
+ if err == nil {
+ t.Errorf("%s: Should have returned an error", name)
+ }
+ if err != nil && err != expected {
+ t.Errorf("%s gave err %v but should have given %v", name, err, expected)
+ }
+ }
+ for _, iht := range invalidTests {
+ _, err := newFromHash(iht.hash)
+ check("newFromHash", iht.err, err)
+ err = CompareHashAndPassword(iht.hash, []byte("anything"))
+ check("CompareHashAndPassword", iht.err, err)
+ }
+}
+
+func TestUnpaddedBase64Encoding(t *testing.T) {
+ original := []byte{101, 201, 101, 75, 19, 227, 199, 20, 239, 236, 133, 32, 30, 109, 243, 30}
+ encodedOriginal := []byte("XajjQvNhvvRt5GSeFk1xFe")
+
+ encoded := base64Encode(original)
+
+ if !bytes.Equal(encodedOriginal, encoded) {
+ t.Errorf("Encoded %v should have equaled %v", encoded, encodedOriginal)
+ }
+
+ decoded, err := base64Decode(encodedOriginal)
+ if err != nil {
+ t.Fatalf("base64Decode blew up: %s", err)
+ }
+
+ if !bytes.Equal(decoded, original) {
+ t.Errorf("Decoded %v should have equaled %v", decoded, original)
+ }
+}
+
+func TestCost(t *testing.T) {
+ suffix := "XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C"
+ for _, vers := range []string{"2a", "2"} {
+ for _, cost := range []int{4, 10} {
+ s := fmt.Sprintf("$%s$%02d$%s", vers, cost, suffix)
+ h := []byte(s)
+ actual, err := Cost(h)
+ if err != nil {
+ t.Errorf("Cost, error: %s", err)
+ continue
+ }
+ if actual != cost {
+ t.Errorf("Cost, expected: %d, actual: %d", cost, actual)
+ }
+ }
+ }
+ _, err := Cost([]byte("$a$a$" + suffix))
+ if err == nil {
+ t.Errorf("Cost, malformed but no error returned")
+ }
+}
+
+func TestCostValidationInHash(t *testing.T) {
+ if testing.Short() {
+ return
+ }
+
+ pass := []byte("mypassword")
+
+ for c := 0; c < MinCost; c++ {
+ p, _ := newFromPassword(pass, c)
+ if p.cost != DefaultCost {
+ t.Errorf("newFromPassword should default costs below %d to %d, but was %d", MinCost, DefaultCost, p.cost)
+ }
+ }
+
+ p, _ := newFromPassword(pass, 14)
+ if p.cost != 14 {
+ t.Errorf("newFromPassword should default cost to 14, but was %d", p.cost)
+ }
+
+ hp, _ := newFromHash(p.Hash())
+ if p.cost != hp.cost {
+ t.Errorf("newFromHash should maintain the cost at %d, but was %d", p.cost, hp.cost)
+ }
+
+ _, err := newFromPassword(pass, 32)
+ if err == nil {
+ t.Fatalf("newFromPassword: should return a cost error")
+ }
+ if err != InvalidCostError(32) {
+ t.Errorf("newFromPassword: should return cost error, got %#v", err)
+ }
+}
+
+func TestCostReturnsWithLeadingZeroes(t *testing.T) {
+ hp, _ := newFromPassword([]byte("abcdefgh"), 7)
+ cost := hp.Hash()[4:7]
+ expected := []byte("07$")
+
+ if !bytes.Equal(expected, cost) {
+ t.Errorf("single digit costs in hash should have leading zeros: was %v instead of %v", cost, expected)
+ }
+}
+
+func TestMinorNotRequired(t *testing.T) {
+ noMinorHash := []byte("$2$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
+ h, err := newFromHash(noMinorHash)
+ if err != nil {
+ t.Fatalf("No minor hash blew up: %s", err)
+ }
+ if h.minor != 0 {
+ t.Errorf("Should leave minor version at 0, but was %d", h.minor)
+ }
+
+ if !bytes.Equal(noMinorHash, h.Hash()) {
+ t.Errorf("Should generate hash %v, but created %v", noMinorHash, h.Hash())
+ }
+}
+
+func BenchmarkEqual(b *testing.B) {
+ b.StopTimer()
+ passwd := []byte("somepasswordyoulike")
+ hash, _ := GenerateFromPassword(passwd, 10)
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ CompareHashAndPassword(hash, passwd)
+ }
+}
+
+func BenchmarkGeneration(b *testing.B) {
+ b.StopTimer()
+ passwd := []byte("mylongpassword1234")
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ GenerateFromPassword(passwd, 10)
+ }
+}
diff --git a/cmd/ponzu/vendor/golang.org/x/text/transform/examples_test.go b/cmd/ponzu/vendor/golang.org/x/text/transform/examples_test.go
new file mode 100644
index 0000000..f2e284d
--- /dev/null
+++ b/cmd/ponzu/vendor/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/cmd/ponzu/vendor/golang.org/x/text/transform/transform.go b/cmd/ponzu/vendor/golang.org/x/text/transform/transform.go
new file mode 100644
index 0000000..fe47b9b
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/text/transform/transform.go
@@ -0,0 +1,705 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package transform provides reader and writer wrappers that transform the
+// bytes passing through as well as various transformations. Example
+// transformations provided by other packages include normalization and
+// conversion between character sets.
+package transform // import "golang.org/x/text/transform"
+
+import (
+ "bytes"
+ "errors"
+ "io"
+ "unicode/utf8"
+)
+
+var (
+ // ErrShortDst means that the destination buffer was too short to
+ // receive all of the transformed bytes.
+ ErrShortDst = errors.New("transform: short destination buffer")
+
+ // ErrShortSrc means that the source buffer has insufficient data to
+ // complete the transformation.
+ ErrShortSrc = errors.New("transform: short source buffer")
+
+ // ErrEndOfSpan means that the input and output (the transformed input)
+ // are not identical.
+ ErrEndOfSpan = errors.New("transform: input and output are not identical")
+
+ // errInconsistentByteCount means that Transform returned success (nil
+ // error) but also returned nSrc inconsistent with the src argument.
+ errInconsistentByteCount = errors.New("transform: inconsistent byte count returned")
+
+ // errShortInternal means that an internal buffer is not large enough
+ // to make progress and the Transform operation must be aborted.
+ errShortInternal = errors.New("transform: short internal buffer")
+)
+
+// Transformer transforms bytes.
+type Transformer interface {
+ // Transform writes to dst the transformed bytes read from src, and
+ // returns the number of dst bytes written and src bytes read. The
+ // atEOF argument tells whether src represents the last bytes of the
+ // input.
+ //
+ // Callers should always process the nDst bytes produced and account
+ // for the nSrc bytes consumed before considering the error err.
+ //
+ // A nil error means that all of the transformed bytes (whether freshly
+ // transformed from src or left over from previous Transform calls)
+ // were written to dst. A nil error can be returned regardless of
+ // whether atEOF is true. If err is nil then nSrc must equal len(src);
+ // the converse is not necessarily true.
+ //
+ // ErrShortDst means that dst was too short to receive all of the
+ // transformed bytes. ErrShortSrc means that src had insufficient data
+ // to complete the transformation. If both conditions apply, then
+ // either error may be returned. Other than the error conditions listed
+ // here, implementations are free to report other errors that arise.
+ Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error)
+
+ // Reset resets the state and allows a Transformer to be reused.
+ Reset()
+}
+
+// SpanningTransformer extends the Transformer interface with a Span method
+// that determines how much of the input already conforms to the Transformer.
+type SpanningTransformer interface {
+ Transformer
+
+ // Span returns a position in src such that transforming src[:n] results in
+ // identical output src[:n] for these bytes. It does not necessarily return
+ // the largest such n. The atEOF argument tells whether src represents the
+ // last bytes of the input.
+ //
+ // Callers should always account for the n bytes consumed before
+ // considering the error err.
+ //
+ // A nil error means that all input bytes are known to be identical to the
+ // output produced by the Transformer. A nil error can be be returned
+ // regardless of whether atEOF is true. If err is nil, then then n must
+ // equal len(src); the converse is not necessarily true.
+ //
+ // ErrEndOfSpan means that the Transformer output may differ from the
+ // input after n bytes. Note that n may be len(src), meaning that the output
+ // would contain additional bytes after otherwise identical output.
+ // ErrShortSrc means that src had insufficient data to determine whether the
+ // remaining bytes would change. Other than the error conditions listed
+ // here, implementations are free to report other errors that arise.
+ //
+ // Calling Span can modify the Transformer state as a side effect. In
+ // effect, it does the transformation just as calling Transform would, only
+ // without copying to a destination buffer and only up to a point it can
+ // determine the input and output bytes are the same. This is obviously more
+ // limited than calling Transform, but can be more efficient in terms of
+ // copying and allocating buffers. Calls to Span and Transform may be
+ // interleaved.
+ Span(src []byte, atEOF bool) (n int, err error)
+}
+
+// NopResetter can be embedded by implementations of Transformer to add a nop
+// Reset method.
+type NopResetter struct{}
+
+// Reset implements the Reset method of the Transformer interface.
+func (NopResetter) Reset() {}
+
+// Reader wraps another io.Reader by transforming the bytes read.
+type Reader struct {
+ r io.Reader
+ t Transformer
+ err error
+
+ // dst[dst0:dst1] contains bytes that have been transformed by t but
+ // not yet copied out via Read.
+ dst []byte
+ dst0, dst1 int
+
+ // src[src0:src1] contains bytes that have been read from r but not
+ // yet transformed through t.
+ src []byte
+ src0, src1 int
+
+ // transformComplete is whether the transformation is complete,
+ // regardless of whether or not it was successful.
+ transformComplete bool
+}
+
+const defaultBufSize = 4096
+
+// NewReader returns a new Reader that wraps r by transforming the bytes read
+// via t. It calls Reset on t.
+func NewReader(r io.Reader, t Transformer) *Reader {
+ t.Reset()
+ return &Reader{
+ r: r,
+ t: t,
+ dst: make([]byte, defaultBufSize),
+ src: make([]byte, defaultBufSize),
+ }
+}
+
+// Read implements the io.Reader interface.
+func (r *Reader) Read(p []byte) (int, error) {
+ n, err := 0, error(nil)
+ for {
+ // Copy out any transformed bytes and return the final error if we are done.
+ if r.dst0 != r.dst1 {
+ n = copy(p, r.dst[r.dst0:r.dst1])
+ r.dst0 += n
+ if r.dst0 == r.dst1 && r.transformComplete {
+ return n, r.err
+ }
+ return n, nil
+ } else if r.transformComplete {
+ return 0, r.err
+ }
+
+ // Try to transform some source bytes, or to flush the transformer if we
+ // are out of source bytes. We do this even if r.r.Read returned an error.
+ // As the io.Reader documentation says, "process the n > 0 bytes returned
+ // before considering the error".
+ if r.src0 != r.src1 || r.err != nil {
+ r.dst0 = 0
+ r.dst1, n, err = r.t.Transform(r.dst, r.src[r.src0:r.src1], r.err == io.EOF)
+ r.src0 += n
+
+ switch {
+ case err == nil:
+ if r.src0 != r.src1 {
+ r.err = errInconsistentByteCount
+ }
+ // The Transform call was successful; we are complete if we
+ // cannot read more bytes into src.
+ r.transformComplete = r.err != nil
+ continue
+ case err == ErrShortDst && (r.dst1 != 0 || n != 0):
+ // Make room in dst by copying out, and try again.
+ continue
+ case err == ErrShortSrc && r.src1-r.src0 != len(r.src) && r.err == nil:
+ // Read more bytes into src via the code below, and try again.
+ default:
+ r.transformComplete = true
+ // The reader error (r.err) takes precedence over the
+ // transformer error (err) unless r.err is nil or io.EOF.
+ if r.err == nil || r.err == io.EOF {
+ r.err = err
+ }
+ continue
+ }
+ }
+
+ // Move any untransformed source bytes to the start of the buffer
+ // and read more bytes.
+ if r.src0 != 0 {
+ r.src0, r.src1 = 0, copy(r.src, r.src[r.src0:r.src1])
+ }
+ n, r.err = r.r.Read(r.src[r.src1:])
+ r.src1 += n
+ }
+}
+
+// TODO: implement ReadByte (and ReadRune??).
+
+// Writer wraps another io.Writer by transforming the bytes read.
+// The user needs to call Close to flush unwritten bytes that may
+// be buffered.
+type Writer struct {
+ w io.Writer
+ t Transformer
+ dst []byte
+
+ // src[:n] contains bytes that have not yet passed through t.
+ src []byte
+ n int
+}
+
+// NewWriter returns a new Writer that wraps w by transforming the bytes written
+// via t. It calls Reset on t.
+func NewWriter(w io.Writer, t Transformer) *Writer {
+ t.Reset()
+ return &Writer{
+ w: w,
+ t: t,
+ dst: make([]byte, defaultBufSize),
+ src: make([]byte, defaultBufSize),
+ }
+}
+
+// Write implements the io.Writer interface. If there are not enough
+// bytes available to complete a Transform, the bytes will be buffered
+// for the next write. Call Close to convert the remaining bytes.
+func (w *Writer) Write(data []byte) (n int, err error) {
+ src := data
+ if w.n > 0 {
+ // Append bytes from data to the last remainder.
+ // TODO: limit the amount copied on first try.
+ n = copy(w.src[w.n:], data)
+ w.n += n
+ src = w.src[:w.n]
+ }
+ for {
+ nDst, nSrc, err := w.t.Transform(w.dst, src, false)
+ if _, werr := w.w.Write(w.dst[:nDst]); werr != nil {
+ return n, werr
+ }
+ src = src[nSrc:]
+ if w.n == 0 {
+ n += nSrc
+ } else if len(src) <= n {
+ // Enough bytes from w.src have been consumed. We make src point
+ // to data instead to reduce the copying.
+ w.n = 0
+ n -= len(src)
+ src = data[n:]
+ if n < len(data) && (err == nil || err == ErrShortSrc) {
+ continue
+ }
+ }
+ switch err {
+ case ErrShortDst:
+ // This error is okay as long as we are making progress.
+ if nDst > 0 || nSrc > 0 {
+ continue
+ }
+ case ErrShortSrc:
+ if len(src) < len(w.src) {
+ m := copy(w.src, src)
+ // If w.n > 0, bytes from data were already copied to w.src and n
+ // was already set to the number of bytes consumed.
+ if w.n == 0 {
+ n += m
+ }
+ w.n = m
+ err = nil
+ } else if nDst > 0 || nSrc > 0 {
+ // Not enough buffer to store the remainder. Keep processing as
+ // long as there is progress. Without this case, transforms that
+ // require a lookahead larger than the buffer may result in an
+ // error. This is not something one may expect to be common in
+ // practice, but it may occur when buffers are set to small
+ // sizes during testing.
+ continue
+ }
+ case nil:
+ if w.n > 0 {
+ err = errInconsistentByteCount
+ }
+ }
+ return n, err
+ }
+}
+
+// Close implements the io.Closer interface.
+func (w *Writer) Close() error {
+ src := w.src[:w.n]
+ for {
+ nDst, nSrc, err := w.t.Transform(w.dst, src, true)
+ if _, werr := w.w.Write(w.dst[:nDst]); werr != nil {
+ return werr
+ }
+ if err != ErrShortDst {
+ return err
+ }
+ src = src[nSrc:]
+ }
+}
+
+type nop struct{ NopResetter }
+
+func (nop) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ n := copy(dst, src)
+ if n < len(src) {
+ err = ErrShortDst
+ }
+ return n, n, err
+}
+
+func (nop) Span(src []byte, atEOF bool) (n int, err error) {
+ return len(src), nil
+}
+
+type discard struct{ NopResetter }
+
+func (discard) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ return 0, len(src), nil
+}
+
+var (
+ // Discard is a Transformer for which all Transform calls succeed
+ // by consuming all bytes and writing nothing.
+ Discard Transformer = discard{}
+
+ // Nop is a SpanningTransformer that copies src to dst.
+ Nop SpanningTransformer = nop{}
+)
+
+// chain is a sequence of links. A chain with N Transformers has N+1 links and
+// N+1 buffers. Of those N+1 buffers, the first and last are the src and dst
+// buffers given to chain.Transform and the middle N-1 buffers are intermediate
+// buffers owned by the chain. The i'th link transforms bytes from the i'th
+// buffer chain.link[i].b at read offset chain.link[i].p to the i+1'th buffer
+// chain.link[i+1].b at write offset chain.link[i+1].n, for i in [0, N).
+type chain struct {
+ link []link
+ err error
+ // errStart is the index at which the error occurred plus 1. Processing
+ // errStart at this level at the next call to Transform. As long as
+ // errStart > 0, chain will not consume any more source bytes.
+ errStart int
+}
+
+func (c *chain) fatalError(errIndex int, err error) {
+ if i := errIndex + 1; i > c.errStart {
+ c.errStart = i
+ c.err = err
+ }
+}
+
+type link struct {
+ t Transformer
+ // b[p:n] holds the bytes to be transformed by t.
+ b []byte
+ p int
+ n int
+}
+
+func (l *link) src() []byte {
+ return l.b[l.p:l.n]
+}
+
+func (l *link) dst() []byte {
+ return l.b[l.n:]
+}
+
+// Chain returns a Transformer that applies t in sequence.
+func Chain(t ...Transformer) Transformer {
+ if len(t) == 0 {
+ return nop{}
+ }
+ c := &chain{link: make([]link, len(t)+1)}
+ for i, tt := range t {
+ c.link[i].t = tt
+ }
+ // Allocate intermediate buffers.
+ b := make([][defaultBufSize]byte, len(t)-1)
+ for i := range b {
+ c.link[i+1].b = b[i][:]
+ }
+ return c
+}
+
+// Reset resets the state of Chain. It calls Reset on all the Transformers.
+func (c *chain) Reset() {
+ for i, l := range c.link {
+ if l.t != nil {
+ l.t.Reset()
+ }
+ c.link[i].p, c.link[i].n = 0, 0
+ }
+}
+
+// TODO: make chain use Span (is going to be fun to implement!)
+
+// Transform applies the transformers of c in sequence.
+func (c *chain) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ // Set up src and dst in the chain.
+ srcL := &c.link[0]
+ dstL := &c.link[len(c.link)-1]
+ srcL.b, srcL.p, srcL.n = src, 0, len(src)
+ dstL.b, dstL.n = dst, 0
+ var lastFull, needProgress bool // for detecting progress
+
+ // i is the index of the next Transformer to apply, for i in [low, high].
+ // low is the lowest index for which c.link[low] may still produce bytes.
+ // high is the highest index for which c.link[high] has a Transformer.
+ // The error returned by Transform determines whether to increase or
+ // decrease i. We try to completely fill a buffer before converting it.
+ for low, i, high := c.errStart, c.errStart, len(c.link)-2; low <= i && i <= high; {
+ in, out := &c.link[i], &c.link[i+1]
+ nDst, nSrc, err0 := in.t.Transform(out.dst(), in.src(), atEOF && low == i)
+ out.n += nDst
+ in.p += nSrc
+ if i > 0 && in.p == in.n {
+ in.p, in.n = 0, 0
+ }
+ needProgress, lastFull = lastFull, false
+ switch err0 {
+ case ErrShortDst:
+ // Process the destination buffer next. Return if we are already
+ // at the high index.
+ if i == high {
+ return dstL.n, srcL.p, ErrShortDst
+ }
+ if out.n != 0 {
+ i++
+ // If the Transformer at the next index is not able to process any
+ // source bytes there is nothing that can be done to make progress
+ // and the bytes will remain unprocessed. lastFull is used to
+ // detect this and break out of the loop with a fatal error.
+ lastFull = true
+ continue
+ }
+ // The destination buffer was too small, but is completely empty.
+ // Return a fatal error as this transformation can never complete.
+ c.fatalError(i, errShortInternal)
+ case ErrShortSrc:
+ if i == 0 {
+ // Save ErrShortSrc in err. All other errors take precedence.
+ err = ErrShortSrc
+ break
+ }
+ // Source bytes were depleted before filling up the destination buffer.
+ // Verify we made some progress, move the remaining bytes to the errStart
+ // and try to get more source bytes.
+ if needProgress && nSrc == 0 || in.n-in.p == len(in.b) {
+ // There were not enough source bytes to proceed while the source
+ // buffer cannot hold any more bytes. Return a fatal error as this
+ // transformation can never complete.
+ c.fatalError(i, errShortInternal)
+ break
+ }
+ // in.b is an internal buffer and we can make progress.
+ in.p, in.n = 0, copy(in.b, in.src())
+ fallthrough
+ case nil:
+ // if i == low, we have depleted the bytes at index i or any lower levels.
+ // In that case we increase low and i. In all other cases we decrease i to
+ // fetch more bytes before proceeding to the next index.
+ if i > low {
+ i--
+ continue
+ }
+ default:
+ c.fatalError(i, err0)
+ }
+ // Exhausted level low or fatal error: increase low and continue
+ // to process the bytes accepted so far.
+ i++
+ low = i
+ }
+
+ // If c.errStart > 0, this means we found a fatal error. We will clear
+ // all upstream buffers. At this point, no more progress can be made
+ // downstream, as Transform would have bailed while handling ErrShortDst.
+ if c.errStart > 0 {
+ for i := 1; i < c.errStart; i++ {
+ c.link[i].p, c.link[i].n = 0, 0
+ }
+ err, c.errStart, c.err = c.err, 0, nil
+ }
+ return dstL.n, srcL.p, err
+}
+
+// Deprecated: use runes.Remove instead.
+func RemoveFunc(f func(r rune) bool) Transformer {
+ return removeF(f)
+}
+
+type removeF func(r rune) bool
+
+func (removeF) Reset() {}
+
+// Transform implements the Transformer interface.
+func (t removeF) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ for r, sz := rune(0), 0; len(src) > 0; src = src[sz:] {
+
+ if r = rune(src[0]); r < utf8.RuneSelf {
+ sz = 1
+ } else {
+ r, sz = utf8.DecodeRune(src)
+
+ if sz == 1 {
+ // Invalid rune.
+ if !atEOF && !utf8.FullRune(src) {
+ err = ErrShortSrc
+ break
+ }
+ // We replace illegal bytes with RuneError. Not doing so might
+ // otherwise turn a sequence of invalid UTF-8 into valid UTF-8.
+ // The resulting byte sequence may subsequently contain runes
+ // for which t(r) is true that were passed unnoticed.
+ if !t(r) {
+ if nDst+3 > len(dst) {
+ err = ErrShortDst
+ break
+ }
+ nDst += copy(dst[nDst:], "\uFFFD")
+ }
+ nSrc++
+ continue
+ }
+ }
+
+ if !t(r) {
+ if nDst+sz > len(dst) {
+ err = ErrShortDst
+ break
+ }
+ nDst += copy(dst[nDst:], src[:sz])
+ }
+ nSrc += sz
+ }
+ return
+}
+
+// grow returns a new []byte that is longer than b, and copies the first n bytes
+// of b to the start of the new slice.
+func grow(b []byte, n int) []byte {
+ m := len(b)
+ if m <= 32 {
+ m = 64
+ } else if m <= 256 {
+ m *= 2
+ } else {
+ m += m >> 1
+ }
+ buf := make([]byte, m)
+ copy(buf, b[:n])
+ return buf
+}
+
+const initialBufSize = 128
+
+// String returns a string with the result of converting s[:n] using t, where
+// n <= len(s). If err == nil, n will be len(s). It calls Reset on t.
+func String(t Transformer, s string) (result string, n int, err error) {
+ t.Reset()
+ if s == "" {
+ // Fast path for the common case for empty input. Results in about a
+ // 86% reduction of running time for BenchmarkStringLowerEmpty.
+ if _, _, err := t.Transform(nil, nil, true); err == nil {
+ return "", 0, nil
+ }
+ }
+
+ // Allocate only once. Note that both dst and src escape when passed to
+ // Transform.
+ buf := [2 * initialBufSize]byte{}
+ dst := buf[:initialBufSize:initialBufSize]
+ src := buf[initialBufSize : 2*initialBufSize]
+
+ // The input string s is transformed in multiple chunks (starting with a
+ // chunk size of initialBufSize). nDst and nSrc are per-chunk (or
+ // per-Transform-call) indexes, pDst and pSrc are overall indexes.
+ nDst, nSrc := 0, 0
+ pDst, pSrc := 0, 0
+
+ // pPrefix is the length of a common prefix: the first pPrefix bytes of the
+ // result will equal the first pPrefix bytes of s. It is not guaranteed to
+ // be the largest such value, but if pPrefix, len(result) and len(s) are
+ // all equal after the final transform (i.e. calling Transform with atEOF
+ // being true returned nil error) then we don't need to allocate a new
+ // result string.
+ pPrefix := 0
+ for {
+ // Invariant: pDst == pPrefix && pSrc == pPrefix.
+
+ n := copy(src, s[pSrc:])
+ nDst, nSrc, err = t.Transform(dst, src[:n], pSrc+n == len(s))
+ pDst += nDst
+ pSrc += nSrc
+
+ // TODO: let transformers implement an optional Spanner interface, akin
+ // to norm's QuickSpan. This would even allow us to avoid any allocation.
+ if !bytes.Equal(dst[:nDst], src[:nSrc]) {
+ break
+ }
+ pPrefix = pSrc
+ if err == ErrShortDst {
+ // A buffer can only be short if a transformer modifies its input.
+ break
+ } else if err == ErrShortSrc {
+ if nSrc == 0 {
+ // No progress was made.
+ break
+ }
+ // Equal so far and !atEOF, so continue checking.
+ } else if err != nil || pPrefix == len(s) {
+ return string(s[:pPrefix]), pPrefix, err
+ }
+ }
+ // Post-condition: pDst == pPrefix + nDst && pSrc == pPrefix + nSrc.
+
+ // We have transformed the first pSrc bytes of the input s to become pDst
+ // transformed bytes. Those transformed bytes are discontiguous: the first
+ // pPrefix of them equal s[:pPrefix] and the last nDst of them equal
+ // dst[:nDst]. We copy them around, into a new dst buffer if necessary, so
+ // that they become one contiguous slice: dst[:pDst].
+ if pPrefix != 0 {
+ newDst := dst
+ if pDst > len(newDst) {
+ newDst = make([]byte, len(s)+nDst-nSrc)
+ }
+ copy(newDst[pPrefix:pDst], dst[:nDst])
+ copy(newDst[:pPrefix], s[:pPrefix])
+ dst = newDst
+ }
+
+ // Prevent duplicate Transform calls with atEOF being true at the end of
+ // the input. Also return if we have an unrecoverable error.
+ if (err == nil && pSrc == len(s)) ||
+ (err != nil && err != ErrShortDst && err != ErrShortSrc) {
+ return string(dst[:pDst]), pSrc, err
+ }
+
+ // Transform the remaining input, growing dst and src buffers as necessary.
+ for {
+ n := copy(src, s[pSrc:])
+ nDst, nSrc, err := t.Transform(dst[pDst:], src[:n], pSrc+n == len(s))
+ pDst += nDst
+ pSrc += nSrc
+
+ // If we got ErrShortDst or ErrShortSrc, do not grow as long as we can
+ // make progress. This may avoid excessive allocations.
+ if err == ErrShortDst {
+ if nDst == 0 {
+ dst = grow(dst, pDst)
+ }
+ } else if err == ErrShortSrc {
+ if nSrc == 0 {
+ src = grow(src, 0)
+ }
+ } else if err != nil || pSrc == len(s) {
+ return string(dst[:pDst]), pSrc, err
+ }
+ }
+}
+
+// Bytes returns a new byte slice with the result of converting b[:n] using t,
+// where n <= len(b). If err == nil, n will be len(b). It calls Reset on t.
+func Bytes(t Transformer, b []byte) (result []byte, n int, err error) {
+ return doAppend(t, 0, make([]byte, len(b)), b)
+}
+
+// Append appends the result of converting src[:n] using t to dst, where
+// n <= len(src), If err == nil, n will be len(src). It calls Reset on t.
+func Append(t Transformer, dst, src []byte) (result []byte, n int, err error) {
+ if len(dst) == cap(dst) {
+ n := len(src) + len(dst) // It is okay for this to be 0.
+ b := make([]byte, n)
+ dst = b[:copy(b, dst)]
+ }
+ return doAppend(t, len(dst), dst[:cap(dst)], src)
+}
+
+func doAppend(t Transformer, pDst int, dst, src []byte) (result []byte, n int, err error) {
+ t.Reset()
+ pSrc := 0
+ for {
+ nDst, nSrc, err := t.Transform(dst[pDst:], src[pSrc:], true)
+ pDst += nDst
+ pSrc += nSrc
+ if err != ErrShortDst {
+ return dst[:pDst], pSrc, err
+ }
+
+ // Grow the destination buffer, but do not grow as long as we can make
+ // progress. This may avoid excessive allocations.
+ if nDst == 0 {
+ dst = grow(dst, pDst)
+ }
+ }
+}
diff --git a/cmd/ponzu/vendor/golang.org/x/text/transform/transform_test.go b/cmd/ponzu/vendor/golang.org/x/text/transform/transform_test.go
new file mode 100644
index 0000000..771633d
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/text/transform/transform_test.go
@@ -0,0 +1,1317 @@
+// 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"
+
+ "golang.org/x/text/internal/testtext"
+)
+
+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
+}
+
+// lowerCaseASCIILookahead lowercases the string and reports ErrShortSrc as long
+// as the input is not atEOF.
+type lowerCaseASCIILookahead struct{ NopResetter }
+
+func (lowerCaseASCIILookahead) 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
+ }
+ if !atEOF {
+ err = ErrShortSrc
+ }
+ 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
+}
+
+var errAtEnd = errors.New("error after all text")
+
+type errorAtEnd struct{ NopResetter }
+
+func (errorAtEnd) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ n := copy(dst, src)
+ if n < len(src) {
+ return n, n, ErrShortDst
+ }
+ if atEOF {
+ return n, n, errAtEnd
+ }
+ return n, n, nil
+}
+
+type replaceWithConstant struct {
+ replacement string
+ written int
+}
+
+func (t *replaceWithConstant) Reset() {
+ t.written = 0
+}
+
+func (t *replaceWithConstant) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ if atEOF {
+ nDst = copy(dst, t.replacement[t.written:])
+ t.written += nDst
+ if t.written < len(t.replacement) {
+ err = ErrShortDst
+ }
+ }
+ return nDst, len(src), err
+}
+
+type addAnXAtTheEnd struct{ NopResetter }
+
+func (addAnXAtTheEnd) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ n := copy(dst, src)
+ if n < len(src) {
+ return n, n, ErrShortDst
+ }
+ if !atEOF {
+ return n, n, nil
+ }
+ if len(dst) == n {
+ return n, n, ErrShortDst
+ }
+ dst[n] = 'X'
+ return n + 1, n, nil
+}
+
+// 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: "small dst with lookahead",
+ t: lowerCaseASCIILookahead{},
+ src: "Hello WORLD.",
+ dstSize: 3,
+ srcSize: 100,
+ wantStr: "hello world.",
+ },
+
+ {
+ desc: "small src with lookahead",
+ t: lowerCaseASCIILookahead{},
+ src: "Hello WORLD.",
+ dstSize: 100,
+ srcSize: 4,
+ wantStr: "hello world.",
+ },
+
+ {
+ desc: "small buffers with lookahead",
+ t: lowerCaseASCIILookahead{},
+ src: "Hello WORLD.",
+ dstSize: 3,
+ srcSize: 4,
+ wantStr: "hello world.",
+ },
+
+ {
+ desc: "very small buffers with lookahead",
+ t: lowerCaseASCIILookahead{},
+ src: "Hello WORLD.",
+ dstSize: 1,
+ srcSize: 2,
+ wantStr: "hello world.",
+ },
+
+ {
+ desc: "user error",
+ 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: "user error at end",
+ t: errorAtEnd{},
+ src: "All goes well until it doesn't.",
+ dstSize: 100,
+ srcSize: 100,
+ wantStr: "All goes well until it doesn't.",
+ wantErr: errAtEnd,
+ },
+
+ {
+ desc: "user error at end, incremental",
+ t: errorAtEnd{},
+ src: "All goes well until it doesn't.",
+ dstSize: 10,
+ srcSize: 10,
+ wantStr: "All goes well until it doesn't.",
+ wantErr: errAtEnd,
+ },
+
+ {
+ desc: "replace entire non-empty string with one byte",
+ t: &replaceWithConstant{replacement: "X"},
+ src: "none of this will be copied",
+ dstSize: 1,
+ srcSize: 10,
+ wantStr: "X",
+ },
+
+ {
+ desc: "replace entire empty string with one byte",
+ t: &replaceWithConstant{replacement: "X"},
+ src: "",
+ dstSize: 1,
+ srcSize: 10,
+ wantStr: "X",
+ },
+
+ {
+ desc: "replace entire empty string with seven bytes",
+ t: &replaceWithConstant{replacement: "ABCDEFG"},
+ src: "",
+ dstSize: 3,
+ srcSize: 10,
+ wantStr: "ABCDEFG",
+ },
+
+ {
+ desc: "add an X (initialBufSize-1)",
+ t: addAnXAtTheEnd{},
+ src: aaa[:initialBufSize-1],
+ dstSize: 10,
+ srcSize: 10,
+ wantStr: aaa[:initialBufSize-1] + "X",
+ },
+
+ {
+ desc: "add an X (initialBufSize+0)",
+ t: addAnXAtTheEnd{},
+ src: aaa[:initialBufSize+0],
+ dstSize: 10,
+ srcSize: 10,
+ wantStr: aaa[:initialBufSize+0] + "X",
+ },
+
+ {
+ desc: "add an X (initialBufSize+1)",
+ t: addAnXAtTheEnd{},
+ src: aaa[:initialBufSize+1],
+ dstSize: 10,
+ srcSize: 10,
+ wantStr: aaa[:initialBufSize+1] + "X",
+ },
+
+ {
+ 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 {
+ testtext.Run(t, tc.desc, func(t *testing.T) {
+ 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("\ngot %q, %v\nwant %q, %v", 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 {
+ testtext.Run(t, fmt.Sprintf("%s/%d", tc.desc, sz), func(t *testing.T) {
+ 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("did not consume all bytes %d < %d", m, n)
+ }
+ }
+ if err == nil {
+ err = w.Close()
+ }
+ str := bb.String()
+ if str != tc.wantStr || err != tc.wantErr {
+ t.Errorf("\ngot %q, %v\nwant %q, %v", 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
+ }
+ testtext.Run(t, tt.desc, func(t *testing.T) {
+ got, n, err := f(tt.t, tt.src)
+ if tt.wantErr != err {
+ t.Errorf("error: got %v; want %v", err, tt.wantErr)
+ }
+ // Check that err == nil implies that n == len(tt.src). Note that vice
+ // versa isn't necessarily true.
+ if err == nil && n != len(tt.src) {
+ t.Errorf("err == nil: got %d bytes, want %d", n, err)
+ }
+ if got != tt.wantStr {
+ t.Errorf("string: got %q; want %q", 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 TestAppend(t *testing.T) {
+ // Create a bunch of subtests for different buffer sizes.
+ testCases := [][]byte{
+ nil,
+ make([]byte, 0, 0),
+ make([]byte, 0, 1),
+ make([]byte, 1, 1),
+ make([]byte, 1, 5),
+ make([]byte, 100, 100),
+ make([]byte, 100, 200),
+ }
+ for _, tc := range testCases {
+ testString(t, func(z Transformer, s string) (string, int, error) {
+ b, n, err := Append(z, tc, []byte(s))
+ return string(b[len(tc):]), n, err
+ })
+ }
+}
+
+func TestString(t *testing.T) {
+ testtext.Run(t, "transform", func(t *testing.T) { testString(t, String) })
+
+ // Overrun the internal destination buffer.
+ for i, s := range []string{
+ aaa[:1*initialBufSize-1],
+ aaa[:1*initialBufSize+0],
+ aaa[:1*initialBufSize+1],
+ AAA[:1*initialBufSize-1],
+ AAA[:1*initialBufSize+0],
+ AAA[:1*initialBufSize+1],
+ AAA[:2*initialBufSize-1],
+ AAA[:2*initialBufSize+0],
+ AAA[:2*initialBufSize+1],
+ aaa[:1*initialBufSize-2] + "A",
+ aaa[:1*initialBufSize-1] + "A",
+ aaa[:1*initialBufSize+0] + "A",
+ aaa[:1*initialBufSize+1] + "A",
+ } {
+ testtext.Run(t, fmt.Sprint("dst buffer test using lower/", i), func(t *testing.T) {
+ got, _, _ := String(lowerCaseASCII{}, s)
+ if want := strings.ToLower(s); got != want {
+ t.Errorf("got %s (%d); want %s (%d)", got, len(got), want, len(want))
+ }
+ })
+ }
+
+ // Overrun the internal source buffer.
+ for i, s := range []string{
+ aaa[:1*initialBufSize-1],
+ aaa[:1*initialBufSize+0],
+ aaa[:1*initialBufSize+1],
+ aaa[:2*initialBufSize+1],
+ aaa[:2*initialBufSize+0],
+ aaa[:2*initialBufSize+1],
+ } {
+ testtext.Run(t, fmt.Sprint("src buffer test using rleEncode/", i), func(t *testing.T) {
+ got, _, _ := String(rleEncode{}, s)
+ if want := fmt.Sprintf("%da", len(s)); got != want {
+ t.Errorf("got %s (%d); want %s (%d)", 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{
+ "",
+ "123456789",
+ aaa[:initialBufSize-1],
+ aaa[:initialBufSize+0],
+ aaa[:initialBufSize+1],
+ aaa[:10*initialBufSize],
+ } {
+ testtext.Run(t, fmt.Sprint("alloc/", i), func(t *testing.T) {
+ if n := testtext.AllocsPerRun(5, func() { String(&lowerCaseASCIILookahead{}, s) }); n > 1 {
+ t.Errorf("#allocs was %f; want 1", 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() {
+ tr := trickler(make([]byte, 1))
+ String(&tr, aaa[:1000])
+ done <- true
+ }()
+ select {
+ case <-done:
+ case <-time.After(3 * time.Second):
+ t.Error("time out, likely due to excessive allocation")
+ }
+}
+
+func BenchmarkStringLowerEmpty(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ String(&lowerCaseASCIILookahead{}, "")
+ }
+}
+
+func BenchmarkStringLowerIdentical(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ String(&lowerCaseASCIILookahead{}, aaa[:4096])
+ }
+}
+
+func BenchmarkStringLowerChanged(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ String(&lowerCaseASCIILookahead{}, AAA[:4096])
+ }
+}
+
+var (
+ aaa = strings.Repeat("a", 4096)
+ AAA = strings.Repeat("A", 4096)
+)
diff --git a/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/composition.go b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/composition.go
new file mode 100644
index 0000000..d17b278
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/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/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/composition_test.go b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/composition_test.go
new file mode 100644
index 0000000..1168406
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/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/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/example_iter_test.go b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/example_iter_test.go
new file mode 100644
index 0000000..82df89c
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/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/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/example_test.go b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/example_test.go
new file mode 100644
index 0000000..f2bec5b
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/example_test.go
@@ -0,0 +1,27 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package norm_test
+
+import (
+ "fmt"
+
+ "golang.org/x/text/unicode/norm"
+)
+
+func ExampleNextBoundary() {
+ s := norm.NFD.String("Mêlée")
+
+ for i := 0; i < len(s); {
+ d := norm.NFC.NextBoundaryInString(s[i:], true)
+ fmt.Printf("%[1]s: %+[1]q\n", s[i:i+d])
+ i += d
+ }
+ // Output:
+ // M: "M"
+ // ê: "e\u0302"
+ // l: "l"
+ // é: "e\u0301"
+ // e: "e"
+}
diff --git a/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/forminfo.go b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/forminfo.go
new file mode 100644
index 0000000..15a67c6
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/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/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/forminfo_test.go b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/forminfo_test.go
new file mode 100644
index 0000000..e15ba9b
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/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/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/input.go b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/input.go
new file mode 100644
index 0000000..045d4cc
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/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/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/iter.go b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/iter.go
new file mode 100644
index 0000000..0a42a72
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/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/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/iter_test.go b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/iter_test.go
new file mode 100644
index 0000000..e2aa6f2
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/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/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/maketables.go b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/maketables.go
new file mode 100644
index 0000000..07bdff6
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/maketables.go
@@ -0,0 +1,978 @@
+// 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"
+ "sort"
+ "strconv"
+ "strings"
+
+ "golang.org/x/text/internal/gen"
+ "golang.org/x/text/internal/triegen"
+ "golang.org/x/text/internal/ucd"
+)
+
+func main() {
+ gen.Init()
+ loadUnicodeData()
+ compactCCC()
+ loadCompositionExclusions()
+ completeCharFields(FCanonical)
+ completeCharFields(FCompatibility)
+ computeNonStarterCounts()
+ verifyComputed()
+ printChars()
+ if *test {
+ testDerived()
+ printTestdata()
+ } else {
+ makeTables()
+ }
+}
+
+var (
+ tablelist = flag.String("tables",
+ "all",
+ "comma-separated list of which tables to generate; "+
+ "can be 'decomp', 'recomp', 'info' and 'all'")
+ test = flag.Bool("test",
+ false,
+ "test existing tables against DerivedNormalizationProps and generate test data for regression testing")
+ verbose = flag.Bool("verbose",
+ false,
+ "write data to stdout as it is parsed")
+)
+
+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 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 := gen.OpenUCDFile("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 {
+ log.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 {
+ log.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 := gen.OpenUCDFile("CompositionExclusions.txt")
+ defer f.Close()
+ p := ucd.New(f)
+ for p.Next() {
+ c := &chars[p.Rune(0)]
+ if c.excludeInComp {
+ log.Fatalf("%U: Duplicate entry in exclusions.", c.codePoint)
+ }
+ c.excludeInComp = true
+ }
+ if e := p.Err(); e != nil {
+ log.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
+ }
+ // We consider runes that combine backwards to be non-starters for the
+ // purpose of Stream-Safe Text Processing.
+ for _, r := range runes {
+ if cr := &chars[r]; cr.ccc == 0 && !cr.forms[FCompatibility].combinesBackward {
+ break
+ }
+ c.nLeadingNonStarters++
+ }
+ for i := len(runes) - 1; i >= 0; i-- {
+ if cr := &chars[runes[i]]; cr.ccc == 0 && !cr.forms[FCompatibility].combinesBackward {
+ break
+ }
+ c.nTrailingNonStarters++
+ }
+ if c.nTrailingNonStarters > 3 {
+ log.Fatalf("%U: Decomposition with more than 3 (%d) trailing modifiers (%U)", i, c.nTrailingNonStarters, runes)
+ }
+
+ 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(w io.Writer, b []byte, name string) {
+ fmt.Fprintf(w, "// %s: %d bytes\n", name, len(b))
+ fmt.Fprintf(w, "var %s = [...]byte {", name)
+ for i, c := range b {
+ switch {
+ case i%64 == 0:
+ fmt.Fprintf(w, "\n// Bytes %x - %x\n", i, i+63)
+ case i%8 == 0:
+ fmt.Fprintf(w, "\n")
+ }
+ fmt.Fprintf(w, "0x%.2X, ", c)
+ }
+ fmt.Fprint(w, "\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(w io.Writer) 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"
+ log.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 {
+ log.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)"
+ log.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 {
+ log.Fatalf("%U: multi-segment decomposition not supported for decompositions with leading CCC != 0", r)
+ }
+ index = firstLeadingCCC
+ }
+ if cc != lccc {
+ if cc != 0 {
+ log.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 {
+ log.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.Fprintln(w, "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.Fprintf(w, "%s = 0x%X\n", cname[i], decompositions.Len())
+ }
+ }
+ fmt.Fprintln(w, "maxDecomp = 0x8000")
+ fmt.Fprintln(w, ")")
+ b := decompositions.Bytes()
+ printBytes(w, 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 {
+ log.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(w, triegen.Compact(&normCompacter{name: varnames[i]}))
+ if err != nil {
+ log.Fatal(err)
+ }
+ size += sz
+ }
+ return size
+}
+
+func contains(sa []string, s string) bool {
+ for _, a := range sa {
+ if a == s {
+ return true
+ }
+ }
+ return false
+}
+
+func makeTables() {
+ w := &bytes.Buffer{}
+
+ size := 0
+ if *tablelist == "" {
+ return
+ }
+ list := strings.Split(*tablelist, ",")
+ if *tablelist == "all" {
+ list = []string{"recomp", "info"}
+ }
+
+ // Compute maximum decomposition size.
+ max := 0
+ for _, c := range chars {
+ if n := len(string(c.forms[FCompatibility].expandedDecomp)); n > max {
+ max = n
+ }
+ }
+
+ fmt.Fprintln(w, "const (")
+ fmt.Fprintln(w, "\t// Version is the Unicode edition from which the tables are derived.")
+ fmt.Fprintf(w, "\tVersion = %q\n", gen.UnicodeVersion())
+ fmt.Fprintln(w)
+ fmt.Fprintln(w, "\t// MaxTransformChunkSize indicates the maximum number of bytes that Transform")
+ fmt.Fprintln(w, "\t// may need to write atomically for any Form. Making a destination buffer at")
+ fmt.Fprintln(w, "\t// least this size ensures that Transform can always make progress and that")
+ fmt.Fprintln(w, "\t// the user does not need to grow the buffer on an ErrShortDst.")
+ fmt.Fprintf(w, "\tMaxTransformChunkSize = %d+maxNonStarters*4\n", len(string(0x034F))+max)
+ fmt.Fprintln(w, ")\n")
+
+ // Print the CCC remap table.
+ size += len(cccMap)
+ fmt.Fprintf(w, "var ccc = [%d]uint8{", len(cccMap))
+ for i := 0; i < len(cccMap); i++ {
+ if i%8 == 0 {
+ fmt.Fprintln(w)
+ }
+ fmt.Fprintf(w, "%3d, ", cccMap[uint8(i)])
+ }
+ fmt.Fprintln(w, "\n}\n")
+
+ if contains(list, "info") {
+ size += printCharInfoTables(w)
+ }
+
+ 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.Fprintf(w, "// recompMap: %d bytes (entries only)\n", sz)
+ fmt.Fprintln(w, "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.Fprintf(w, "0x%.8X: 0x%.4X,\n", key, i)
+ }
+ }
+ fmt.Fprintf(w, "}\n\n")
+ }
+
+ fmt.Fprintf(w, "// Total size of tables: %dKB (%d bytes)\n", (size+512)/1024, size)
+ gen.WriteGoFile("tables.go", "norm", w.Bytes())
+}
+
+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 runes to be treated differently (it only affects
+ // segment breaking in iteration, most likely on improper use), but
+ // reconsider if more characters are added.
+ // U+FF9E HALFWIDTH KATAKANA VOICED SOUND MARK;Lm;0;L;<narrow> 3099;;;;N;;;;;
+ // U+FF9F HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK;Lm;0;L;<narrow> 309A;;;;N;;;;;
+ // U+3133 HANGUL LETTER KIYEOK-SIOS;Lo;0;L;<compat> 11AA;;;;N;HANGUL LETTER GIYEOG SIOS;;;;
+ // U+318E HANGUL LETTER ARAEAE;Lo;0;L;<compat> 11A1;;;;N;HANGUL LETTER ALAE AE;;;;
+ // U+FFA3 HALFWIDTH HANGUL LETTER KIYEOK-SIOS;Lo;0;L;<narrow> 3133;;;;N;HALFWIDTH HANGUL LETTER GIYEOG SIOS;;;;
+ // U+FFDC HALFWIDTH HANGUL LETTER I;Lo;0;L;<narrow> 3163;;;;N;;;;;
+ if i != 0xFF9E && i != 0xFF9F && !(0x3133 <= i && i <= 0x318E) && !(0xFFA3 <= i && i <= 0xFFDC) {
+ log.Fatalf("%U: nLead was %v; want %v", i, a, b)
+ }
+ }
+ }
+ nfc := c.forms[FCanonical]
+ nfkc := c.forms[FCompatibility]
+ if nfc.combinesBackward != nfkc.combinesBackward {
+ log.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 := gen.OpenUCDFile("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 {
+ log.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 {
+ log.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"
+ log.Printf(m, i, j, k, qr, c.name)
+ }
+ }
+ }
+ }
+}
+
+var testHeader = `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{}
+ w := &bytes.Buffer{}
+ fmt.Fprintf(w, testHeader)
+ 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.Fprintf(w, "\t{0x%x, %d, %d, %d, %s},\n", r, c.origCCC, c.nLeadingNonStarters, c.nTrailingNonStarters, s)
+ last = current
+ }
+ }
+ fmt.Fprintln(w, "}")
+ gen.WriteGoFile("data_test.go", "norm", w.Bytes())
+}
diff --git a/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/norm_test.go b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/norm_test.go
new file mode 100644
index 0000000..12dacfc
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/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/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/normalize.go b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/normalize.go
new file mode 100644
index 0000000..bba8ce9
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/normalize.go
@@ -0,0 +1,608 @@
+// 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.
+
+//go:generate go run maketables.go triegen.go
+//go:generate go run maketables.go triegen.go -test
+
+// Package norm contains types and functions for normalizing Unicode strings.
+package norm // import "golang.org/x/text/unicode/norm"
+
+import (
+ "unicode/utf8"
+
+ "golang.org/x/text/transform"
+)
+
+// 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
+}
+
+// Span implements transform.SpanningTransformer. It 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) Span(b []byte, atEOF bool) (n int, err error) {
+ n, ok := formTable[f].quickSpan(inputBytes(b), 0, len(b), atEOF)
+ if n < len(b) {
+ if !ok {
+ err = transform.ErrEndOfSpan
+ } else {
+ err = transform.ErrShortSrc
+ }
+ }
+ return n, err
+}
+
+// SpanString returns a boundary n such that s[0:n] == f(s[0:n]).
+// It is not guaranteed to return the largest such n.
+func (f Form) SpanString(s string, atEOF bool) (n int, err error) {
+ n, ok := formTable[f].quickSpan(inputString(s), 0, len(s), atEOF)
+ if n < len(s) {
+ if !ok {
+ err = transform.ErrEndOfSpan
+ } else {
+ err = transform.ErrShortSrc
+ }
+ }
+ return n, err
+}
+
+// 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 s[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.
+ 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))
+}
+
+// NextBoundary reports the index of the boundary between the first and next
+// segment in b or -1 if atEOF is false and there are not enough bytes to
+// determine this boundary.
+func (f Form) NextBoundary(b []byte, atEOF bool) int {
+ return f.nextBoundary(inputBytes(b), len(b), atEOF)
+}
+
+// NextBoundaryInString reports the index of the boundary between the first and
+// next segment in b or -1 if atEOF is false and there are not enough bytes to
+// determine this boundary.
+func (f Form) NextBoundaryInString(s string, atEOF bool) int {
+ return f.nextBoundary(inputString(s), len(s), atEOF)
+}
+
+func (f Form) nextBoundary(src input, nsrc int, atEOF bool) int {
+ if nsrc == 0 {
+ if atEOF {
+ return 0
+ }
+ return -1
+ }
+ fd := formTable[f]
+ info := fd.info(src, 0)
+ if info.size == 0 {
+ if atEOF {
+ return 1
+ }
+ return -1
+ }
+ ss := streamSafe(0)
+ ss.first(info)
+
+ for i := int(info.size); i < nsrc; i += int(info.size) {
+ info = fd.info(src, i)
+ if info.size == 0 {
+ if atEOF {
+ return i
+ }
+ return -1
+ }
+ if s := ss.next(info); s != ssSuccess {
+ return i
+ }
+ }
+ if !atEOF && !info.BoundaryAfter() && !ss.isMax() {
+ return -1
+ }
+ return nsrc
+}
+
+// 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/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/normalize_test.go b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/normalize_test.go
new file mode 100644
index 0000000..04810e7
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/normalize_test.go
@@ -0,0 +1,1226 @@
+// 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"
+
+ "golang.org/x/text/internal/testtext"
+ "golang.org/x/text/transform"
+)
+
+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
+ {"\xC2", 0, ""},
+ {"\xC0", 1, "\xC0"},
+ {"\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},
+ {"a" + grave(31), 61, "a" + grave(30) + cgj},
+
+ // Stability tests: see http://www.unicode.org/review/pr-29.html.
+ // U+0300 COMBINING GRAVE ACCENT;Mn;230;NSM;;;;;N;NON-SPACING GRAVE;;;;
+ // U+0B47 ORIYA VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
+ // U+0B3E ORIYA VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
+ // U+1100 HANGUL CHOSEONG KIYEOK;Lo;0;L;;;;;N;;;;;
+ // U+1161 HANGUL JUNGSEONG A;Lo;0;L;;;;;N;;;;;
+ {"\u0B47\u0300\u0B3E", 8, "\u0B47\u0300\u0B3E"},
+ {"\u1100\u0300\u1161", 8, "\u1100\u0300\u1161"},
+ {"\u0B47\u0B3E", 6, "\u0B47\u0B3E"},
+ {"\u1100\u1161", 6, "\u1100\u1161"},
+
+ // U+04DA MALAYALAM VOWEL SIGN O;Mc;0;L;0D46 0D3E;;;;N;;;;;
+ // Sequence of decomposing characters that are starters and modifiers.
+ {"\u0d4a" + strings.Repeat("\u0d3e", 31), 90, "\u0d46" + strings.Repeat("\u0d3e", 30) + cgj},
+
+ {grave(30), 60, grave(30)},
+ // U+FF9E is a starter, but decomposes to U+3099, which is not.
+ {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)
+}
+
+func TestNextBoundary(t *testing.T) {
+ testCases := []struct {
+ input string
+ atEOF bool
+ want int
+ }{
+ // no boundary
+ {"", true, 0},
+ {"", false, -1},
+ {"\u0300", true, 2},
+ {"\u0300", false, -1},
+ {"\x80\x80", true, 1},
+ {"\x80\x80", false, 1},
+ // illegal runes
+ {"\xff", false, 1},
+ {"\u0300\xff", false, 2},
+ {"\u0300\xc0\x80\x80", false, 2},
+ {"\xc2\x80\x80", false, 2},
+ {"\xc2", false, -1},
+ {"\xc2", true, 1},
+ {"a\u0300\xc2", false, -1},
+ {"a\u0300\xc2", true, 3},
+ // boundaries
+ {"a", true, 1},
+ {"a", false, -1},
+ {"aa", false, 1},
+ {"\u0300", true, 2},
+ {"\u0300", false, -1},
+ {"\u0300a", false, 2},
+ // Hangul
+ {"\u1103\u1161", true, 6},
+ {"\u1103\u1161", false, -1},
+ {"\u110B\u1173\u11B7", false, -1},
+ {"\u110B\u1173\u11B7\u110B\u1173\u11B7", false, 9},
+ {"\u1161\u110B\u1173\u11B7", false, 3},
+ {"\u1173\u11B7\u1103\u1161", false, 6},
+ // too many combining characters.
+ {grave(maxNonStarters - 1), false, -1},
+ {grave(maxNonStarters), false, 60},
+ {grave(maxNonStarters + 1), false, 60},
+ }
+
+ for _, tc := range testCases {
+ if got := NFC.NextBoundary([]byte(tc.input), tc.atEOF); got != tc.want {
+ t.Errorf("NextBoundary(%+q, %v) = %d; want %d", tc.input, tc.atEOF, got, tc.want)
+ }
+ if got := NFC.NextBoundaryInString(tc.input, tc.atEOF); got != tc.want {
+ t.Errorf("NextBoundaryInString(%+q, %v) = %d; want %d", tc.input, tc.atEOF, got, tc.want)
+ }
+ }
+}
+
+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, ""}, // TODO: should probably be 2.
+ {"\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, ""},
+ {"\u00C2", 0, ""},
+ {"a\u00C2", 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)
+}
+
+type spanTest struct {
+ input string
+ atEOF bool
+ n int
+ err error
+}
+
+var quickSpanTests = []spanTest{
+ {"", true, 0, nil},
+ // starters
+ {"a", true, 1, nil},
+ {"abc", true, 3, nil},
+ {"\u043Eb", true, 3, nil},
+ // incomplete last rune.
+ {"\xCC", true, 1, nil},
+ {"\xCC", false, 0, transform.ErrShortSrc},
+ {"a\xCC", true, 2, nil},
+ {"a\xCC", false, 0, transform.ErrShortSrc}, // TODO: could be 1 for NFD
+ // incorrectly ordered combining characters
+ {"\u0300\u0316", true, 0, transform.ErrEndOfSpan},
+ {"\u0300\u0316", false, 0, transform.ErrEndOfSpan},
+ {"\u0300\u0316cd", true, 0, transform.ErrEndOfSpan},
+ {"\u0300\u0316cd", false, 0, transform.ErrEndOfSpan},
+ // have a maximum number of combining characters.
+ {rep(0x035D, 30) + "\u035B", true, 0, transform.ErrEndOfSpan},
+ {"a" + rep(0x035D, 30) + "\u035B", true, 0, transform.ErrEndOfSpan},
+ {"Ɵ" + rep(0x035D, 30) + "\u035B", true, 0, transform.ErrEndOfSpan},
+ {"aa" + rep(0x035D, 30) + "\u035B", true, 1, transform.ErrEndOfSpan},
+ {rep(0x035D, 30) + cgj + "\u035B", true, 64, nil},
+ {"a" + rep(0x035D, 30) + cgj + "\u035B", true, 65, nil},
+ {"Ɵ" + rep(0x035D, 30) + cgj + "\u035B", true, 66, nil},
+ {"aa" + rep(0x035D, 30) + cgj + "\u035B", true, 66, nil},
+
+ {"a" + rep(0x035D, 30) + cgj + "\u035B", false, 61, transform.ErrShortSrc},
+ {"Ɵ" + rep(0x035D, 30) + cgj + "\u035B", false, 62, transform.ErrShortSrc},
+ {"aa" + rep(0x035D, 30) + cgj + "\u035B", false, 62, transform.ErrShortSrc},
+}
+
+var quickSpanNFDTests = []spanTest{
+ // needs decomposing
+ {"\u00C0", true, 0, transform.ErrEndOfSpan},
+ {"abc\u00C0", true, 3, transform.ErrEndOfSpan},
+ // correctly ordered combining characters
+ {"\u0300", true, 2, nil},
+ {"ab\u0300", true, 4, nil},
+ {"ab\u0300cd", true, 6, nil},
+ {"\u0300cd", true, 4, nil},
+ {"\u0316\u0300", true, 4, nil},
+ {"ab\u0316\u0300", true, 6, nil},
+ {"ab\u0316\u0300cd", true, 8, nil},
+ {"ab\u0316\u0300\u00C0", true, 6, transform.ErrEndOfSpan},
+ {"\u0316\u0300cd", true, 6, nil},
+ {"\u043E\u0308b", true, 5, nil},
+ // incorrectly ordered combining characters
+ {"ab\u0300\u0316", true, 1, transform.ErrEndOfSpan}, // TODO: we could skip 'b' as well.
+ {"ab\u0300\u0316cd", true, 1, transform.ErrEndOfSpan},
+ // Hangul
+ {"같은", true, 0, transform.ErrEndOfSpan},
+}
+
+var quickSpanNFCTests = []spanTest{
+ // okay composed
+ {"\u00C0", true, 2, nil},
+ {"abc\u00C0", true, 5, nil},
+ // correctly ordered combining characters
+ // TODO: b may combine with modifiers, which is why this fails. We could
+ // make a more precise test that that actually checks whether last
+ // characters combines. Probably not worth it.
+ {"ab\u0300", true, 1, transform.ErrEndOfSpan},
+ {"ab\u0300cd", true, 1, transform.ErrEndOfSpan},
+ {"ab\u0316\u0300", true, 1, transform.ErrEndOfSpan},
+ {"ab\u0316\u0300cd", true, 1, transform.ErrEndOfSpan},
+ {"\u00C0\u035D", true, 4, nil},
+ // we do not special case leading combining characters
+ {"\u0300cd", true, 0, transform.ErrEndOfSpan},
+ {"\u0300", true, 0, transform.ErrEndOfSpan},
+ {"\u0316\u0300", true, 0, transform.ErrEndOfSpan},
+ {"\u0316\u0300cd", true, 0, transform.ErrEndOfSpan},
+ // incorrectly ordered combining characters
+ {"ab\u0300\u0316", true, 1, transform.ErrEndOfSpan},
+ {"ab\u0300\u0316cd", true, 1, transform.ErrEndOfSpan},
+ // Hangul
+ {"같은", true, 6, nil},
+ {"같은", false, 3, transform.ErrShortSrc},
+ // We return the start of the violating segment in case of overflow.
+ {grave(30) + "\uff9e", true, 0, transform.ErrEndOfSpan},
+ {grave(30), true, 0, transform.ErrEndOfSpan},
+}
+
+func runSpanTests(t *testing.T, name string, f Form, testCases []spanTest) {
+ for i, tc := range testCases {
+ s := fmt.Sprintf("Bytes/%s/%d=%+q/atEOF=%v", name, i, pc(tc.input), tc.atEOF)
+ ok := testtext.Run(t, s, func(t *testing.T) {
+ n, err := f.Span([]byte(tc.input), tc.atEOF)
+ if n != tc.n || err != tc.err {
+ t.Errorf("\n got %d, %v;\nwant %d, %v", n, err, tc.n, tc.err)
+ }
+ })
+ if !ok {
+ continue // Don't do the String variant if the Bytes variant failed.
+ }
+ s = fmt.Sprintf("String/%s/%d=%+q/atEOF=%v", name, i, pc(tc.input), tc.atEOF)
+ testtext.Run(t, s, func(t *testing.T) {
+ n, err := f.SpanString(tc.input, tc.atEOF)
+ if n != tc.n || err != tc.err {
+ t.Errorf("\n got %d, %v;\nwant %d, %v", n, err, tc.n, tc.err)
+ }
+ })
+ }
+}
+
+func TestSpan(t *testing.T) {
+ runSpanTests(t, "NFD", NFD, quickSpanTests)
+ runSpanTests(t, "NFD", NFD, quickSpanNFDTests)
+ runSpanTests(t, "NFC", NFC, quickSpanTests)
+ runSpanTests(t, "NFC", NFC, 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),
+ },
+
+ { // Combine across non-blocking non-starters.
+ // U+0327 COMBINING CEDILLA;Mn;202;NSM;;;;;N;NON-SPACING CEDILLA;;;;
+ // U+0325 COMBINING RING BELOW;Mn;220;NSM;;;;;N;NON-SPACING RING BELOW;;;;
+ "", "a\u0327\u0325", "\u1e01\u0327",
+ },
+
+ { // Jamo V+T does not combine.
+ "",
+ "\u1161\u11a8",
+ "\u1161\u11a8",
+ },
+
+ // Stability tests: see http://www.unicode.org/review/pr-29.html.
+ {"", "\u0b47\u0300\u0b3e", "\u0b47\u0300\u0b3e"},
+ {"", "\u1100\u0300\u1161", "\u1100\u0300\u1161"},
+ {"", "\u0b47\u0b3e", "\u0b4b"},
+ {"", "\u1100\u1161", "\uac00"},
+
+ // U+04DA MALAYALAM VOWEL SIGN O;Mc;0;L;0D46 0D3E;;;;N;;;;;
+ { // 0d4a starts a new segment.
+ "",
+ "\u0d4a" + strings.Repeat("\u0d3e", 15) + "\u0d4a" + strings.Repeat("\u0d3e", 15),
+ "\u0d4a" + strings.Repeat("\u0d3e", 15) + "\u0d4a" + strings.Repeat("\u0d3e", 15),
+ },
+
+ { // Split combining characters.
+ // TODO: don't insert CGJ before starters.
+ "",
+ "\u0d46" + strings.Repeat("\u0d3e", 31),
+ "\u0d4a" + strings.Repeat("\u0d3e", 29) + cgj + "\u0d3e",
+ },
+
+ { // Split combining characters.
+ "",
+ "\u0d4a" + strings.Repeat("\u0d3e", 30),
+ "\u0d4a" + strings.Repeat("\u0d3e", 29) + cgj + "\u0d3e",
+ },
+}
+
+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/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/readwriter.go b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/readwriter.go
new file mode 100644
index 0000000..4fa0e04
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/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/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/readwriter_test.go b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/readwriter_test.go
new file mode 100644
index 0000000..b7756ba
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/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/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/tables.go b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/tables.go
new file mode 100644
index 0000000..a56697b
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/tables.go
@@ -0,0 +1,7627 @@
+// This file was generated by go generate; DO NOT EDIT
+
+package norm
+
+const (
+ // Version is the Unicode edition from which the tables are derived.
+ Version = "9.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 = 0x186D
+ firstCCC = 0x2C9E
+ endMulti = 0x2F60
+ firstLeadingCCC = 0x4A44
+ firstCCCZeroExcept = 0x4A5A
+ firstStarterWithNLead = 0x4A81
+ lastDecomp = 0x4A83
+ maxDecomp = 0x8000
+)
+
+// decomps: 19075 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, 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, 0x87, 0x87, 0x43, 0xE1, 0x87, 0x88, 0x43,
+ 0xE1, 0x87, 0x8C, 0x43, 0xE1, 0x87, 0x8E, 0x43,
+ 0xE1, 0x87, 0x93, 0x43, 0xE1, 0x87, 0x97, 0x43,
+ // Bytes 400 - 43f
+ 0xE1, 0x87, 0x99, 0x43, 0xE1, 0x87, 0x9D, 0x43,
+ 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,
+ // Bytes 440 - 47f
+ 0xE2, 0x80, 0x93, 0x43, 0xE2, 0x80, 0x94, 0x43,
+ 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,
+ // Bytes 480 - 4bf
+ 0xE2, 0xB5, 0xA1, 0x43, 0xE3, 0x80, 0x81, 0x43,
+ 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,
+ // Bytes 4c0 - 4ff
+ 0xE3, 0x80, 0x96, 0x43, 0xE3, 0x80, 0x97, 0x43,
+ 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,
+ // Bytes 500 - 53f
+ 0xE3, 0x82, 0xB3, 0x43, 0xE3, 0x82, 0xB5, 0x43,
+ 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,
+ // Bytes 540 - 57f
+ 0xE3, 0x83, 0x8E, 0x43, 0xE3, 0x83, 0x8F, 0x43,
+ 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,
+ // Bytes 580 - 5bf
+ 0xE3, 0x83, 0xA8, 0x43, 0xE3, 0x83, 0xA9, 0x43,
+ 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,
+ // Bytes 5c0 - 5ff
+ 0xE3, 0x93, 0x9F, 0x43, 0xE3, 0x94, 0x95, 0x43,
+ 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,
+ // Bytes 600 - 63f
+ 0xE3, 0xAC, 0x99, 0x43, 0xE3, 0xAD, 0x89, 0x43,
+ 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,
+ // Bytes 640 - 67f
+ 0xE4, 0x83, 0xA3, 0x43, 0xE4, 0x84, 0xAF, 0x43,
+ 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,
+ // Bytes 680 - 6bf
+ 0xE4, 0x97, 0x97, 0x43, 0xE4, 0x97, 0xB9, 0x43,
+ 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,
+ // Bytes 6c0 - 6ff
+ 0xE4, 0xB8, 0x80, 0x43, 0xE4, 0xB8, 0x81, 0x43,
+ 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,
+ // Bytes 700 - 73f
+ 0xE4, 0xB8, 0xBF, 0x43, 0xE4, 0xB9, 0x81, 0x43,
+ 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,
+ // Bytes 740 - 77f
+ 0xE4, 0xBC, 0x81, 0x43, 0xE4, 0xBC, 0x91, 0x43,
+ 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,
+ // Bytes 780 - 7bf
+ 0xE5, 0x84, 0xAA, 0x43, 0xE5, 0x84, 0xBF, 0x43,
+ 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,
+ // Bytes 7c0 - 7ff
+ 0xE5, 0x86, 0x8D, 0x43, 0xE5, 0x86, 0x92, 0x43,
+ 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,
+ // Bytes 800 - 83f
+ 0xE5, 0x87, 0xB5, 0x43, 0xE5, 0x88, 0x80, 0x43,
+ 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,
+ // Bytes 840 - 87f
+ 0xE5, 0x8A, 0xB3, 0x43, 0xE5, 0x8A, 0xB4, 0x43,
+ 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,
+ // Bytes 880 - 8bf
+ 0xE5, 0x8C, 0xBB, 0x43, 0xE5, 0x8C, 0xBF, 0x43,
+ 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,
+ // Bytes 8c0 - 8ff
+ 0xE5, 0x8E, 0x82, 0x43, 0xE5, 0x8E, 0xB6, 0x43,
+ 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,
+ // Bytes 900 - 93f
+ 0xE5, 0x90, 0x8F, 0x43, 0xE5, 0x90, 0x9D, 0x43,
+ 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,
+ // Bytes 940 - 97f
+ 0xE5, 0x96, 0x84, 0x43, 0xE5, 0x96, 0x87, 0x43,
+ 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,
+ // Bytes 980 - 9bf
+ 0xE5, 0x9B, 0xB9, 0x43, 0xE5, 0x9C, 0x96, 0x43,
+ 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,
+ // Bytes 9c0 - 9ff
+ 0xE5, 0xA2, 0xB3, 0x43, 0xE5, 0xA3, 0x98, 0x43,
+ 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,
+ // Bytes a00 - a3f
+ 0xE5, 0xA4, 0xA9, 0x43, 0xE5, 0xA5, 0x84, 0x43,
+ 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,
+ // Bytes a40 - a7f
+ 0xE5, 0xAC, 0xBE, 0x43, 0xE5, 0xAD, 0x90, 0x43,
+ 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,
+ // Bytes a80 - abf
+ 0xE5, 0xB0, 0xA2, 0x43, 0xE5, 0xB0, 0xB8, 0x43,
+ 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,
+ // Bytes ac0 - aff
+ 0xE5, 0xB5, 0xBC, 0x43, 0xE5, 0xB6, 0xB2, 0x43,
+ 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,
+ // Bytes b00 - b3f
+ 0xE5, 0xB9, 0xBA, 0x43, 0xE5, 0xB9, 0xBC, 0x43,
+ 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,
+ // Bytes b40 - b7f
+ 0xE5, 0xBC, 0x8B, 0x43, 0xE5, 0xBC, 0x93, 0x43,
+ 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,
+ // Bytes b80 - bbf
+ 0xE5, 0xBF, 0x83, 0x43, 0xE5, 0xBF, 0x8D, 0x43,
+ 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,
+ // Bytes bc0 - bff
+ 0xE6, 0x85, 0x8C, 0x43, 0xE6, 0x85, 0x8E, 0x43,
+ 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,
+ // Bytes c00 - c3f
+ 0xE6, 0x88, 0x9B, 0x43, 0xE6, 0x88, 0xAE, 0x43,
+ 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,
+ // Bytes c40 - c7f
+ 0xE6, 0x8C, 0xBD, 0x43, 0xE6, 0x8D, 0x90, 0x43,
+ 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,
+ // Bytes c80 - cbf
+ 0xE6, 0x91, 0xBE, 0x43, 0xE6, 0x92, 0x9A, 0x43,
+ 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,
+ // Bytes cc0 - cff
+ 0xE6, 0x97, 0x85, 0x43, 0xE6, 0x97, 0xA0, 0x43,
+ 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,
+ // Bytes d00 - d3f
+ 0xE6, 0x9B, 0xB8, 0x43, 0xE6, 0x9C, 0x80, 0x43,
+ 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,
+ // Bytes d40 - d7f
+ 0xE6, 0x9F, 0xBA, 0x43, 0xE6, 0xA0, 0x97, 0x43,
+ 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,
+ // Bytes d80 - dbf
+ 0xE6, 0xAB, 0x93, 0x43, 0xE6, 0xAB, 0x9B, 0x43,
+ 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,
+ // Bytes dc0 - dff
+ 0xE6, 0xAF, 0x8B, 0x43, 0xE6, 0xAF, 0x8D, 0x43,
+ 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,
+ // Bytes e00 - e3f
+ 0xE6, 0xB4, 0x9B, 0x43, 0xE6, 0xB4, 0x9E, 0x43,
+ 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,
+ // Bytes e40 - e7f
+ 0xE6, 0xB9, 0xAE, 0x43, 0xE6, 0xBA, 0x80, 0x43,
+ 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,
+ // Bytes e80 - ebf
+ 0xE7, 0x80, 0x9B, 0x43, 0xE7, 0x80, 0x9E, 0x43,
+ 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,
+ // Bytes ec0 - eff
+ 0xE7, 0x86, 0x9C, 0x43, 0xE7, 0x87, 0x8E, 0x43,
+ 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,
+ // Bytes f00 - f3f
+ 0xE7, 0x89, 0xA2, 0x43, 0xE7, 0x89, 0xB9, 0x43,
+ 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,
+ // Bytes f40 - f7f
+ 0xE7, 0x8E, 0xB2, 0x43, 0xE7, 0x8F, 0x9E, 0x43,
+ 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,
+ // Bytes f80 - fbf
+ 0xE7, 0x94, 0x98, 0x43, 0xE7, 0x94, 0x9F, 0x43,
+ 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,
+ // Bytes fc0 - fff
+ 0xE7, 0x98, 0x90, 0x43, 0xE7, 0x98, 0x9D, 0x43,
+ 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,
+ // Bytes 1000 - 103f
+ 0xE7, 0x9C, 0x9E, 0x43, 0xE7, 0x9C, 0x9F, 0x43,
+ 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,
+ // Bytes 1040 - 107f
+ 0xE7, 0xA4, 0xAA, 0x43, 0xE7, 0xA4, 0xBA, 0x43,
+ 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,
+ // Bytes 1080 - 10bf
+ 0xE7, 0xA6, 0xAE, 0x43, 0xE7, 0xA6, 0xB8, 0x43,
+ 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,
+ // Bytes 10c0 - 10ff
+ 0xE7, 0xAB, 0xB9, 0x43, 0xE7, 0xAC, 0xA0, 0x43,
+ 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,
+ // Bytes 1100 - 113f
+ 0xE7, 0xB3, 0xA8, 0x43, 0xE7, 0xB3, 0xB8, 0x43,
+ 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,
+ // Bytes 1140 - 117f
+ 0xE7, 0xB9, 0x81, 0x43, 0xE7, 0xB9, 0x85, 0x43,
+ 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,
+ // Bytes 1180 - 11bf
+ 0xE8, 0x80, 0x8C, 0x43, 0xE8, 0x80, 0x92, 0x43,
+ 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,
+ // Bytes 11c0 - 11ff
+ 0xE8, 0x87, 0xA3, 0x43, 0xE8, 0x87, 0xA8, 0x43,
+ 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,
+ // Bytes 1200 - 123f
+ 0xE8, 0x89, 0xB9, 0x43, 0xE8, 0x8A, 0x8B, 0x43,
+ 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,
+ // Bytes 1240 - 127f
+ 0xE8, 0x8E, 0xBD, 0x43, 0xE8, 0x8F, 0x89, 0x43,
+ 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,
+ // Bytes 1280 - 12bf
+ 0xE8, 0x95, 0xA4, 0x43, 0xE8, 0x97, 0x8D, 0x43,
+ 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,
+ // Bytes 12c0 - 12ff
+ 0xE8, 0x9C, 0x8E, 0x43, 0xE8, 0x9C, 0xA8, 0x43,
+ 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,
+ // Bytes 1300 - 133f
+ 0xE8, 0xA3, 0x9E, 0x43, 0xE8, 0xA3, 0xA1, 0x43,
+ 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,
+ // Bytes 1340 - 137f
+ 0xE8, 0xAA, 0xBF, 0x43, 0xE8, 0xAB, 0x8B, 0x43,
+ 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,
+ // Bytes 1380 - 13bf
+ 0xE8, 0xB1, 0xB8, 0x43, 0xE8, 0xB2, 0x9D, 0x43,
+ 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,
+ // Bytes 13c0 - 13ff
+ 0xE8, 0xB6, 0xBC, 0x43, 0xE8, 0xB7, 0x8B, 0x43,
+ 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,
+ // Bytes 1400 - 143f
+ 0xE8, 0xBE, 0xB6, 0x43, 0xE9, 0x80, 0xA3, 0x43,
+ 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,
+ // Bytes 1440 - 147f
+ 0xE9, 0x85, 0x89, 0x43, 0xE9, 0x85, 0x8D, 0x43,
+ 0xE9, 0x85, 0xAA, 0x43, 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,
+ // Bytes 1480 - 14bf
+ 0xE9, 0x8D, 0x8A, 0x43, 0xE9, 0x8F, 0xB9, 0x43,
+ 0xE9, 0x90, 0x95, 0x43, 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,
+ // Bytes 14c0 - 14ff
+ 0xE9, 0x9A, 0xA3, 0x43, 0xE9, 0x9A, 0xB6, 0x43,
+ 0xE9, 0x9A, 0xB7, 0x43, 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,
+ // Bytes 1500 - 153f
+ 0xE9, 0x9D, 0x9E, 0x43, 0xE9, 0x9D, 0xA2, 0x43,
+ 0xE9, 0x9D, 0xA9, 0x43, 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,
+ // Bytes 1540 - 157f
+ 0xE9, 0xA2, 0xA8, 0x43, 0xE9, 0xA3, 0x9B, 0x43,
+ 0xE9, 0xA3, 0x9F, 0x43, 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,
+ // Bytes 1580 - 15bf
+ 0xE9, 0xAA, 0xA8, 0x43, 0xE9, 0xAB, 0x98, 0x43,
+ 0xE9, 0xAB, 0x9F, 0x43, 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,
+ // Bytes 15c0 - 15ff
+ 0xE9, 0xB7, 0xBA, 0x43, 0xE9, 0xB8, 0x9E, 0x43,
+ 0xE9, 0xB9, 0xB5, 0x43, 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,
+ // Bytes 1600 - 163f
+ 0xE9, 0xBC, 0x8E, 0x43, 0xE9, 0xBC, 0x8F, 0x43,
+ 0xE9, 0xBC, 0x93, 0x43, 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,
+ // Bytes 1640 - 167f
+ 0xEA, 0xAC, 0xB7, 0x43, 0xEA, 0xAD, 0x92, 0x44,
+ 0xF0, 0xA0, 0x84, 0xA2, 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,
+ // Bytes 1680 - 16bf
+ 0xA1, 0x9B, 0xAA, 0x44, 0xF0, 0xA1, 0xA7, 0x88,
+ 0x44, 0xF0, 0xA1, 0xAC, 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,
+ // Bytes 16c0 - 16ff
+ 0xF0, 0xA2, 0xAF, 0xB1, 0x44, 0xF0, 0xA3, 0x80,
+ 0x8A, 0x44, 0xF0, 0xA3, 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,
+ // Bytes 1700 - 173f
+ 0x44, 0xF0, 0xA3, 0xB2, 0xBC, 0x44, 0xF0, 0xA3,
+ 0xB4, 0x9E, 0x44, 0xF0, 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,
+ // Bytes 1740 - 177f
+ 0x92, 0x44, 0xF0, 0xA4, 0xBE, 0xA1, 0x44, 0xF0,
+ 0xA4, 0xBE, 0xB8, 0x44, 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,
+ // Bytes 1780 - 17bf
+ 0xA5, 0xBC, 0x44, 0xF0, 0xA5, 0xAA, 0xA7, 0x44,
+ 0xF0, 0xA5, 0xAE, 0xAB, 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,
+ // Bytes 17c0 - 17ff
+ 0xA6, 0x96, 0xA8, 0x44, 0xF0, 0xA6, 0x9E, 0xA7,
+ 0x44, 0xF0, 0xA6, 0x9E, 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,
+ // Bytes 1800 - 183f
+ 0xF0, 0xA7, 0xA5, 0xA6, 0x44, 0xF0, 0xA7, 0xB2,
+ 0xA8, 0x44, 0xF0, 0xA7, 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,
+ // Bytes 1840 - 187f
+ 0x44, 0xF0, 0xA9, 0x92, 0x96, 0x44, 0xF0, 0xA9,
+ 0x96, 0xB6, 0x44, 0xF0, 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, 0x42, 0x21, 0x21,
+ 0x42, 0x21, 0x3F, 0x42, 0x2E, 0x2E, 0x42, 0x30,
+ 0x2C, 0x42, 0x30, 0x2E, 0x42, 0x31, 0x2C, 0x42,
+ // Bytes 1880 - 18bf
+ 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, 0x32, 0x32, 0x42,
+ 0x32, 0x33, 0x42, 0x32, 0x34, 0x42, 0x32, 0x35,
+ 0x42, 0x32, 0x36, 0x42, 0x32, 0x37, 0x42, 0x32,
+ // Bytes 18c0 - 18ff
+ 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, 0x2E, 0x42, 0x34,
+ 0x30, 0x42, 0x34, 0x31, 0x42, 0x34, 0x32, 0x42,
+ 0x34, 0x33, 0x42, 0x34, 0x34, 0x42, 0x34, 0x35,
+ // Bytes 1900 - 193f
+ 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, 0x42, 0x3D, 0x3D,
+ 0x42, 0x3F, 0x21, 0x42, 0x3F, 0x3F, 0x42, 0x41,
+ 0x55, 0x42, 0x42, 0x71, 0x42, 0x43, 0x44, 0x42,
+ // Bytes 1940 - 197f
+ 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, 0x4B, 0x4B, 0x42,
+ 0x4B, 0x4D, 0x42, 0x4C, 0x4A, 0x42, 0x4C, 0x6A,
+ 0x42, 0x4D, 0x42, 0x42, 0x4D, 0x43, 0x42, 0x4D,
+ // Bytes 1980 - 19bf
+ 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, 0x49, 0x42, 0x57,
+ 0x43, 0x42, 0x57, 0x5A, 0x42, 0x57, 0x62, 0x42,
+ 0x58, 0x49, 0x42, 0x63, 0x63, 0x42, 0x63, 0x64,
+ // Bytes 19c0 - 19ff
+ 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, 0x42, 0x69, 0x76,
+ 0x42, 0x69, 0x78, 0x42, 0x6B, 0x41, 0x42, 0x6B,
+ 0x56, 0x42, 0x6B, 0x57, 0x42, 0x6B, 0x67, 0x42,
+ // Bytes 1a00 - 1a3f
+ 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, 0x6D, 0x6D, 0x42,
+ 0x6D, 0x73, 0x42, 0x6E, 0x41, 0x42, 0x6E, 0x46,
+ 0x42, 0x6E, 0x56, 0x42, 0x6E, 0x57, 0x42, 0x6E,
+ // Bytes 1a40 - 1a7f
+ 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, 0x28, 0x32, 0x29,
+ 0x43, 0x28, 0x33, 0x29, 0x43, 0x28, 0x34, 0x29,
+ 0x43, 0x28, 0x35, 0x29, 0x43, 0x28, 0x36, 0x29,
+ // Bytes 1a80 - 1abf
+ 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, 0x28, 0x49, 0x29,
+ 0x43, 0x28, 0x4A, 0x29, 0x43, 0x28, 0x4B, 0x29,
+ 0x43, 0x28, 0x4C, 0x29, 0x43, 0x28, 0x4D, 0x29,
+ // Bytes 1ac0 - 1aff
+ 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, 0x28, 0x59, 0x29,
+ 0x43, 0x28, 0x5A, 0x29, 0x43, 0x28, 0x61, 0x29,
+ 0x43, 0x28, 0x62, 0x29, 0x43, 0x28, 0x63, 0x29,
+ // Bytes 1b00 - 1b3f
+ 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, 0x28, 0x6F, 0x29,
+ 0x43, 0x28, 0x70, 0x29, 0x43, 0x28, 0x71, 0x29,
+ 0x43, 0x28, 0x72, 0x29, 0x43, 0x28, 0x73, 0x29,
+ // Bytes 1b40 - 1b7f
+ 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, 0x31, 0x33, 0x2E,
+ 0x43, 0x31, 0x34, 0x2E, 0x43, 0x31, 0x35, 0x2E,
+ 0x43, 0x31, 0x36, 0x2E, 0x43, 0x31, 0x37, 0x2E,
+ // Bytes 1b80 - 1bbf
+ 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, 0x4C, 0xC2, 0xB7,
+ 0x43, 0x4D, 0x48, 0x7A, 0x43, 0x4D, 0x50, 0x61,
+ 0x43, 0x4D, 0xCE, 0xA9, 0x43, 0x50, 0x50, 0x4D,
+ // Bytes 1bc0 - 1bff
+ 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, 0x63, 0x2F, 0x75,
+ 0x43, 0x63, 0x61, 0x6C, 0x43, 0x63, 0x6D, 0x32,
+ 0x43, 0x63, 0x6D, 0x33, 0x43, 0x64, 0x6D, 0x32,
+ // Bytes 1c00 - 1c3f
+ 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, 0x6B, 0xCE, 0xA9,
+ 0x43, 0x6C, 0x6F, 0x67, 0x43, 0x6C, 0xC2, 0xB7,
+ 0x43, 0x6D, 0x69, 0x6C, 0x43, 0x6D, 0x6D, 0x32,
+ // Bytes 1c40 - 1c7f
+ 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, 0xCE, 0xBC, 0x57,
+ 0x43, 0xCE, 0xBC, 0x67, 0x43, 0xCE, 0xBC, 0x6C,
+ 0x43, 0xCE, 0xBC, 0x6D, 0x43, 0xCE, 0xBC, 0x73,
+ // Bytes 1c80 - 1cbf
+ 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, 0x44, 0x28, 0x31,
+ 0x39, 0x29, 0x44, 0x28, 0x32, 0x30, 0x29, 0x44,
+ 0x30, 0xE7, 0x82, 0xB9, 0x44, 0x31, 0xE2, 0x81,
+ // Bytes 1cc0 - 1cff
+ 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, 0xB9, 0x44, 0x34,
+ 0xE6, 0x97, 0xA5, 0x44, 0x34, 0xE6, 0x9C, 0x88,
+ 0x44, 0x34, 0xE7, 0x82, 0xB9, 0x44, 0x35, 0xE6,
+ // Bytes 1d00 - 1d3f
+ 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, 0x97, 0xA5, 0x44,
+ 0x38, 0xE6, 0x9C, 0x88, 0x44, 0x38, 0xE7, 0x82,
+ 0xB9, 0x44, 0x39, 0xE6, 0x97, 0xA5, 0x44, 0x39,
+ // Bytes 1d40 - 1d7f
+ 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, 0xB4, 0xD5, 0xAB,
+ 0x44, 0xD5, 0xB4, 0xD5, 0xAD, 0x44, 0xD5, 0xB4,
+ 0xD5, 0xB6, 0x44, 0xD5, 0xBE, 0xD5, 0xB6, 0x44,
+ // Bytes 1d80 - 1dbf
+ 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, 0xD8, 0xA8, 0xD9,
+ 0x87, 0x44, 0xD8, 0xA8, 0xD9, 0x89, 0x44, 0xD8,
+ 0xA8, 0xD9, 0x8A, 0x44, 0xD8, 0xAA, 0xD8, 0xAC,
+ // Bytes 1dc0 - 1dff
+ 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, 0x44, 0xD8, 0xAB,
+ 0xD8, 0xAC, 0x44, 0xD8, 0xAB, 0xD8, 0xB1, 0x44,
+ 0xD8, 0xAB, 0xD8, 0xB2, 0x44, 0xD8, 0xAB, 0xD9,
+ // Bytes 1e00 - 1e3f
+ 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, 0xAC, 0x44, 0xD8,
+ 0xAD, 0xD9, 0x85, 0x44, 0xD8, 0xAD, 0xD9, 0x89,
+ 0x44, 0xD8, 0xAD, 0xD9, 0x8A, 0x44, 0xD8, 0xAE,
+ // Bytes 1e40 - 1e7f
+ 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, 0xD9, 0x85, 0x44,
+ 0xD8, 0xB3, 0xD9, 0x87, 0x44, 0xD8, 0xB3, 0xD9,
+ 0x89, 0x44, 0xD8, 0xB3, 0xD9, 0x8A, 0x44, 0xD8,
+ // Bytes 1e80 - 1ebf
+ 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, 0xB5, 0xD8, 0xAE,
+ 0x44, 0xD8, 0xB5, 0xD8, 0xB1, 0x44, 0xD8, 0xB5,
+ 0xD9, 0x85, 0x44, 0xD8, 0xB5, 0xD9, 0x89, 0x44,
+ // Bytes 1ec0 - 1eff
+ 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, 0xD8, 0xB7, 0xD9,
+ 0x85, 0x44, 0xD8, 0xB7, 0xD9, 0x89, 0x44, 0xD8,
+ 0xB7, 0xD9, 0x8A, 0x44, 0xD8, 0xB8, 0xD9, 0x85,
+ // Bytes 1f00 - 1f3f
+ 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, 0x44, 0xD9, 0x81,
+ 0xD8, 0xAD, 0x44, 0xD9, 0x81, 0xD8, 0xAE, 0x44,
+ 0xD9, 0x81, 0xD9, 0x85, 0x44, 0xD9, 0x81, 0xD9,
+ // Bytes 1f40 - 1f7f
+ 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, 0xAE, 0x44, 0xD9,
+ 0x83, 0xD9, 0x84, 0x44, 0xD9, 0x83, 0xD9, 0x85,
+ 0x44, 0xD9, 0x83, 0xD9, 0x89, 0x44, 0xD9, 0x83,
+ // Bytes 1f80 - 1fbf
+ 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, 0xD8, 0xA7, 0x44,
+ 0xD9, 0x85, 0xD8, 0xAC, 0x44, 0xD9, 0x85, 0xD8,
+ 0xAD, 0x44, 0xD9, 0x85, 0xD8, 0xAE, 0x44, 0xD9,
+ // Bytes 1fc0 - 1fff
+ 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, 0x86, 0xD9, 0x86,
+ 0x44, 0xD9, 0x86, 0xD9, 0x87, 0x44, 0xD9, 0x86,
+ 0xD9, 0x89, 0x44, 0xD9, 0x86, 0xD9, 0x8A, 0x44,
+ // Bytes 2000 - 203f
+ 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, 0xD9, 0x8A, 0xD8,
+ 0xB2, 0x44, 0xD9, 0x8A, 0xD9, 0x85, 0x44, 0xD9,
+ 0x8A, 0xD9, 0x86, 0x44, 0xD9, 0x8A, 0xD9, 0x87,
+ // Bytes 2040 - 207f
+ 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, 0x28, 0xE1, 0x84,
+ 0x86, 0x29, 0x45, 0x28, 0xE1, 0x84, 0x87, 0x29,
+ 0x45, 0x28, 0xE1, 0x84, 0x89, 0x29, 0x45, 0x28,
+ // Bytes 2080 - 20bf
+ 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, 0x29, 0x45, 0x28,
+ 0xE4, 0xB8, 0x83, 0x29, 0x45, 0x28, 0xE4, 0xB8,
+ 0x89, 0x29, 0x45, 0x28, 0xE4, 0xB9, 0x9D, 0x29,
+ // Bytes 20c0 - 20ff
+ 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, 0x8A, 0xB4, 0x29,
+ 0x45, 0x28, 0xE5, 0x8D, 0x81, 0x29, 0x45, 0x28,
+ 0xE5, 0x8D, 0x94, 0x29, 0x45, 0x28, 0xE5, 0x90,
+ // Bytes 2100 - 213f
+ 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, 0x28, 0xE6, 0x9C,
+ 0xA8, 0x29, 0x45, 0x28, 0xE6, 0xA0, 0xAA, 0x29,
+ 0x45, 0x28, 0xE6, 0xB0, 0xB4, 0x29, 0x45, 0x28,
+ // Bytes 2140 - 217f
+ 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, 0x29, 0x45, 0x28,
+ 0xE8, 0xB2, 0xA1, 0x29, 0x45, 0x28, 0xE8, 0xB3,
+ 0x87, 0x29, 0x45, 0x28, 0xE9, 0x87, 0x91, 0x29,
+ // Bytes 2180 - 21bf
+ 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, 0xE6, 0x97, 0xA5,
+ 0x45, 0x31, 0x32, 0xE6, 0x9C, 0x88, 0x45, 0x31,
+ 0x32, 0xE7, 0x82, 0xB9, 0x45, 0x31, 0x33, 0xE6,
+ // Bytes 21c0 - 21ff
+ 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, 0x31, 0x37, 0xE6,
+ 0x97, 0xA5, 0x45, 0x31, 0x37, 0xE7, 0x82, 0xB9,
+ 0x45, 0x31, 0x38, 0xE6, 0x97, 0xA5, 0x45, 0x31,
+ // Bytes 2200 - 223f
+ 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, 0x36, 0x45, 0x31,
+ 0xE2, 0x81, 0x84, 0x37, 0x45, 0x31, 0xE2, 0x81,
+ 0x84, 0x38, 0x45, 0x31, 0xE2, 0x81, 0x84, 0x39,
+ // Bytes 2240 - 227f
+ 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, 0xE7, 0x82, 0xB9,
+ 0x45, 0x32, 0x34, 0xE6, 0x97, 0xA5, 0x45, 0x32,
+ 0x34, 0xE7, 0x82, 0xB9, 0x45, 0x32, 0x35, 0xE6,
+ // Bytes 2280 - 22bf
+ 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, 0x33, 0x31, 0xE6,
+ 0x97, 0xA5, 0x45, 0x33, 0xE2, 0x81, 0x84, 0x34,
+ 0x45, 0x33, 0xE2, 0x81, 0x84, 0x35, 0x45, 0x33,
+ // Bytes 22c0 - 22ff
+ 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, 0x73, 0x46, 0x31,
+ 0xE2, 0x81, 0x84, 0x31, 0x30, 0x46, 0x43, 0xE2,
+ 0x88, 0x95, 0x6B, 0x67, 0x46, 0x6D, 0xE2, 0x88,
+ // Bytes 2300 - 233f
+ 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, 0x46, 0xD8, 0xAA,
+ 0xD8, 0xAD, 0xD9, 0x85, 0x46, 0xD8, 0xAA, 0xD8,
+ 0xAE, 0xD9, 0x85, 0x46, 0xD8, 0xAA, 0xD8, 0xAE,
+ // Bytes 2340 - 237f
+ 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, 0xD8, 0xAC, 0xD8,
+ 0xAD, 0xD9, 0x89, 0x46, 0xD8, 0xAC, 0xD8, 0xAD,
+ 0xD9, 0x8A, 0x46, 0xD8, 0xAC, 0xD9, 0x85, 0xD8,
+ // Bytes 2380 - 23bf
+ 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, 0xB3, 0xD8, 0xAC,
+ 0xD9, 0x89, 0x46, 0xD8, 0xB3, 0xD8, 0xAD, 0xD8,
+ 0xAC, 0x46, 0xD8, 0xB3, 0xD8, 0xAE, 0xD9, 0x89,
+ // Bytes 23c0 - 23ff
+ 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, 0xD8, 0xAD, 0xD9,
+ 0x8A, 0x46, 0xD8, 0xB4, 0xD9, 0x85, 0xD8, 0xAE,
+ 0x46, 0xD8, 0xB4, 0xD9, 0x85, 0xD9, 0x85, 0x46,
+ // Bytes 2400 - 243f
+ 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, 0xAD, 0xD9, 0x8A,
+ 0x46, 0xD8, 0xB6, 0xD8, 0xAE, 0xD9, 0x85, 0x46,
+ 0xD8, 0xB7, 0xD9, 0x85, 0xD8, 0xAD, 0x46, 0xD8,
+ // Bytes 2440 - 247f
+ 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, 0xD9, 0x85, 0x46,
+ 0xD8, 0xBA, 0xD9, 0x85, 0xD9, 0x89, 0x46, 0xD8,
+ 0xBA, 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD9, 0x81,
+ // Bytes 2480 - 24bf
+ 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, 0x85, 0x46, 0xD9,
+ 0x83, 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD9, 0x84,
+ 0xD8, 0xAC, 0xD8, 0xAC, 0x46, 0xD9, 0x84, 0xD8,
+ // Bytes 24c0 - 24ff
+ 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, 0x46, 0xD9, 0x84,
+ 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD9, 0x85, 0xD8,
+ 0xAC, 0xD8, 0xAD, 0x46, 0xD9, 0x85, 0xD8, 0xAC,
+ // Bytes 2500 - 253f
+ 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, 0xD9, 0x85, 0xD8,
+ 0xAE, 0xD9, 0x85, 0x46, 0xD9, 0x85, 0xD8, 0xAE,
+ 0xD9, 0x8A, 0x46, 0xD9, 0x85, 0xD9, 0x85, 0xD9,
+ // Bytes 2540 - 257f
+ 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, 0x86, 0xD8, 0xAD,
+ 0xD9, 0x8A, 0x46, 0xD9, 0x86, 0xD9, 0x85, 0xD9,
+ 0x89, 0x46, 0xD9, 0x86, 0xD9, 0x85, 0xD9, 0x8A,
+ // Bytes 2580 - 25bf
+ 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, 0xD9, 0x94, 0xD8,
+ 0xA7, 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD8, 0xAC,
+ 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD8, 0xAD, 0x46,
+ // Bytes 25c0 - 25ff
+ 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, 0x94, 0xD9, 0x88,
+ 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD9, 0x89, 0x46,
+ 0xD9, 0x8A, 0xD9, 0x94, 0xD9, 0x8A, 0x46, 0xD9,
+ // Bytes 2600 - 263f
+ 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, 0xBA, 0x99, 0x46,
+ 0xE0, 0xBA, 0xAB, 0xE0, 0xBA, 0xA1, 0x46, 0xE0,
+ 0xBB, 0x8D, 0xE0, 0xBA, 0xB2, 0x46, 0xE0, 0xBD,
+ // Bytes 2640 - 267f
+ 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, 0xB5, 0x46, 0xE0,
+ 0xBE, 0x92, 0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBE,
+ 0x9C, 0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBE, 0xA1,
+ // Bytes 2680 - 26bf
+ 0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBE, 0xA6, 0xE0,
+ 0xBE, 0xB7, 0x46, 0xE0, 0xBE, 0xAB, 0xE0, 0xBE,
+ 0xB7, 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,
+ // Bytes 26c0 - 26ff
+ 0x83, 0xAD, 0x46, 0xE3, 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,
+ // Bytes 2700 - 273f
+ 0xA3, 0x46, 0xE5, 0xB9, 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,
+ // Bytes 2740 - 277f
+ 0x29, 0x48, 0x28, 0xE1, 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,
+ // Bytes 2780 - 27bf
+ 0x48, 0x28, 0xE1, 0x84, 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,
+ // Bytes 27c0 - 27ff
+ 0xD8, 0xA7, 0xD9, 0x84, 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,
+ // Bytes 2800 - 283f
+ 0x80, 0xB2, 0xE2, 0x80, 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,
+ // Bytes 2840 - 287f
+ 0x9D, 0xE3, 0x80, 0x95, 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,
+ // Bytes 2880 - 28bf
+ 0x49, 0xE3, 0x82, 0xA2, 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,
+ // Bytes 28c0 - 28ff
+ 0xE3, 0x83, 0xBC, 0xE3, 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,
+ // Bytes 2900 - 293f
+ 0x83, 0x88, 0x49, 0xE3, 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,
+ // Bytes 2940 - 297f
+ 0x83, 0x9B, 0xE3, 0x83, 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,
+ // Bytes 2980 - 29bf
+ 0xA2, 0xE3, 0x83, 0xB3, 0x49, 0xE3, 0x83, 0xAF,
+ 0xE3, 0x83, 0x83, 0xE3, 0x83, 0x88, 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, 0x82,
+ 0xA8, 0xE3, 0x83, 0xBC, 0xE3, 0x82, 0xAB, 0xE3,
+ // Bytes 29c0 - 29ff
+ 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, 0xE3,
+ 0x82, 0xAD, 0xE3, 0x82, 0x99, 0xE3, 0x83, 0x8B,
+ // Bytes 2a00 - 2a3f
+ 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, 0x4C,
+ 0xE3, 0x82, 0xBF, 0xE3, 0x82, 0x99, 0xE3, 0x83,
+ // Bytes 2a40 - 2a7f
+ 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, 0xBF,
+ 0x4C, 0xE3, 0x83, 0x98, 0xE3, 0x82, 0x9A, 0xE3,
+ // Bytes 2a80 - 2abf
+ 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, 0x83,
+ 0xB3, 0x4C, 0xE3, 0x83, 0xA1, 0xE3, 0x83, 0xBC,
+ // Bytes 2ac0 - 2aff
+ 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, 0x92,
+ 0xE1, 0x85, 0xAE, 0x29, 0x4F, 0xD8, 0xAC, 0xD9,
+ // Bytes 2b00 - 2b3f
+ 0x84, 0x20, 0xD8, 0xAC, 0xD9, 0x84, 0xD8, 0xA7,
+ 0xD9, 0x84, 0xD9, 0x87, 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, 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,
+ // Bytes 2b40 - 2b7f
+ 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, 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,
+ // Bytes 2b80 - 2bbf
+ 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, 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,
+ // Bytes 2bc0 - 2bff
+ 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, 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,
+ // Bytes 2c00 - 2c3f
+ 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, 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,
+ // Bytes 2c40 - 2c7f
+ 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, 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,
+ // Bytes 2c80 - 2cbf
+ 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, 0x06, 0xE0,
+ 0xA7, 0x87, 0xE0, 0xA6, 0xBE, 0x01, 0x06, 0xE0,
+ 0xA7, 0x87, 0xE0, 0xA7, 0x97, 0x01, 0x06, 0xE0,
+ 0xAD, 0x87, 0xE0, 0xAC, 0xBE, 0x01, 0x06, 0xE0,
+ 0xAD, 0x87, 0xE0, 0xAD, 0x96, 0x01, 0x06, 0xE0,
+ // Bytes 2cc0 - 2cff
+ 0xAD, 0x87, 0xE0, 0xAD, 0x97, 0x01, 0x06, 0xE0,
+ 0xAE, 0x92, 0xE0, 0xAF, 0x97, 0x01, 0x06, 0xE0,
+ 0xAF, 0x86, 0xE0, 0xAE, 0xBE, 0x01, 0x06, 0xE0,
+ 0xAF, 0x86, 0xE0, 0xAF, 0x97, 0x01, 0x06, 0xE0,
+ 0xAF, 0x87, 0xE0, 0xAE, 0xBE, 0x01, 0x06, 0xE0,
+ 0xB2, 0xBF, 0xE0, 0xB3, 0x95, 0x01, 0x06, 0xE0,
+ 0xB3, 0x86, 0xE0, 0xB3, 0x95, 0x01, 0x06, 0xE0,
+ 0xB3, 0x86, 0xE0, 0xB3, 0x96, 0x01, 0x06, 0xE0,
+ // Bytes 2d00 - 2d3f
+ 0xB5, 0x86, 0xE0, 0xB4, 0xBE, 0x01, 0x06, 0xE0,
+ 0xB5, 0x86, 0xE0, 0xB5, 0x97, 0x01, 0x06, 0xE0,
+ 0xB5, 0x87, 0xE0, 0xB4, 0xBE, 0x01, 0x06, 0xE0,
+ 0xB7, 0x99, 0xE0, 0xB7, 0x9F, 0x01, 0x06, 0xE1,
+ 0x80, 0xA5, 0xE1, 0x80, 0xAE, 0x01, 0x06, 0xE1,
+ 0xAC, 0x85, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0x87, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0x89, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ // Bytes 2d40 - 2d7f
+ 0xAC, 0x8B, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0x8D, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0x91, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0xBA, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0xBC, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0xBE, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0xBF, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAD, 0x82, 0xE1, 0xAC, 0xB5, 0x01, 0x08, 0xF0,
+ // Bytes 2d80 - 2dbf
+ 0x91, 0x84, 0xB1, 0xF0, 0x91, 0x84, 0xA7, 0x01,
+ 0x08, 0xF0, 0x91, 0x84, 0xB2, 0xF0, 0x91, 0x84,
+ 0xA7, 0x01, 0x08, 0xF0, 0x91, 0x8D, 0x87, 0xF0,
+ 0x91, 0x8C, 0xBE, 0x01, 0x08, 0xF0, 0x91, 0x8D,
+ 0x87, 0xF0, 0x91, 0x8D, 0x97, 0x01, 0x08, 0xF0,
+ 0x91, 0x92, 0xB9, 0xF0, 0x91, 0x92, 0xB0, 0x01,
+ 0x08, 0xF0, 0x91, 0x92, 0xB9, 0xF0, 0x91, 0x92,
+ 0xBA, 0x01, 0x08, 0xF0, 0x91, 0x92, 0xB9, 0xF0,
+ // Bytes 2dc0 - 2dff
+ 0x91, 0x92, 0xBD, 0x01, 0x08, 0xF0, 0x91, 0x96,
+ 0xB8, 0xF0, 0x91, 0x96, 0xAF, 0x01, 0x08, 0xF0,
+ 0x91, 0x96, 0xB9, 0xF0, 0x91, 0x96, 0xAF, 0x01,
+ 0x09, 0xE0, 0xB3, 0x86, 0xE0, 0xB3, 0x82, 0xE0,
+ 0xB3, 0x95, 0x02, 0x09, 0xE0, 0xB7, 0x99, 0xE0,
+ 0xB7, 0x8F, 0xE0, 0xB7, 0x8A, 0x12, 0x44, 0x44,
+ 0x5A, 0xCC, 0x8C, 0xC9, 0x44, 0x44, 0x7A, 0xCC,
+ 0x8C, 0xC9, 0x44, 0x64, 0x7A, 0xCC, 0x8C, 0xC9,
+ // Bytes 2e00 - 2e3f
+ 0x46, 0xD9, 0x84, 0xD8, 0xA7, 0xD9, 0x93, 0xC9,
+ 0x46, 0xD9, 0x84, 0xD8, 0xA7, 0xD9, 0x94, 0xC9,
+ 0x46, 0xD9, 0x84, 0xD8, 0xA7, 0xD9, 0x95, 0xB5,
+ 0x46, 0xE1, 0x84, 0x80, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x82, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x83, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x85, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x86, 0xE1, 0x85, 0xA1, 0x01,
+ // Bytes 2e40 - 2e7f
+ 0x46, 0xE1, 0x84, 0x87, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x89, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x8B, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x8B, 0xE1, 0x85, 0xAE, 0x01,
+ 0x46, 0xE1, 0x84, 0x8C, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x8E, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x8F, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x90, 0xE1, 0x85, 0xA1, 0x01,
+ // Bytes 2e80 - 2ebf
+ 0x46, 0xE1, 0x84, 0x91, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x92, 0xE1, 0x85, 0xA1, 0x01,
+ 0x49, 0xE3, 0x83, 0xA1, 0xE3, 0x82, 0xAB, 0xE3,
+ 0x82, 0x99, 0x0D, 0x4C, 0xE1, 0x84, 0x8C, 0xE1,
+ 0x85, 0xAE, 0xE1, 0x84, 0x8B, 0xE1, 0x85, 0xB4,
+ 0x01, 0x4C, 0xE3, 0x82, 0xAD, 0xE3, 0x82, 0x99,
+ 0xE3, 0x82, 0xAB, 0xE3, 0x82, 0x99, 0x0D, 0x4C,
+ 0xE3, 0x82, 0xB3, 0xE3, 0x83, 0xBC, 0xE3, 0x83,
+ // Bytes 2ec0 - 2eff
+ 0x9B, 0xE3, 0x82, 0x9A, 0x0D, 0x4C, 0xE3, 0x83,
+ 0xA4, 0xE3, 0x83, 0xBC, 0xE3, 0x83, 0x88, 0xE3,
+ 0x82, 0x99, 0x0D, 0x4F, 0xE1, 0x84, 0x8E, 0xE1,
+ 0x85, 0xA1, 0xE1, 0x86, 0xB7, 0xE1, 0x84, 0x80,
+ 0xE1, 0x85, 0xA9, 0x01, 0x4F, 0xE3, 0x82, 0xA4,
+ 0xE3, 0x83, 0x8B, 0xE3, 0x83, 0xB3, 0xE3, 0x82,
+ 0xAF, 0xE3, 0x82, 0x99, 0x0D, 0x4F, 0xE3, 0x82,
+ 0xB7, 0xE3, 0x83, 0xAA, 0xE3, 0x83, 0xB3, 0xE3,
+ // Bytes 2f00 - 2f3f
+ 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, 0xE3, 0x83, 0x88,
+ 0xE3, 0x82, 0x99, 0x0D, 0x52, 0xE3, 0x83, 0x95,
+ // Bytes 2f40 - 2f7f
+ 0xE3, 0x82, 0xA1, 0xE3, 0x83, 0xA9, 0xE3, 0x83,
+ 0x83, 0xE3, 0x83, 0x88, 0xE3, 0x82, 0x99, 0x0D,
+ 0x86, 0xE0, 0xB3, 0x86, 0xE0, 0xB3, 0x82, 0x01,
+ 0x86, 0xE0, 0xB7, 0x99, 0xE0, 0xB7, 0x8F, 0x01,
+ 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,
+ // Bytes 2f80 - 2fbf
+ 0xCC, 0x84, 0xC9, 0x03, 0x41, 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,
+ // Bytes 2fc0 - 2fff
+ 0x43, 0xCC, 0x8C, 0xC9, 0x03, 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,
+ // Bytes 3000 - 303f
+ 0x03, 0x45, 0xCC, 0x89, 0xC9, 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,
+ // Bytes 3040 - 307f
+ 0xC9, 0x03, 0x47, 0xCC, 0x8C, 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,
+ // Bytes 3080 - 30bf
+ 0x83, 0xC9, 0x03, 0x49, 0xCC, 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,
+ // Bytes 30c0 - 30ff
+ 0xCC, 0x8C, 0xC9, 0x03, 0x4B, 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,
+ // Bytes 3100 - 313f
+ 0x4E, 0xCC, 0x81, 0xC9, 0x03, 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,
+ // Bytes 3140 - 317f
+ 0x03, 0x4F, 0xCC, 0x8C, 0xC9, 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,
+ // Bytes 3180 - 31bf
+ 0xC9, 0x03, 0x53, 0xCC, 0x87, 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,
+ // Bytes 31c0 - 31ff
+ 0x82, 0xC9, 0x03, 0x55, 0xCC, 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,
+ // Bytes 3200 - 323f
+ 0xCC, 0x83, 0xC9, 0x03, 0x56, 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,
+ // Bytes 3240 - 327f
+ 0x59, 0xCC, 0x83, 0xC9, 0x03, 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,
+ // Bytes 3280 - 32bf
+ 0x03, 0x61, 0xCC, 0x81, 0xC9, 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,
+ // Bytes 32c0 - 32ff
+ 0xC9, 0x03, 0x63, 0xCC, 0x82, 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,
+ // Bytes 3300 - 333f
+ 0x86, 0xC9, 0x03, 0x65, 0xCC, 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,
+ // Bytes 3340 - 337f
+ 0xCC, 0x84, 0xC9, 0x03, 0x67, 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,
+ // Bytes 3380 - 33bf
+ 0x69, 0xCC, 0x80, 0xC9, 0x03, 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,
+ // Bytes 33c0 - 33ff
+ 0x03, 0x6A, 0xCC, 0x82, 0xC9, 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,
+ // Bytes 3400 - 343f
+ 0xC9, 0x03, 0x6D, 0xCC, 0x87, 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,
+ // Bytes 3440 - 347f
+ 0x81, 0xC9, 0x03, 0x6F, 0xCC, 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,
+ // Bytes 3480 - 34bf
+ 0xCC, 0x91, 0xC9, 0x03, 0x72, 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,
+ // Bytes 34c0 - 34ff
+ 0x74, 0xCC, 0xAD, 0xB5, 0x03, 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,
+ // Bytes 3500 - 353f
+ 0x03, 0x75, 0xCC, 0xA4, 0xB5, 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,
+ // Bytes 3540 - 357f
+ 0xB5, 0x03, 0x78, 0xCC, 0x87, 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,
+ // Bytes 3580 - 35bf
+ 0x81, 0xC9, 0x03, 0x7A, 0xCC, 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,
+ // Bytes 35c0 - 35ff
+ 0xC3, 0xA6, 0xCC, 0x81, 0xC9, 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,
+ // Bytes 3600 - 363f
+ 0xD9, 0x04, 0xCE, 0x95, 0xCC, 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,
+ // Bytes 3640 - 367f
+ 0xCC, 0x80, 0xC9, 0x04, 0xCE, 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,
+ // Bytes 3680 - 36bf
+ 0xCE, 0xB1, 0xCC, 0x84, 0xC9, 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,
+ // Bytes 36c0 - 36ff
+ 0xC9, 0x04, 0xCE, 0xBF, 0xCC, 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,
+ // Bytes 3700 - 373f
+ 0xCC, 0x81, 0xC9, 0x04, 0xCF, 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,
+ // Bytes 3740 - 377f
+ 0xD0, 0x97, 0xCC, 0x88, 0xC9, 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,
+ // Bytes 3780 - 37bf
+ 0xC9, 0x04, 0xD0, 0xA7, 0xCC, 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,
+ // Bytes 37c0 - 37ff
+ 0xCC, 0x88, 0xC9, 0x04, 0xD0, 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,
+ // Bytes 3800 - 383f
+ 0xD1, 0x83, 0xCC, 0x8B, 0xC9, 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,
+ // Bytes 3840 - 387f
+ 0xC9, 0x04, 0xD8, 0xA7, 0xD9, 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,
+ // Bytes 3880 - 38bf
+ 0x41, 0xCC, 0x82, 0xCC, 0x83, 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,
+ // Bytes 38c0 - 38ff
+ 0xCC, 0xA3, 0xCC, 0x82, 0xCA, 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,
+ // Bytes 3900 - 393f
+ 0xA3, 0xCC, 0x82, 0xCA, 0x05, 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,
+ // Bytes 3940 - 397f
+ 0xCC, 0x84, 0xCA, 0x05, 0x4F, 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,
+ // Bytes 3980 - 39bf
+ 0x89, 0xCA, 0x05, 0x4F, 0xCC, 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,
+ // Bytes 39c0 - 39ff
+ 0xCA, 0x05, 0x55, 0xCC, 0x88, 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,
+ // Bytes 3a00 - 3a3f
+ 0x05, 0x61, 0xCC, 0x82, 0xCC, 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,
+ // Bytes 3a40 - 3a7f
+ 0x61, 0xCC, 0x88, 0xCC, 0x84, 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,
+ // Bytes 3a80 - 3abf
+ 0xCC, 0x84, 0xCC, 0x80, 0xCA, 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,
+ // Bytes 3ac0 - 3aff
+ 0x82, 0xCC, 0x89, 0xCA, 0x05, 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,
+ // Bytes 3b00 - 3b3f
+ 0xCC, 0x81, 0xCA, 0x05, 0x6F, 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,
+ // Bytes 3b40 - 3b7f
+ 0x87, 0xCA, 0x05, 0x75, 0xCC, 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,
+ // Bytes 3b80 - 3bbf
+ 0xCA, 0x05, 0x75, 0xCC, 0x9B, 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,
+ // Bytes 3bc0 - 3bff
+ 0x05, 0xE2, 0x86, 0x92, 0xCC, 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,
+ // Bytes 3c00 - 3c3f
+ 0xE2, 0x88, 0xA5, 0xCC, 0xB8, 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,
+ // Bytes 3c40 - 3c7f
+ 0x89, 0xB2, 0xCC, 0xB8, 0x05, 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,
+ // Bytes 3c80 - 3cbf
+ 0x83, 0xCC, 0xB8, 0x05, 0x05, 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,
+ // Bytes 3cc0 - 3cff
+ 0xCC, 0xB8, 0x05, 0x05, 0xE2, 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,
+ // Bytes 3d00 - 3d3f
+ 0x06, 0xCE, 0x95, 0xCC, 0x94, 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,
+ // Bytes 3d40 - 3d7f
+ 0x06, 0xCE, 0x99, 0xCC, 0x94, 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,
+ // Bytes 3d80 - 3dbf
+ 0x06, 0xCE, 0xA9, 0xCC, 0x93, 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,
+ // Bytes 3dc0 - 3dff
+ 0x06, 0xCE, 0xB5, 0xCC, 0x93, 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,
+ // Bytes 3e00 - 3e3f
+ 0x06, 0xCE, 0xB9, 0xCC, 0x88, 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,
+ // Bytes 3e40 - 3e7f
+ 0x06, 0xCE, 0xB9, 0xCC, 0x94, 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,
+ // Bytes 3e80 - 3ebf
+ 0x06, 0xCF, 0x85, 0xCC, 0x93, 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,
+ // Bytes 3ec0 - 3eff
+ 0x06, 0xCF, 0x89, 0xCC, 0x93, 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,
+ // Bytes 3f00 - 3f3f
+ 0x06, 0xE3, 0x81, 0x86, 0xE3, 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,
+ // Bytes 3f40 - 3f7f
+ 0x06, 0xE3, 0x81, 0x99, 0xE3, 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,
+ // Bytes 3f80 - 3fbf
+ 0x06, 0xE3, 0x81, 0xAF, 0xE3, 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,
+ // Bytes 3fc0 - 3fff
+ 0x06, 0xE3, 0x81, 0xBB, 0xE3, 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,
+ // Bytes 4000 - 403f
+ 0x06, 0xE3, 0x82, 0xB3, 0xE3, 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,
+ // Bytes 4040 - 407f
+ 0x06, 0xE3, 0x83, 0x84, 0xE3, 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,
+ // Bytes 4080 - 40bf
+ 0x06, 0xE3, 0x83, 0x95, 0xE3, 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,
+ // Bytes 40c0 - 40ff
+ 0x06, 0xE3, 0x83, 0xB2, 0xE3, 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,
+ // Bytes 4100 - 413f
+ 0x85, 0xDB, 0x08, 0xCE, 0x91, 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,
+ // Bytes 4140 - 417f
+ 0x97, 0xCC, 0x94, 0xCD, 0x82, 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,
+ // Bytes 4180 - 41bf
+ 0x82, 0xCD, 0x85, 0xDB, 0x08, 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,
+ // Bytes 41c0 - 41ff
+ 0x08, 0xCE, 0xB7, 0xCC, 0x93, 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,
+ // Bytes 4200 - 423f
+ 0x93, 0xCC, 0x80, 0xCD, 0x85, 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,
+ // Bytes 4240 - 427f
+ 0xBA, 0x09, 0x08, 0xF0, 0x91, 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,
+ // Bytes 4280 - 42bf
+ 0x8A, 0xC9, 0x43, 0x20, 0xCC, 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,
+ // Bytes 42c0 - 42ff
+ 0xD9, 0x8F, 0x69, 0x43, 0x20, 0xD9, 0x90, 0x6D,
+ 0x43, 0x20, 0xD9, 0x91, 0x71, 0x43, 0x20, 0xD9,
+ 0x92, 0x75, 0x43, 0x41, 0xCC, 0x8A, 0xC9, 0x43,
+ 0x73, 0xCC, 0x87, 0xC9, 0x43, 0xE1, 0x85, 0xA1,
+ 0x01, 0x43, 0xE1, 0x85, 0xA2, 0x01, 0x43, 0xE1,
+ 0x85, 0xA3, 0x01, 0x43, 0xE1, 0x85, 0xA4, 0x01,
+ 0x43, 0xE1, 0x85, 0xA5, 0x01, 0x43, 0xE1, 0x85,
+ 0xA6, 0x01, 0x43, 0xE1, 0x85, 0xA7, 0x01, 0x43,
+ // Bytes 4300 - 433f
+ 0xE1, 0x85, 0xA8, 0x01, 0x43, 0xE1, 0x85, 0xA9,
+ 0x01, 0x43, 0xE1, 0x85, 0xAA, 0x01, 0x43, 0xE1,
+ 0x85, 0xAB, 0x01, 0x43, 0xE1, 0x85, 0xAC, 0x01,
+ 0x43, 0xE1, 0x85, 0xAD, 0x01, 0x43, 0xE1, 0x85,
+ 0xAE, 0x01, 0x43, 0xE1, 0x85, 0xAF, 0x01, 0x43,
+ 0xE1, 0x85, 0xB0, 0x01, 0x43, 0xE1, 0x85, 0xB1,
+ 0x01, 0x43, 0xE1, 0x85, 0xB2, 0x01, 0x43, 0xE1,
+ 0x85, 0xB3, 0x01, 0x43, 0xE1, 0x85, 0xB4, 0x01,
+ // Bytes 4340 - 437f
+ 0x43, 0xE1, 0x85, 0xB5, 0x01, 0x43, 0xE1, 0x86,
+ 0xAA, 0x01, 0x43, 0xE1, 0x86, 0xAC, 0x01, 0x43,
+ 0xE1, 0x86, 0xAD, 0x01, 0x43, 0xE1, 0x86, 0xB0,
+ 0x01, 0x43, 0xE1, 0x86, 0xB1, 0x01, 0x43, 0xE1,
+ 0x86, 0xB2, 0x01, 0x43, 0xE1, 0x86, 0xB3, 0x01,
+ 0x43, 0xE1, 0x86, 0xB4, 0x01, 0x43, 0xE1, 0x86,
+ 0xB5, 0x01, 0x44, 0x20, 0xE3, 0x82, 0x99, 0x0D,
+ 0x44, 0x20, 0xE3, 0x82, 0x9A, 0x0D, 0x44, 0xC2,
+ // Bytes 4380 - 43bf
+ 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, 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,
+ // Bytes 43c0 - 43ff
+ 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, 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,
+ // Bytes 4400 - 443f
+ 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, 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,
+ // Bytes 4440 - 447f
+ 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, 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,
+ // Bytes 4480 - 44bf
+ 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, 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,
+ // Bytes 44c0 - 44ff
+ 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, 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,
+ // Bytes 4500 - 453f
+ 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, 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,
+ // Bytes 4540 - 457f
+ 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, 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,
+ // Bytes 4580 - 45bf
+ 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, 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,
+ // Bytes 45c0 - 45ff
+ 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, 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,
+ // Bytes 4600 - 463f
+ 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, 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,
+ // Bytes 4640 - 467f
+ 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, 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,
+ // Bytes 4680 - 46bf
+ 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, 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,
+ // Bytes 46c0 - 46ff
+ 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, 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,
+ // Bytes 4700 - 473f
+ 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, 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,
+ // Bytes 4740 - 477f
+ 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, 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,
+ // Bytes 4780 - 47bf
+ 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, 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,
+ // Bytes 47c0 - 47ff
+ 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, 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,
+ // Bytes 4800 - 483f
+ 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, 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,
+ // Bytes 4840 - 487f
+ 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, 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,
+ // Bytes 4880 - 48bf
+ 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, 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,
+ // Bytes 48c0 - 48ff
+ 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, 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,
+ // Bytes 4900 - 493f
+ 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, 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,
+ // Bytes 4940 - 497f
+ 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, 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,
+ // Bytes 4980 - 49bf
+ 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, 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,
+ // Bytes 49c0 - 49ff
+ 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, 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,
+ // Bytes 4a00 - 4a3f
+ 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, 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,
+ // Bytes 4a40 - 4a7f
+ 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, 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,
+ // Bytes 4a80 - 4abf
+ 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 < 0xC2:
+ 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 < 0xC2:
+ 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: 10332 bytes (10.09 KiB). Checksum: ad355b768fddb1b6.
+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: 0x2f6f, 0xc1: 0x2f74, 0xc2: 0x471e, 0xc3: 0x2f79, 0xc4: 0x472d, 0xc5: 0x4732,
+ 0xc6: 0xa000, 0xc7: 0x473c, 0xc8: 0x2fe2, 0xc9: 0x2fe7, 0xca: 0x4741, 0xcb: 0x2ffb,
+ 0xcc: 0x306e, 0xcd: 0x3073, 0xce: 0x3078, 0xcf: 0x4755, 0xd1: 0x3104,
+ 0xd2: 0x3127, 0xd3: 0x312c, 0xd4: 0x475f, 0xd5: 0x4764, 0xd6: 0x4773,
+ 0xd8: 0xa000, 0xd9: 0x31b3, 0xda: 0x31b8, 0xdb: 0x31bd, 0xdc: 0x47a5, 0xdd: 0x3235,
+ 0xe0: 0x327b, 0xe1: 0x3280, 0xe2: 0x47af, 0xe3: 0x3285,
+ 0xe4: 0x47be, 0xe5: 0x47c3, 0xe6: 0xa000, 0xe7: 0x47cd, 0xe8: 0x32ee, 0xe9: 0x32f3,
+ 0xea: 0x47d2, 0xeb: 0x3307, 0xec: 0x337f, 0xed: 0x3384, 0xee: 0x3389, 0xef: 0x47e6,
+ 0xf1: 0x3415, 0xf2: 0x3438, 0xf3: 0x343d, 0xf4: 0x47f0, 0xf5: 0x47f5,
+ 0xf6: 0x4804, 0xf8: 0xa000, 0xf9: 0x34c9, 0xfa: 0x34ce, 0xfb: 0x34d3,
+ 0xfc: 0x4836, 0xfd: 0x3550, 0xff: 0x3569,
+ // Block 0x4, offset 0x100
+ 0x100: 0x2f7e, 0x101: 0x328a, 0x102: 0x4723, 0x103: 0x47b4, 0x104: 0x2f9c, 0x105: 0x32a8,
+ 0x106: 0x2fb0, 0x107: 0x32bc, 0x108: 0x2fb5, 0x109: 0x32c1, 0x10a: 0x2fba, 0x10b: 0x32c6,
+ 0x10c: 0x2fbf, 0x10d: 0x32cb, 0x10e: 0x2fc9, 0x10f: 0x32d5,
+ 0x112: 0x4746, 0x113: 0x47d7, 0x114: 0x2ff1, 0x115: 0x32fd, 0x116: 0x2ff6, 0x117: 0x3302,
+ 0x118: 0x3014, 0x119: 0x3320, 0x11a: 0x3005, 0x11b: 0x3311, 0x11c: 0x302d, 0x11d: 0x3339,
+ 0x11e: 0x3037, 0x11f: 0x3343, 0x120: 0x303c, 0x121: 0x3348, 0x122: 0x3046, 0x123: 0x3352,
+ 0x124: 0x304b, 0x125: 0x3357, 0x128: 0x307d, 0x129: 0x338e,
+ 0x12a: 0x3082, 0x12b: 0x3393, 0x12c: 0x3087, 0x12d: 0x3398, 0x12e: 0x30aa, 0x12f: 0x33b6,
+ 0x130: 0x308c, 0x134: 0x30b4, 0x135: 0x33c0,
+ 0x136: 0x30c8, 0x137: 0x33d9, 0x139: 0x30d2, 0x13a: 0x33e3, 0x13b: 0x30dc,
+ 0x13c: 0x33ed, 0x13d: 0x30d7, 0x13e: 0x33e8,
+ // Block 0x5, offset 0x140
+ 0x143: 0x30ff, 0x144: 0x3410, 0x145: 0x3118,
+ 0x146: 0x3429, 0x147: 0x310e, 0x148: 0x341f,
+ 0x14c: 0x4769, 0x14d: 0x47fa, 0x14e: 0x3131, 0x14f: 0x3442, 0x150: 0x313b, 0x151: 0x344c,
+ 0x154: 0x3159, 0x155: 0x346a, 0x156: 0x3172, 0x157: 0x3483,
+ 0x158: 0x3163, 0x159: 0x3474, 0x15a: 0x478c, 0x15b: 0x481d, 0x15c: 0x317c, 0x15d: 0x348d,
+ 0x15e: 0x318b, 0x15f: 0x349c, 0x160: 0x4791, 0x161: 0x4822, 0x162: 0x31a4, 0x163: 0x34ba,
+ 0x164: 0x3195, 0x165: 0x34ab, 0x168: 0x479b, 0x169: 0x482c,
+ 0x16a: 0x47a0, 0x16b: 0x4831, 0x16c: 0x31c2, 0x16d: 0x34d8, 0x16e: 0x31cc, 0x16f: 0x34e2,
+ 0x170: 0x31d1, 0x171: 0x34e7, 0x172: 0x31ef, 0x173: 0x3505, 0x174: 0x3212, 0x175: 0x3528,
+ 0x176: 0x323a, 0x177: 0x3555, 0x178: 0x324e, 0x179: 0x325d, 0x17a: 0x357d, 0x17b: 0x3267,
+ 0x17c: 0x3587, 0x17d: 0x326c, 0x17e: 0x358c, 0x17f: 0xa000,
+ // Block 0x6, offset 0x180
+ 0x184: 0x8100, 0x185: 0x8100,
+ 0x186: 0x8100,
+ 0x18d: 0x2f88, 0x18e: 0x3294, 0x18f: 0x3096, 0x190: 0x33a2, 0x191: 0x3140,
+ 0x192: 0x3451, 0x193: 0x31d6, 0x194: 0x34ec, 0x195: 0x39cf, 0x196: 0x3b5e, 0x197: 0x39c8,
+ 0x198: 0x3b57, 0x199: 0x39d6, 0x19a: 0x3b65, 0x19b: 0x39c1, 0x19c: 0x3b50,
+ 0x19e: 0x38b0, 0x19f: 0x3a3f, 0x1a0: 0x38a9, 0x1a1: 0x3a38, 0x1a2: 0x35b3, 0x1a3: 0x35c5,
+ 0x1a6: 0x3041, 0x1a7: 0x334d, 0x1a8: 0x30be, 0x1a9: 0x33cf,
+ 0x1aa: 0x4782, 0x1ab: 0x4813, 0x1ac: 0x3990, 0x1ad: 0x3b1f, 0x1ae: 0x35d7, 0x1af: 0x35dd,
+ 0x1b0: 0x33c5, 0x1b4: 0x3028, 0x1b5: 0x3334,
+ 0x1b8: 0x30fa, 0x1b9: 0x340b, 0x1ba: 0x38b7, 0x1bb: 0x3a46,
+ 0x1bc: 0x35ad, 0x1bd: 0x35bf, 0x1be: 0x35b9, 0x1bf: 0x35cb,
+ // Block 0x7, offset 0x1c0
+ 0x1c0: 0x2f8d, 0x1c1: 0x3299, 0x1c2: 0x2f92, 0x1c3: 0x329e, 0x1c4: 0x300a, 0x1c5: 0x3316,
+ 0x1c6: 0x300f, 0x1c7: 0x331b, 0x1c8: 0x309b, 0x1c9: 0x33a7, 0x1ca: 0x30a0, 0x1cb: 0x33ac,
+ 0x1cc: 0x3145, 0x1cd: 0x3456, 0x1ce: 0x314a, 0x1cf: 0x345b, 0x1d0: 0x3168, 0x1d1: 0x3479,
+ 0x1d2: 0x316d, 0x1d3: 0x347e, 0x1d4: 0x31db, 0x1d5: 0x34f1, 0x1d6: 0x31e0, 0x1d7: 0x34f6,
+ 0x1d8: 0x3186, 0x1d9: 0x3497, 0x1da: 0x319f, 0x1db: 0x34b5,
+ 0x1de: 0x305a, 0x1df: 0x3366,
+ 0x1e6: 0x4728, 0x1e7: 0x47b9, 0x1e8: 0x4750, 0x1e9: 0x47e1,
+ 0x1ea: 0x395f, 0x1eb: 0x3aee, 0x1ec: 0x393c, 0x1ed: 0x3acb, 0x1ee: 0x476e, 0x1ef: 0x47ff,
+ 0x1f0: 0x3958, 0x1f1: 0x3ae7, 0x1f2: 0x3244, 0x1f3: 0x355f,
+ // 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: 0x4a44, 0x241: 0x4a49, 0x242: 0x9932, 0x243: 0x4a4e, 0x244: 0x4a53, 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: 0x35a1,
+ 0x286: 0x35e9, 0x287: 0x00ce, 0x288: 0x3607, 0x289: 0x3613, 0x28a: 0x3625,
+ 0x28c: 0x3643, 0x28e: 0x3655, 0x28f: 0x3673, 0x290: 0x3e08, 0x291: 0xa000,
+ 0x295: 0xa000, 0x297: 0xa000,
+ 0x299: 0xa000,
+ 0x29f: 0xa000, 0x2a1: 0xa000,
+ 0x2a5: 0xa000, 0x2a9: 0xa000,
+ 0x2aa: 0x3637, 0x2ab: 0x3667, 0x2ac: 0x4894, 0x2ad: 0x3697, 0x2ae: 0x48be, 0x2af: 0x36a9,
+ 0x2b0: 0x3e70, 0x2b1: 0xa000, 0x2b5: 0xa000,
+ 0x2b7: 0xa000, 0x2b9: 0xa000,
+ 0x2bf: 0xa000,
+ // Block 0xb, offset 0x2c0
+ 0x2c0: 0x3721, 0x2c1: 0x372d, 0x2c3: 0x371b,
+ 0x2c6: 0xa000, 0x2c7: 0x3709,
+ 0x2cc: 0x375d, 0x2cd: 0x3745, 0x2ce: 0x376f, 0x2d0: 0xa000,
+ 0x2d3: 0xa000, 0x2d5: 0xa000, 0x2d6: 0xa000, 0x2d7: 0xa000,
+ 0x2d8: 0xa000, 0x2d9: 0x3751, 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: 0x37d5, 0x2fa: 0xa000,
+ 0x2fe: 0xa000,
+ // Block 0xc, offset 0x300
+ 0x301: 0x3733, 0x302: 0x37b7,
+ 0x310: 0x370f, 0x311: 0x3793,
+ 0x312: 0x3715, 0x313: 0x3799, 0x316: 0x3727, 0x317: 0x37ab,
+ 0x318: 0xa000, 0x319: 0xa000, 0x31a: 0x3829, 0x31b: 0x382f, 0x31c: 0x3739, 0x31d: 0x37bd,
+ 0x31e: 0x373f, 0x31f: 0x37c3, 0x322: 0x374b, 0x323: 0x37cf,
+ 0x324: 0x3757, 0x325: 0x37db, 0x326: 0x3763, 0x327: 0x37e7, 0x328: 0xa000, 0x329: 0xa000,
+ 0x32a: 0x3835, 0x32b: 0x383b, 0x32c: 0x378d, 0x32d: 0x3811, 0x32e: 0x3769, 0x32f: 0x37ed,
+ 0x330: 0x3775, 0x331: 0x37f9, 0x332: 0x377b, 0x333: 0x37ff, 0x334: 0x3781, 0x335: 0x3805,
+ 0x338: 0x3787, 0x339: 0x380b,
+ // 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: 0x2d26, 0x3c7: 0xa000, 0x3c8: 0x2d2e, 0x3c9: 0xa000, 0x3ca: 0x2d36, 0x3cb: 0xa000,
+ 0x3cc: 0x2d3e, 0x3cd: 0xa000, 0x3ce: 0x2d46, 0x3d1: 0xa000,
+ 0x3d2: 0x2d4e,
+ 0x3f4: 0x8102, 0x3f5: 0x9900,
+ 0x3fa: 0xa000, 0x3fb: 0x2d56,
+ 0x3fc: 0xa000, 0x3fd: 0x2d5e, 0x3fe: 0xa000, 0x3ff: 0xa000,
+ // Block 0x10, offset 0x400
+ 0x400: 0x2f97, 0x401: 0x32a3, 0x402: 0x2fa1, 0x403: 0x32ad, 0x404: 0x2fa6, 0x405: 0x32b2,
+ 0x406: 0x2fab, 0x407: 0x32b7, 0x408: 0x38cc, 0x409: 0x3a5b, 0x40a: 0x2fc4, 0x40b: 0x32d0,
+ 0x40c: 0x2fce, 0x40d: 0x32da, 0x40e: 0x2fdd, 0x40f: 0x32e9, 0x410: 0x2fd3, 0x411: 0x32df,
+ 0x412: 0x2fd8, 0x413: 0x32e4, 0x414: 0x38ef, 0x415: 0x3a7e, 0x416: 0x38f6, 0x417: 0x3a85,
+ 0x418: 0x3019, 0x419: 0x3325, 0x41a: 0x301e, 0x41b: 0x332a, 0x41c: 0x3904, 0x41d: 0x3a93,
+ 0x41e: 0x3023, 0x41f: 0x332f, 0x420: 0x3032, 0x421: 0x333e, 0x422: 0x3050, 0x423: 0x335c,
+ 0x424: 0x305f, 0x425: 0x336b, 0x426: 0x3055, 0x427: 0x3361, 0x428: 0x3064, 0x429: 0x3370,
+ 0x42a: 0x3069, 0x42b: 0x3375, 0x42c: 0x30af, 0x42d: 0x33bb, 0x42e: 0x390b, 0x42f: 0x3a9a,
+ 0x430: 0x30b9, 0x431: 0x33ca, 0x432: 0x30c3, 0x433: 0x33d4, 0x434: 0x30cd, 0x435: 0x33de,
+ 0x436: 0x475a, 0x437: 0x47eb, 0x438: 0x3912, 0x439: 0x3aa1, 0x43a: 0x30e6, 0x43b: 0x33f7,
+ 0x43c: 0x30e1, 0x43d: 0x33f2, 0x43e: 0x30eb, 0x43f: 0x33fc,
+ // Block 0x11, offset 0x440
+ 0x440: 0x30f0, 0x441: 0x3401, 0x442: 0x30f5, 0x443: 0x3406, 0x444: 0x3109, 0x445: 0x341a,
+ 0x446: 0x3113, 0x447: 0x3424, 0x448: 0x3122, 0x449: 0x3433, 0x44a: 0x311d, 0x44b: 0x342e,
+ 0x44c: 0x3935, 0x44d: 0x3ac4, 0x44e: 0x3943, 0x44f: 0x3ad2, 0x450: 0x394a, 0x451: 0x3ad9,
+ 0x452: 0x3951, 0x453: 0x3ae0, 0x454: 0x314f, 0x455: 0x3460, 0x456: 0x3154, 0x457: 0x3465,
+ 0x458: 0x315e, 0x459: 0x346f, 0x45a: 0x4787, 0x45b: 0x4818, 0x45c: 0x3997, 0x45d: 0x3b26,
+ 0x45e: 0x3177, 0x45f: 0x3488, 0x460: 0x3181, 0x461: 0x3492, 0x462: 0x4796, 0x463: 0x4827,
+ 0x464: 0x399e, 0x465: 0x3b2d, 0x466: 0x39a5, 0x467: 0x3b34, 0x468: 0x39ac, 0x469: 0x3b3b,
+ 0x46a: 0x3190, 0x46b: 0x34a1, 0x46c: 0x319a, 0x46d: 0x34b0, 0x46e: 0x31ae, 0x46f: 0x34c4,
+ 0x470: 0x31a9, 0x471: 0x34bf, 0x472: 0x31ea, 0x473: 0x3500, 0x474: 0x31f9, 0x475: 0x350f,
+ 0x476: 0x31f4, 0x477: 0x350a, 0x478: 0x39b3, 0x479: 0x3b42, 0x47a: 0x39ba, 0x47b: 0x3b49,
+ 0x47c: 0x31fe, 0x47d: 0x3514, 0x47e: 0x3203, 0x47f: 0x3519,
+ // Block 0x12, offset 0x480
+ 0x480: 0x3208, 0x481: 0x351e, 0x482: 0x320d, 0x483: 0x3523, 0x484: 0x321c, 0x485: 0x3532,
+ 0x486: 0x3217, 0x487: 0x352d, 0x488: 0x3221, 0x489: 0x353c, 0x48a: 0x3226, 0x48b: 0x3541,
+ 0x48c: 0x322b, 0x48d: 0x3546, 0x48e: 0x3249, 0x48f: 0x3564, 0x490: 0x3262, 0x491: 0x3582,
+ 0x492: 0x3271, 0x493: 0x3591, 0x494: 0x3276, 0x495: 0x3596, 0x496: 0x337a, 0x497: 0x34a6,
+ 0x498: 0x3537, 0x499: 0x3573, 0x49b: 0x35d1,
+ 0x4a0: 0x4737, 0x4a1: 0x47c8, 0x4a2: 0x2f83, 0x4a3: 0x328f,
+ 0x4a4: 0x3878, 0x4a5: 0x3a07, 0x4a6: 0x3871, 0x4a7: 0x3a00, 0x4a8: 0x3886, 0x4a9: 0x3a15,
+ 0x4aa: 0x387f, 0x4ab: 0x3a0e, 0x4ac: 0x38be, 0x4ad: 0x3a4d, 0x4ae: 0x3894, 0x4af: 0x3a23,
+ 0x4b0: 0x388d, 0x4b1: 0x3a1c, 0x4b2: 0x38a2, 0x4b3: 0x3a31, 0x4b4: 0x389b, 0x4b5: 0x3a2a,
+ 0x4b6: 0x38c5, 0x4b7: 0x3a54, 0x4b8: 0x474b, 0x4b9: 0x47dc, 0x4ba: 0x3000, 0x4bb: 0x330c,
+ 0x4bc: 0x2fec, 0x4bd: 0x32f8, 0x4be: 0x38da, 0x4bf: 0x3a69,
+ // Block 0x13, offset 0x4c0
+ 0x4c0: 0x38d3, 0x4c1: 0x3a62, 0x4c2: 0x38e8, 0x4c3: 0x3a77, 0x4c4: 0x38e1, 0x4c5: 0x3a70,
+ 0x4c6: 0x38fd, 0x4c7: 0x3a8c, 0x4c8: 0x3091, 0x4c9: 0x339d, 0x4ca: 0x30a5, 0x4cb: 0x33b1,
+ 0x4cc: 0x477d, 0x4cd: 0x480e, 0x4ce: 0x3136, 0x4cf: 0x3447, 0x4d0: 0x3920, 0x4d1: 0x3aaf,
+ 0x4d2: 0x3919, 0x4d3: 0x3aa8, 0x4d4: 0x392e, 0x4d5: 0x3abd, 0x4d6: 0x3927, 0x4d7: 0x3ab6,
+ 0x4d8: 0x3989, 0x4d9: 0x3b18, 0x4da: 0x396d, 0x4db: 0x3afc, 0x4dc: 0x3966, 0x4dd: 0x3af5,
+ 0x4de: 0x397b, 0x4df: 0x3b0a, 0x4e0: 0x3974, 0x4e1: 0x3b03, 0x4e2: 0x3982, 0x4e3: 0x3b11,
+ 0x4e4: 0x31e5, 0x4e5: 0x34fb, 0x4e6: 0x31c7, 0x4e7: 0x34dd, 0x4e8: 0x39e4, 0x4e9: 0x3b73,
+ 0x4ea: 0x39dd, 0x4eb: 0x3b6c, 0x4ec: 0x39f2, 0x4ed: 0x3b81, 0x4ee: 0x39eb, 0x4ef: 0x3b7a,
+ 0x4f0: 0x39f9, 0x4f1: 0x3b88, 0x4f2: 0x3230, 0x4f3: 0x354b, 0x4f4: 0x3258, 0x4f5: 0x3578,
+ 0x4f6: 0x3253, 0x4f7: 0x356e, 0x4f8: 0x323f, 0x4f9: 0x355a,
+ // Block 0x14, offset 0x500
+ 0x500: 0x489a, 0x501: 0x48a0, 0x502: 0x49b4, 0x503: 0x49cc, 0x504: 0x49bc, 0x505: 0x49d4,
+ 0x506: 0x49c4, 0x507: 0x49dc, 0x508: 0x4840, 0x509: 0x4846, 0x50a: 0x4924, 0x50b: 0x493c,
+ 0x50c: 0x492c, 0x50d: 0x4944, 0x50e: 0x4934, 0x50f: 0x494c, 0x510: 0x48ac, 0x511: 0x48b2,
+ 0x512: 0x3db8, 0x513: 0x3dc8, 0x514: 0x3dc0, 0x515: 0x3dd0,
+ 0x518: 0x484c, 0x519: 0x4852, 0x51a: 0x3ce8, 0x51b: 0x3cf8, 0x51c: 0x3cf0, 0x51d: 0x3d00,
+ 0x520: 0x48c4, 0x521: 0x48ca, 0x522: 0x49e4, 0x523: 0x49fc,
+ 0x524: 0x49ec, 0x525: 0x4a04, 0x526: 0x49f4, 0x527: 0x4a0c, 0x528: 0x4858, 0x529: 0x485e,
+ 0x52a: 0x4954, 0x52b: 0x496c, 0x52c: 0x495c, 0x52d: 0x4974, 0x52e: 0x4964, 0x52f: 0x497c,
+ 0x530: 0x48dc, 0x531: 0x48e2, 0x532: 0x3e18, 0x533: 0x3e30, 0x534: 0x3e20, 0x535: 0x3e38,
+ 0x536: 0x3e28, 0x537: 0x3e40, 0x538: 0x4864, 0x539: 0x486a, 0x53a: 0x3d18, 0x53b: 0x3d30,
+ 0x53c: 0x3d20, 0x53d: 0x3d38, 0x53e: 0x3d28, 0x53f: 0x3d40,
+ // Block 0x15, offset 0x540
+ 0x540: 0x48e8, 0x541: 0x48ee, 0x542: 0x3e48, 0x543: 0x3e58, 0x544: 0x3e50, 0x545: 0x3e60,
+ 0x548: 0x4870, 0x549: 0x4876, 0x54a: 0x3d48, 0x54b: 0x3d58,
+ 0x54c: 0x3d50, 0x54d: 0x3d60, 0x550: 0x48fa, 0x551: 0x4900,
+ 0x552: 0x3e80, 0x553: 0x3e98, 0x554: 0x3e88, 0x555: 0x3ea0, 0x556: 0x3e90, 0x557: 0x3ea8,
+ 0x559: 0x487c, 0x55b: 0x3d68, 0x55d: 0x3d70,
+ 0x55f: 0x3d78, 0x560: 0x4912, 0x561: 0x4918, 0x562: 0x4a14, 0x563: 0x4a2c,
+ 0x564: 0x4a1c, 0x565: 0x4a34, 0x566: 0x4a24, 0x567: 0x4a3c, 0x568: 0x4882, 0x569: 0x4888,
+ 0x56a: 0x4984, 0x56b: 0x499c, 0x56c: 0x498c, 0x56d: 0x49a4, 0x56e: 0x4994, 0x56f: 0x49ac,
+ 0x570: 0x488e, 0x571: 0x43b4, 0x572: 0x3691, 0x573: 0x43ba, 0x574: 0x48b8, 0x575: 0x43c0,
+ 0x576: 0x36a3, 0x577: 0x43c6, 0x578: 0x36c1, 0x579: 0x43cc, 0x57a: 0x36d9, 0x57b: 0x43d2,
+ 0x57c: 0x4906, 0x57d: 0x43d8,
+ // Block 0x16, offset 0x580
+ 0x580: 0x3da0, 0x581: 0x3da8, 0x582: 0x4184, 0x583: 0x41a2, 0x584: 0x418e, 0x585: 0x41ac,
+ 0x586: 0x4198, 0x587: 0x41b6, 0x588: 0x3cd8, 0x589: 0x3ce0, 0x58a: 0x40d0, 0x58b: 0x40ee,
+ 0x58c: 0x40da, 0x58d: 0x40f8, 0x58e: 0x40e4, 0x58f: 0x4102, 0x590: 0x3de8, 0x591: 0x3df0,
+ 0x592: 0x41c0, 0x593: 0x41de, 0x594: 0x41ca, 0x595: 0x41e8, 0x596: 0x41d4, 0x597: 0x41f2,
+ 0x598: 0x3d08, 0x599: 0x3d10, 0x59a: 0x410c, 0x59b: 0x412a, 0x59c: 0x4116, 0x59d: 0x4134,
+ 0x59e: 0x4120, 0x59f: 0x413e, 0x5a0: 0x3ec0, 0x5a1: 0x3ec8, 0x5a2: 0x41fc, 0x5a3: 0x421a,
+ 0x5a4: 0x4206, 0x5a5: 0x4224, 0x5a6: 0x4210, 0x5a7: 0x422e, 0x5a8: 0x3d80, 0x5a9: 0x3d88,
+ 0x5aa: 0x4148, 0x5ab: 0x4166, 0x5ac: 0x4152, 0x5ad: 0x4170, 0x5ae: 0x415c, 0x5af: 0x417a,
+ 0x5b0: 0x3685, 0x5b1: 0x367f, 0x5b2: 0x3d90, 0x5b3: 0x368b, 0x5b4: 0x3d98,
+ 0x5b6: 0x48a6, 0x5b7: 0x3db0, 0x5b8: 0x35f5, 0x5b9: 0x35ef, 0x5ba: 0x35e3, 0x5bb: 0x4384,
+ 0x5bc: 0x35fb, 0x5bd: 0x8100, 0x5be: 0x01d3, 0x5bf: 0xa100,
+ // Block 0x17, offset 0x5c0
+ 0x5c0: 0x8100, 0x5c1: 0x35a7, 0x5c2: 0x3dd8, 0x5c3: 0x369d, 0x5c4: 0x3de0,
+ 0x5c6: 0x48d0, 0x5c7: 0x3df8, 0x5c8: 0x3601, 0x5c9: 0x438a, 0x5ca: 0x360d, 0x5cb: 0x4390,
+ 0x5cc: 0x3619, 0x5cd: 0x3b8f, 0x5ce: 0x3b96, 0x5cf: 0x3b9d, 0x5d0: 0x36b5, 0x5d1: 0x36af,
+ 0x5d2: 0x3e00, 0x5d3: 0x457a, 0x5d6: 0x36bb, 0x5d7: 0x3e10,
+ 0x5d8: 0x3631, 0x5d9: 0x362b, 0x5da: 0x361f, 0x5db: 0x4396, 0x5dd: 0x3ba4,
+ 0x5de: 0x3bab, 0x5df: 0x3bb2, 0x5e0: 0x36eb, 0x5e1: 0x36e5, 0x5e2: 0x3e68, 0x5e3: 0x4582,
+ 0x5e4: 0x36cd, 0x5e5: 0x36d3, 0x5e6: 0x36f1, 0x5e7: 0x3e78, 0x5e8: 0x3661, 0x5e9: 0x365b,
+ 0x5ea: 0x364f, 0x5eb: 0x43a2, 0x5ec: 0x3649, 0x5ed: 0x359b, 0x5ee: 0x437e, 0x5ef: 0x0081,
+ 0x5f2: 0x3eb0, 0x5f3: 0x36f7, 0x5f4: 0x3eb8,
+ 0x5f6: 0x491e, 0x5f7: 0x3ed0, 0x5f8: 0x363d, 0x5f9: 0x439c, 0x5fa: 0x366d, 0x5fb: 0x43ae,
+ 0x5fc: 0x3679, 0x5fd: 0x4256, 0x5fe: 0xa100,
+ // Block 0x18, offset 0x600
+ 0x601: 0x3c06, 0x603: 0xa000, 0x604: 0x3c0d, 0x605: 0xa000,
+ 0x607: 0x3c14, 0x608: 0xa000, 0x609: 0x3c1b,
+ 0x60d: 0xa000,
+ 0x620: 0x2f65, 0x621: 0xa000, 0x622: 0x3c29,
+ 0x624: 0xa000, 0x625: 0xa000,
+ 0x62d: 0x3c22, 0x62e: 0x2f60, 0x62f: 0x2f6a,
+ 0x630: 0x3c30, 0x631: 0x3c37, 0x632: 0xa000, 0x633: 0xa000, 0x634: 0x3c3e, 0x635: 0x3c45,
+ 0x636: 0xa000, 0x637: 0xa000, 0x638: 0x3c4c, 0x639: 0x3c53, 0x63a: 0xa000, 0x63b: 0xa000,
+ 0x63c: 0xa000, 0x63d: 0xa000,
+ // Block 0x19, offset 0x640
+ 0x640: 0x3c5a, 0x641: 0x3c61, 0x642: 0xa000, 0x643: 0xa000, 0x644: 0x3c76, 0x645: 0x3c7d,
+ 0x646: 0xa000, 0x647: 0xa000, 0x648: 0x3c84, 0x649: 0x3c8b,
+ 0x651: 0xa000,
+ 0x652: 0xa000,
+ 0x662: 0xa000,
+ 0x668: 0xa000, 0x669: 0xa000,
+ 0x66b: 0xa000, 0x66c: 0x3ca0, 0x66d: 0x3ca7, 0x66e: 0x3cae, 0x66f: 0x3cb5,
+ 0x672: 0xa000, 0x673: 0xa000, 0x674: 0xa000, 0x675: 0xa000,
+ // Block 0x1a, offset 0x680
+ 0x686: 0xa000, 0x68b: 0xa000,
+ 0x68c: 0x3f08, 0x68d: 0xa000, 0x68e: 0x3f10, 0x68f: 0xa000, 0x690: 0x3f18, 0x691: 0xa000,
+ 0x692: 0x3f20, 0x693: 0xa000, 0x694: 0x3f28, 0x695: 0xa000, 0x696: 0x3f30, 0x697: 0xa000,
+ 0x698: 0x3f38, 0x699: 0xa000, 0x69a: 0x3f40, 0x69b: 0xa000, 0x69c: 0x3f48, 0x69d: 0xa000,
+ 0x69e: 0x3f50, 0x69f: 0xa000, 0x6a0: 0x3f58, 0x6a1: 0xa000, 0x6a2: 0x3f60,
+ 0x6a4: 0xa000, 0x6a5: 0x3f68, 0x6a6: 0xa000, 0x6a7: 0x3f70, 0x6a8: 0xa000, 0x6a9: 0x3f78,
+ 0x6af: 0xa000,
+ 0x6b0: 0x3f80, 0x6b1: 0x3f88, 0x6b2: 0xa000, 0x6b3: 0x3f90, 0x6b4: 0x3f98, 0x6b5: 0xa000,
+ 0x6b6: 0x3fa0, 0x6b7: 0x3fa8, 0x6b8: 0xa000, 0x6b9: 0x3fb0, 0x6ba: 0x3fb8, 0x6bb: 0xa000,
+ 0x6bc: 0x3fc0, 0x6bd: 0x3fc8,
+ // Block 0x1b, offset 0x6c0
+ 0x6d4: 0x3f00,
+ 0x6d9: 0x9903, 0x6da: 0x9903, 0x6db: 0x8100, 0x6dc: 0x8100, 0x6dd: 0xa000,
+ 0x6de: 0x3fd0,
+ 0x6e6: 0xa000,
+ 0x6eb: 0xa000, 0x6ec: 0x3fe0, 0x6ed: 0xa000, 0x6ee: 0x3fe8, 0x6ef: 0xa000,
+ 0x6f0: 0x3ff0, 0x6f1: 0xa000, 0x6f2: 0x3ff8, 0x6f3: 0xa000, 0x6f4: 0x4000, 0x6f5: 0xa000,
+ 0x6f6: 0x4008, 0x6f7: 0xa000, 0x6f8: 0x4010, 0x6f9: 0xa000, 0x6fa: 0x4018, 0x6fb: 0xa000,
+ 0x6fc: 0x4020, 0x6fd: 0xa000, 0x6fe: 0x4028, 0x6ff: 0xa000,
+ // Block 0x1c, offset 0x700
+ 0x700: 0x4030, 0x701: 0xa000, 0x702: 0x4038, 0x704: 0xa000, 0x705: 0x4040,
+ 0x706: 0xa000, 0x707: 0x4048, 0x708: 0xa000, 0x709: 0x4050,
+ 0x70f: 0xa000, 0x710: 0x4058, 0x711: 0x4060,
+ 0x712: 0xa000, 0x713: 0x4068, 0x714: 0x4070, 0x715: 0xa000, 0x716: 0x4078, 0x717: 0x4080,
+ 0x718: 0xa000, 0x719: 0x4088, 0x71a: 0x4090, 0x71b: 0xa000, 0x71c: 0x4098, 0x71d: 0x40a0,
+ 0x72f: 0xa000,
+ 0x730: 0xa000, 0x731: 0xa000, 0x732: 0xa000, 0x734: 0x3fd8,
+ 0x737: 0x40a8, 0x738: 0x40b0, 0x739: 0x40b8, 0x73a: 0x40c0,
+ 0x73d: 0xa000, 0x73e: 0x40c8,
+ // Block 0x1d, offset 0x740
+ 0x740: 0x1377, 0x741: 0x0cfb, 0x742: 0x13d3, 0x743: 0x139f, 0x744: 0x0e57, 0x745: 0x06eb,
+ 0x746: 0x08df, 0x747: 0x162b, 0x748: 0x162b, 0x749: 0x0a0b, 0x74a: 0x145f, 0x74b: 0x0943,
+ 0x74c: 0x0a07, 0x74d: 0x0bef, 0x74e: 0x0fcf, 0x74f: 0x115f, 0x750: 0x1297, 0x751: 0x12d3,
+ 0x752: 0x1307, 0x753: 0x141b, 0x754: 0x0d73, 0x755: 0x0dff, 0x756: 0x0eab, 0x757: 0x0f43,
+ 0x758: 0x125f, 0x759: 0x1447, 0x75a: 0x1573, 0x75b: 0x070f, 0x75c: 0x08b3, 0x75d: 0x0d87,
+ 0x75e: 0x0ecf, 0x75f: 0x1293, 0x760: 0x15c3, 0x761: 0x0ab3, 0x762: 0x0e77, 0x763: 0x1283,
+ 0x764: 0x1317, 0x765: 0x0c23, 0x766: 0x11bb, 0x767: 0x12df, 0x768: 0x0b1f, 0x769: 0x0d0f,
+ 0x76a: 0x0e17, 0x76b: 0x0f1b, 0x76c: 0x1427, 0x76d: 0x074f, 0x76e: 0x07e7, 0x76f: 0x0853,
+ 0x770: 0x0c8b, 0x771: 0x0d7f, 0x772: 0x0ecb, 0x773: 0x0fef, 0x774: 0x1177, 0x775: 0x128b,
+ 0x776: 0x12a3, 0x777: 0x13c7, 0x778: 0x14ef, 0x779: 0x15a3, 0x77a: 0x15bf, 0x77b: 0x102b,
+ 0x77c: 0x106b, 0x77d: 0x1123, 0x77e: 0x1243, 0x77f: 0x147b,
+ // Block 0x1e, offset 0x780
+ 0x780: 0x15cb, 0x781: 0x134b, 0x782: 0x09c7, 0x783: 0x0b3b, 0x784: 0x10db, 0x785: 0x119b,
+ 0x786: 0x0eff, 0x787: 0x1033, 0x788: 0x1397, 0x789: 0x14e7, 0x78a: 0x09c3, 0x78b: 0x0a8f,
+ 0x78c: 0x0d77, 0x78d: 0x0e2b, 0x78e: 0x0e5f, 0x78f: 0x1113, 0x790: 0x113b, 0x791: 0x14a7,
+ 0x792: 0x084f, 0x793: 0x11a7, 0x794: 0x07f3, 0x795: 0x07ef, 0x796: 0x1097, 0x797: 0x1127,
+ 0x798: 0x125b, 0x799: 0x14af, 0x79a: 0x1367, 0x79b: 0x0c27, 0x79c: 0x0d73, 0x79d: 0x1357,
+ 0x79e: 0x06f7, 0x79f: 0x0a63, 0x7a0: 0x0b93, 0x7a1: 0x0f2f, 0x7a2: 0x0faf, 0x7a3: 0x0873,
+ 0x7a4: 0x103b, 0x7a5: 0x075f, 0x7a6: 0x0b77, 0x7a7: 0x06d7, 0x7a8: 0x0deb, 0x7a9: 0x0ca3,
+ 0x7aa: 0x110f, 0x7ab: 0x08c7, 0x7ac: 0x09b3, 0x7ad: 0x0ffb, 0x7ae: 0x1263, 0x7af: 0x133b,
+ 0x7b0: 0x0db7, 0x7b1: 0x13f7, 0x7b2: 0x0de3, 0x7b3: 0x0c37, 0x7b4: 0x121b, 0x7b5: 0x0c57,
+ 0x7b6: 0x0fab, 0x7b7: 0x072b, 0x7b8: 0x07a7, 0x7b9: 0x07eb, 0x7ba: 0x0d53, 0x7bb: 0x10fb,
+ 0x7bc: 0x11f3, 0x7bd: 0x1347, 0x7be: 0x145b, 0x7bf: 0x085b,
+ // Block 0x1f, offset 0x7c0
+ 0x7c0: 0x090f, 0x7c1: 0x0a17, 0x7c2: 0x0b2f, 0x7c3: 0x0cbf, 0x7c4: 0x0e7b, 0x7c5: 0x103f,
+ 0x7c6: 0x1497, 0x7c7: 0x157b, 0x7c8: 0x15cf, 0x7c9: 0x15e7, 0x7ca: 0x0837, 0x7cb: 0x0cf3,
+ 0x7cc: 0x0da3, 0x7cd: 0x13eb, 0x7ce: 0x0afb, 0x7cf: 0x0bd7, 0x7d0: 0x0bf3, 0x7d1: 0x0c83,
+ 0x7d2: 0x0e6b, 0x7d3: 0x0eb7, 0x7d4: 0x0f67, 0x7d5: 0x108b, 0x7d6: 0x112f, 0x7d7: 0x1193,
+ 0x7d8: 0x13db, 0x7d9: 0x126b, 0x7da: 0x1403, 0x7db: 0x147f, 0x7dc: 0x080f, 0x7dd: 0x083b,
+ 0x7de: 0x0923, 0x7df: 0x0ea7, 0x7e0: 0x12f3, 0x7e1: 0x133b, 0x7e2: 0x0b1b, 0x7e3: 0x0b8b,
+ 0x7e4: 0x0c4f, 0x7e5: 0x0daf, 0x7e6: 0x10d7, 0x7e7: 0x0f23, 0x7e8: 0x073b, 0x7e9: 0x097f,
+ 0x7ea: 0x0a63, 0x7eb: 0x0ac7, 0x7ec: 0x0b97, 0x7ed: 0x0f3f, 0x7ee: 0x0f5b, 0x7ef: 0x116b,
+ 0x7f0: 0x118b, 0x7f1: 0x1463, 0x7f2: 0x14e3, 0x7f3: 0x14f3, 0x7f4: 0x152f, 0x7f5: 0x0753,
+ 0x7f6: 0x107f, 0x7f7: 0x144f, 0x7f8: 0x14cb, 0x7f9: 0x0baf, 0x7fa: 0x0717, 0x7fb: 0x0777,
+ 0x7fc: 0x0a67, 0x7fd: 0x0a87, 0x7fe: 0x0caf, 0x7ff: 0x0d73,
+ // Block 0x20, offset 0x800
+ 0x800: 0x0ec3, 0x801: 0x0fcb, 0x802: 0x1277, 0x803: 0x1417, 0x804: 0x1623, 0x805: 0x0ce3,
+ 0x806: 0x14a3, 0x807: 0x0833, 0x808: 0x0d2f, 0x809: 0x0d3b, 0x80a: 0x0e0f, 0x80b: 0x0e47,
+ 0x80c: 0x0f4b, 0x80d: 0x0fa7, 0x80e: 0x1027, 0x80f: 0x110b, 0x810: 0x153b, 0x811: 0x07af,
+ 0x812: 0x0c03, 0x813: 0x14b3, 0x814: 0x0767, 0x815: 0x0aab, 0x816: 0x0e2f, 0x817: 0x13df,
+ 0x818: 0x0b67, 0x819: 0x0bb7, 0x81a: 0x0d43, 0x81b: 0x0f2f, 0x81c: 0x14bb, 0x81d: 0x0817,
+ 0x81e: 0x08ff, 0x81f: 0x0a97, 0x820: 0x0cd3, 0x821: 0x0d1f, 0x822: 0x0d5f, 0x823: 0x0df3,
+ 0x824: 0x0f47, 0x825: 0x0fbb, 0x826: 0x1157, 0x827: 0x12f7, 0x828: 0x1303, 0x829: 0x1457,
+ 0x82a: 0x14d7, 0x82b: 0x0883, 0x82c: 0x0e4b, 0x82d: 0x0903, 0x82e: 0x0ec7, 0x82f: 0x0f6b,
+ 0x830: 0x1287, 0x831: 0x14bf, 0x832: 0x15ab, 0x833: 0x15d3, 0x834: 0x0d37, 0x835: 0x0e27,
+ 0x836: 0x11c3, 0x837: 0x10b7, 0x838: 0x10c3, 0x839: 0x10e7, 0x83a: 0x0f17, 0x83b: 0x0e9f,
+ 0x83c: 0x1363, 0x83d: 0x0733, 0x83e: 0x122b, 0x83f: 0x081b,
+ // Block 0x21, offset 0x840
+ 0x840: 0x080b, 0x841: 0x0b0b, 0x842: 0x0c2b, 0x843: 0x10f3, 0x844: 0x0a53, 0x845: 0x0e03,
+ 0x846: 0x0cef, 0x847: 0x13e7, 0x848: 0x12e7, 0x849: 0x14ab, 0x84a: 0x1323, 0x84b: 0x0b27,
+ 0x84c: 0x0787, 0x84d: 0x095b, 0x850: 0x09af,
+ 0x852: 0x0cdf, 0x855: 0x07f7, 0x856: 0x0f1f, 0x857: 0x0fe3,
+ 0x858: 0x1047, 0x859: 0x1063, 0x85a: 0x1067, 0x85b: 0x107b, 0x85c: 0x14fb, 0x85d: 0x10eb,
+ 0x85e: 0x116f, 0x860: 0x128f, 0x862: 0x1353,
+ 0x865: 0x1407, 0x866: 0x1433,
+ 0x86a: 0x154f, 0x86b: 0x1553, 0x86c: 0x1557, 0x86d: 0x15bb, 0x86e: 0x142b, 0x86f: 0x14c7,
+ 0x870: 0x0757, 0x871: 0x077b, 0x872: 0x078f, 0x873: 0x084b, 0x874: 0x0857, 0x875: 0x0897,
+ 0x876: 0x094b, 0x877: 0x0967, 0x878: 0x096f, 0x879: 0x09ab, 0x87a: 0x09b7, 0x87b: 0x0a93,
+ 0x87c: 0x0a9b, 0x87d: 0x0ba3, 0x87e: 0x0bcb, 0x87f: 0x0bd3,
+ // Block 0x22, offset 0x880
+ 0x880: 0x0beb, 0x881: 0x0c97, 0x882: 0x0cc7, 0x883: 0x0ce7, 0x884: 0x0d57, 0x885: 0x0e1b,
+ 0x886: 0x0e37, 0x887: 0x0e67, 0x888: 0x0ebb, 0x889: 0x0edb, 0x88a: 0x0f4f, 0x88b: 0x102f,
+ 0x88c: 0x104b, 0x88d: 0x1053, 0x88e: 0x104f, 0x88f: 0x1057, 0x890: 0x105b, 0x891: 0x105f,
+ 0x892: 0x1073, 0x893: 0x1077, 0x894: 0x109b, 0x895: 0x10af, 0x896: 0x10cb, 0x897: 0x112f,
+ 0x898: 0x1137, 0x899: 0x113f, 0x89a: 0x1153, 0x89b: 0x117b, 0x89c: 0x11cb, 0x89d: 0x11ff,
+ 0x89e: 0x11ff, 0x89f: 0x1267, 0x8a0: 0x130f, 0x8a1: 0x1327, 0x8a2: 0x135b, 0x8a3: 0x135f,
+ 0x8a4: 0x13a3, 0x8a5: 0x13a7, 0x8a6: 0x13ff, 0x8a7: 0x1407, 0x8a8: 0x14db, 0x8a9: 0x151f,
+ 0x8aa: 0x1537, 0x8ab: 0x0b9b, 0x8ac: 0x171e, 0x8ad: 0x11e3,
+ 0x8b0: 0x06df, 0x8b1: 0x07e3, 0x8b2: 0x07a3, 0x8b3: 0x074b, 0x8b4: 0x078b, 0x8b5: 0x07b7,
+ 0x8b6: 0x0847, 0x8b7: 0x0863, 0x8b8: 0x094b, 0x8b9: 0x0937, 0x8ba: 0x0947, 0x8bb: 0x0963,
+ 0x8bc: 0x09af, 0x8bd: 0x09bf, 0x8be: 0x0a03, 0x8bf: 0x0a0f,
+ // Block 0x23, offset 0x8c0
+ 0x8c0: 0x0a2b, 0x8c1: 0x0a3b, 0x8c2: 0x0b23, 0x8c3: 0x0b2b, 0x8c4: 0x0b5b, 0x8c5: 0x0b7b,
+ 0x8c6: 0x0bab, 0x8c7: 0x0bc3, 0x8c8: 0x0bb3, 0x8c9: 0x0bd3, 0x8ca: 0x0bc7, 0x8cb: 0x0beb,
+ 0x8cc: 0x0c07, 0x8cd: 0x0c5f, 0x8ce: 0x0c6b, 0x8cf: 0x0c73, 0x8d0: 0x0c9b, 0x8d1: 0x0cdf,
+ 0x8d2: 0x0d0f, 0x8d3: 0x0d13, 0x8d4: 0x0d27, 0x8d5: 0x0da7, 0x8d6: 0x0db7, 0x8d7: 0x0e0f,
+ 0x8d8: 0x0e5b, 0x8d9: 0x0e53, 0x8da: 0x0e67, 0x8db: 0x0e83, 0x8dc: 0x0ebb, 0x8dd: 0x1013,
+ 0x8de: 0x0edf, 0x8df: 0x0f13, 0x8e0: 0x0f1f, 0x8e1: 0x0f5f, 0x8e2: 0x0f7b, 0x8e3: 0x0f9f,
+ 0x8e4: 0x0fc3, 0x8e5: 0x0fc7, 0x8e6: 0x0fe3, 0x8e7: 0x0fe7, 0x8e8: 0x0ff7, 0x8e9: 0x100b,
+ 0x8ea: 0x1007, 0x8eb: 0x1037, 0x8ec: 0x10b3, 0x8ed: 0x10cb, 0x8ee: 0x10e3, 0x8ef: 0x111b,
+ 0x8f0: 0x112f, 0x8f1: 0x114b, 0x8f2: 0x117b, 0x8f3: 0x122f, 0x8f4: 0x1257, 0x8f5: 0x12cb,
+ 0x8f6: 0x1313, 0x8f7: 0x131f, 0x8f8: 0x1327, 0x8f9: 0x133f, 0x8fa: 0x1353, 0x8fb: 0x1343,
+ 0x8fc: 0x135b, 0x8fd: 0x1357, 0x8fe: 0x134f, 0x8ff: 0x135f,
+ // Block 0x24, offset 0x900
+ 0x900: 0x136b, 0x901: 0x13a7, 0x902: 0x13e3, 0x903: 0x1413, 0x904: 0x144b, 0x905: 0x146b,
+ 0x906: 0x14b7, 0x907: 0x14db, 0x908: 0x14fb, 0x909: 0x150f, 0x90a: 0x151f, 0x90b: 0x152b,
+ 0x90c: 0x1537, 0x90d: 0x158b, 0x90e: 0x162b, 0x90f: 0x16b5, 0x910: 0x16b0, 0x911: 0x16e2,
+ 0x912: 0x0607, 0x913: 0x062f, 0x914: 0x0633, 0x915: 0x1764, 0x916: 0x1791, 0x917: 0x1809,
+ 0x918: 0x1617, 0x919: 0x1627,
+ // Block 0x25, offset 0x940
+ 0x940: 0x06fb, 0x941: 0x06f3, 0x942: 0x0703, 0x943: 0x1647, 0x944: 0x0747, 0x945: 0x0757,
+ 0x946: 0x075b, 0x947: 0x0763, 0x948: 0x076b, 0x949: 0x076f, 0x94a: 0x077b, 0x94b: 0x0773,
+ 0x94c: 0x05b3, 0x94d: 0x165b, 0x94e: 0x078f, 0x94f: 0x0793, 0x950: 0x0797, 0x951: 0x07b3,
+ 0x952: 0x164c, 0x953: 0x05b7, 0x954: 0x079f, 0x955: 0x07bf, 0x956: 0x1656, 0x957: 0x07cf,
+ 0x958: 0x07d7, 0x959: 0x0737, 0x95a: 0x07df, 0x95b: 0x07e3, 0x95c: 0x1831, 0x95d: 0x07ff,
+ 0x95e: 0x0807, 0x95f: 0x05bf, 0x960: 0x081f, 0x961: 0x0823, 0x962: 0x082b, 0x963: 0x082f,
+ 0x964: 0x05c3, 0x965: 0x0847, 0x966: 0x084b, 0x967: 0x0857, 0x968: 0x0863, 0x969: 0x0867,
+ 0x96a: 0x086b, 0x96b: 0x0873, 0x96c: 0x0893, 0x96d: 0x0897, 0x96e: 0x089f, 0x96f: 0x08af,
+ 0x970: 0x08b7, 0x971: 0x08bb, 0x972: 0x08bb, 0x973: 0x08bb, 0x974: 0x166a, 0x975: 0x0e93,
+ 0x976: 0x08cf, 0x977: 0x08d7, 0x978: 0x166f, 0x979: 0x08e3, 0x97a: 0x08eb, 0x97b: 0x08f3,
+ 0x97c: 0x091b, 0x97d: 0x0907, 0x97e: 0x0913, 0x97f: 0x0917,
+ // Block 0x26, offset 0x980
+ 0x980: 0x091f, 0x981: 0x0927, 0x982: 0x092b, 0x983: 0x0933, 0x984: 0x093b, 0x985: 0x093f,
+ 0x986: 0x093f, 0x987: 0x0947, 0x988: 0x094f, 0x989: 0x0953, 0x98a: 0x095f, 0x98b: 0x0983,
+ 0x98c: 0x0967, 0x98d: 0x0987, 0x98e: 0x096b, 0x98f: 0x0973, 0x990: 0x080b, 0x991: 0x09cf,
+ 0x992: 0x0997, 0x993: 0x099b, 0x994: 0x099f, 0x995: 0x0993, 0x996: 0x09a7, 0x997: 0x09a3,
+ 0x998: 0x09bb, 0x999: 0x1674, 0x99a: 0x09d7, 0x99b: 0x09db, 0x99c: 0x09e3, 0x99d: 0x09ef,
+ 0x99e: 0x09f7, 0x99f: 0x0a13, 0x9a0: 0x1679, 0x9a1: 0x167e, 0x9a2: 0x0a1f, 0x9a3: 0x0a23,
+ 0x9a4: 0x0a27, 0x9a5: 0x0a1b, 0x9a6: 0x0a2f, 0x9a7: 0x05c7, 0x9a8: 0x05cb, 0x9a9: 0x0a37,
+ 0x9aa: 0x0a3f, 0x9ab: 0x0a3f, 0x9ac: 0x1683, 0x9ad: 0x0a5b, 0x9ae: 0x0a5f, 0x9af: 0x0a63,
+ 0x9b0: 0x0a6b, 0x9b1: 0x1688, 0x9b2: 0x0a73, 0x9b3: 0x0a77, 0x9b4: 0x0b4f, 0x9b5: 0x0a7f,
+ 0x9b6: 0x05cf, 0x9b7: 0x0a8b, 0x9b8: 0x0a9b, 0x9b9: 0x0aa7, 0x9ba: 0x0aa3, 0x9bb: 0x1692,
+ 0x9bc: 0x0aaf, 0x9bd: 0x1697, 0x9be: 0x0abb, 0x9bf: 0x0ab7,
+ // Block 0x27, offset 0x9c0
+ 0x9c0: 0x0abf, 0x9c1: 0x0acf, 0x9c2: 0x0ad3, 0x9c3: 0x05d3, 0x9c4: 0x0ae3, 0x9c5: 0x0aeb,
+ 0x9c6: 0x0aef, 0x9c7: 0x0af3, 0x9c8: 0x05d7, 0x9c9: 0x169c, 0x9ca: 0x05db, 0x9cb: 0x0b0f,
+ 0x9cc: 0x0b13, 0x9cd: 0x0b17, 0x9ce: 0x0b1f, 0x9cf: 0x1863, 0x9d0: 0x0b37, 0x9d1: 0x16a6,
+ 0x9d2: 0x16a6, 0x9d3: 0x11d7, 0x9d4: 0x0b47, 0x9d5: 0x0b47, 0x9d6: 0x05df, 0x9d7: 0x16c9,
+ 0x9d8: 0x179b, 0x9d9: 0x0b57, 0x9da: 0x0b5f, 0x9db: 0x05e3, 0x9dc: 0x0b73, 0x9dd: 0x0b83,
+ 0x9de: 0x0b87, 0x9df: 0x0b8f, 0x9e0: 0x0b9f, 0x9e1: 0x05eb, 0x9e2: 0x05e7, 0x9e3: 0x0ba3,
+ 0x9e4: 0x16ab, 0x9e5: 0x0ba7, 0x9e6: 0x0bbb, 0x9e7: 0x0bbf, 0x9e8: 0x0bc3, 0x9e9: 0x0bbf,
+ 0x9ea: 0x0bcf, 0x9eb: 0x0bd3, 0x9ec: 0x0be3, 0x9ed: 0x0bdb, 0x9ee: 0x0bdf, 0x9ef: 0x0be7,
+ 0x9f0: 0x0beb, 0x9f1: 0x0bef, 0x9f2: 0x0bfb, 0x9f3: 0x0bff, 0x9f4: 0x0c17, 0x9f5: 0x0c1f,
+ 0x9f6: 0x0c2f, 0x9f7: 0x0c43, 0x9f8: 0x16ba, 0x9f9: 0x0c3f, 0x9fa: 0x0c33, 0x9fb: 0x0c4b,
+ 0x9fc: 0x0c53, 0x9fd: 0x0c67, 0x9fe: 0x16bf, 0x9ff: 0x0c6f,
+ // Block 0x28, offset 0xa00
+ 0xa00: 0x0c63, 0xa01: 0x0c5b, 0xa02: 0x05ef, 0xa03: 0x0c77, 0xa04: 0x0c7f, 0xa05: 0x0c87,
+ 0xa06: 0x0c7b, 0xa07: 0x05f3, 0xa08: 0x0c97, 0xa09: 0x0c9f, 0xa0a: 0x16c4, 0xa0b: 0x0ccb,
+ 0xa0c: 0x0cff, 0xa0d: 0x0cdb, 0xa0e: 0x05ff, 0xa0f: 0x0ce7, 0xa10: 0x05fb, 0xa11: 0x05f7,
+ 0xa12: 0x07c3, 0xa13: 0x07c7, 0xa14: 0x0d03, 0xa15: 0x0ceb, 0xa16: 0x11ab, 0xa17: 0x0663,
+ 0xa18: 0x0d0f, 0xa19: 0x0d13, 0xa1a: 0x0d17, 0xa1b: 0x0d2b, 0xa1c: 0x0d23, 0xa1d: 0x16dd,
+ 0xa1e: 0x0603, 0xa1f: 0x0d3f, 0xa20: 0x0d33, 0xa21: 0x0d4f, 0xa22: 0x0d57, 0xa23: 0x16e7,
+ 0xa24: 0x0d5b, 0xa25: 0x0d47, 0xa26: 0x0d63, 0xa27: 0x0607, 0xa28: 0x0d67, 0xa29: 0x0d6b,
+ 0xa2a: 0x0d6f, 0xa2b: 0x0d7b, 0xa2c: 0x16ec, 0xa2d: 0x0d83, 0xa2e: 0x060b, 0xa2f: 0x0d8f,
+ 0xa30: 0x16f1, 0xa31: 0x0d93, 0xa32: 0x060f, 0xa33: 0x0d9f, 0xa34: 0x0dab, 0xa35: 0x0db7,
+ 0xa36: 0x0dbb, 0xa37: 0x16f6, 0xa38: 0x168d, 0xa39: 0x16fb, 0xa3a: 0x0ddb, 0xa3b: 0x1700,
+ 0xa3c: 0x0de7, 0xa3d: 0x0def, 0xa3e: 0x0ddf, 0xa3f: 0x0dfb,
+ // Block 0x29, offset 0xa40
+ 0xa40: 0x0e0b, 0xa41: 0x0e1b, 0xa42: 0x0e0f, 0xa43: 0x0e13, 0xa44: 0x0e1f, 0xa45: 0x0e23,
+ 0xa46: 0x1705, 0xa47: 0x0e07, 0xa48: 0x0e3b, 0xa49: 0x0e3f, 0xa4a: 0x0613, 0xa4b: 0x0e53,
+ 0xa4c: 0x0e4f, 0xa4d: 0x170a, 0xa4e: 0x0e33, 0xa4f: 0x0e6f, 0xa50: 0x170f, 0xa51: 0x1714,
+ 0xa52: 0x0e73, 0xa53: 0x0e87, 0xa54: 0x0e83, 0xa55: 0x0e7f, 0xa56: 0x0617, 0xa57: 0x0e8b,
+ 0xa58: 0x0e9b, 0xa59: 0x0e97, 0xa5a: 0x0ea3, 0xa5b: 0x1651, 0xa5c: 0x0eb3, 0xa5d: 0x1719,
+ 0xa5e: 0x0ebf, 0xa5f: 0x1723, 0xa60: 0x0ed3, 0xa61: 0x0edf, 0xa62: 0x0ef3, 0xa63: 0x1728,
+ 0xa64: 0x0f07, 0xa65: 0x0f0b, 0xa66: 0x172d, 0xa67: 0x1732, 0xa68: 0x0f27, 0xa69: 0x0f37,
+ 0xa6a: 0x061b, 0xa6b: 0x0f3b, 0xa6c: 0x061f, 0xa6d: 0x061f, 0xa6e: 0x0f53, 0xa6f: 0x0f57,
+ 0xa70: 0x0f5f, 0xa71: 0x0f63, 0xa72: 0x0f6f, 0xa73: 0x0623, 0xa74: 0x0f87, 0xa75: 0x1737,
+ 0xa76: 0x0fa3, 0xa77: 0x173c, 0xa78: 0x0faf, 0xa79: 0x16a1, 0xa7a: 0x0fbf, 0xa7b: 0x1741,
+ 0xa7c: 0x1746, 0xa7d: 0x174b, 0xa7e: 0x0627, 0xa7f: 0x062b,
+ // Block 0x2a, offset 0xa80
+ 0xa80: 0x0ff7, 0xa81: 0x1755, 0xa82: 0x1750, 0xa83: 0x175a, 0xa84: 0x175f, 0xa85: 0x0fff,
+ 0xa86: 0x1003, 0xa87: 0x1003, 0xa88: 0x100b, 0xa89: 0x0633, 0xa8a: 0x100f, 0xa8b: 0x0637,
+ 0xa8c: 0x063b, 0xa8d: 0x1769, 0xa8e: 0x1023, 0xa8f: 0x102b, 0xa90: 0x1037, 0xa91: 0x063f,
+ 0xa92: 0x176e, 0xa93: 0x105b, 0xa94: 0x1773, 0xa95: 0x1778, 0xa96: 0x107b, 0xa97: 0x1093,
+ 0xa98: 0x0643, 0xa99: 0x109b, 0xa9a: 0x109f, 0xa9b: 0x10a3, 0xa9c: 0x177d, 0xa9d: 0x1782,
+ 0xa9e: 0x1782, 0xa9f: 0x10bb, 0xaa0: 0x0647, 0xaa1: 0x1787, 0xaa2: 0x10cf, 0xaa3: 0x10d3,
+ 0xaa4: 0x064b, 0xaa5: 0x178c, 0xaa6: 0x10ef, 0xaa7: 0x064f, 0xaa8: 0x10ff, 0xaa9: 0x10f7,
+ 0xaaa: 0x1107, 0xaab: 0x1796, 0xaac: 0x111f, 0xaad: 0x0653, 0xaae: 0x112b, 0xaaf: 0x1133,
+ 0xab0: 0x1143, 0xab1: 0x0657, 0xab2: 0x17a0, 0xab3: 0x17a5, 0xab4: 0x065b, 0xab5: 0x17aa,
+ 0xab6: 0x115b, 0xab7: 0x17af, 0xab8: 0x1167, 0xab9: 0x1173, 0xaba: 0x117b, 0xabb: 0x17b4,
+ 0xabc: 0x17b9, 0xabd: 0x118f, 0xabe: 0x17be, 0xabf: 0x1197,
+ // Block 0x2b, offset 0xac0
+ 0xac0: 0x16ce, 0xac1: 0x065f, 0xac2: 0x11af, 0xac3: 0x11b3, 0xac4: 0x0667, 0xac5: 0x11b7,
+ 0xac6: 0x0a33, 0xac7: 0x17c3, 0xac8: 0x17c8, 0xac9: 0x16d3, 0xaca: 0x16d8, 0xacb: 0x11d7,
+ 0xacc: 0x11db, 0xacd: 0x13f3, 0xace: 0x066b, 0xacf: 0x1207, 0xad0: 0x1203, 0xad1: 0x120b,
+ 0xad2: 0x083f, 0xad3: 0x120f, 0xad4: 0x1213, 0xad5: 0x1217, 0xad6: 0x121f, 0xad7: 0x17cd,
+ 0xad8: 0x121b, 0xad9: 0x1223, 0xada: 0x1237, 0xadb: 0x123b, 0xadc: 0x1227, 0xadd: 0x123f,
+ 0xade: 0x1253, 0xadf: 0x1267, 0xae0: 0x1233, 0xae1: 0x1247, 0xae2: 0x124b, 0xae3: 0x124f,
+ 0xae4: 0x17d2, 0xae5: 0x17dc, 0xae6: 0x17d7, 0xae7: 0x066f, 0xae8: 0x126f, 0xae9: 0x1273,
+ 0xaea: 0x127b, 0xaeb: 0x17f0, 0xaec: 0x127f, 0xaed: 0x17e1, 0xaee: 0x0673, 0xaef: 0x0677,
+ 0xaf0: 0x17e6, 0xaf1: 0x17eb, 0xaf2: 0x067b, 0xaf3: 0x129f, 0xaf4: 0x12a3, 0xaf5: 0x12a7,
+ 0xaf6: 0x12ab, 0xaf7: 0x12b7, 0xaf8: 0x12b3, 0xaf9: 0x12bf, 0xafa: 0x12bb, 0xafb: 0x12cb,
+ 0xafc: 0x12c3, 0xafd: 0x12c7, 0xafe: 0x12cf, 0xaff: 0x067f,
+ // Block 0x2c, offset 0xb00
+ 0xb00: 0x12d7, 0xb01: 0x12db, 0xb02: 0x0683, 0xb03: 0x12eb, 0xb04: 0x12ef, 0xb05: 0x17f5,
+ 0xb06: 0x12fb, 0xb07: 0x12ff, 0xb08: 0x0687, 0xb09: 0x130b, 0xb0a: 0x05bb, 0xb0b: 0x17fa,
+ 0xb0c: 0x17ff, 0xb0d: 0x068b, 0xb0e: 0x068f, 0xb0f: 0x1337, 0xb10: 0x134f, 0xb11: 0x136b,
+ 0xb12: 0x137b, 0xb13: 0x1804, 0xb14: 0x138f, 0xb15: 0x1393, 0xb16: 0x13ab, 0xb17: 0x13b7,
+ 0xb18: 0x180e, 0xb19: 0x1660, 0xb1a: 0x13c3, 0xb1b: 0x13bf, 0xb1c: 0x13cb, 0xb1d: 0x1665,
+ 0xb1e: 0x13d7, 0xb1f: 0x13e3, 0xb20: 0x1813, 0xb21: 0x1818, 0xb22: 0x1423, 0xb23: 0x142f,
+ 0xb24: 0x1437, 0xb25: 0x181d, 0xb26: 0x143b, 0xb27: 0x1467, 0xb28: 0x1473, 0xb29: 0x1477,
+ 0xb2a: 0x146f, 0xb2b: 0x1483, 0xb2c: 0x1487, 0xb2d: 0x1822, 0xb2e: 0x1493, 0xb2f: 0x0693,
+ 0xb30: 0x149b, 0xb31: 0x1827, 0xb32: 0x0697, 0xb33: 0x14d3, 0xb34: 0x0ac3, 0xb35: 0x14eb,
+ 0xb36: 0x182c, 0xb37: 0x1836, 0xb38: 0x069b, 0xb39: 0x069f, 0xb3a: 0x1513, 0xb3b: 0x183b,
+ 0xb3c: 0x06a3, 0xb3d: 0x1840, 0xb3e: 0x152b, 0xb3f: 0x152b,
+ // Block 0x2d, offset 0xb40
+ 0xb40: 0x1533, 0xb41: 0x1845, 0xb42: 0x154b, 0xb43: 0x06a7, 0xb44: 0x155b, 0xb45: 0x1567,
+ 0xb46: 0x156f, 0xb47: 0x1577, 0xb48: 0x06ab, 0xb49: 0x184a, 0xb4a: 0x158b, 0xb4b: 0x15a7,
+ 0xb4c: 0x15b3, 0xb4d: 0x06af, 0xb4e: 0x06b3, 0xb4f: 0x15b7, 0xb50: 0x184f, 0xb51: 0x06b7,
+ 0xb52: 0x1854, 0xb53: 0x1859, 0xb54: 0x185e, 0xb55: 0x15db, 0xb56: 0x06bb, 0xb57: 0x15ef,
+ 0xb58: 0x15f7, 0xb59: 0x15fb, 0xb5a: 0x1603, 0xb5b: 0x160b, 0xb5c: 0x1613, 0xb5d: 0x1868,
+}
+
+// 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, 0x1c4: 0x76, 0x1c5: 0x77,
+ 0x1c9: 0x78, 0x1cc: 0x79, 0x1cd: 0x7a,
+ // Block 0x8, offset 0x200
+ 0x219: 0x7b, 0x21a: 0x7c, 0x21b: 0x7d,
+ 0x220: 0x7e, 0x223: 0x7f, 0x224: 0x80, 0x225: 0x81, 0x226: 0x82, 0x227: 0x83,
+ 0x22a: 0x84, 0x22b: 0x85, 0x22f: 0x86,
+ 0x230: 0x87, 0x231: 0x88, 0x232: 0x89, 0x233: 0x8a, 0x234: 0x8b, 0x235: 0x8c, 0x236: 0x8d, 0x237: 0x87,
+ 0x238: 0x88, 0x239: 0x89, 0x23a: 0x8a, 0x23b: 0x8b, 0x23c: 0x8c, 0x23d: 0x8d, 0x23e: 0x87, 0x23f: 0x88,
+ // Block 0x9, offset 0x240
+ 0x240: 0x89, 0x241: 0x8a, 0x242: 0x8b, 0x243: 0x8c, 0x244: 0x8d, 0x245: 0x87, 0x246: 0x88, 0x247: 0x89,
+ 0x248: 0x8a, 0x249: 0x8b, 0x24a: 0x8c, 0x24b: 0x8d, 0x24c: 0x87, 0x24d: 0x88, 0x24e: 0x89, 0x24f: 0x8a,
+ 0x250: 0x8b, 0x251: 0x8c, 0x252: 0x8d, 0x253: 0x87, 0x254: 0x88, 0x255: 0x89, 0x256: 0x8a, 0x257: 0x8b,
+ 0x258: 0x8c, 0x259: 0x8d, 0x25a: 0x87, 0x25b: 0x88, 0x25c: 0x89, 0x25d: 0x8a, 0x25e: 0x8b, 0x25f: 0x8c,
+ 0x260: 0x8d, 0x261: 0x87, 0x262: 0x88, 0x263: 0x89, 0x264: 0x8a, 0x265: 0x8b, 0x266: 0x8c, 0x267: 0x8d,
+ 0x268: 0x87, 0x269: 0x88, 0x26a: 0x89, 0x26b: 0x8a, 0x26c: 0x8b, 0x26d: 0x8c, 0x26e: 0x8d, 0x26f: 0x87,
+ 0x270: 0x88, 0x271: 0x89, 0x272: 0x8a, 0x273: 0x8b, 0x274: 0x8c, 0x275: 0x8d, 0x276: 0x87, 0x277: 0x88,
+ 0x278: 0x89, 0x279: 0x8a, 0x27a: 0x8b, 0x27b: 0x8c, 0x27c: 0x8d, 0x27d: 0x87, 0x27e: 0x88, 0x27f: 0x89,
+ // Block 0xa, offset 0x280
+ 0x280: 0x8a, 0x281: 0x8b, 0x282: 0x8c, 0x283: 0x8d, 0x284: 0x87, 0x285: 0x88, 0x286: 0x89, 0x287: 0x8a,
+ 0x288: 0x8b, 0x289: 0x8c, 0x28a: 0x8d, 0x28b: 0x87, 0x28c: 0x88, 0x28d: 0x89, 0x28e: 0x8a, 0x28f: 0x8b,
+ 0x290: 0x8c, 0x291: 0x8d, 0x292: 0x87, 0x293: 0x88, 0x294: 0x89, 0x295: 0x8a, 0x296: 0x8b, 0x297: 0x8c,
+ 0x298: 0x8d, 0x299: 0x87, 0x29a: 0x88, 0x29b: 0x89, 0x29c: 0x8a, 0x29d: 0x8b, 0x29e: 0x8c, 0x29f: 0x8d,
+ 0x2a0: 0x87, 0x2a1: 0x88, 0x2a2: 0x89, 0x2a3: 0x8a, 0x2a4: 0x8b, 0x2a5: 0x8c, 0x2a6: 0x8d, 0x2a7: 0x87,
+ 0x2a8: 0x88, 0x2a9: 0x89, 0x2aa: 0x8a, 0x2ab: 0x8b, 0x2ac: 0x8c, 0x2ad: 0x8d, 0x2ae: 0x87, 0x2af: 0x88,
+ 0x2b0: 0x89, 0x2b1: 0x8a, 0x2b2: 0x8b, 0x2b3: 0x8c, 0x2b4: 0x8d, 0x2b5: 0x87, 0x2b6: 0x88, 0x2b7: 0x89,
+ 0x2b8: 0x8a, 0x2b9: 0x8b, 0x2ba: 0x8c, 0x2bb: 0x8d, 0x2bc: 0x87, 0x2bd: 0x88, 0x2be: 0x89, 0x2bf: 0x8a,
+ // Block 0xb, offset 0x2c0
+ 0x2c0: 0x8b, 0x2c1: 0x8c, 0x2c2: 0x8d, 0x2c3: 0x87, 0x2c4: 0x88, 0x2c5: 0x89, 0x2c6: 0x8a, 0x2c7: 0x8b,
+ 0x2c8: 0x8c, 0x2c9: 0x8d, 0x2ca: 0x87, 0x2cb: 0x88, 0x2cc: 0x89, 0x2cd: 0x8a, 0x2ce: 0x8b, 0x2cf: 0x8c,
+ 0x2d0: 0x8d, 0x2d1: 0x87, 0x2d2: 0x88, 0x2d3: 0x89, 0x2d4: 0x8a, 0x2d5: 0x8b, 0x2d6: 0x8c, 0x2d7: 0x8d,
+ 0x2d8: 0x87, 0x2d9: 0x88, 0x2da: 0x89, 0x2db: 0x8a, 0x2dc: 0x8b, 0x2dd: 0x8c, 0x2de: 0x8e,
+ // Block 0xc, offset 0x300
+ 0x324: 0x1b, 0x325: 0x1c, 0x326: 0x1d, 0x327: 0x1e,
+ 0x328: 0x1f, 0x329: 0x20, 0x32a: 0x21, 0x32b: 0x22, 0x32c: 0x8f, 0x32d: 0x90, 0x32e: 0x91,
+ 0x331: 0x92, 0x332: 0x93, 0x333: 0x94, 0x334: 0x95,
+ 0x338: 0x96, 0x339: 0x97, 0x33a: 0x98, 0x33b: 0x99, 0x33e: 0x9a, 0x33f: 0x9b,
+ // Block 0xd, offset 0x340
+ 0x347: 0x9c,
+ 0x34b: 0x9d, 0x34d: 0x9e,
+ 0x368: 0x9f, 0x36b: 0xa0,
+ // Block 0xe, offset 0x380
+ 0x381: 0xa1, 0x382: 0xa2, 0x384: 0xa3, 0x385: 0x82, 0x387: 0xa4,
+ 0x388: 0xa5, 0x38b: 0xa6, 0x38c: 0x3e, 0x38d: 0xa7,
+ 0x391: 0xa8, 0x392: 0xa9, 0x393: 0xaa, 0x396: 0xab, 0x397: 0xac,
+ 0x398: 0x73, 0x39a: 0xad, 0x39c: 0xae,
+ 0x3b0: 0x73,
+ // Block 0xf, offset 0x3c0
+ 0x3eb: 0xaf, 0x3ec: 0xb0,
+ // Block 0x10, offset 0x400
+ 0x432: 0xb1,
+ // Block 0x11, offset 0x440
+ 0x445: 0xb2, 0x446: 0xb3, 0x447: 0xb4,
+ 0x449: 0xb5,
+ // Block 0x12, offset 0x480
+ 0x480: 0xb6,
+ 0x4a3: 0xb7, 0x4a5: 0xb8,
+ // Block 0x13, offset 0x4c0
+ 0x4c8: 0xb9,
+ // 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: 142 entries, 284 bytes
+var nfcSparseOffset = []uint16{0x0, 0x5, 0x9, 0xb, 0xd, 0x18, 0x28, 0x2a, 0x2f, 0x3a, 0x49, 0x56, 0x5e, 0x62, 0x67, 0x69, 0x7a, 0x82, 0x89, 0x8c, 0x93, 0x97, 0x9b, 0x9d, 0x9f, 0xa8, 0xac, 0xb3, 0xb8, 0xbb, 0xc5, 0xc7, 0xce, 0xd6, 0xd9, 0xdb, 0xdd, 0xdf, 0xe4, 0xf5, 0x101, 0x103, 0x109, 0x10b, 0x10d, 0x10f, 0x111, 0x113, 0x115, 0x118, 0x11b, 0x11d, 0x120, 0x123, 0x127, 0x12c, 0x135, 0x137, 0x13a, 0x13c, 0x147, 0x157, 0x15b, 0x169, 0x16c, 0x172, 0x178, 0x183, 0x187, 0x189, 0x18b, 0x18d, 0x18f, 0x191, 0x197, 0x19b, 0x19d, 0x19f, 0x1a7, 0x1ab, 0x1ae, 0x1b0, 0x1b2, 0x1b4, 0x1b7, 0x1b9, 0x1bb, 0x1bd, 0x1bf, 0x1c5, 0x1c8, 0x1ca, 0x1d1, 0x1d7, 0x1dd, 0x1e5, 0x1eb, 0x1f1, 0x1f7, 0x1fb, 0x209, 0x212, 0x215, 0x218, 0x21a, 0x21d, 0x21f, 0x223, 0x228, 0x22a, 0x22c, 0x231, 0x237, 0x239, 0x23b, 0x23d, 0x243, 0x246, 0x249, 0x251, 0x258, 0x25b, 0x25e, 0x260, 0x268, 0x26b, 0x272, 0x275, 0x27b, 0x27d, 0x280, 0x282, 0x284, 0x286, 0x288, 0x295, 0x29f, 0x2a1, 0x2a3, 0x2a9, 0x2ab, 0x2ae}
+
+// nfcSparseValues: 688 entries, 2752 bytes
+var nfcSparseValues = [688]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: 0x4778, lo: 0xa0, hi: 0xa1},
+ {value: 0x47aa, 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: 0x48d6, lo: 0x8a, hi: 0x8a},
+ {value: 0x48f4, lo: 0x8b, hi: 0x8b},
+ {value: 0x36c7, lo: 0x8c, hi: 0x8c},
+ {value: 0x36df, lo: 0x8d, hi: 0x8d},
+ {value: 0x490c, lo: 0x8e, hi: 0x8e},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0x36fd, 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: 0x37a5, lo: 0x90, hi: 0x90},
+ {value: 0x37b1, lo: 0x91, hi: 0x91},
+ {value: 0x379f, lo: 0x93, hi: 0x93},
+ {value: 0xa000, lo: 0x96, hi: 0x96},
+ {value: 0x3817, lo: 0x97, hi: 0x97},
+ {value: 0x37e1, lo: 0x9c, hi: 0x9c},
+ {value: 0x37c9, lo: 0x9d, hi: 0x9d},
+ {value: 0x37f3, lo: 0x9e, hi: 0x9e},
+ {value: 0xa000, lo: 0xb4, hi: 0xb5},
+ {value: 0x381d, lo: 0xb6, hi: 0xb6},
+ {value: 0x3823, 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: 0x3841, lo: 0xa2, hi: 0xa2},
+ {value: 0x3847, lo: 0xa3, hi: 0xa3},
+ {value: 0x3853, lo: 0xa4, hi: 0xa4},
+ {value: 0x384d, lo: 0xa5, hi: 0xa5},
+ {value: 0x3859, lo: 0xa6, hi: 0xa6},
+ {value: 0xa000, lo: 0xa7, hi: 0xa7},
+ // Block 0x9, offset 0x3a
+ {value: 0x0000, lo: 0x0e},
+ {value: 0x386b, lo: 0x80, hi: 0x80},
+ {value: 0xa000, lo: 0x81, hi: 0x81},
+ {value: 0x385f, lo: 0x82, hi: 0x82},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0x3865, 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: 0x10},
+ {value: 0x8132, lo: 0x94, hi: 0xa1},
+ {value: 0x812d, lo: 0xa3, hi: 0xa3},
+ {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 0x7a
+ {value: 0x0000, lo: 0x07},
+ {value: 0xa000, lo: 0xa8, hi: 0xa8},
+ {value: 0x3ed8, lo: 0xa9, hi: 0xa9},
+ {value: 0xa000, lo: 0xb0, hi: 0xb0},
+ {value: 0x3ee0, lo: 0xb1, hi: 0xb1},
+ {value: 0xa000, lo: 0xb3, hi: 0xb3},
+ {value: 0x3ee8, lo: 0xb4, hi: 0xb4},
+ {value: 0x9902, lo: 0xbc, hi: 0xbc},
+ // Block 0x11, offset 0x82
+ {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: 0x45b2, lo: 0x98, hi: 0x9f},
+ // Block 0x12, offset 0x89
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ {value: 0x9900, lo: 0xbe, hi: 0xbe},
+ // Block 0x13, offset 0x8c
+ {value: 0x0008, lo: 0x06},
+ {value: 0xa000, lo: 0x87, hi: 0x87},
+ {value: 0x2c9e, lo: 0x8b, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x97, hi: 0x97},
+ {value: 0x45f2, lo: 0x9c, hi: 0x9d},
+ {value: 0x4602, lo: 0x9f, hi: 0x9f},
+ // Block 0x14, offset 0x93
+ {value: 0x0000, lo: 0x03},
+ {value: 0x462a, lo: 0xb3, hi: 0xb3},
+ {value: 0x4632, lo: 0xb6, hi: 0xb6},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ // Block 0x15, offset 0x97
+ {value: 0x0008, lo: 0x03},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x460a, lo: 0x99, hi: 0x9b},
+ {value: 0x4622, lo: 0x9e, hi: 0x9e},
+ // Block 0x16, offset 0x9b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ // Block 0x17, offset 0x9d
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ // Block 0x18, offset 0x9f
+ {value: 0x0000, lo: 0x08},
+ {value: 0xa000, lo: 0x87, hi: 0x87},
+ {value: 0x2cb6, lo: 0x88, hi: 0x88},
+ {value: 0x2cae, lo: 0x8b, hi: 0x8b},
+ {value: 0x2cbe, lo: 0x8c, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x96, hi: 0x97},
+ {value: 0x463a, lo: 0x9c, hi: 0x9c},
+ {value: 0x4642, lo: 0x9d, hi: 0x9d},
+ // Block 0x19, offset 0xa8
+ {value: 0x0000, lo: 0x03},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0x2cc6, lo: 0x94, hi: 0x94},
+ {value: 0x9900, lo: 0xbe, hi: 0xbe},
+ // Block 0x1a, offset 0xac
+ {value: 0x0000, lo: 0x06},
+ {value: 0xa000, lo: 0x86, hi: 0x87},
+ {value: 0x2cce, lo: 0x8a, hi: 0x8a},
+ {value: 0x2cde, lo: 0x8b, hi: 0x8b},
+ {value: 0x2cd6, lo: 0x8c, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x97, hi: 0x97},
+ // Block 0x1b, offset 0xb3
+ {value: 0x1801, lo: 0x04},
+ {value: 0xa000, lo: 0x86, hi: 0x86},
+ {value: 0x3ef0, lo: 0x88, hi: 0x88},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x8120, lo: 0x95, hi: 0x96},
+ // Block 0x1c, offset 0xb8
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ {value: 0xa000, lo: 0xbf, hi: 0xbf},
+ // Block 0x1d, offset 0xbb
+ {value: 0x0000, lo: 0x09},
+ {value: 0x2ce6, lo: 0x80, hi: 0x80},
+ {value: 0x9900, lo: 0x82, hi: 0x82},
+ {value: 0xa000, lo: 0x86, hi: 0x86},
+ {value: 0x2cee, lo: 0x87, hi: 0x87},
+ {value: 0x2cf6, lo: 0x88, hi: 0x88},
+ {value: 0x2f50, lo: 0x8a, hi: 0x8a},
+ {value: 0x2dd8, lo: 0x8b, hi: 0x8b},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x95, hi: 0x96},
+ // Block 0x1e, offset 0xc5
+ {value: 0x0000, lo: 0x01},
+ {value: 0x9900, lo: 0xbe, hi: 0xbe},
+ // Block 0x1f, offset 0xc7
+ {value: 0x0000, lo: 0x06},
+ {value: 0xa000, lo: 0x86, hi: 0x87},
+ {value: 0x2cfe, lo: 0x8a, hi: 0x8a},
+ {value: 0x2d0e, lo: 0x8b, hi: 0x8b},
+ {value: 0x2d06, lo: 0x8c, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x97, hi: 0x97},
+ // Block 0x20, offset 0xce
+ {value: 0x6bea, lo: 0x07},
+ {value: 0x9904, lo: 0x8a, hi: 0x8a},
+ {value: 0x9900, lo: 0x8f, hi: 0x8f},
+ {value: 0xa000, lo: 0x99, hi: 0x99},
+ {value: 0x3ef8, lo: 0x9a, hi: 0x9a},
+ {value: 0x2f58, lo: 0x9c, hi: 0x9c},
+ {value: 0x2de3, lo: 0x9d, hi: 0x9d},
+ {value: 0x2d16, lo: 0x9e, hi: 0x9f},
+ // Block 0x21, offset 0xd6
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8122, lo: 0xb8, hi: 0xb9},
+ {value: 0x8104, lo: 0xba, hi: 0xba},
+ // Block 0x22, offset 0xd9
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8123, lo: 0x88, hi: 0x8b},
+ // Block 0x23, offset 0xdb
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8124, lo: 0xb8, hi: 0xb9},
+ // Block 0x24, offset 0xdd
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8125, lo: 0x88, hi: 0x8b},
+ // Block 0x25, offset 0xdf
+ {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 0xe4
+ {value: 0x0000, lo: 0x10},
+ {value: 0x2644, lo: 0x83, hi: 0x83},
+ {value: 0x264b, lo: 0x8d, hi: 0x8d},
+ {value: 0x2652, lo: 0x92, hi: 0x92},
+ {value: 0x2659, lo: 0x97, hi: 0x97},
+ {value: 0x2660, lo: 0x9c, hi: 0x9c},
+ {value: 0x263d, lo: 0xa9, hi: 0xa9},
+ {value: 0x8126, lo: 0xb1, hi: 0xb1},
+ {value: 0x8127, lo: 0xb2, hi: 0xb2},
+ {value: 0x4a66, lo: 0xb3, hi: 0xb3},
+ {value: 0x8128, lo: 0xb4, hi: 0xb4},
+ {value: 0x4a6f, lo: 0xb5, hi: 0xb5},
+ {value: 0x464a, lo: 0xb6, hi: 0xb6},
+ {value: 0x8200, lo: 0xb7, hi: 0xb7},
+ {value: 0x4652, lo: 0xb8, hi: 0xb8},
+ {value: 0x8200, lo: 0xb9, hi: 0xb9},
+ {value: 0x8127, lo: 0xba, hi: 0xbd},
+ // Block 0x27, offset 0xf5
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x8127, lo: 0x80, hi: 0x80},
+ {value: 0x4a78, lo: 0x81, hi: 0x81},
+ {value: 0x8132, lo: 0x82, hi: 0x83},
+ {value: 0x8104, lo: 0x84, hi: 0x84},
+ {value: 0x8132, lo: 0x86, hi: 0x87},
+ {value: 0x266e, lo: 0x93, hi: 0x93},
+ {value: 0x2675, lo: 0x9d, hi: 0x9d},
+ {value: 0x267c, lo: 0xa2, hi: 0xa2},
+ {value: 0x2683, lo: 0xa7, hi: 0xa7},
+ {value: 0x268a, lo: 0xac, hi: 0xac},
+ {value: 0x2667, lo: 0xb9, hi: 0xb9},
+ // Block 0x28, offset 0x101
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0x86, hi: 0x86},
+ // Block 0x29, offset 0x103
+ {value: 0x0000, lo: 0x05},
+ {value: 0xa000, lo: 0xa5, hi: 0xa5},
+ {value: 0x2d1e, 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 0x109
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0x8d, hi: 0x8d},
+ // Block 0x2b, offset 0x10b
+ {value: 0x0000, lo: 0x01},
+ {value: 0xa000, lo: 0x80, hi: 0x92},
+ // Block 0x2c, offset 0x10d
+ {value: 0x0000, lo: 0x01},
+ {value: 0xb900, lo: 0xa1, hi: 0xb5},
+ // Block 0x2d, offset 0x10f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x9900, lo: 0xa8, hi: 0xbf},
+ // Block 0x2e, offset 0x111
+ {value: 0x0000, lo: 0x01},
+ {value: 0x9900, lo: 0x80, hi: 0x82},
+ // Block 0x2f, offset 0x113
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0x9d, hi: 0x9f},
+ // Block 0x30, offset 0x115
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x94, hi: 0x94},
+ {value: 0x8104, lo: 0xb4, hi: 0xb4},
+ // Block 0x31, offset 0x118
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x92, hi: 0x92},
+ {value: 0x8132, lo: 0x9d, hi: 0x9d},
+ // Block 0x32, offset 0x11b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8131, lo: 0xa9, hi: 0xa9},
+ // Block 0x33, offset 0x11d
+ {value: 0x0004, lo: 0x02},
+ {value: 0x812e, lo: 0xb9, hi: 0xba},
+ {value: 0x812d, lo: 0xbb, hi: 0xbb},
+ // Block 0x34, offset 0x120
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0x97, hi: 0x97},
+ {value: 0x812d, lo: 0x98, hi: 0x98},
+ // Block 0x35, offset 0x123
+ {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 0x127
+ {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 0x12c
+ {value: 0x0000, lo: 0x08},
+ {value: 0x2d66, lo: 0x80, hi: 0x80},
+ {value: 0x2d6e, lo: 0x81, hi: 0x81},
+ {value: 0xa000, lo: 0x82, hi: 0x82},
+ {value: 0x2d76, 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 0x135
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xaa, hi: 0xab},
+ // Block 0x39, offset 0x137
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8102, lo: 0xa6, hi: 0xa6},
+ {value: 0x8104, lo: 0xb2, hi: 0xb3},
+ // Block 0x3a, offset 0x13a
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0xb7, hi: 0xb7},
+ // Block 0x3b, offset 0x13c
+ {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 0x147
+ {value: 0x0000, lo: 0x0f},
+ {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: 0x8132, lo: 0xbb, hi: 0xbb},
+ {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 0x157
+ {value: 0x0004, lo: 0x03},
+ {value: 0x0433, lo: 0x80, hi: 0x81},
+ {value: 0x8100, lo: 0x97, hi: 0x97},
+ {value: 0x8100, lo: 0xbe, hi: 0xbe},
+ // Block 0x3e, offset 0x15b
+ {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 0x169
+ {value: 0x427b, lo: 0x02},
+ {value: 0x01b8, lo: 0xa6, hi: 0xa6},
+ {value: 0x0057, lo: 0xaa, hi: 0xab},
+ // Block 0x40, offset 0x16c
+ {value: 0x0007, lo: 0x05},
+ {value: 0xa000, lo: 0x90, hi: 0x90},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0xa000, lo: 0x94, hi: 0x94},
+ {value: 0x3bb9, lo: 0x9a, hi: 0x9b},
+ {value: 0x3bc7, lo: 0xae, hi: 0xae},
+ // Block 0x41, offset 0x172
+ {value: 0x000e, lo: 0x05},
+ {value: 0x3bce, lo: 0x8d, hi: 0x8e},
+ {value: 0x3bd5, 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 0x178
+ {value: 0x6408, lo: 0x0a},
+ {value: 0xa000, lo: 0x83, hi: 0x83},
+ {value: 0x3be3, lo: 0x84, hi: 0x84},
+ {value: 0xa000, lo: 0x88, hi: 0x88},
+ {value: 0x3bea, lo: 0x89, hi: 0x89},
+ {value: 0xa000, lo: 0x8b, hi: 0x8b},
+ {value: 0x3bf1, lo: 0x8c, hi: 0x8c},
+ {value: 0xa000, lo: 0xa3, hi: 0xa3},
+ {value: 0x3bf8, lo: 0xa4, hi: 0xa5},
+ {value: 0x3bff, lo: 0xa6, hi: 0xa6},
+ {value: 0xa000, lo: 0xbc, hi: 0xbc},
+ // Block 0x43, offset 0x183
+ {value: 0x0007, lo: 0x03},
+ {value: 0x3c68, lo: 0xa0, hi: 0xa1},
+ {value: 0x3c92, lo: 0xa2, hi: 0xa3},
+ {value: 0x3cbc, lo: 0xaa, hi: 0xad},
+ // Block 0x44, offset 0x187
+ {value: 0x0004, lo: 0x01},
+ {value: 0x048b, lo: 0xa9, hi: 0xaa},
+ // Block 0x45, offset 0x189
+ {value: 0x0000, lo: 0x01},
+ {value: 0x4573, lo: 0x9c, hi: 0x9c},
+ // Block 0x46, offset 0x18b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xaf, hi: 0xb1},
+ // Block 0x47, offset 0x18d
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x48, offset 0x18f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xa0, hi: 0xbf},
+ // Block 0x49, offset 0x191
+ {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 0x197
+ {value: 0x0000, lo: 0x03},
+ {value: 0x4a81, lo: 0xb3, hi: 0xb3},
+ {value: 0x4a81, lo: 0xb5, hi: 0xb6},
+ {value: 0x4a81, lo: 0xba, hi: 0xbf},
+ // Block 0x4b, offset 0x19b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x4a81, lo: 0x8f, hi: 0xa3},
+ // Block 0x4c, offset 0x19d
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8100, lo: 0xae, hi: 0xbe},
+ // Block 0x4d, offset 0x19f
+ {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 0x4e, offset 0x1a7
+ {value: 0x0000, lo: 0x03},
+ {value: 0x8100, lo: 0x80, hi: 0x80},
+ {value: 0x8100, lo: 0x8b, hi: 0x8b},
+ {value: 0x8100, lo: 0x8e, hi: 0x8e},
+ // Block 0x4f, offset 0x1ab
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0xaf, hi: 0xaf},
+ {value: 0x8132, lo: 0xb4, hi: 0xbd},
+ // Block 0x50, offset 0x1ae
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0x9e, hi: 0x9f},
+ // Block 0x51, offset 0x1b0
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xb0, hi: 0xb1},
+ // Block 0x52, offset 0x1b2
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x86, hi: 0x86},
+ // Block 0x53, offset 0x1b4
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x84, hi: 0x84},
+ {value: 0x8132, lo: 0xa0, hi: 0xb1},
+ // Block 0x54, offset 0x1b7
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0xab, hi: 0xad},
+ // Block 0x55, offset 0x1b9
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x93, hi: 0x93},
+ // Block 0x56, offset 0x1bb
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0xb3, hi: 0xb3},
+ // Block 0x57, offset 0x1bd
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x80, hi: 0x80},
+ // Block 0x58, offset 0x1bf
+ {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 0x59, offset 0x1c5
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0x81, hi: 0x81},
+ {value: 0x8104, lo: 0xb6, hi: 0xb6},
+ // Block 0x5a, offset 0x1c8
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xad, hi: 0xad},
+ // Block 0x5b, offset 0x1ca
+ {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 0x5c, offset 0x1d1
+ {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 0x5d, offset 0x1d7
+ {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 0x5e, offset 0x1dd
+ {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 0x5f, offset 0x1e5
+ {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 0x60, offset 0x1eb
+ {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 0x61, offset 0x1f1
+ {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 0x62, offset 0x1f7
+ {value: 0x0000, lo: 0x03},
+ {value: 0xc600, lo: 0x80, hi: 0x87},
+ {value: 0xe500, lo: 0x88, hi: 0x88},
+ {value: 0xc600, lo: 0x89, hi: 0xa3},
+ // Block 0x63, offset 0x1fb
+ {value: 0x0006, lo: 0x0d},
+ {value: 0x4426, lo: 0x9d, hi: 0x9d},
+ {value: 0x8115, lo: 0x9e, hi: 0x9e},
+ {value: 0x4498, lo: 0x9f, hi: 0x9f},
+ {value: 0x4486, lo: 0xaa, hi: 0xab},
+ {value: 0x458a, lo: 0xac, hi: 0xac},
+ {value: 0x4592, lo: 0xad, hi: 0xad},
+ {value: 0x43de, lo: 0xae, hi: 0xb1},
+ {value: 0x43fc, lo: 0xb2, hi: 0xb4},
+ {value: 0x4414, lo: 0xb5, hi: 0xb6},
+ {value: 0x4420, lo: 0xb8, hi: 0xb8},
+ {value: 0x442c, lo: 0xb9, hi: 0xbb},
+ {value: 0x4444, lo: 0xbc, hi: 0xbc},
+ {value: 0x444a, lo: 0xbe, hi: 0xbe},
+ // Block 0x64, offset 0x209
+ {value: 0x0006, lo: 0x08},
+ {value: 0x4450, lo: 0x80, hi: 0x81},
+ {value: 0x445c, lo: 0x83, hi: 0x84},
+ {value: 0x446e, lo: 0x86, hi: 0x89},
+ {value: 0x4492, lo: 0x8a, hi: 0x8a},
+ {value: 0x440e, lo: 0x8b, hi: 0x8b},
+ {value: 0x43f6, lo: 0x8c, hi: 0x8c},
+ {value: 0x443e, lo: 0x8d, hi: 0x8d},
+ {value: 0x4468, lo: 0x8e, hi: 0x8e},
+ // Block 0x65, offset 0x212
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8100, lo: 0xa4, hi: 0xa5},
+ {value: 0x8100, lo: 0xb0, hi: 0xb1},
+ // Block 0x66, offset 0x215
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8100, lo: 0x9b, hi: 0x9d},
+ {value: 0x8200, lo: 0x9e, hi: 0xa3},
+ // Block 0x67, offset 0x218
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8100, lo: 0x90, hi: 0x90},
+ // Block 0x68, offset 0x21a
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8100, lo: 0x99, hi: 0x99},
+ {value: 0x8200, lo: 0xb2, hi: 0xb4},
+ // Block 0x69, offset 0x21d
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8100, lo: 0xbc, hi: 0xbd},
+ // Block 0x6a, offset 0x21f
+ {value: 0x0000, lo: 0x03},
+ {value: 0x8132, lo: 0xa0, hi: 0xa6},
+ {value: 0x812d, lo: 0xa7, hi: 0xad},
+ {value: 0x8132, lo: 0xae, hi: 0xaf},
+ // Block 0x6b, offset 0x223
+ {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 0x6c, offset 0x228
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8100, lo: 0x81, hi: 0x8c},
+ // Block 0x6d, offset 0x22a
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8100, lo: 0xb5, hi: 0xba},
+ // Block 0x6e, offset 0x22c
+ {value: 0x0000, lo: 0x04},
+ {value: 0x4a81, lo: 0x9e, hi: 0x9f},
+ {value: 0x4a81, lo: 0xa3, hi: 0xa3},
+ {value: 0x4a81, lo: 0xa5, hi: 0xa6},
+ {value: 0x4a81, lo: 0xaa, hi: 0xaf},
+ // Block 0x6f, offset 0x231
+ {value: 0x0000, lo: 0x05},
+ {value: 0x4a81, lo: 0x82, hi: 0x87},
+ {value: 0x4a81, lo: 0x8a, hi: 0x8f},
+ {value: 0x4a81, lo: 0x92, hi: 0x97},
+ {value: 0x4a81, lo: 0x9a, hi: 0x9c},
+ {value: 0x8100, lo: 0xa3, hi: 0xa3},
+ // Block 0x70, offset 0x237
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0xbd, hi: 0xbd},
+ // Block 0x71, offset 0x239
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0xa0, hi: 0xa0},
+ // Block 0x72, offset 0x23b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xb6, hi: 0xba},
+ // Block 0x73, offset 0x23d
+ {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 0x74, offset 0x243
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0xa5, hi: 0xa5},
+ {value: 0x812d, lo: 0xa6, hi: 0xa6},
+ // Block 0x75, offset 0x246
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x86, hi: 0x86},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x76, offset 0x249
+ {value: 0x17fe, lo: 0x07},
+ {value: 0xa000, lo: 0x99, hi: 0x99},
+ {value: 0x4238, lo: 0x9a, hi: 0x9a},
+ {value: 0xa000, lo: 0x9b, hi: 0x9b},
+ {value: 0x4242, lo: 0x9c, hi: 0x9c},
+ {value: 0xa000, lo: 0xa5, hi: 0xa5},
+ {value: 0x424c, lo: 0xab, hi: 0xab},
+ {value: 0x8104, lo: 0xb9, hi: 0xba},
+ // Block 0x77, offset 0x251
+ {value: 0x0000, lo: 0x06},
+ {value: 0x8132, lo: 0x80, hi: 0x82},
+ {value: 0x9900, lo: 0xa7, hi: 0xa7},
+ {value: 0x2d7e, lo: 0xae, hi: 0xae},
+ {value: 0x2d88, lo: 0xaf, hi: 0xaf},
+ {value: 0xa000, lo: 0xb1, hi: 0xb2},
+ {value: 0x8104, lo: 0xb3, hi: 0xb4},
+ // Block 0x78, offset 0x258
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x80, hi: 0x80},
+ {value: 0x8102, lo: 0x8a, hi: 0x8a},
+ // Block 0x79, offset 0x25b
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0xb5, hi: 0xb5},
+ {value: 0x8102, lo: 0xb6, hi: 0xb6},
+ // Block 0x7a, offset 0x25e
+ {value: 0x0002, lo: 0x01},
+ {value: 0x8102, lo: 0xa9, hi: 0xaa},
+ // Block 0x7b, offset 0x260
+ {value: 0x0000, lo: 0x07},
+ {value: 0xa000, lo: 0x87, hi: 0x87},
+ {value: 0x2d92, lo: 0x8b, hi: 0x8b},
+ {value: 0x2d9c, 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 0x7c, offset 0x268
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x82, hi: 0x82},
+ {value: 0x8102, lo: 0x86, hi: 0x86},
+ // Block 0x7d, offset 0x26b
+ {value: 0x6b5a, lo: 0x06},
+ {value: 0x9900, lo: 0xb0, hi: 0xb0},
+ {value: 0xa000, lo: 0xb9, hi: 0xb9},
+ {value: 0x9900, lo: 0xba, hi: 0xba},
+ {value: 0x2db0, lo: 0xbb, hi: 0xbb},
+ {value: 0x2da6, lo: 0xbc, hi: 0xbd},
+ {value: 0x2dba, lo: 0xbe, hi: 0xbe},
+ // Block 0x7e, offset 0x272
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x82, hi: 0x82},
+ {value: 0x8102, lo: 0x83, hi: 0x83},
+ // Block 0x7f, offset 0x275
+ {value: 0x0000, lo: 0x05},
+ {value: 0x9900, lo: 0xaf, hi: 0xaf},
+ {value: 0xa000, lo: 0xb8, hi: 0xb9},
+ {value: 0x2dc4, lo: 0xba, hi: 0xba},
+ {value: 0x2dce, lo: 0xbb, hi: 0xbb},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x80, offset 0x27b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0x80, hi: 0x80},
+ // Block 0x81, offset 0x27d
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0xb6, hi: 0xb6},
+ {value: 0x8102, lo: 0xb7, hi: 0xb7},
+ // Block 0x82, offset 0x280
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xab, hi: 0xab},
+ // Block 0x83, offset 0x282
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8101, lo: 0xb0, hi: 0xb4},
+ // Block 0x84, offset 0x284
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xb0, hi: 0xb6},
+ // Block 0x85, offset 0x286
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8101, lo: 0x9e, hi: 0x9e},
+ // Block 0x86, offset 0x288
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x4662, lo: 0x9e, hi: 0x9e},
+ {value: 0x466c, lo: 0x9f, hi: 0x9f},
+ {value: 0x46a0, lo: 0xa0, hi: 0xa0},
+ {value: 0x46ae, lo: 0xa1, hi: 0xa1},
+ {value: 0x46bc, lo: 0xa2, hi: 0xa2},
+ {value: 0x46ca, lo: 0xa3, hi: 0xa3},
+ {value: 0x46d8, 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 0x87, offset 0x295
+ {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: 0x4676, lo: 0xbb, hi: 0xbb},
+ {value: 0x4680, lo: 0xbc, hi: 0xbc},
+ {value: 0x46e6, lo: 0xbd, hi: 0xbd},
+ {value: 0x4702, lo: 0xbe, hi: 0xbe},
+ {value: 0x46f4, lo: 0xbf, hi: 0xbf},
+ // Block 0x88, offset 0x29f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x4710, lo: 0x80, hi: 0x80},
+ // Block 0x89, offset 0x2a1
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0x82, hi: 0x84},
+ // Block 0x8a, offset 0x2a3
+ {value: 0x0000, lo: 0x05},
+ {value: 0x8132, lo: 0x80, hi: 0x86},
+ {value: 0x8132, lo: 0x88, hi: 0x98},
+ {value: 0x8132, lo: 0x9b, hi: 0xa1},
+ {value: 0x8132, lo: 0xa3, hi: 0xa4},
+ {value: 0x8132, lo: 0xa6, hi: 0xaa},
+ // Block 0x8b, offset 0x2a9
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0x90, hi: 0x96},
+ // Block 0x8c, offset 0x2ab
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0x84, hi: 0x89},
+ {value: 0x8102, lo: 0x8a, hi: 0x8a},
+ // Block 0x8d, offset 0x2ae
+ {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 < 0xC2:
+ 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 < 0xC2:
+ 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: 16994 bytes (16.60 KiB). Checksum: 146925fc21092b17.
+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 < 90:
+ return uint16(nfkcValues[n<<6+uint32(b)])
+ default:
+ n -= 90
+ return uint16(nfkcSparse.lookup(n, b))
+ }
+}
+
+// nfkcValues: 92 blocks, 5888 entries, 11776 bytes
+// The third block is the zero block.
+var nfkcValues = [5888]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: 0x2f6f, 0xc1: 0x2f74, 0xc2: 0x471e, 0xc3: 0x2f79, 0xc4: 0x472d, 0xc5: 0x4732,
+ 0xc6: 0xa000, 0xc7: 0x473c, 0xc8: 0x2fe2, 0xc9: 0x2fe7, 0xca: 0x4741, 0xcb: 0x2ffb,
+ 0xcc: 0x306e, 0xcd: 0x3073, 0xce: 0x3078, 0xcf: 0x4755, 0xd1: 0x3104,
+ 0xd2: 0x3127, 0xd3: 0x312c, 0xd4: 0x475f, 0xd5: 0x4764, 0xd6: 0x4773,
+ 0xd8: 0xa000, 0xd9: 0x31b3, 0xda: 0x31b8, 0xdb: 0x31bd, 0xdc: 0x47a5, 0xdd: 0x3235,
+ 0xe0: 0x327b, 0xe1: 0x3280, 0xe2: 0x47af, 0xe3: 0x3285,
+ 0xe4: 0x47be, 0xe5: 0x47c3, 0xe6: 0xa000, 0xe7: 0x47cd, 0xe8: 0x32ee, 0xe9: 0x32f3,
+ 0xea: 0x47d2, 0xeb: 0x3307, 0xec: 0x337f, 0xed: 0x3384, 0xee: 0x3389, 0xef: 0x47e6,
+ 0xf1: 0x3415, 0xf2: 0x3438, 0xf3: 0x343d, 0xf4: 0x47f0, 0xf5: 0x47f5,
+ 0xf6: 0x4804, 0xf8: 0xa000, 0xf9: 0x34c9, 0xfa: 0x34ce, 0xfb: 0x34d3,
+ 0xfc: 0x4836, 0xfd: 0x3550, 0xff: 0x3569,
+ // Block 0x4, offset 0x100
+ 0x100: 0x2f7e, 0x101: 0x328a, 0x102: 0x4723, 0x103: 0x47b4, 0x104: 0x2f9c, 0x105: 0x32a8,
+ 0x106: 0x2fb0, 0x107: 0x32bc, 0x108: 0x2fb5, 0x109: 0x32c1, 0x10a: 0x2fba, 0x10b: 0x32c6,
+ 0x10c: 0x2fbf, 0x10d: 0x32cb, 0x10e: 0x2fc9, 0x10f: 0x32d5,
+ 0x112: 0x4746, 0x113: 0x47d7, 0x114: 0x2ff1, 0x115: 0x32fd, 0x116: 0x2ff6, 0x117: 0x3302,
+ 0x118: 0x3014, 0x119: 0x3320, 0x11a: 0x3005, 0x11b: 0x3311, 0x11c: 0x302d, 0x11d: 0x3339,
+ 0x11e: 0x3037, 0x11f: 0x3343, 0x120: 0x303c, 0x121: 0x3348, 0x122: 0x3046, 0x123: 0x3352,
+ 0x124: 0x304b, 0x125: 0x3357, 0x128: 0x307d, 0x129: 0x338e,
+ 0x12a: 0x3082, 0x12b: 0x3393, 0x12c: 0x3087, 0x12d: 0x3398, 0x12e: 0x30aa, 0x12f: 0x33b6,
+ 0x130: 0x308c, 0x132: 0x195d, 0x133: 0x19e7, 0x134: 0x30b4, 0x135: 0x33c0,
+ 0x136: 0x30c8, 0x137: 0x33d9, 0x139: 0x30d2, 0x13a: 0x33e3, 0x13b: 0x30dc,
+ 0x13c: 0x33ed, 0x13d: 0x30d7, 0x13e: 0x33e8, 0x13f: 0x1bac,
+ // Block 0x5, offset 0x140
+ 0x140: 0x1c34, 0x143: 0x30ff, 0x144: 0x3410, 0x145: 0x3118,
+ 0x146: 0x3429, 0x147: 0x310e, 0x148: 0x341f, 0x149: 0x1c5c,
+ 0x14c: 0x4769, 0x14d: 0x47fa, 0x14e: 0x3131, 0x14f: 0x3442, 0x150: 0x313b, 0x151: 0x344c,
+ 0x154: 0x3159, 0x155: 0x346a, 0x156: 0x3172, 0x157: 0x3483,
+ 0x158: 0x3163, 0x159: 0x3474, 0x15a: 0x478c, 0x15b: 0x481d, 0x15c: 0x317c, 0x15d: 0x348d,
+ 0x15e: 0x318b, 0x15f: 0x349c, 0x160: 0x4791, 0x161: 0x4822, 0x162: 0x31a4, 0x163: 0x34ba,
+ 0x164: 0x3195, 0x165: 0x34ab, 0x168: 0x479b, 0x169: 0x482c,
+ 0x16a: 0x47a0, 0x16b: 0x4831, 0x16c: 0x31c2, 0x16d: 0x34d8, 0x16e: 0x31cc, 0x16f: 0x34e2,
+ 0x170: 0x31d1, 0x171: 0x34e7, 0x172: 0x31ef, 0x173: 0x3505, 0x174: 0x3212, 0x175: 0x3528,
+ 0x176: 0x323a, 0x177: 0x3555, 0x178: 0x324e, 0x179: 0x325d, 0x17a: 0x357d, 0x17b: 0x3267,
+ 0x17c: 0x3587, 0x17d: 0x326c, 0x17e: 0x358c, 0x17f: 0x00a7,
+ // Block 0x6, offset 0x180
+ 0x184: 0x2dee, 0x185: 0x2df4,
+ 0x186: 0x2dfa, 0x187: 0x1972, 0x188: 0x1975, 0x189: 0x1a08, 0x18a: 0x1987, 0x18b: 0x198a,
+ 0x18c: 0x1a3e, 0x18d: 0x2f88, 0x18e: 0x3294, 0x18f: 0x3096, 0x190: 0x33a2, 0x191: 0x3140,
+ 0x192: 0x3451, 0x193: 0x31d6, 0x194: 0x34ec, 0x195: 0x39cf, 0x196: 0x3b5e, 0x197: 0x39c8,
+ 0x198: 0x3b57, 0x199: 0x39d6, 0x19a: 0x3b65, 0x19b: 0x39c1, 0x19c: 0x3b50,
+ 0x19e: 0x38b0, 0x19f: 0x3a3f, 0x1a0: 0x38a9, 0x1a1: 0x3a38, 0x1a2: 0x35b3, 0x1a3: 0x35c5,
+ 0x1a6: 0x3041, 0x1a7: 0x334d, 0x1a8: 0x30be, 0x1a9: 0x33cf,
+ 0x1aa: 0x4782, 0x1ab: 0x4813, 0x1ac: 0x3990, 0x1ad: 0x3b1f, 0x1ae: 0x35d7, 0x1af: 0x35dd,
+ 0x1b0: 0x33c5, 0x1b1: 0x1942, 0x1b2: 0x1945, 0x1b3: 0x19cf, 0x1b4: 0x3028, 0x1b5: 0x3334,
+ 0x1b8: 0x30fa, 0x1b9: 0x340b, 0x1ba: 0x38b7, 0x1bb: 0x3a46,
+ 0x1bc: 0x35ad, 0x1bd: 0x35bf, 0x1be: 0x35b9, 0x1bf: 0x35cb,
+ // Block 0x7, offset 0x1c0
+ 0x1c0: 0x2f8d, 0x1c1: 0x3299, 0x1c2: 0x2f92, 0x1c3: 0x329e, 0x1c4: 0x300a, 0x1c5: 0x3316,
+ 0x1c6: 0x300f, 0x1c7: 0x331b, 0x1c8: 0x309b, 0x1c9: 0x33a7, 0x1ca: 0x30a0, 0x1cb: 0x33ac,
+ 0x1cc: 0x3145, 0x1cd: 0x3456, 0x1ce: 0x314a, 0x1cf: 0x345b, 0x1d0: 0x3168, 0x1d1: 0x3479,
+ 0x1d2: 0x316d, 0x1d3: 0x347e, 0x1d4: 0x31db, 0x1d5: 0x34f1, 0x1d6: 0x31e0, 0x1d7: 0x34f6,
+ 0x1d8: 0x3186, 0x1d9: 0x3497, 0x1da: 0x319f, 0x1db: 0x34b5,
+ 0x1de: 0x305a, 0x1df: 0x3366,
+ 0x1e6: 0x4728, 0x1e7: 0x47b9, 0x1e8: 0x4750, 0x1e9: 0x47e1,
+ 0x1ea: 0x395f, 0x1eb: 0x3aee, 0x1ec: 0x393c, 0x1ed: 0x3acb, 0x1ee: 0x476e, 0x1ef: 0x47ff,
+ 0x1f0: 0x3958, 0x1f1: 0x3ae7, 0x1f2: 0x3244, 0x1f3: 0x355f,
+ // 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: 0x4a44, 0x241: 0x4a49, 0x242: 0x9932, 0x243: 0x4a4e, 0x244: 0x4a53, 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: 0x42a5,
+ 0x27e: 0x0037,
+ // Block 0xa, offset 0x280
+ 0x284: 0x425a, 0x285: 0x4511,
+ 0x286: 0x35e9, 0x287: 0x00ce, 0x288: 0x3607, 0x289: 0x3613, 0x28a: 0x3625,
+ 0x28c: 0x3643, 0x28e: 0x3655, 0x28f: 0x3673, 0x290: 0x3e08, 0x291: 0xa000,
+ 0x295: 0xa000, 0x297: 0xa000,
+ 0x299: 0xa000,
+ 0x29f: 0xa000, 0x2a1: 0xa000,
+ 0x2a5: 0xa000, 0x2a9: 0xa000,
+ 0x2aa: 0x3637, 0x2ab: 0x3667, 0x2ac: 0x4894, 0x2ad: 0x3697, 0x2ae: 0x48be, 0x2af: 0x36a9,
+ 0x2b0: 0x3e70, 0x2b1: 0xa000, 0x2b5: 0xa000,
+ 0x2b7: 0xa000, 0x2b9: 0xa000,
+ 0x2bf: 0xa000,
+ // Block 0xb, offset 0x2c0
+ 0x2c1: 0xa000, 0x2c5: 0xa000,
+ 0x2c9: 0xa000, 0x2ca: 0x48d6, 0x2cb: 0x48f4,
+ 0x2cc: 0x36c7, 0x2cd: 0x36df, 0x2ce: 0x490c, 0x2d0: 0x01be, 0x2d1: 0x01d0,
+ 0x2d2: 0x01ac, 0x2d3: 0x43a2, 0x2d4: 0x43a8, 0x2d5: 0x01fa, 0x2d6: 0x01e8,
+ 0x2f0: 0x01d6, 0x2f1: 0x01eb, 0x2f2: 0x01ee, 0x2f4: 0x0188, 0x2f5: 0x01c7,
+ 0x2f9: 0x01a6,
+ // Block 0xc, offset 0x300
+ 0x300: 0x3721, 0x301: 0x372d, 0x303: 0x371b,
+ 0x306: 0xa000, 0x307: 0x3709,
+ 0x30c: 0x375d, 0x30d: 0x3745, 0x30e: 0x376f, 0x310: 0xa000,
+ 0x313: 0xa000, 0x315: 0xa000, 0x316: 0xa000, 0x317: 0xa000,
+ 0x318: 0xa000, 0x319: 0x3751, 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: 0x37d5, 0x33a: 0xa000,
+ 0x33e: 0xa000,
+ // Block 0xd, offset 0x340
+ 0x341: 0x3733, 0x342: 0x37b7,
+ 0x350: 0x370f, 0x351: 0x3793,
+ 0x352: 0x3715, 0x353: 0x3799, 0x356: 0x3727, 0x357: 0x37ab,
+ 0x358: 0xa000, 0x359: 0xa000, 0x35a: 0x3829, 0x35b: 0x382f, 0x35c: 0x3739, 0x35d: 0x37bd,
+ 0x35e: 0x373f, 0x35f: 0x37c3, 0x362: 0x374b, 0x363: 0x37cf,
+ 0x364: 0x3757, 0x365: 0x37db, 0x366: 0x3763, 0x367: 0x37e7, 0x368: 0xa000, 0x369: 0xa000,
+ 0x36a: 0x3835, 0x36b: 0x383b, 0x36c: 0x378d, 0x36d: 0x3811, 0x36e: 0x3769, 0x36f: 0x37ed,
+ 0x370: 0x3775, 0x371: 0x37f9, 0x372: 0x377b, 0x373: 0x37ff, 0x374: 0x3781, 0x375: 0x3805,
+ 0x378: 0x3787, 0x379: 0x380b,
+ // Block 0xe, offset 0x380
+ 0x387: 0x1d61,
+ 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: 0x1d84,
+ 0x3f6: 0x2013, 0x3f7: 0x204f, 0x3f8: 0x204a,
+ // Block 0x10, offset 0x400
+ 0x405: 0xa000,
+ 0x406: 0x2d26, 0x407: 0xa000, 0x408: 0x2d2e, 0x409: 0xa000, 0x40a: 0x2d36, 0x40b: 0xa000,
+ 0x40c: 0x2d3e, 0x40d: 0xa000, 0x40e: 0x2d46, 0x411: 0xa000,
+ 0x412: 0x2d4e,
+ 0x434: 0x8102, 0x435: 0x9900,
+ 0x43a: 0xa000, 0x43b: 0x2d56,
+ 0x43c: 0xa000, 0x43d: 0x2d5e, 0x43e: 0xa000, 0x43f: 0xa000,
+ // Block 0x11, offset 0x440
+ 0x440: 0x0069, 0x441: 0x006b, 0x442: 0x006f, 0x443: 0x0083, 0x444: 0x00f5, 0x445: 0x00f8,
+ 0x446: 0x0413, 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: 0x0417, 0x455: 0x041b, 0x456: 0x00a1, 0x457: 0x00a9,
+ 0x458: 0x00ab, 0x459: 0x0423, 0x45a: 0x012b, 0x45b: 0x00ad, 0x45c: 0x0427, 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: 0x042b, 0x4a8: 0x016a, 0x4a9: 0x0128,
+ 0x4aa: 0x042f, 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: 0x041f, 0x4b9: 0x0158, 0x4ba: 0x015b, 0x4bb: 0x00b5,
+ 0x4bc: 0x015e, 0x4bd: 0x0161, 0x4be: 0x0164, 0x4bf: 0x01d0,
+ // Block 0x13, offset 0x4c0
+ 0x4c0: 0x2f97, 0x4c1: 0x32a3, 0x4c2: 0x2fa1, 0x4c3: 0x32ad, 0x4c4: 0x2fa6, 0x4c5: 0x32b2,
+ 0x4c6: 0x2fab, 0x4c7: 0x32b7, 0x4c8: 0x38cc, 0x4c9: 0x3a5b, 0x4ca: 0x2fc4, 0x4cb: 0x32d0,
+ 0x4cc: 0x2fce, 0x4cd: 0x32da, 0x4ce: 0x2fdd, 0x4cf: 0x32e9, 0x4d0: 0x2fd3, 0x4d1: 0x32df,
+ 0x4d2: 0x2fd8, 0x4d3: 0x32e4, 0x4d4: 0x38ef, 0x4d5: 0x3a7e, 0x4d6: 0x38f6, 0x4d7: 0x3a85,
+ 0x4d8: 0x3019, 0x4d9: 0x3325, 0x4da: 0x301e, 0x4db: 0x332a, 0x4dc: 0x3904, 0x4dd: 0x3a93,
+ 0x4de: 0x3023, 0x4df: 0x332f, 0x4e0: 0x3032, 0x4e1: 0x333e, 0x4e2: 0x3050, 0x4e3: 0x335c,
+ 0x4e4: 0x305f, 0x4e5: 0x336b, 0x4e6: 0x3055, 0x4e7: 0x3361, 0x4e8: 0x3064, 0x4e9: 0x3370,
+ 0x4ea: 0x3069, 0x4eb: 0x3375, 0x4ec: 0x30af, 0x4ed: 0x33bb, 0x4ee: 0x390b, 0x4ef: 0x3a9a,
+ 0x4f0: 0x30b9, 0x4f1: 0x33ca, 0x4f2: 0x30c3, 0x4f3: 0x33d4, 0x4f4: 0x30cd, 0x4f5: 0x33de,
+ 0x4f6: 0x475a, 0x4f7: 0x47eb, 0x4f8: 0x3912, 0x4f9: 0x3aa1, 0x4fa: 0x30e6, 0x4fb: 0x33f7,
+ 0x4fc: 0x30e1, 0x4fd: 0x33f2, 0x4fe: 0x30eb, 0x4ff: 0x33fc,
+ // Block 0x14, offset 0x500
+ 0x500: 0x30f0, 0x501: 0x3401, 0x502: 0x30f5, 0x503: 0x3406, 0x504: 0x3109, 0x505: 0x341a,
+ 0x506: 0x3113, 0x507: 0x3424, 0x508: 0x3122, 0x509: 0x3433, 0x50a: 0x311d, 0x50b: 0x342e,
+ 0x50c: 0x3935, 0x50d: 0x3ac4, 0x50e: 0x3943, 0x50f: 0x3ad2, 0x510: 0x394a, 0x511: 0x3ad9,
+ 0x512: 0x3951, 0x513: 0x3ae0, 0x514: 0x314f, 0x515: 0x3460, 0x516: 0x3154, 0x517: 0x3465,
+ 0x518: 0x315e, 0x519: 0x346f, 0x51a: 0x4787, 0x51b: 0x4818, 0x51c: 0x3997, 0x51d: 0x3b26,
+ 0x51e: 0x3177, 0x51f: 0x3488, 0x520: 0x3181, 0x521: 0x3492, 0x522: 0x4796, 0x523: 0x4827,
+ 0x524: 0x399e, 0x525: 0x3b2d, 0x526: 0x39a5, 0x527: 0x3b34, 0x528: 0x39ac, 0x529: 0x3b3b,
+ 0x52a: 0x3190, 0x52b: 0x34a1, 0x52c: 0x319a, 0x52d: 0x34b0, 0x52e: 0x31ae, 0x52f: 0x34c4,
+ 0x530: 0x31a9, 0x531: 0x34bf, 0x532: 0x31ea, 0x533: 0x3500, 0x534: 0x31f9, 0x535: 0x350f,
+ 0x536: 0x31f4, 0x537: 0x350a, 0x538: 0x39b3, 0x539: 0x3b42, 0x53a: 0x39ba, 0x53b: 0x3b49,
+ 0x53c: 0x31fe, 0x53d: 0x3514, 0x53e: 0x3203, 0x53f: 0x3519,
+ // Block 0x15, offset 0x540
+ 0x540: 0x3208, 0x541: 0x351e, 0x542: 0x320d, 0x543: 0x3523, 0x544: 0x321c, 0x545: 0x3532,
+ 0x546: 0x3217, 0x547: 0x352d, 0x548: 0x3221, 0x549: 0x353c, 0x54a: 0x3226, 0x54b: 0x3541,
+ 0x54c: 0x322b, 0x54d: 0x3546, 0x54e: 0x3249, 0x54f: 0x3564, 0x550: 0x3262, 0x551: 0x3582,
+ 0x552: 0x3271, 0x553: 0x3591, 0x554: 0x3276, 0x555: 0x3596, 0x556: 0x337a, 0x557: 0x34a6,
+ 0x558: 0x3537, 0x559: 0x3573, 0x55a: 0x1be0, 0x55b: 0x42d7,
+ 0x560: 0x4737, 0x561: 0x47c8, 0x562: 0x2f83, 0x563: 0x328f,
+ 0x564: 0x3878, 0x565: 0x3a07, 0x566: 0x3871, 0x567: 0x3a00, 0x568: 0x3886, 0x569: 0x3a15,
+ 0x56a: 0x387f, 0x56b: 0x3a0e, 0x56c: 0x38be, 0x56d: 0x3a4d, 0x56e: 0x3894, 0x56f: 0x3a23,
+ 0x570: 0x388d, 0x571: 0x3a1c, 0x572: 0x38a2, 0x573: 0x3a31, 0x574: 0x389b, 0x575: 0x3a2a,
+ 0x576: 0x38c5, 0x577: 0x3a54, 0x578: 0x474b, 0x579: 0x47dc, 0x57a: 0x3000, 0x57b: 0x330c,
+ 0x57c: 0x2fec, 0x57d: 0x32f8, 0x57e: 0x38da, 0x57f: 0x3a69,
+ // Block 0x16, offset 0x580
+ 0x580: 0x38d3, 0x581: 0x3a62, 0x582: 0x38e8, 0x583: 0x3a77, 0x584: 0x38e1, 0x585: 0x3a70,
+ 0x586: 0x38fd, 0x587: 0x3a8c, 0x588: 0x3091, 0x589: 0x339d, 0x58a: 0x30a5, 0x58b: 0x33b1,
+ 0x58c: 0x477d, 0x58d: 0x480e, 0x58e: 0x3136, 0x58f: 0x3447, 0x590: 0x3920, 0x591: 0x3aaf,
+ 0x592: 0x3919, 0x593: 0x3aa8, 0x594: 0x392e, 0x595: 0x3abd, 0x596: 0x3927, 0x597: 0x3ab6,
+ 0x598: 0x3989, 0x599: 0x3b18, 0x59a: 0x396d, 0x59b: 0x3afc, 0x59c: 0x3966, 0x59d: 0x3af5,
+ 0x59e: 0x397b, 0x59f: 0x3b0a, 0x5a0: 0x3974, 0x5a1: 0x3b03, 0x5a2: 0x3982, 0x5a3: 0x3b11,
+ 0x5a4: 0x31e5, 0x5a5: 0x34fb, 0x5a6: 0x31c7, 0x5a7: 0x34dd, 0x5a8: 0x39e4, 0x5a9: 0x3b73,
+ 0x5aa: 0x39dd, 0x5ab: 0x3b6c, 0x5ac: 0x39f2, 0x5ad: 0x3b81, 0x5ae: 0x39eb, 0x5af: 0x3b7a,
+ 0x5b0: 0x39f9, 0x5b1: 0x3b88, 0x5b2: 0x3230, 0x5b3: 0x354b, 0x5b4: 0x3258, 0x5b5: 0x3578,
+ 0x5b6: 0x3253, 0x5b7: 0x356e, 0x5b8: 0x323f, 0x5b9: 0x355a,
+ // Block 0x17, offset 0x5c0
+ 0x5c0: 0x489a, 0x5c1: 0x48a0, 0x5c2: 0x49b4, 0x5c3: 0x49cc, 0x5c4: 0x49bc, 0x5c5: 0x49d4,
+ 0x5c6: 0x49c4, 0x5c7: 0x49dc, 0x5c8: 0x4840, 0x5c9: 0x4846, 0x5ca: 0x4924, 0x5cb: 0x493c,
+ 0x5cc: 0x492c, 0x5cd: 0x4944, 0x5ce: 0x4934, 0x5cf: 0x494c, 0x5d0: 0x48ac, 0x5d1: 0x48b2,
+ 0x5d2: 0x3db8, 0x5d3: 0x3dc8, 0x5d4: 0x3dc0, 0x5d5: 0x3dd0,
+ 0x5d8: 0x484c, 0x5d9: 0x4852, 0x5da: 0x3ce8, 0x5db: 0x3cf8, 0x5dc: 0x3cf0, 0x5dd: 0x3d00,
+ 0x5e0: 0x48c4, 0x5e1: 0x48ca, 0x5e2: 0x49e4, 0x5e3: 0x49fc,
+ 0x5e4: 0x49ec, 0x5e5: 0x4a04, 0x5e6: 0x49f4, 0x5e7: 0x4a0c, 0x5e8: 0x4858, 0x5e9: 0x485e,
+ 0x5ea: 0x4954, 0x5eb: 0x496c, 0x5ec: 0x495c, 0x5ed: 0x4974, 0x5ee: 0x4964, 0x5ef: 0x497c,
+ 0x5f0: 0x48dc, 0x5f1: 0x48e2, 0x5f2: 0x3e18, 0x5f3: 0x3e30, 0x5f4: 0x3e20, 0x5f5: 0x3e38,
+ 0x5f6: 0x3e28, 0x5f7: 0x3e40, 0x5f8: 0x4864, 0x5f9: 0x486a, 0x5fa: 0x3d18, 0x5fb: 0x3d30,
+ 0x5fc: 0x3d20, 0x5fd: 0x3d38, 0x5fe: 0x3d28, 0x5ff: 0x3d40,
+ // Block 0x18, offset 0x600
+ 0x600: 0x48e8, 0x601: 0x48ee, 0x602: 0x3e48, 0x603: 0x3e58, 0x604: 0x3e50, 0x605: 0x3e60,
+ 0x608: 0x4870, 0x609: 0x4876, 0x60a: 0x3d48, 0x60b: 0x3d58,
+ 0x60c: 0x3d50, 0x60d: 0x3d60, 0x610: 0x48fa, 0x611: 0x4900,
+ 0x612: 0x3e80, 0x613: 0x3e98, 0x614: 0x3e88, 0x615: 0x3ea0, 0x616: 0x3e90, 0x617: 0x3ea8,
+ 0x619: 0x487c, 0x61b: 0x3d68, 0x61d: 0x3d70,
+ 0x61f: 0x3d78, 0x620: 0x4912, 0x621: 0x4918, 0x622: 0x4a14, 0x623: 0x4a2c,
+ 0x624: 0x4a1c, 0x625: 0x4a34, 0x626: 0x4a24, 0x627: 0x4a3c, 0x628: 0x4882, 0x629: 0x4888,
+ 0x62a: 0x4984, 0x62b: 0x499c, 0x62c: 0x498c, 0x62d: 0x49a4, 0x62e: 0x4994, 0x62f: 0x49ac,
+ 0x630: 0x488e, 0x631: 0x43b4, 0x632: 0x3691, 0x633: 0x43ba, 0x634: 0x48b8, 0x635: 0x43c0,
+ 0x636: 0x36a3, 0x637: 0x43c6, 0x638: 0x36c1, 0x639: 0x43cc, 0x63a: 0x36d9, 0x63b: 0x43d2,
+ 0x63c: 0x4906, 0x63d: 0x43d8,
+ // Block 0x19, offset 0x640
+ 0x640: 0x3da0, 0x641: 0x3da8, 0x642: 0x4184, 0x643: 0x41a2, 0x644: 0x418e, 0x645: 0x41ac,
+ 0x646: 0x4198, 0x647: 0x41b6, 0x648: 0x3cd8, 0x649: 0x3ce0, 0x64a: 0x40d0, 0x64b: 0x40ee,
+ 0x64c: 0x40da, 0x64d: 0x40f8, 0x64e: 0x40e4, 0x64f: 0x4102, 0x650: 0x3de8, 0x651: 0x3df0,
+ 0x652: 0x41c0, 0x653: 0x41de, 0x654: 0x41ca, 0x655: 0x41e8, 0x656: 0x41d4, 0x657: 0x41f2,
+ 0x658: 0x3d08, 0x659: 0x3d10, 0x65a: 0x410c, 0x65b: 0x412a, 0x65c: 0x4116, 0x65d: 0x4134,
+ 0x65e: 0x4120, 0x65f: 0x413e, 0x660: 0x3ec0, 0x661: 0x3ec8, 0x662: 0x41fc, 0x663: 0x421a,
+ 0x664: 0x4206, 0x665: 0x4224, 0x666: 0x4210, 0x667: 0x422e, 0x668: 0x3d80, 0x669: 0x3d88,
+ 0x66a: 0x4148, 0x66b: 0x4166, 0x66c: 0x4152, 0x66d: 0x4170, 0x66e: 0x415c, 0x66f: 0x417a,
+ 0x670: 0x3685, 0x671: 0x367f, 0x672: 0x3d90, 0x673: 0x368b, 0x674: 0x3d98,
+ 0x676: 0x48a6, 0x677: 0x3db0, 0x678: 0x35f5, 0x679: 0x35ef, 0x67a: 0x35e3, 0x67b: 0x4384,
+ 0x67c: 0x35fb, 0x67d: 0x4287, 0x67e: 0x01d3, 0x67f: 0x4287,
+ // Block 0x1a, offset 0x680
+ 0x680: 0x42a0, 0x681: 0x4518, 0x682: 0x3dd8, 0x683: 0x369d, 0x684: 0x3de0,
+ 0x686: 0x48d0, 0x687: 0x3df8, 0x688: 0x3601, 0x689: 0x438a, 0x68a: 0x360d, 0x68b: 0x4390,
+ 0x68c: 0x3619, 0x68d: 0x451f, 0x68e: 0x4526, 0x68f: 0x452d, 0x690: 0x36b5, 0x691: 0x36af,
+ 0x692: 0x3e00, 0x693: 0x457a, 0x696: 0x36bb, 0x697: 0x3e10,
+ 0x698: 0x3631, 0x699: 0x362b, 0x69a: 0x361f, 0x69b: 0x4396, 0x69d: 0x4534,
+ 0x69e: 0x453b, 0x69f: 0x4542, 0x6a0: 0x36eb, 0x6a1: 0x36e5, 0x6a2: 0x3e68, 0x6a3: 0x4582,
+ 0x6a4: 0x36cd, 0x6a5: 0x36d3, 0x6a6: 0x36f1, 0x6a7: 0x3e78, 0x6a8: 0x3661, 0x6a9: 0x365b,
+ 0x6aa: 0x364f, 0x6ab: 0x43a2, 0x6ac: 0x3649, 0x6ad: 0x450a, 0x6ae: 0x4511, 0x6af: 0x0081,
+ 0x6b2: 0x3eb0, 0x6b3: 0x36f7, 0x6b4: 0x3eb8,
+ 0x6b6: 0x491e, 0x6b7: 0x3ed0, 0x6b8: 0x363d, 0x6b9: 0x439c, 0x6ba: 0x366d, 0x6bb: 0x43ae,
+ 0x6bc: 0x3679, 0x6bd: 0x425a, 0x6be: 0x428c,
+ // Block 0x1b, offset 0x6c0
+ 0x6c0: 0x1bd8, 0x6c1: 0x1bdc, 0x6c2: 0x0047, 0x6c3: 0x1c54, 0x6c5: 0x1be8,
+ 0x6c6: 0x1bec, 0x6c7: 0x00e9, 0x6c9: 0x1c58, 0x6ca: 0x008f, 0x6cb: 0x0051,
+ 0x6cc: 0x0051, 0x6cd: 0x0051, 0x6ce: 0x0091, 0x6cf: 0x00da, 0x6d0: 0x0053, 0x6d1: 0x0053,
+ 0x6d2: 0x0059, 0x6d3: 0x0099, 0x6d5: 0x005d, 0x6d6: 0x198d,
+ 0x6d9: 0x0061, 0x6da: 0x0063, 0x6db: 0x0065, 0x6dc: 0x0065, 0x6dd: 0x0065,
+ 0x6e0: 0x199f, 0x6e1: 0x1bc8, 0x6e2: 0x19a8,
+ 0x6e4: 0x0075, 0x6e6: 0x01b8, 0x6e8: 0x0075,
+ 0x6ea: 0x0057, 0x6eb: 0x42d2, 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: 0x1b98,
+ 0x6fc: 0x01e8, 0x6fd: 0x01c1, 0x6fe: 0x0179, 0x6ff: 0x01a0,
+ // Block 0x1c, offset 0x700
+ 0x700: 0x0463, 0x705: 0x0049,
+ 0x706: 0x0089, 0x707: 0x008b, 0x708: 0x0093, 0x709: 0x0095,
+ 0x710: 0x222e, 0x711: 0x223a,
+ 0x712: 0x22ee, 0x713: 0x2216, 0x714: 0x229a, 0x715: 0x2222, 0x716: 0x22a0, 0x717: 0x22b8,
+ 0x718: 0x22c4, 0x719: 0x2228, 0x71a: 0x22ca, 0x71b: 0x2234, 0x71c: 0x22be, 0x71d: 0x22d0,
+ 0x71e: 0x22d6, 0x71f: 0x1cbc, 0x720: 0x0053, 0x721: 0x195a, 0x722: 0x1ba4, 0x723: 0x1963,
+ 0x724: 0x006d, 0x725: 0x19ab, 0x726: 0x1bd0, 0x727: 0x1d48, 0x728: 0x1966, 0x729: 0x0071,
+ 0x72a: 0x19b7, 0x72b: 0x1bd4, 0x72c: 0x0059, 0x72d: 0x0047, 0x72e: 0x0049, 0x72f: 0x005b,
+ 0x730: 0x0093, 0x731: 0x19e4, 0x732: 0x1c18, 0x733: 0x19ed, 0x734: 0x00ad, 0x735: 0x1a62,
+ 0x736: 0x1c4c, 0x737: 0x1d5c, 0x738: 0x19f0, 0x739: 0x00b1, 0x73a: 0x1a65, 0x73b: 0x1c50,
+ 0x73c: 0x0099, 0x73d: 0x0087, 0x73e: 0x0089, 0x73f: 0x009b,
+ // Block 0x1d, offset 0x740
+ 0x741: 0x3c06, 0x743: 0xa000, 0x744: 0x3c0d, 0x745: 0xa000,
+ 0x747: 0x3c14, 0x748: 0xa000, 0x749: 0x3c1b,
+ 0x74d: 0xa000,
+ 0x760: 0x2f65, 0x761: 0xa000, 0x762: 0x3c29,
+ 0x764: 0xa000, 0x765: 0xa000,
+ 0x76d: 0x3c22, 0x76e: 0x2f60, 0x76f: 0x2f6a,
+ 0x770: 0x3c30, 0x771: 0x3c37, 0x772: 0xa000, 0x773: 0xa000, 0x774: 0x3c3e, 0x775: 0x3c45,
+ 0x776: 0xa000, 0x777: 0xa000, 0x778: 0x3c4c, 0x779: 0x3c53, 0x77a: 0xa000, 0x77b: 0xa000,
+ 0x77c: 0xa000, 0x77d: 0xa000,
+ // Block 0x1e, offset 0x780
+ 0x780: 0x3c5a, 0x781: 0x3c61, 0x782: 0xa000, 0x783: 0xa000, 0x784: 0x3c76, 0x785: 0x3c7d,
+ 0x786: 0xa000, 0x787: 0xa000, 0x788: 0x3c84, 0x789: 0x3c8b,
+ 0x791: 0xa000,
+ 0x792: 0xa000,
+ 0x7a2: 0xa000,
+ 0x7a8: 0xa000, 0x7a9: 0xa000,
+ 0x7ab: 0xa000, 0x7ac: 0x3ca0, 0x7ad: 0x3ca7, 0x7ae: 0x3cae, 0x7af: 0x3cb5,
+ 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: 0x1882,
+ 0x7ea: 0x1885, 0x7eb: 0x1888, 0x7ec: 0x188b, 0x7ed: 0x188e, 0x7ee: 0x1891, 0x7ef: 0x1894,
+ 0x7f0: 0x1897, 0x7f1: 0x189a, 0x7f2: 0x189d, 0x7f3: 0x18a6, 0x7f4: 0x1a68, 0x7f5: 0x1a6c,
+ 0x7f6: 0x1a70, 0x7f7: 0x1a74, 0x7f8: 0x1a78, 0x7f9: 0x1a7c, 0x7fa: 0x1a80, 0x7fb: 0x1a84,
+ 0x7fc: 0x1a88, 0x7fd: 0x1c80, 0x7fe: 0x1c85, 0x7ff: 0x1c8a,
+ // Block 0x20, offset 0x800
+ 0x800: 0x1c8f, 0x801: 0x1c94, 0x802: 0x1c99, 0x803: 0x1c9e, 0x804: 0x1ca3, 0x805: 0x1ca8,
+ 0x806: 0x1cad, 0x807: 0x1cb2, 0x808: 0x187f, 0x809: 0x18a3, 0x80a: 0x18c7, 0x80b: 0x18eb,
+ 0x80c: 0x190f, 0x80d: 0x1918, 0x80e: 0x191e, 0x80f: 0x1924, 0x810: 0x192a, 0x811: 0x1b60,
+ 0x812: 0x1b64, 0x813: 0x1b68, 0x814: 0x1b6c, 0x815: 0x1b70, 0x816: 0x1b74, 0x817: 0x1b78,
+ 0x818: 0x1b7c, 0x819: 0x1b80, 0x81a: 0x1b84, 0x81b: 0x1b88, 0x81c: 0x1af4, 0x81d: 0x1af8,
+ 0x81e: 0x1afc, 0x81f: 0x1b00, 0x820: 0x1b04, 0x821: 0x1b08, 0x822: 0x1b0c, 0x823: 0x1b10,
+ 0x824: 0x1b14, 0x825: 0x1b18, 0x826: 0x1b1c, 0x827: 0x1b20, 0x828: 0x1b24, 0x829: 0x1b28,
+ 0x82a: 0x1b2c, 0x82b: 0x1b30, 0x82c: 0x1b34, 0x82d: 0x1b38, 0x82e: 0x1b3c, 0x82f: 0x1b40,
+ 0x830: 0x1b44, 0x831: 0x1b48, 0x832: 0x1b4c, 0x833: 0x1b50, 0x834: 0x1b54, 0x835: 0x1b58,
+ 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: 0x06bf, 0x841: 0x06e3, 0x842: 0x06ef, 0x843: 0x06ff, 0x844: 0x0707, 0x845: 0x0713,
+ 0x846: 0x071b, 0x847: 0x0723, 0x848: 0x072f, 0x849: 0x0783, 0x84a: 0x079b, 0x84b: 0x07ab,
+ 0x84c: 0x07bb, 0x84d: 0x07cb, 0x84e: 0x07db, 0x84f: 0x07fb, 0x850: 0x07ff, 0x851: 0x0803,
+ 0x852: 0x0837, 0x853: 0x085f, 0x854: 0x086f, 0x855: 0x0877, 0x856: 0x087b, 0x857: 0x0887,
+ 0x858: 0x08a3, 0x859: 0x08a7, 0x85a: 0x08bf, 0x85b: 0x08c3, 0x85c: 0x08cb, 0x85d: 0x08db,
+ 0x85e: 0x0977, 0x85f: 0x098b, 0x860: 0x09cb, 0x861: 0x09df, 0x862: 0x09e7, 0x863: 0x09eb,
+ 0x864: 0x09fb, 0x865: 0x0a17, 0x866: 0x0a43, 0x867: 0x0a4f, 0x868: 0x0a6f, 0x869: 0x0a7b,
+ 0x86a: 0x0a7f, 0x86b: 0x0a83, 0x86c: 0x0a9b, 0x86d: 0x0a9f, 0x86e: 0x0acb, 0x86f: 0x0ad7,
+ 0x870: 0x0adf, 0x871: 0x0ae7, 0x872: 0x0af7, 0x873: 0x0aff, 0x874: 0x0b07, 0x875: 0x0b33,
+ 0x876: 0x0b37, 0x877: 0x0b3f, 0x878: 0x0b43, 0x879: 0x0b4b, 0x87a: 0x0b53, 0x87b: 0x0b63,
+ 0x87c: 0x0b7f, 0x87d: 0x0bf7, 0x87e: 0x0c0b, 0x87f: 0x0c0f,
+ // Block 0x22, offset 0x880
+ 0x880: 0x0c8f, 0x881: 0x0c93, 0x882: 0x0ca7, 0x883: 0x0cab, 0x884: 0x0cb3, 0x885: 0x0cbb,
+ 0x886: 0x0cc3, 0x887: 0x0ccf, 0x888: 0x0cf7, 0x889: 0x0d07, 0x88a: 0x0d1b, 0x88b: 0x0d8b,
+ 0x88c: 0x0d97, 0x88d: 0x0da7, 0x88e: 0x0db3, 0x88f: 0x0dbf, 0x890: 0x0dc7, 0x891: 0x0dcb,
+ 0x892: 0x0dcf, 0x893: 0x0dd3, 0x894: 0x0dd7, 0x895: 0x0e8f, 0x896: 0x0ed7, 0x897: 0x0ee3,
+ 0x898: 0x0ee7, 0x899: 0x0eeb, 0x89a: 0x0eef, 0x89b: 0x0ef7, 0x89c: 0x0efb, 0x89d: 0x0f0f,
+ 0x89e: 0x0f2b, 0x89f: 0x0f33, 0x8a0: 0x0f73, 0x8a1: 0x0f77, 0x8a2: 0x0f7f, 0x8a3: 0x0f83,
+ 0x8a4: 0x0f8b, 0x8a5: 0x0f8f, 0x8a6: 0x0fb3, 0x8a7: 0x0fb7, 0x8a8: 0x0fd3, 0x8a9: 0x0fd7,
+ 0x8aa: 0x0fdb, 0x8ab: 0x0fdf, 0x8ac: 0x0ff3, 0x8ad: 0x1017, 0x8ae: 0x101b, 0x8af: 0x101f,
+ 0x8b0: 0x1043, 0x8b1: 0x1083, 0x8b2: 0x1087, 0x8b3: 0x10a7, 0x8b4: 0x10b7, 0x8b5: 0x10bf,
+ 0x8b6: 0x10df, 0x8b7: 0x1103, 0x8b8: 0x1147, 0x8b9: 0x114f, 0x8ba: 0x1163, 0x8bb: 0x116f,
+ 0x8bc: 0x1177, 0x8bd: 0x117f, 0x8be: 0x1183, 0x8bf: 0x1187,
+ // Block 0x23, offset 0x8c0
+ 0x8c0: 0x119f, 0x8c1: 0x11a3, 0x8c2: 0x11bf, 0x8c3: 0x11c7, 0x8c4: 0x11cf, 0x8c5: 0x11d3,
+ 0x8c6: 0x11df, 0x8c7: 0x11e7, 0x8c8: 0x11eb, 0x8c9: 0x11ef, 0x8ca: 0x11f7, 0x8cb: 0x11fb,
+ 0x8cc: 0x129b, 0x8cd: 0x12af, 0x8ce: 0x12e3, 0x8cf: 0x12e7, 0x8d0: 0x12ef, 0x8d1: 0x131b,
+ 0x8d2: 0x1323, 0x8d3: 0x132b, 0x8d4: 0x1333, 0x8d5: 0x136f, 0x8d6: 0x1373, 0x8d7: 0x137b,
+ 0x8d8: 0x137f, 0x8d9: 0x1383, 0x8da: 0x13af, 0x8db: 0x13b3, 0x8dc: 0x13bb, 0x8dd: 0x13cf,
+ 0x8de: 0x13d3, 0x8df: 0x13ef, 0x8e0: 0x13f7, 0x8e1: 0x13fb, 0x8e2: 0x141f, 0x8e3: 0x143f,
+ 0x8e4: 0x1453, 0x8e5: 0x1457, 0x8e6: 0x145f, 0x8e7: 0x148b, 0x8e8: 0x148f, 0x8e9: 0x149f,
+ 0x8ea: 0x14c3, 0x8eb: 0x14cf, 0x8ec: 0x14df, 0x8ed: 0x14f7, 0x8ee: 0x14ff, 0x8ef: 0x1503,
+ 0x8f0: 0x1507, 0x8f1: 0x150b, 0x8f2: 0x1517, 0x8f3: 0x151b, 0x8f4: 0x1523, 0x8f5: 0x153f,
+ 0x8f6: 0x1543, 0x8f7: 0x1547, 0x8f8: 0x155f, 0x8f9: 0x1563, 0x8fa: 0x156b, 0x8fb: 0x157f,
+ 0x8fc: 0x1583, 0x8fd: 0x1587, 0x8fe: 0x158f, 0x8ff: 0x1593,
+ // Block 0x24, offset 0x900
+ 0x906: 0xa000, 0x90b: 0xa000,
+ 0x90c: 0x3f08, 0x90d: 0xa000, 0x90e: 0x3f10, 0x90f: 0xa000, 0x910: 0x3f18, 0x911: 0xa000,
+ 0x912: 0x3f20, 0x913: 0xa000, 0x914: 0x3f28, 0x915: 0xa000, 0x916: 0x3f30, 0x917: 0xa000,
+ 0x918: 0x3f38, 0x919: 0xa000, 0x91a: 0x3f40, 0x91b: 0xa000, 0x91c: 0x3f48, 0x91d: 0xa000,
+ 0x91e: 0x3f50, 0x91f: 0xa000, 0x920: 0x3f58, 0x921: 0xa000, 0x922: 0x3f60,
+ 0x924: 0xa000, 0x925: 0x3f68, 0x926: 0xa000, 0x927: 0x3f70, 0x928: 0xa000, 0x929: 0x3f78,
+ 0x92f: 0xa000,
+ 0x930: 0x3f80, 0x931: 0x3f88, 0x932: 0xa000, 0x933: 0x3f90, 0x934: 0x3f98, 0x935: 0xa000,
+ 0x936: 0x3fa0, 0x937: 0x3fa8, 0x938: 0xa000, 0x939: 0x3fb0, 0x93a: 0x3fb8, 0x93b: 0xa000,
+ 0x93c: 0x3fc0, 0x93d: 0x3fc8,
+ // Block 0x25, offset 0x940
+ 0x954: 0x3f00,
+ 0x959: 0x9903, 0x95a: 0x9903, 0x95b: 0x4372, 0x95c: 0x4378, 0x95d: 0xa000,
+ 0x95e: 0x3fd0, 0x95f: 0x26b4,
+ 0x966: 0xa000,
+ 0x96b: 0xa000, 0x96c: 0x3fe0, 0x96d: 0xa000, 0x96e: 0x3fe8, 0x96f: 0xa000,
+ 0x970: 0x3ff0, 0x971: 0xa000, 0x972: 0x3ff8, 0x973: 0xa000, 0x974: 0x4000, 0x975: 0xa000,
+ 0x976: 0x4008, 0x977: 0xa000, 0x978: 0x4010, 0x979: 0xa000, 0x97a: 0x4018, 0x97b: 0xa000,
+ 0x97c: 0x4020, 0x97d: 0xa000, 0x97e: 0x4028, 0x97f: 0xa000,
+ // Block 0x26, offset 0x980
+ 0x980: 0x4030, 0x981: 0xa000, 0x982: 0x4038, 0x984: 0xa000, 0x985: 0x4040,
+ 0x986: 0xa000, 0x987: 0x4048, 0x988: 0xa000, 0x989: 0x4050,
+ 0x98f: 0xa000, 0x990: 0x4058, 0x991: 0x4060,
+ 0x992: 0xa000, 0x993: 0x4068, 0x994: 0x4070, 0x995: 0xa000, 0x996: 0x4078, 0x997: 0x4080,
+ 0x998: 0xa000, 0x999: 0x4088, 0x99a: 0x4090, 0x99b: 0xa000, 0x99c: 0x4098, 0x99d: 0x40a0,
+ 0x9af: 0xa000,
+ 0x9b0: 0xa000, 0x9b1: 0xa000, 0x9b2: 0xa000, 0x9b4: 0x3fd8,
+ 0x9b7: 0x40a8, 0x9b8: 0x40b0, 0x9b9: 0x40b8, 0x9ba: 0x40c0,
+ 0x9bd: 0xa000, 0x9be: 0x40c8, 0x9bf: 0x26c9,
+ // Block 0x27, offset 0x9c0
+ 0x9c0: 0x0367, 0x9c1: 0x032b, 0x9c2: 0x032f, 0x9c3: 0x0333, 0x9c4: 0x037b, 0x9c5: 0x0337,
+ 0x9c6: 0x033b, 0x9c7: 0x033f, 0x9c8: 0x0343, 0x9c9: 0x0347, 0x9ca: 0x034b, 0x9cb: 0x034f,
+ 0x9cc: 0x0353, 0x9cd: 0x0357, 0x9ce: 0x035b, 0x9cf: 0x42dc, 0x9d0: 0x42e1, 0x9d1: 0x42e6,
+ 0x9d2: 0x42eb, 0x9d3: 0x42f0, 0x9d4: 0x42f5, 0x9d5: 0x42fa, 0x9d6: 0x42ff, 0x9d7: 0x4304,
+ 0x9d8: 0x4309, 0x9d9: 0x430e, 0x9da: 0x4313, 0x9db: 0x4318, 0x9dc: 0x431d, 0x9dd: 0x4322,
+ 0x9de: 0x4327, 0x9df: 0x432c, 0x9e0: 0x4331, 0x9e1: 0x4336, 0x9e2: 0x433b, 0x9e3: 0x4340,
+ 0x9e4: 0x03c3, 0x9e5: 0x035f, 0x9e6: 0x0363, 0x9e7: 0x03e7, 0x9e8: 0x03eb, 0x9e9: 0x03ef,
+ 0x9ea: 0x03f3, 0x9eb: 0x03f7, 0x9ec: 0x03fb, 0x9ed: 0x03ff, 0x9ee: 0x036b, 0x9ef: 0x0403,
+ 0x9f0: 0x0407, 0x9f1: 0x036f, 0x9f2: 0x0373, 0x9f3: 0x0377, 0x9f4: 0x037f, 0x9f5: 0x0383,
+ 0x9f6: 0x0387, 0x9f7: 0x038b, 0x9f8: 0x038f, 0x9f9: 0x0393, 0x9fa: 0x0397, 0x9fb: 0x039b,
+ 0x9fc: 0x039f, 0x9fd: 0x03a3, 0x9fe: 0x03a7, 0x9ff: 0x03ab,
+ // Block 0x28, offset 0xa00
+ 0xa00: 0x03af, 0xa01: 0x03b3, 0xa02: 0x040b, 0xa03: 0x040f, 0xa04: 0x03b7, 0xa05: 0x03bb,
+ 0xa06: 0x03bf, 0xa07: 0x03c7, 0xa08: 0x03cb, 0xa09: 0x03cf, 0xa0a: 0x03d3, 0xa0b: 0x03d7,
+ 0xa0c: 0x03db, 0xa0d: 0x03df, 0xa0e: 0x03e3,
+ 0xa12: 0x06bf, 0xa13: 0x071b, 0xa14: 0x06cb, 0xa15: 0x097b, 0xa16: 0x06cf, 0xa17: 0x06e7,
+ 0xa18: 0x06d3, 0xa19: 0x0f93, 0xa1a: 0x0707, 0xa1b: 0x06db, 0xa1c: 0x06c3, 0xa1d: 0x09ff,
+ 0xa1e: 0x098f, 0xa1f: 0x072f,
+ // Block 0x29, offset 0xa40
+ 0xa40: 0x2054, 0xa41: 0x205a, 0xa42: 0x2060, 0xa43: 0x2066, 0xa44: 0x206c, 0xa45: 0x2072,
+ 0xa46: 0x2078, 0xa47: 0x207e, 0xa48: 0x2084, 0xa49: 0x208a, 0xa4a: 0x2090, 0xa4b: 0x2096,
+ 0xa4c: 0x209c, 0xa4d: 0x20a2, 0xa4e: 0x2726, 0xa4f: 0x272f, 0xa50: 0x2738, 0xa51: 0x2741,
+ 0xa52: 0x274a, 0xa53: 0x2753, 0xa54: 0x275c, 0xa55: 0x2765, 0xa56: 0x276e, 0xa57: 0x2780,
+ 0xa58: 0x2789, 0xa59: 0x2792, 0xa5a: 0x279b, 0xa5b: 0x27a4, 0xa5c: 0x2777, 0xa5d: 0x2bac,
+ 0xa5e: 0x2aed, 0xa60: 0x20a8, 0xa61: 0x20c0, 0xa62: 0x20b4, 0xa63: 0x2108,
+ 0xa64: 0x20c6, 0xa65: 0x20e4, 0xa66: 0x20ae, 0xa67: 0x20de, 0xa68: 0x20ba, 0xa69: 0x20f0,
+ 0xa6a: 0x2120, 0xa6b: 0x213e, 0xa6c: 0x2138, 0xa6d: 0x212c, 0xa6e: 0x217a, 0xa6f: 0x210e,
+ 0xa70: 0x211a, 0xa71: 0x2132, 0xa72: 0x2126, 0xa73: 0x2150, 0xa74: 0x20fc, 0xa75: 0x2144,
+ 0xa76: 0x216e, 0xa77: 0x2156, 0xa78: 0x20ea, 0xa79: 0x20cc, 0xa7a: 0x2102, 0xa7b: 0x2114,
+ 0xa7c: 0x214a, 0xa7d: 0x20d2, 0xa7e: 0x2174, 0xa7f: 0x20f6,
+ // Block 0x2a, offset 0xa80
+ 0xa80: 0x215c, 0xa81: 0x20d8, 0xa82: 0x2162, 0xa83: 0x2168, 0xa84: 0x092f, 0xa85: 0x0b03,
+ 0xa86: 0x0ca7, 0xa87: 0x10c7,
+ 0xa90: 0x1bc4, 0xa91: 0x18a9,
+ 0xa92: 0x18ac, 0xa93: 0x18af, 0xa94: 0x18b2, 0xa95: 0x18b5, 0xa96: 0x18b8, 0xa97: 0x18bb,
+ 0xa98: 0x18be, 0xa99: 0x18c1, 0xa9a: 0x18ca, 0xa9b: 0x18cd, 0xa9c: 0x18d0, 0xa9d: 0x18d3,
+ 0xa9e: 0x18d6, 0xa9f: 0x18d9, 0xaa0: 0x0313, 0xaa1: 0x031b, 0xaa2: 0x031f, 0xaa3: 0x0327,
+ 0xaa4: 0x032b, 0xaa5: 0x032f, 0xaa6: 0x0337, 0xaa7: 0x033f, 0xaa8: 0x0343, 0xaa9: 0x034b,
+ 0xaaa: 0x034f, 0xaab: 0x0353, 0xaac: 0x0357, 0xaad: 0x035b, 0xaae: 0x2e18, 0xaaf: 0x2e20,
+ 0xab0: 0x2e28, 0xab1: 0x2e30, 0xab2: 0x2e38, 0xab3: 0x2e40, 0xab4: 0x2e48, 0xab5: 0x2e50,
+ 0xab6: 0x2e60, 0xab7: 0x2e68, 0xab8: 0x2e70, 0xab9: 0x2e78, 0xaba: 0x2e80, 0xabb: 0x2e88,
+ 0xabc: 0x2ed3, 0xabd: 0x2e9b, 0xabe: 0x2e58,
+ // Block 0x2b, offset 0xac0
+ 0xac0: 0x06bf, 0xac1: 0x071b, 0xac2: 0x06cb, 0xac3: 0x097b, 0xac4: 0x071f, 0xac5: 0x07af,
+ 0xac6: 0x06c7, 0xac7: 0x07ab, 0xac8: 0x070b, 0xac9: 0x0887, 0xaca: 0x0d07, 0xacb: 0x0e8f,
+ 0xacc: 0x0dd7, 0xacd: 0x0d1b, 0xace: 0x145f, 0xacf: 0x098b, 0xad0: 0x0ccf, 0xad1: 0x0d4b,
+ 0xad2: 0x0d0b, 0xad3: 0x104b, 0xad4: 0x08fb, 0xad5: 0x0f03, 0xad6: 0x1387, 0xad7: 0x105f,
+ 0xad8: 0x0843, 0xad9: 0x108f, 0xada: 0x0f9b, 0xadb: 0x0a17, 0xadc: 0x140f, 0xadd: 0x077f,
+ 0xade: 0x08ab, 0xadf: 0x0df7, 0xae0: 0x1527, 0xae1: 0x0743, 0xae2: 0x07d3, 0xae3: 0x0d9b,
+ 0xae4: 0x06cf, 0xae5: 0x06e7, 0xae6: 0x06d3, 0xae7: 0x0adb, 0xae8: 0x08ef, 0xae9: 0x087f,
+ 0xaea: 0x0a57, 0xaeb: 0x0a4b, 0xaec: 0x0feb, 0xaed: 0x073f, 0xaee: 0x139b, 0xaef: 0x089b,
+ 0xaf0: 0x09f3, 0xaf1: 0x18dc, 0xaf2: 0x18df, 0xaf3: 0x18e2, 0xaf4: 0x18e5, 0xaf5: 0x18ee,
+ 0xaf6: 0x18f1, 0xaf7: 0x18f4, 0xaf8: 0x18f7, 0xaf9: 0x18fa, 0xafa: 0x18fd, 0xafb: 0x1900,
+ 0xafc: 0x1903, 0xafd: 0x1906, 0xafe: 0x1909, 0xaff: 0x1912,
+ // Block 0x2c, offset 0xb00
+ 0xb00: 0x1cc6, 0xb01: 0x1cd5, 0xb02: 0x1ce4, 0xb03: 0x1cf3, 0xb04: 0x1d02, 0xb05: 0x1d11,
+ 0xb06: 0x1d20, 0xb07: 0x1d2f, 0xb08: 0x1d3e, 0xb09: 0x218c, 0xb0a: 0x219e, 0xb0b: 0x21b0,
+ 0xb0c: 0x1954, 0xb0d: 0x1c04, 0xb0e: 0x19d2, 0xb0f: 0x1ba8, 0xb10: 0x04cb, 0xb11: 0x04d3,
+ 0xb12: 0x04db, 0xb13: 0x04e3, 0xb14: 0x04eb, 0xb15: 0x04ef, 0xb16: 0x04f3, 0xb17: 0x04f7,
+ 0xb18: 0x04fb, 0xb19: 0x04ff, 0xb1a: 0x0503, 0xb1b: 0x0507, 0xb1c: 0x050b, 0xb1d: 0x050f,
+ 0xb1e: 0x0513, 0xb1f: 0x0517, 0xb20: 0x051b, 0xb21: 0x0523, 0xb22: 0x0527, 0xb23: 0x052b,
+ 0xb24: 0x052f, 0xb25: 0x0533, 0xb26: 0x0537, 0xb27: 0x053b, 0xb28: 0x053f, 0xb29: 0x0543,
+ 0xb2a: 0x0547, 0xb2b: 0x054b, 0xb2c: 0x054f, 0xb2d: 0x0553, 0xb2e: 0x0557, 0xb2f: 0x055b,
+ 0xb30: 0x055f, 0xb31: 0x0563, 0xb32: 0x0567, 0xb33: 0x056f, 0xb34: 0x0577, 0xb35: 0x057f,
+ 0xb36: 0x0583, 0xb37: 0x0587, 0xb38: 0x058b, 0xb39: 0x058f, 0xb3a: 0x0593, 0xb3b: 0x0597,
+ 0xb3c: 0x059b, 0xb3d: 0x059f, 0xb3e: 0x05a3,
+ // Block 0x2d, offset 0xb40
+ 0xb40: 0x2b0c, 0xb41: 0x29a8, 0xb42: 0x2b1c, 0xb43: 0x2880, 0xb44: 0x2ee4, 0xb45: 0x288a,
+ 0xb46: 0x2894, 0xb47: 0x2f28, 0xb48: 0x29b5, 0xb49: 0x289e, 0xb4a: 0x28a8, 0xb4b: 0x28b2,
+ 0xb4c: 0x29dc, 0xb4d: 0x29e9, 0xb4e: 0x29c2, 0xb4f: 0x29cf, 0xb50: 0x2ea9, 0xb51: 0x29f6,
+ 0xb52: 0x2a03, 0xb53: 0x2bbe, 0xb54: 0x26bb, 0xb55: 0x2bd1, 0xb56: 0x2be4, 0xb57: 0x2b2c,
+ 0xb58: 0x2a10, 0xb59: 0x2bf7, 0xb5a: 0x2c0a, 0xb5b: 0x2a1d, 0xb5c: 0x28bc, 0xb5d: 0x28c6,
+ 0xb5e: 0x2eb7, 0xb5f: 0x2a2a, 0xb60: 0x2b3c, 0xb61: 0x2ef5, 0xb62: 0x28d0, 0xb63: 0x28da,
+ 0xb64: 0x2a37, 0xb65: 0x28e4, 0xb66: 0x28ee, 0xb67: 0x26d0, 0xb68: 0x26d7, 0xb69: 0x28f8,
+ 0xb6a: 0x2902, 0xb6b: 0x2c1d, 0xb6c: 0x2a44, 0xb6d: 0x2b4c, 0xb6e: 0x2c30, 0xb6f: 0x2a51,
+ 0xb70: 0x2916, 0xb71: 0x290c, 0xb72: 0x2f3c, 0xb73: 0x2a5e, 0xb74: 0x2c43, 0xb75: 0x2920,
+ 0xb76: 0x2b5c, 0xb77: 0x292a, 0xb78: 0x2a78, 0xb79: 0x2934, 0xb7a: 0x2a85, 0xb7b: 0x2f06,
+ 0xb7c: 0x2a6b, 0xb7d: 0x2b6c, 0xb7e: 0x2a92, 0xb7f: 0x26de,
+ // Block 0x2e, offset 0xb80
+ 0xb80: 0x2f17, 0xb81: 0x293e, 0xb82: 0x2948, 0xb83: 0x2a9f, 0xb84: 0x2952, 0xb85: 0x295c,
+ 0xb86: 0x2966, 0xb87: 0x2b7c, 0xb88: 0x2aac, 0xb89: 0x26e5, 0xb8a: 0x2c56, 0xb8b: 0x2e90,
+ 0xb8c: 0x2b8c, 0xb8d: 0x2ab9, 0xb8e: 0x2ec5, 0xb8f: 0x2970, 0xb90: 0x297a, 0xb91: 0x2ac6,
+ 0xb92: 0x26ec, 0xb93: 0x2ad3, 0xb94: 0x2b9c, 0xb95: 0x26f3, 0xb96: 0x2c69, 0xb97: 0x2984,
+ 0xb98: 0x1cb7, 0xb99: 0x1ccb, 0xb9a: 0x1cda, 0xb9b: 0x1ce9, 0xb9c: 0x1cf8, 0xb9d: 0x1d07,
+ 0xb9e: 0x1d16, 0xb9f: 0x1d25, 0xba0: 0x1d34, 0xba1: 0x1d43, 0xba2: 0x2192, 0xba3: 0x21a4,
+ 0xba4: 0x21b6, 0xba5: 0x21c2, 0xba6: 0x21ce, 0xba7: 0x21da, 0xba8: 0x21e6, 0xba9: 0x21f2,
+ 0xbaa: 0x21fe, 0xbab: 0x220a, 0xbac: 0x2246, 0xbad: 0x2252, 0xbae: 0x225e, 0xbaf: 0x226a,
+ 0xbb0: 0x2276, 0xbb1: 0x1c14, 0xbb2: 0x19c6, 0xbb3: 0x1936, 0xbb4: 0x1be4, 0xbb5: 0x1a47,
+ 0xbb6: 0x1a56, 0xbb7: 0x19cc, 0xbb8: 0x1bfc, 0xbb9: 0x1c00, 0xbba: 0x1960, 0xbbb: 0x2701,
+ 0xbbc: 0x270f, 0xbbd: 0x26fa, 0xbbe: 0x2708, 0xbbf: 0x2ae0,
+ // Block 0x2f, offset 0xbc0
+ 0xbc0: 0x1a4a, 0xbc1: 0x1a32, 0xbc2: 0x1c60, 0xbc3: 0x1a1a, 0xbc4: 0x19f3, 0xbc5: 0x1969,
+ 0xbc6: 0x1978, 0xbc7: 0x1948, 0xbc8: 0x1bf0, 0xbc9: 0x1d52, 0xbca: 0x1a4d, 0xbcb: 0x1a35,
+ 0xbcc: 0x1c64, 0xbcd: 0x1c70, 0xbce: 0x1a26, 0xbcf: 0x19fc, 0xbd0: 0x1957, 0xbd1: 0x1c1c,
+ 0xbd2: 0x1bb0, 0xbd3: 0x1b9c, 0xbd4: 0x1bcc, 0xbd5: 0x1c74, 0xbd6: 0x1a29, 0xbd7: 0x19c9,
+ 0xbd8: 0x19ff, 0xbd9: 0x19de, 0xbda: 0x1a41, 0xbdb: 0x1c78, 0xbdc: 0x1a2c, 0xbdd: 0x19c0,
+ 0xbde: 0x1a02, 0xbdf: 0x1c3c, 0xbe0: 0x1bf4, 0xbe1: 0x1a14, 0xbe2: 0x1c24, 0xbe3: 0x1c40,
+ 0xbe4: 0x1bf8, 0xbe5: 0x1a17, 0xbe6: 0x1c28, 0xbe7: 0x22e8, 0xbe8: 0x22fc, 0xbe9: 0x1996,
+ 0xbea: 0x1c20, 0xbeb: 0x1bb4, 0xbec: 0x1ba0, 0xbed: 0x1c48, 0xbee: 0x2716, 0xbef: 0x27ad,
+ 0xbf0: 0x1a59, 0xbf1: 0x1a44, 0xbf2: 0x1c7c, 0xbf3: 0x1a2f, 0xbf4: 0x1a50, 0xbf5: 0x1a38,
+ 0xbf6: 0x1c68, 0xbf7: 0x1a1d, 0xbf8: 0x19f6, 0xbf9: 0x1981, 0xbfa: 0x1a53, 0xbfb: 0x1a3b,
+ 0xbfc: 0x1c6c, 0xbfd: 0x1a20, 0xbfe: 0x19f9, 0xbff: 0x1984,
+ // Block 0x30, offset 0xc00
+ 0xc00: 0x1c2c, 0xc01: 0x1bb8, 0xc02: 0x1d4d, 0xc03: 0x1939, 0xc04: 0x19ba, 0xc05: 0x19bd,
+ 0xc06: 0x22f5, 0xc07: 0x1b94, 0xc08: 0x19c3, 0xc09: 0x194b, 0xc0a: 0x19e1, 0xc0b: 0x194e,
+ 0xc0c: 0x19ea, 0xc0d: 0x196c, 0xc0e: 0x196f, 0xc0f: 0x1a05, 0xc10: 0x1a0b, 0xc11: 0x1a0e,
+ 0xc12: 0x1c30, 0xc13: 0x1a11, 0xc14: 0x1a23, 0xc15: 0x1c38, 0xc16: 0x1c44, 0xc17: 0x1990,
+ 0xc18: 0x1d57, 0xc19: 0x1bbc, 0xc1a: 0x1993, 0xc1b: 0x1a5c, 0xc1c: 0x19a5, 0xc1d: 0x19b4,
+ 0xc1e: 0x22e2, 0xc1f: 0x22dc, 0xc20: 0x1cc1, 0xc21: 0x1cd0, 0xc22: 0x1cdf, 0xc23: 0x1cee,
+ 0xc24: 0x1cfd, 0xc25: 0x1d0c, 0xc26: 0x1d1b, 0xc27: 0x1d2a, 0xc28: 0x1d39, 0xc29: 0x2186,
+ 0xc2a: 0x2198, 0xc2b: 0x21aa, 0xc2c: 0x21bc, 0xc2d: 0x21c8, 0xc2e: 0x21d4, 0xc2f: 0x21e0,
+ 0xc30: 0x21ec, 0xc31: 0x21f8, 0xc32: 0x2204, 0xc33: 0x2240, 0xc34: 0x224c, 0xc35: 0x2258,
+ 0xc36: 0x2264, 0xc37: 0x2270, 0xc38: 0x227c, 0xc39: 0x2282, 0xc3a: 0x2288, 0xc3b: 0x228e,
+ 0xc3c: 0x2294, 0xc3d: 0x22a6, 0xc3e: 0x22ac, 0xc3f: 0x1c10,
+ // Block 0x31, offset 0xc40
+ 0xc40: 0x1377, 0xc41: 0x0cfb, 0xc42: 0x13d3, 0xc43: 0x139f, 0xc44: 0x0e57, 0xc45: 0x06eb,
+ 0xc46: 0x08df, 0xc47: 0x162b, 0xc48: 0x162b, 0xc49: 0x0a0b, 0xc4a: 0x145f, 0xc4b: 0x0943,
+ 0xc4c: 0x0a07, 0xc4d: 0x0bef, 0xc4e: 0x0fcf, 0xc4f: 0x115f, 0xc50: 0x1297, 0xc51: 0x12d3,
+ 0xc52: 0x1307, 0xc53: 0x141b, 0xc54: 0x0d73, 0xc55: 0x0dff, 0xc56: 0x0eab, 0xc57: 0x0f43,
+ 0xc58: 0x125f, 0xc59: 0x1447, 0xc5a: 0x1573, 0xc5b: 0x070f, 0xc5c: 0x08b3, 0xc5d: 0x0d87,
+ 0xc5e: 0x0ecf, 0xc5f: 0x1293, 0xc60: 0x15c3, 0xc61: 0x0ab3, 0xc62: 0x0e77, 0xc63: 0x1283,
+ 0xc64: 0x1317, 0xc65: 0x0c23, 0xc66: 0x11bb, 0xc67: 0x12df, 0xc68: 0x0b1f, 0xc69: 0x0d0f,
+ 0xc6a: 0x0e17, 0xc6b: 0x0f1b, 0xc6c: 0x1427, 0xc6d: 0x074f, 0xc6e: 0x07e7, 0xc6f: 0x0853,
+ 0xc70: 0x0c8b, 0xc71: 0x0d7f, 0xc72: 0x0ecb, 0xc73: 0x0fef, 0xc74: 0x1177, 0xc75: 0x128b,
+ 0xc76: 0x12a3, 0xc77: 0x13c7, 0xc78: 0x14ef, 0xc79: 0x15a3, 0xc7a: 0x15bf, 0xc7b: 0x102b,
+ 0xc7c: 0x106b, 0xc7d: 0x1123, 0xc7e: 0x1243, 0xc7f: 0x147b,
+ // Block 0x32, offset 0xc80
+ 0xc80: 0x15cb, 0xc81: 0x134b, 0xc82: 0x09c7, 0xc83: 0x0b3b, 0xc84: 0x10db, 0xc85: 0x119b,
+ 0xc86: 0x0eff, 0xc87: 0x1033, 0xc88: 0x1397, 0xc89: 0x14e7, 0xc8a: 0x09c3, 0xc8b: 0x0a8f,
+ 0xc8c: 0x0d77, 0xc8d: 0x0e2b, 0xc8e: 0x0e5f, 0xc8f: 0x1113, 0xc90: 0x113b, 0xc91: 0x14a7,
+ 0xc92: 0x084f, 0xc93: 0x11a7, 0xc94: 0x07f3, 0xc95: 0x07ef, 0xc96: 0x1097, 0xc97: 0x1127,
+ 0xc98: 0x125b, 0xc99: 0x14af, 0xc9a: 0x1367, 0xc9b: 0x0c27, 0xc9c: 0x0d73, 0xc9d: 0x1357,
+ 0xc9e: 0x06f7, 0xc9f: 0x0a63, 0xca0: 0x0b93, 0xca1: 0x0f2f, 0xca2: 0x0faf, 0xca3: 0x0873,
+ 0xca4: 0x103b, 0xca5: 0x075f, 0xca6: 0x0b77, 0xca7: 0x06d7, 0xca8: 0x0deb, 0xca9: 0x0ca3,
+ 0xcaa: 0x110f, 0xcab: 0x08c7, 0xcac: 0x09b3, 0xcad: 0x0ffb, 0xcae: 0x1263, 0xcaf: 0x133b,
+ 0xcb0: 0x0db7, 0xcb1: 0x13f7, 0xcb2: 0x0de3, 0xcb3: 0x0c37, 0xcb4: 0x121b, 0xcb5: 0x0c57,
+ 0xcb6: 0x0fab, 0xcb7: 0x072b, 0xcb8: 0x07a7, 0xcb9: 0x07eb, 0xcba: 0x0d53, 0xcbb: 0x10fb,
+ 0xcbc: 0x11f3, 0xcbd: 0x1347, 0xcbe: 0x145b, 0xcbf: 0x085b,
+ // Block 0x33, offset 0xcc0
+ 0xcc0: 0x090f, 0xcc1: 0x0a17, 0xcc2: 0x0b2f, 0xcc3: 0x0cbf, 0xcc4: 0x0e7b, 0xcc5: 0x103f,
+ 0xcc6: 0x1497, 0xcc7: 0x157b, 0xcc8: 0x15cf, 0xcc9: 0x15e7, 0xcca: 0x0837, 0xccb: 0x0cf3,
+ 0xccc: 0x0da3, 0xccd: 0x13eb, 0xcce: 0x0afb, 0xccf: 0x0bd7, 0xcd0: 0x0bf3, 0xcd1: 0x0c83,
+ 0xcd2: 0x0e6b, 0xcd3: 0x0eb7, 0xcd4: 0x0f67, 0xcd5: 0x108b, 0xcd6: 0x112f, 0xcd7: 0x1193,
+ 0xcd8: 0x13db, 0xcd9: 0x126b, 0xcda: 0x1403, 0xcdb: 0x147f, 0xcdc: 0x080f, 0xcdd: 0x083b,
+ 0xcde: 0x0923, 0xcdf: 0x0ea7, 0xce0: 0x12f3, 0xce1: 0x133b, 0xce2: 0x0b1b, 0xce3: 0x0b8b,
+ 0xce4: 0x0c4f, 0xce5: 0x0daf, 0xce6: 0x10d7, 0xce7: 0x0f23, 0xce8: 0x073b, 0xce9: 0x097f,
+ 0xcea: 0x0a63, 0xceb: 0x0ac7, 0xcec: 0x0b97, 0xced: 0x0f3f, 0xcee: 0x0f5b, 0xcef: 0x116b,
+ 0xcf0: 0x118b, 0xcf1: 0x1463, 0xcf2: 0x14e3, 0xcf3: 0x14f3, 0xcf4: 0x152f, 0xcf5: 0x0753,
+ 0xcf6: 0x107f, 0xcf7: 0x144f, 0xcf8: 0x14cb, 0xcf9: 0x0baf, 0xcfa: 0x0717, 0xcfb: 0x0777,
+ 0xcfc: 0x0a67, 0xcfd: 0x0a87, 0xcfe: 0x0caf, 0xcff: 0x0d73,
+ // Block 0x34, offset 0xd00
+ 0xd00: 0x0ec3, 0xd01: 0x0fcb, 0xd02: 0x1277, 0xd03: 0x1417, 0xd04: 0x1623, 0xd05: 0x0ce3,
+ 0xd06: 0x14a3, 0xd07: 0x0833, 0xd08: 0x0d2f, 0xd09: 0x0d3b, 0xd0a: 0x0e0f, 0xd0b: 0x0e47,
+ 0xd0c: 0x0f4b, 0xd0d: 0x0fa7, 0xd0e: 0x1027, 0xd0f: 0x110b, 0xd10: 0x153b, 0xd11: 0x07af,
+ 0xd12: 0x0c03, 0xd13: 0x14b3, 0xd14: 0x0767, 0xd15: 0x0aab, 0xd16: 0x0e2f, 0xd17: 0x13df,
+ 0xd18: 0x0b67, 0xd19: 0x0bb7, 0xd1a: 0x0d43, 0xd1b: 0x0f2f, 0xd1c: 0x14bb, 0xd1d: 0x0817,
+ 0xd1e: 0x08ff, 0xd1f: 0x0a97, 0xd20: 0x0cd3, 0xd21: 0x0d1f, 0xd22: 0x0d5f, 0xd23: 0x0df3,
+ 0xd24: 0x0f47, 0xd25: 0x0fbb, 0xd26: 0x1157, 0xd27: 0x12f7, 0xd28: 0x1303, 0xd29: 0x1457,
+ 0xd2a: 0x14d7, 0xd2b: 0x0883, 0xd2c: 0x0e4b, 0xd2d: 0x0903, 0xd2e: 0x0ec7, 0xd2f: 0x0f6b,
+ 0xd30: 0x1287, 0xd31: 0x14bf, 0xd32: 0x15ab, 0xd33: 0x15d3, 0xd34: 0x0d37, 0xd35: 0x0e27,
+ 0xd36: 0x11c3, 0xd37: 0x10b7, 0xd38: 0x10c3, 0xd39: 0x10e7, 0xd3a: 0x0f17, 0xd3b: 0x0e9f,
+ 0xd3c: 0x1363, 0xd3d: 0x0733, 0xd3e: 0x122b, 0xd3f: 0x081b,
+ // Block 0x35, offset 0xd40
+ 0xd40: 0x080b, 0xd41: 0x0b0b, 0xd42: 0x0c2b, 0xd43: 0x10f3, 0xd44: 0x0a53, 0xd45: 0x0e03,
+ 0xd46: 0x0cef, 0xd47: 0x13e7, 0xd48: 0x12e7, 0xd49: 0x14ab, 0xd4a: 0x1323, 0xd4b: 0x0b27,
+ 0xd4c: 0x0787, 0xd4d: 0x095b, 0xd50: 0x09af,
+ 0xd52: 0x0cdf, 0xd55: 0x07f7, 0xd56: 0x0f1f, 0xd57: 0x0fe3,
+ 0xd58: 0x1047, 0xd59: 0x1063, 0xd5a: 0x1067, 0xd5b: 0x107b, 0xd5c: 0x14fb, 0xd5d: 0x10eb,
+ 0xd5e: 0x116f, 0xd60: 0x128f, 0xd62: 0x1353,
+ 0xd65: 0x1407, 0xd66: 0x1433,
+ 0xd6a: 0x154f, 0xd6b: 0x1553, 0xd6c: 0x1557, 0xd6d: 0x15bb, 0xd6e: 0x142b, 0xd6f: 0x14c7,
+ 0xd70: 0x0757, 0xd71: 0x077b, 0xd72: 0x078f, 0xd73: 0x084b, 0xd74: 0x0857, 0xd75: 0x0897,
+ 0xd76: 0x094b, 0xd77: 0x0967, 0xd78: 0x096f, 0xd79: 0x09ab, 0xd7a: 0x09b7, 0xd7b: 0x0a93,
+ 0xd7c: 0x0a9b, 0xd7d: 0x0ba3, 0xd7e: 0x0bcb, 0xd7f: 0x0bd3,
+ // Block 0x36, offset 0xd80
+ 0xd80: 0x0beb, 0xd81: 0x0c97, 0xd82: 0x0cc7, 0xd83: 0x0ce7, 0xd84: 0x0d57, 0xd85: 0x0e1b,
+ 0xd86: 0x0e37, 0xd87: 0x0e67, 0xd88: 0x0ebb, 0xd89: 0x0edb, 0xd8a: 0x0f4f, 0xd8b: 0x102f,
+ 0xd8c: 0x104b, 0xd8d: 0x1053, 0xd8e: 0x104f, 0xd8f: 0x1057, 0xd90: 0x105b, 0xd91: 0x105f,
+ 0xd92: 0x1073, 0xd93: 0x1077, 0xd94: 0x109b, 0xd95: 0x10af, 0xd96: 0x10cb, 0xd97: 0x112f,
+ 0xd98: 0x1137, 0xd99: 0x113f, 0xd9a: 0x1153, 0xd9b: 0x117b, 0xd9c: 0x11cb, 0xd9d: 0x11ff,
+ 0xd9e: 0x11ff, 0xd9f: 0x1267, 0xda0: 0x130f, 0xda1: 0x1327, 0xda2: 0x135b, 0xda3: 0x135f,
+ 0xda4: 0x13a3, 0xda5: 0x13a7, 0xda6: 0x13ff, 0xda7: 0x1407, 0xda8: 0x14db, 0xda9: 0x151f,
+ 0xdaa: 0x1537, 0xdab: 0x0b9b, 0xdac: 0x171e, 0xdad: 0x11e3,
+ 0xdb0: 0x06df, 0xdb1: 0x07e3, 0xdb2: 0x07a3, 0xdb3: 0x074b, 0xdb4: 0x078b, 0xdb5: 0x07b7,
+ 0xdb6: 0x0847, 0xdb7: 0x0863, 0xdb8: 0x094b, 0xdb9: 0x0937, 0xdba: 0x0947, 0xdbb: 0x0963,
+ 0xdbc: 0x09af, 0xdbd: 0x09bf, 0xdbe: 0x0a03, 0xdbf: 0x0a0f,
+ // Block 0x37, offset 0xdc0
+ 0xdc0: 0x0a2b, 0xdc1: 0x0a3b, 0xdc2: 0x0b23, 0xdc3: 0x0b2b, 0xdc4: 0x0b5b, 0xdc5: 0x0b7b,
+ 0xdc6: 0x0bab, 0xdc7: 0x0bc3, 0xdc8: 0x0bb3, 0xdc9: 0x0bd3, 0xdca: 0x0bc7, 0xdcb: 0x0beb,
+ 0xdcc: 0x0c07, 0xdcd: 0x0c5f, 0xdce: 0x0c6b, 0xdcf: 0x0c73, 0xdd0: 0x0c9b, 0xdd1: 0x0cdf,
+ 0xdd2: 0x0d0f, 0xdd3: 0x0d13, 0xdd4: 0x0d27, 0xdd5: 0x0da7, 0xdd6: 0x0db7, 0xdd7: 0x0e0f,
+ 0xdd8: 0x0e5b, 0xdd9: 0x0e53, 0xdda: 0x0e67, 0xddb: 0x0e83, 0xddc: 0x0ebb, 0xddd: 0x1013,
+ 0xdde: 0x0edf, 0xddf: 0x0f13, 0xde0: 0x0f1f, 0xde1: 0x0f5f, 0xde2: 0x0f7b, 0xde3: 0x0f9f,
+ 0xde4: 0x0fc3, 0xde5: 0x0fc7, 0xde6: 0x0fe3, 0xde7: 0x0fe7, 0xde8: 0x0ff7, 0xde9: 0x100b,
+ 0xdea: 0x1007, 0xdeb: 0x1037, 0xdec: 0x10b3, 0xded: 0x10cb, 0xdee: 0x10e3, 0xdef: 0x111b,
+ 0xdf0: 0x112f, 0xdf1: 0x114b, 0xdf2: 0x117b, 0xdf3: 0x122f, 0xdf4: 0x1257, 0xdf5: 0x12cb,
+ 0xdf6: 0x1313, 0xdf7: 0x131f, 0xdf8: 0x1327, 0xdf9: 0x133f, 0xdfa: 0x1353, 0xdfb: 0x1343,
+ 0xdfc: 0x135b, 0xdfd: 0x1357, 0xdfe: 0x134f, 0xdff: 0x135f,
+ // Block 0x38, offset 0xe00
+ 0xe00: 0x136b, 0xe01: 0x13a7, 0xe02: 0x13e3, 0xe03: 0x1413, 0xe04: 0x144b, 0xe05: 0x146b,
+ 0xe06: 0x14b7, 0xe07: 0x14db, 0xe08: 0x14fb, 0xe09: 0x150f, 0xe0a: 0x151f, 0xe0b: 0x152b,
+ 0xe0c: 0x1537, 0xe0d: 0x158b, 0xe0e: 0x162b, 0xe0f: 0x16b5, 0xe10: 0x16b0, 0xe11: 0x16e2,
+ 0xe12: 0x0607, 0xe13: 0x062f, 0xe14: 0x0633, 0xe15: 0x1764, 0xe16: 0x1791, 0xe17: 0x1809,
+ 0xe18: 0x1617, 0xe19: 0x1627,
+ // Block 0x39, offset 0xe40
+ 0xe40: 0x19d5, 0xe41: 0x19d8, 0xe42: 0x19db, 0xe43: 0x1c08, 0xe44: 0x1c0c, 0xe45: 0x1a5f,
+ 0xe46: 0x1a5f,
+ 0xe53: 0x1d75, 0xe54: 0x1d66, 0xe55: 0x1d6b, 0xe56: 0x1d7a, 0xe57: 0x1d70,
+ 0xe5d: 0x4426,
+ 0xe5e: 0x8115, 0xe5f: 0x4498, 0xe60: 0x022d, 0xe61: 0x0215, 0xe62: 0x021e, 0xe63: 0x0221,
+ 0xe64: 0x0224, 0xe65: 0x0227, 0xe66: 0x022a, 0xe67: 0x0230, 0xe68: 0x0233, 0xe69: 0x0017,
+ 0xe6a: 0x4486, 0xe6b: 0x448c, 0xe6c: 0x458a, 0xe6d: 0x4592, 0xe6e: 0x43de, 0xe6f: 0x43e4,
+ 0xe70: 0x43ea, 0xe71: 0x43f0, 0xe72: 0x43fc, 0xe73: 0x4402, 0xe74: 0x4408, 0xe75: 0x4414,
+ 0xe76: 0x441a, 0xe78: 0x4420, 0xe79: 0x442c, 0xe7a: 0x4432, 0xe7b: 0x4438,
+ 0xe7c: 0x4444, 0xe7e: 0x444a,
+ // Block 0x3a, offset 0xe80
+ 0xe80: 0x4450, 0xe81: 0x4456, 0xe83: 0x445c, 0xe84: 0x4462,
+ 0xe86: 0x446e, 0xe87: 0x4474, 0xe88: 0x447a, 0xe89: 0x4480, 0xe8a: 0x4492, 0xe8b: 0x440e,
+ 0xe8c: 0x43f6, 0xe8d: 0x443e, 0xe8e: 0x4468, 0xe8f: 0x1d7f, 0xe90: 0x0299, 0xe91: 0x0299,
+ 0xe92: 0x02a2, 0xe93: 0x02a2, 0xe94: 0x02a2, 0xe95: 0x02a2, 0xe96: 0x02a5, 0xe97: 0x02a5,
+ 0xe98: 0x02a5, 0xe99: 0x02a5, 0xe9a: 0x02ab, 0xe9b: 0x02ab, 0xe9c: 0x02ab, 0xe9d: 0x02ab,
+ 0xe9e: 0x029f, 0xe9f: 0x029f, 0xea0: 0x029f, 0xea1: 0x029f, 0xea2: 0x02a8, 0xea3: 0x02a8,
+ 0xea4: 0x02a8, 0xea5: 0x02a8, 0xea6: 0x029c, 0xea7: 0x029c, 0xea8: 0x029c, 0xea9: 0x029c,
+ 0xeaa: 0x02cf, 0xeab: 0x02cf, 0xeac: 0x02cf, 0xead: 0x02cf, 0xeae: 0x02d2, 0xeaf: 0x02d2,
+ 0xeb0: 0x02d2, 0xeb1: 0x02d2, 0xeb2: 0x02b1, 0xeb3: 0x02b1, 0xeb4: 0x02b1, 0xeb5: 0x02b1,
+ 0xeb6: 0x02ae, 0xeb7: 0x02ae, 0xeb8: 0x02ae, 0xeb9: 0x02ae, 0xeba: 0x02b4, 0xebb: 0x02b4,
+ 0xebc: 0x02b4, 0xebd: 0x02b4, 0xebe: 0x02b7, 0xebf: 0x02b7,
+ // Block 0x3b, offset 0xec0
+ 0xec0: 0x02b7, 0xec1: 0x02b7, 0xec2: 0x02c0, 0xec3: 0x02c0, 0xec4: 0x02bd, 0xec5: 0x02bd,
+ 0xec6: 0x02c3, 0xec7: 0x02c3, 0xec8: 0x02ba, 0xec9: 0x02ba, 0xeca: 0x02c9, 0xecb: 0x02c9,
+ 0xecc: 0x02c6, 0xecd: 0x02c6, 0xece: 0x02d5, 0xecf: 0x02d5, 0xed0: 0x02d5, 0xed1: 0x02d5,
+ 0xed2: 0x02db, 0xed3: 0x02db, 0xed4: 0x02db, 0xed5: 0x02db, 0xed6: 0x02e1, 0xed7: 0x02e1,
+ 0xed8: 0x02e1, 0xed9: 0x02e1, 0xeda: 0x02de, 0xedb: 0x02de, 0xedc: 0x02de, 0xedd: 0x02de,
+ 0xede: 0x02e4, 0xedf: 0x02e4, 0xee0: 0x02e7, 0xee1: 0x02e7, 0xee2: 0x02e7, 0xee3: 0x02e7,
+ 0xee4: 0x4504, 0xee5: 0x4504, 0xee6: 0x02ed, 0xee7: 0x02ed, 0xee8: 0x02ed, 0xee9: 0x02ed,
+ 0xeea: 0x02ea, 0xeeb: 0x02ea, 0xeec: 0x02ea, 0xeed: 0x02ea, 0xeee: 0x0308, 0xeef: 0x0308,
+ 0xef0: 0x44fe, 0xef1: 0x44fe,
+ // Block 0x3c, offset 0xf00
+ 0xf13: 0x02d8, 0xf14: 0x02d8, 0xf15: 0x02d8, 0xf16: 0x02d8, 0xf17: 0x02f6,
+ 0xf18: 0x02f6, 0xf19: 0x02f3, 0xf1a: 0x02f3, 0xf1b: 0x02f9, 0xf1c: 0x02f9, 0xf1d: 0x204f,
+ 0xf1e: 0x02ff, 0xf1f: 0x02ff, 0xf20: 0x02f0, 0xf21: 0x02f0, 0xf22: 0x02fc, 0xf23: 0x02fc,
+ 0xf24: 0x0305, 0xf25: 0x0305, 0xf26: 0x0305, 0xf27: 0x0305, 0xf28: 0x028d, 0xf29: 0x028d,
+ 0xf2a: 0x25aa, 0xf2b: 0x25aa, 0xf2c: 0x261a, 0xf2d: 0x261a, 0xf2e: 0x25e9, 0xf2f: 0x25e9,
+ 0xf30: 0x2605, 0xf31: 0x2605, 0xf32: 0x25fe, 0xf33: 0x25fe, 0xf34: 0x260c, 0xf35: 0x260c,
+ 0xf36: 0x2613, 0xf37: 0x2613, 0xf38: 0x2613, 0xf39: 0x25f0, 0xf3a: 0x25f0, 0xf3b: 0x25f0,
+ 0xf3c: 0x0302, 0xf3d: 0x0302, 0xf3e: 0x0302, 0xf3f: 0x0302,
+ // Block 0x3d, offset 0xf40
+ 0xf40: 0x25b1, 0xf41: 0x25b8, 0xf42: 0x25d4, 0xf43: 0x25f0, 0xf44: 0x25f7, 0xf45: 0x1d89,
+ 0xf46: 0x1d8e, 0xf47: 0x1d93, 0xf48: 0x1da2, 0xf49: 0x1db1, 0xf4a: 0x1db6, 0xf4b: 0x1dbb,
+ 0xf4c: 0x1dc0, 0xf4d: 0x1dc5, 0xf4e: 0x1dd4, 0xf4f: 0x1de3, 0xf50: 0x1de8, 0xf51: 0x1ded,
+ 0xf52: 0x1dfc, 0xf53: 0x1e0b, 0xf54: 0x1e10, 0xf55: 0x1e15, 0xf56: 0x1e1a, 0xf57: 0x1e29,
+ 0xf58: 0x1e2e, 0xf59: 0x1e3d, 0xf5a: 0x1e42, 0xf5b: 0x1e47, 0xf5c: 0x1e56, 0xf5d: 0x1e5b,
+ 0xf5e: 0x1e60, 0xf5f: 0x1e6a, 0xf60: 0x1ea6, 0xf61: 0x1eb5, 0xf62: 0x1ec4, 0xf63: 0x1ec9,
+ 0xf64: 0x1ece, 0xf65: 0x1ed8, 0xf66: 0x1ee7, 0xf67: 0x1eec, 0xf68: 0x1efb, 0xf69: 0x1f00,
+ 0xf6a: 0x1f05, 0xf6b: 0x1f14, 0xf6c: 0x1f19, 0xf6d: 0x1f28, 0xf6e: 0x1f2d, 0xf6f: 0x1f32,
+ 0xf70: 0x1f37, 0xf71: 0x1f3c, 0xf72: 0x1f41, 0xf73: 0x1f46, 0xf74: 0x1f4b, 0xf75: 0x1f50,
+ 0xf76: 0x1f55, 0xf77: 0x1f5a, 0xf78: 0x1f5f, 0xf79: 0x1f64, 0xf7a: 0x1f69, 0xf7b: 0x1f6e,
+ 0xf7c: 0x1f73, 0xf7d: 0x1f78, 0xf7e: 0x1f7d, 0xf7f: 0x1f87,
+ // Block 0x3e, offset 0xf80
+ 0xf80: 0x1f8c, 0xf81: 0x1f91, 0xf82: 0x1f96, 0xf83: 0x1fa0, 0xf84: 0x1fa5, 0xf85: 0x1faf,
+ 0xf86: 0x1fb4, 0xf87: 0x1fb9, 0xf88: 0x1fbe, 0xf89: 0x1fc3, 0xf8a: 0x1fc8, 0xf8b: 0x1fcd,
+ 0xf8c: 0x1fd2, 0xf8d: 0x1fd7, 0xf8e: 0x1fe6, 0xf8f: 0x1ff5, 0xf90: 0x1ffa, 0xf91: 0x1fff,
+ 0xf92: 0x2004, 0xf93: 0x2009, 0xf94: 0x200e, 0xf95: 0x2018, 0xf96: 0x201d, 0xf97: 0x2022,
+ 0xf98: 0x2031, 0xf99: 0x2040, 0xf9a: 0x2045, 0xf9b: 0x44b6, 0xf9c: 0x44bc, 0xf9d: 0x44f2,
+ 0xf9e: 0x4549, 0xf9f: 0x4550, 0xfa0: 0x4557, 0xfa1: 0x455e, 0xfa2: 0x4565, 0xfa3: 0x456c,
+ 0xfa4: 0x25c6, 0xfa5: 0x25cd, 0xfa6: 0x25d4, 0xfa7: 0x25db, 0xfa8: 0x25f0, 0xfa9: 0x25f7,
+ 0xfaa: 0x1d98, 0xfab: 0x1d9d, 0xfac: 0x1da2, 0xfad: 0x1da7, 0xfae: 0x1db1, 0xfaf: 0x1db6,
+ 0xfb0: 0x1dca, 0xfb1: 0x1dcf, 0xfb2: 0x1dd4, 0xfb3: 0x1dd9, 0xfb4: 0x1de3, 0xfb5: 0x1de8,
+ 0xfb6: 0x1df2, 0xfb7: 0x1df7, 0xfb8: 0x1dfc, 0xfb9: 0x1e01, 0xfba: 0x1e0b, 0xfbb: 0x1e10,
+ 0xfbc: 0x1f3c, 0xfbd: 0x1f41, 0xfbe: 0x1f50, 0xfbf: 0x1f55,
+ // Block 0x3f, offset 0xfc0
+ 0xfc0: 0x1f5a, 0xfc1: 0x1f6e, 0xfc2: 0x1f73, 0xfc3: 0x1f78, 0xfc4: 0x1f7d, 0xfc5: 0x1f96,
+ 0xfc6: 0x1fa0, 0xfc7: 0x1fa5, 0xfc8: 0x1faa, 0xfc9: 0x1fbe, 0xfca: 0x1fdc, 0xfcb: 0x1fe1,
+ 0xfcc: 0x1fe6, 0xfcd: 0x1feb, 0xfce: 0x1ff5, 0xfcf: 0x1ffa, 0xfd0: 0x44f2, 0xfd1: 0x2027,
+ 0xfd2: 0x202c, 0xfd3: 0x2031, 0xfd4: 0x2036, 0xfd5: 0x2040, 0xfd6: 0x2045, 0xfd7: 0x25b1,
+ 0xfd8: 0x25b8, 0xfd9: 0x25bf, 0xfda: 0x25d4, 0xfdb: 0x25e2, 0xfdc: 0x1d89, 0xfdd: 0x1d8e,
+ 0xfde: 0x1d93, 0xfdf: 0x1da2, 0xfe0: 0x1dac, 0xfe1: 0x1dbb, 0xfe2: 0x1dc0, 0xfe3: 0x1dc5,
+ 0xfe4: 0x1dd4, 0xfe5: 0x1dde, 0xfe6: 0x1dfc, 0xfe7: 0x1e15, 0xfe8: 0x1e1a, 0xfe9: 0x1e29,
+ 0xfea: 0x1e2e, 0xfeb: 0x1e3d, 0xfec: 0x1e47, 0xfed: 0x1e56, 0xfee: 0x1e5b, 0xfef: 0x1e60,
+ 0xff0: 0x1e6a, 0xff1: 0x1ea6, 0xff2: 0x1eab, 0xff3: 0x1eb5, 0xff4: 0x1ec4, 0xff5: 0x1ec9,
+ 0xff6: 0x1ece, 0xff7: 0x1ed8, 0xff8: 0x1ee7, 0xff9: 0x1efb, 0xffa: 0x1f00, 0xffb: 0x1f05,
+ 0xffc: 0x1f14, 0xffd: 0x1f19, 0xffe: 0x1f28, 0xfff: 0x1f2d,
+ // Block 0x40, offset 0x1000
+ 0x1000: 0x1f32, 0x1001: 0x1f37, 0x1002: 0x1f46, 0x1003: 0x1f4b, 0x1004: 0x1f5f, 0x1005: 0x1f64,
+ 0x1006: 0x1f69, 0x1007: 0x1f6e, 0x1008: 0x1f73, 0x1009: 0x1f87, 0x100a: 0x1f8c, 0x100b: 0x1f91,
+ 0x100c: 0x1f96, 0x100d: 0x1f9b, 0x100e: 0x1faf, 0x100f: 0x1fb4, 0x1010: 0x1fb9, 0x1011: 0x1fbe,
+ 0x1012: 0x1fcd, 0x1013: 0x1fd2, 0x1014: 0x1fd7, 0x1015: 0x1fe6, 0x1016: 0x1ff0, 0x1017: 0x1fff,
+ 0x1018: 0x2004, 0x1019: 0x44e6, 0x101a: 0x2018, 0x101b: 0x201d, 0x101c: 0x2022, 0x101d: 0x2031,
+ 0x101e: 0x203b, 0x101f: 0x25d4, 0x1020: 0x25e2, 0x1021: 0x1da2, 0x1022: 0x1dac, 0x1023: 0x1dd4,
+ 0x1024: 0x1dde, 0x1025: 0x1dfc, 0x1026: 0x1e06, 0x1027: 0x1e6a, 0x1028: 0x1e6f, 0x1029: 0x1e92,
+ 0x102a: 0x1e97, 0x102b: 0x1f6e, 0x102c: 0x1f73, 0x102d: 0x1f96, 0x102e: 0x1fe6, 0x102f: 0x1ff0,
+ 0x1030: 0x2031, 0x1031: 0x203b, 0x1032: 0x459a, 0x1033: 0x45a2, 0x1034: 0x45aa, 0x1035: 0x1ef1,
+ 0x1036: 0x1ef6, 0x1037: 0x1f0a, 0x1038: 0x1f0f, 0x1039: 0x1f1e, 0x103a: 0x1f23, 0x103b: 0x1e74,
+ 0x103c: 0x1e79, 0x103d: 0x1e9c, 0x103e: 0x1ea1, 0x103f: 0x1e33,
+ // Block 0x41, offset 0x1040
+ 0x1040: 0x1e38, 0x1041: 0x1e1f, 0x1042: 0x1e24, 0x1043: 0x1e4c, 0x1044: 0x1e51, 0x1045: 0x1eba,
+ 0x1046: 0x1ebf, 0x1047: 0x1edd, 0x1048: 0x1ee2, 0x1049: 0x1e7e, 0x104a: 0x1e83, 0x104b: 0x1e88,
+ 0x104c: 0x1e92, 0x104d: 0x1e8d, 0x104e: 0x1e65, 0x104f: 0x1eb0, 0x1050: 0x1ed3, 0x1051: 0x1ef1,
+ 0x1052: 0x1ef6, 0x1053: 0x1f0a, 0x1054: 0x1f0f, 0x1055: 0x1f1e, 0x1056: 0x1f23, 0x1057: 0x1e74,
+ 0x1058: 0x1e79, 0x1059: 0x1e9c, 0x105a: 0x1ea1, 0x105b: 0x1e33, 0x105c: 0x1e38, 0x105d: 0x1e1f,
+ 0x105e: 0x1e24, 0x105f: 0x1e4c, 0x1060: 0x1e51, 0x1061: 0x1eba, 0x1062: 0x1ebf, 0x1063: 0x1edd,
+ 0x1064: 0x1ee2, 0x1065: 0x1e7e, 0x1066: 0x1e83, 0x1067: 0x1e88, 0x1068: 0x1e92, 0x1069: 0x1e8d,
+ 0x106a: 0x1e65, 0x106b: 0x1eb0, 0x106c: 0x1ed3, 0x106d: 0x1e7e, 0x106e: 0x1e83, 0x106f: 0x1e88,
+ 0x1070: 0x1e92, 0x1071: 0x1e6f, 0x1072: 0x1e97, 0x1073: 0x1eec, 0x1074: 0x1e56, 0x1075: 0x1e5b,
+ 0x1076: 0x1e60, 0x1077: 0x1e7e, 0x1078: 0x1e83, 0x1079: 0x1e88, 0x107a: 0x1eec, 0x107b: 0x1efb,
+ 0x107c: 0x449e, 0x107d: 0x449e,
+ // Block 0x42, offset 0x1080
+ 0x1090: 0x2311, 0x1091: 0x2326,
+ 0x1092: 0x2326, 0x1093: 0x232d, 0x1094: 0x2334, 0x1095: 0x2349, 0x1096: 0x2350, 0x1097: 0x2357,
+ 0x1098: 0x237a, 0x1099: 0x237a, 0x109a: 0x239d, 0x109b: 0x2396, 0x109c: 0x23b2, 0x109d: 0x23a4,
+ 0x109e: 0x23ab, 0x109f: 0x23ce, 0x10a0: 0x23ce, 0x10a1: 0x23c7, 0x10a2: 0x23d5, 0x10a3: 0x23d5,
+ 0x10a4: 0x23ff, 0x10a5: 0x23ff, 0x10a6: 0x241b, 0x10a7: 0x23e3, 0x10a8: 0x23e3, 0x10a9: 0x23dc,
+ 0x10aa: 0x23f1, 0x10ab: 0x23f1, 0x10ac: 0x23f8, 0x10ad: 0x23f8, 0x10ae: 0x2422, 0x10af: 0x2430,
+ 0x10b0: 0x2430, 0x10b1: 0x2437, 0x10b2: 0x2437, 0x10b3: 0x243e, 0x10b4: 0x2445, 0x10b5: 0x244c,
+ 0x10b6: 0x2453, 0x10b7: 0x2453, 0x10b8: 0x245a, 0x10b9: 0x2468, 0x10ba: 0x2476, 0x10bb: 0x246f,
+ 0x10bc: 0x247d, 0x10bd: 0x247d, 0x10be: 0x2492, 0x10bf: 0x2499,
+ // Block 0x43, offset 0x10c0
+ 0x10c0: 0x24ca, 0x10c1: 0x24d8, 0x10c2: 0x24d1, 0x10c3: 0x24b5, 0x10c4: 0x24b5, 0x10c5: 0x24df,
+ 0x10c6: 0x24df, 0x10c7: 0x24e6, 0x10c8: 0x24e6, 0x10c9: 0x2510, 0x10ca: 0x2517, 0x10cb: 0x251e,
+ 0x10cc: 0x24f4, 0x10cd: 0x2502, 0x10ce: 0x2525, 0x10cf: 0x252c,
+ 0x10d2: 0x24fb, 0x10d3: 0x2580, 0x10d4: 0x2587, 0x10d5: 0x255d, 0x10d6: 0x2564, 0x10d7: 0x2548,
+ 0x10d8: 0x2548, 0x10d9: 0x254f, 0x10da: 0x2579, 0x10db: 0x2572, 0x10dc: 0x259c, 0x10dd: 0x259c,
+ 0x10de: 0x230a, 0x10df: 0x231f, 0x10e0: 0x2318, 0x10e1: 0x2342, 0x10e2: 0x233b, 0x10e3: 0x2365,
+ 0x10e4: 0x235e, 0x10e5: 0x2388, 0x10e6: 0x236c, 0x10e7: 0x2381, 0x10e8: 0x23b9, 0x10e9: 0x2406,
+ 0x10ea: 0x23ea, 0x10eb: 0x2429, 0x10ec: 0x24c3, 0x10ed: 0x24ed, 0x10ee: 0x2595, 0x10ef: 0x258e,
+ 0x10f0: 0x25a3, 0x10f1: 0x253a, 0x10f2: 0x24a0, 0x10f3: 0x256b, 0x10f4: 0x2492, 0x10f5: 0x24ca,
+ 0x10f6: 0x2461, 0x10f7: 0x24ae, 0x10f8: 0x2541, 0x10f9: 0x2533, 0x10fa: 0x24bc, 0x10fb: 0x24a7,
+ 0x10fc: 0x24bc, 0x10fd: 0x2541, 0x10fe: 0x2373, 0x10ff: 0x238f,
+ // Block 0x44, offset 0x1100
+ 0x1100: 0x2509, 0x1101: 0x2484, 0x1102: 0x2303, 0x1103: 0x24a7, 0x1104: 0x244c, 0x1105: 0x241b,
+ 0x1106: 0x23c0, 0x1107: 0x2556,
+ 0x1130: 0x2414, 0x1131: 0x248b, 0x1132: 0x27bf, 0x1133: 0x27b6, 0x1134: 0x27ec, 0x1135: 0x27da,
+ 0x1136: 0x27c8, 0x1137: 0x27e3, 0x1138: 0x27f5, 0x1139: 0x240d, 0x113a: 0x2c7c, 0x113b: 0x2afc,
+ 0x113c: 0x27d1,
+ // Block 0x45, offset 0x1140
+ 0x1150: 0x0019, 0x1151: 0x0483,
+ 0x1152: 0x0487, 0x1153: 0x0035, 0x1154: 0x0037, 0x1155: 0x0003, 0x1156: 0x003f, 0x1157: 0x04bf,
+ 0x1158: 0x04c3, 0x1159: 0x1b5c,
+ 0x1160: 0x8132, 0x1161: 0x8132, 0x1162: 0x8132, 0x1163: 0x8132,
+ 0x1164: 0x8132, 0x1165: 0x8132, 0x1166: 0x8132, 0x1167: 0x812d, 0x1168: 0x812d, 0x1169: 0x812d,
+ 0x116a: 0x812d, 0x116b: 0x812d, 0x116c: 0x812d, 0x116d: 0x812d, 0x116e: 0x8132, 0x116f: 0x8132,
+ 0x1170: 0x1873, 0x1171: 0x0443, 0x1172: 0x043f, 0x1173: 0x007f, 0x1174: 0x007f, 0x1175: 0x0011,
+ 0x1176: 0x0013, 0x1177: 0x00b7, 0x1178: 0x00bb, 0x1179: 0x04b7, 0x117a: 0x04bb, 0x117b: 0x04ab,
+ 0x117c: 0x04af, 0x117d: 0x0493, 0x117e: 0x0497, 0x117f: 0x048b,
+ // Block 0x46, offset 0x1180
+ 0x1180: 0x048f, 0x1181: 0x049b, 0x1182: 0x049f, 0x1183: 0x04a3, 0x1184: 0x04a7,
+ 0x1187: 0x0077, 0x1188: 0x007b, 0x1189: 0x4269, 0x118a: 0x4269, 0x118b: 0x4269,
+ 0x118c: 0x4269, 0x118d: 0x007f, 0x118e: 0x007f, 0x118f: 0x007f, 0x1190: 0x0019, 0x1191: 0x0483,
+ 0x1192: 0x001d, 0x1194: 0x0037, 0x1195: 0x0035, 0x1196: 0x003f, 0x1197: 0x0003,
+ 0x1198: 0x0443, 0x1199: 0x0011, 0x119a: 0x0013, 0x119b: 0x00b7, 0x119c: 0x00bb, 0x119d: 0x04b7,
+ 0x119e: 0x04bb, 0x119f: 0x0007, 0x11a0: 0x000d, 0x11a1: 0x0015, 0x11a2: 0x0017, 0x11a3: 0x001b,
+ 0x11a4: 0x0039, 0x11a5: 0x003d, 0x11a6: 0x003b, 0x11a8: 0x0079, 0x11a9: 0x0009,
+ 0x11aa: 0x000b, 0x11ab: 0x0041,
+ 0x11b0: 0x42aa, 0x11b1: 0x44c2, 0x11b2: 0x42af, 0x11b4: 0x42b4,
+ 0x11b6: 0x42b9, 0x11b7: 0x44c8, 0x11b8: 0x42be, 0x11b9: 0x44ce, 0x11ba: 0x42c3, 0x11bb: 0x44d4,
+ 0x11bc: 0x42c8, 0x11bd: 0x44da, 0x11be: 0x42cd, 0x11bf: 0x44e0,
+ // Block 0x47, offset 0x11c0
+ 0x11c0: 0x0236, 0x11c1: 0x44a4, 0x11c2: 0x44a4, 0x11c3: 0x44aa, 0x11c4: 0x44aa, 0x11c5: 0x44ec,
+ 0x11c6: 0x44ec, 0x11c7: 0x44b0, 0x11c8: 0x44b0, 0x11c9: 0x44f8, 0x11ca: 0x44f8, 0x11cb: 0x44f8,
+ 0x11cc: 0x44f8, 0x11cd: 0x0239, 0x11ce: 0x0239, 0x11cf: 0x023c, 0x11d0: 0x023c, 0x11d1: 0x023c,
+ 0x11d2: 0x023c, 0x11d3: 0x023f, 0x11d4: 0x023f, 0x11d5: 0x0242, 0x11d6: 0x0242, 0x11d7: 0x0242,
+ 0x11d8: 0x0242, 0x11d9: 0x0245, 0x11da: 0x0245, 0x11db: 0x0245, 0x11dc: 0x0245, 0x11dd: 0x0248,
+ 0x11de: 0x0248, 0x11df: 0x0248, 0x11e0: 0x0248, 0x11e1: 0x024b, 0x11e2: 0x024b, 0x11e3: 0x024b,
+ 0x11e4: 0x024b, 0x11e5: 0x024e, 0x11e6: 0x024e, 0x11e7: 0x024e, 0x11e8: 0x024e, 0x11e9: 0x0251,
+ 0x11ea: 0x0251, 0x11eb: 0x0254, 0x11ec: 0x0254, 0x11ed: 0x0257, 0x11ee: 0x0257, 0x11ef: 0x025a,
+ 0x11f0: 0x025a, 0x11f1: 0x025d, 0x11f2: 0x025d, 0x11f3: 0x025d, 0x11f4: 0x025d, 0x11f5: 0x0260,
+ 0x11f6: 0x0260, 0x11f7: 0x0260, 0x11f8: 0x0260, 0x11f9: 0x0263, 0x11fa: 0x0263, 0x11fb: 0x0263,
+ 0x11fc: 0x0263, 0x11fd: 0x0266, 0x11fe: 0x0266, 0x11ff: 0x0266,
+ // Block 0x48, offset 0x1200
+ 0x1200: 0x0266, 0x1201: 0x0269, 0x1202: 0x0269, 0x1203: 0x0269, 0x1204: 0x0269, 0x1205: 0x026c,
+ 0x1206: 0x026c, 0x1207: 0x026c, 0x1208: 0x026c, 0x1209: 0x026f, 0x120a: 0x026f, 0x120b: 0x026f,
+ 0x120c: 0x026f, 0x120d: 0x0272, 0x120e: 0x0272, 0x120f: 0x0272, 0x1210: 0x0272, 0x1211: 0x0275,
+ 0x1212: 0x0275, 0x1213: 0x0275, 0x1214: 0x0275, 0x1215: 0x0278, 0x1216: 0x0278, 0x1217: 0x0278,
+ 0x1218: 0x0278, 0x1219: 0x027b, 0x121a: 0x027b, 0x121b: 0x027b, 0x121c: 0x027b, 0x121d: 0x027e,
+ 0x121e: 0x027e, 0x121f: 0x027e, 0x1220: 0x027e, 0x1221: 0x0281, 0x1222: 0x0281, 0x1223: 0x0281,
+ 0x1224: 0x0281, 0x1225: 0x0284, 0x1226: 0x0284, 0x1227: 0x0284, 0x1228: 0x0284, 0x1229: 0x0287,
+ 0x122a: 0x0287, 0x122b: 0x0287, 0x122c: 0x0287, 0x122d: 0x028a, 0x122e: 0x028a, 0x122f: 0x028d,
+ 0x1230: 0x028d, 0x1231: 0x0290, 0x1232: 0x0290, 0x1233: 0x0290, 0x1234: 0x0290, 0x1235: 0x2e00,
+ 0x1236: 0x2e00, 0x1237: 0x2e08, 0x1238: 0x2e08, 0x1239: 0x2e10, 0x123a: 0x2e10, 0x123b: 0x1f82,
+ 0x123c: 0x1f82,
+ // Block 0x49, offset 0x1240
+ 0x1240: 0x0081, 0x1241: 0x0083, 0x1242: 0x0085, 0x1243: 0x0087, 0x1244: 0x0089, 0x1245: 0x008b,
+ 0x1246: 0x008d, 0x1247: 0x008f, 0x1248: 0x0091, 0x1249: 0x0093, 0x124a: 0x0095, 0x124b: 0x0097,
+ 0x124c: 0x0099, 0x124d: 0x009b, 0x124e: 0x009d, 0x124f: 0x009f, 0x1250: 0x00a1, 0x1251: 0x00a3,
+ 0x1252: 0x00a5, 0x1253: 0x00a7, 0x1254: 0x00a9, 0x1255: 0x00ab, 0x1256: 0x00ad, 0x1257: 0x00af,
+ 0x1258: 0x00b1, 0x1259: 0x00b3, 0x125a: 0x00b5, 0x125b: 0x00b7, 0x125c: 0x00b9, 0x125d: 0x00bb,
+ 0x125e: 0x00bd, 0x125f: 0x0477, 0x1260: 0x047b, 0x1261: 0x0487, 0x1262: 0x049b, 0x1263: 0x049f,
+ 0x1264: 0x0483, 0x1265: 0x05ab, 0x1266: 0x05a3, 0x1267: 0x04c7, 0x1268: 0x04cf, 0x1269: 0x04d7,
+ 0x126a: 0x04df, 0x126b: 0x04e7, 0x126c: 0x056b, 0x126d: 0x0573, 0x126e: 0x057b, 0x126f: 0x051f,
+ 0x1270: 0x05af, 0x1271: 0x04cb, 0x1272: 0x04d3, 0x1273: 0x04db, 0x1274: 0x04e3, 0x1275: 0x04eb,
+ 0x1276: 0x04ef, 0x1277: 0x04f3, 0x1278: 0x04f7, 0x1279: 0x04fb, 0x127a: 0x04ff, 0x127b: 0x0503,
+ 0x127c: 0x0507, 0x127d: 0x050b, 0x127e: 0x050f, 0x127f: 0x0513,
+ // Block 0x4a, offset 0x1280
+ 0x1280: 0x0517, 0x1281: 0x051b, 0x1282: 0x0523, 0x1283: 0x0527, 0x1284: 0x052b, 0x1285: 0x052f,
+ 0x1286: 0x0533, 0x1287: 0x0537, 0x1288: 0x053b, 0x1289: 0x053f, 0x128a: 0x0543, 0x128b: 0x0547,
+ 0x128c: 0x054b, 0x128d: 0x054f, 0x128e: 0x0553, 0x128f: 0x0557, 0x1290: 0x055b, 0x1291: 0x055f,
+ 0x1292: 0x0563, 0x1293: 0x0567, 0x1294: 0x056f, 0x1295: 0x0577, 0x1296: 0x057f, 0x1297: 0x0583,
+ 0x1298: 0x0587, 0x1299: 0x058b, 0x129a: 0x058f, 0x129b: 0x0593, 0x129c: 0x0597, 0x129d: 0x05a7,
+ 0x129e: 0x4a5a, 0x129f: 0x4a60, 0x12a0: 0x03c3, 0x12a1: 0x0313, 0x12a2: 0x0317, 0x12a3: 0x4345,
+ 0x12a4: 0x031b, 0x12a5: 0x434a, 0x12a6: 0x434f, 0x12a7: 0x031f, 0x12a8: 0x0323, 0x12a9: 0x0327,
+ 0x12aa: 0x4354, 0x12ab: 0x4359, 0x12ac: 0x435e, 0x12ad: 0x4363, 0x12ae: 0x4368, 0x12af: 0x436d,
+ 0x12b0: 0x0367, 0x12b1: 0x032b, 0x12b2: 0x032f, 0x12b3: 0x0333, 0x12b4: 0x037b, 0x12b5: 0x0337,
+ 0x12b6: 0x033b, 0x12b7: 0x033f, 0x12b8: 0x0343, 0x12b9: 0x0347, 0x12ba: 0x034b, 0x12bb: 0x034f,
+ 0x12bc: 0x0353, 0x12bd: 0x0357, 0x12be: 0x035b,
+ // Block 0x4b, offset 0x12c0
+ 0x12c2: 0x42dc, 0x12c3: 0x42e1, 0x12c4: 0x42e6, 0x12c5: 0x42eb,
+ 0x12c6: 0x42f0, 0x12c7: 0x42f5, 0x12ca: 0x42fa, 0x12cb: 0x42ff,
+ 0x12cc: 0x4304, 0x12cd: 0x4309, 0x12ce: 0x430e, 0x12cf: 0x4313,
+ 0x12d2: 0x4318, 0x12d3: 0x431d, 0x12d4: 0x4322, 0x12d5: 0x4327, 0x12d6: 0x432c, 0x12d7: 0x4331,
+ 0x12da: 0x4336, 0x12db: 0x433b, 0x12dc: 0x4340,
+ 0x12e0: 0x00bf, 0x12e1: 0x00c2, 0x12e2: 0x00cb, 0x12e3: 0x4264,
+ 0x12e4: 0x00c8, 0x12e5: 0x00c5, 0x12e6: 0x0447, 0x12e8: 0x046b, 0x12e9: 0x044b,
+ 0x12ea: 0x044f, 0x12eb: 0x0453, 0x12ec: 0x0457, 0x12ed: 0x046f, 0x12ee: 0x0473,
+ // Block 0x4c, offset 0x1300
+ 0x1300: 0x0063, 0x1301: 0x0065, 0x1302: 0x0067, 0x1303: 0x0069, 0x1304: 0x006b, 0x1305: 0x006d,
+ 0x1306: 0x006f, 0x1307: 0x0071, 0x1308: 0x0073, 0x1309: 0x0075, 0x130a: 0x0083, 0x130b: 0x0085,
+ 0x130c: 0x0087, 0x130d: 0x0089, 0x130e: 0x008b, 0x130f: 0x008d, 0x1310: 0x008f, 0x1311: 0x0091,
+ 0x1312: 0x0093, 0x1313: 0x0095, 0x1314: 0x0097, 0x1315: 0x0099, 0x1316: 0x009b, 0x1317: 0x009d,
+ 0x1318: 0x009f, 0x1319: 0x00a1, 0x131a: 0x00a3, 0x131b: 0x00a5, 0x131c: 0x00a7, 0x131d: 0x00a9,
+ 0x131e: 0x00ab, 0x131f: 0x00ad, 0x1320: 0x00af, 0x1321: 0x00b1, 0x1322: 0x00b3, 0x1323: 0x00b5,
+ 0x1324: 0x00dd, 0x1325: 0x00f2, 0x1328: 0x0173, 0x1329: 0x0176,
+ 0x132a: 0x0179, 0x132b: 0x017c, 0x132c: 0x017f, 0x132d: 0x0182, 0x132e: 0x0185, 0x132f: 0x0188,
+ 0x1330: 0x018b, 0x1331: 0x018e, 0x1332: 0x0191, 0x1333: 0x0194, 0x1334: 0x0197, 0x1335: 0x019a,
+ 0x1336: 0x019d, 0x1337: 0x01a0, 0x1338: 0x01a3, 0x1339: 0x0188, 0x133a: 0x01a6, 0x133b: 0x01a9,
+ 0x133c: 0x01ac, 0x133d: 0x01af, 0x133e: 0x01b2, 0x133f: 0x01b5,
+ // Block 0x4d, offset 0x1340
+ 0x1340: 0x01fd, 0x1341: 0x0200, 0x1342: 0x0203, 0x1343: 0x045b, 0x1344: 0x01c7, 0x1345: 0x01d0,
+ 0x1346: 0x01d6, 0x1347: 0x01fa, 0x1348: 0x01eb, 0x1349: 0x01e8, 0x134a: 0x0206, 0x134b: 0x0209,
+ 0x134e: 0x0021, 0x134f: 0x0023, 0x1350: 0x0025, 0x1351: 0x0027,
+ 0x1352: 0x0029, 0x1353: 0x002b, 0x1354: 0x002d, 0x1355: 0x002f, 0x1356: 0x0031, 0x1357: 0x0033,
+ 0x1358: 0x0021, 0x1359: 0x0023, 0x135a: 0x0025, 0x135b: 0x0027, 0x135c: 0x0029, 0x135d: 0x002b,
+ 0x135e: 0x002d, 0x135f: 0x002f, 0x1360: 0x0031, 0x1361: 0x0033, 0x1362: 0x0021, 0x1363: 0x0023,
+ 0x1364: 0x0025, 0x1365: 0x0027, 0x1366: 0x0029, 0x1367: 0x002b, 0x1368: 0x002d, 0x1369: 0x002f,
+ 0x136a: 0x0031, 0x136b: 0x0033, 0x136c: 0x0021, 0x136d: 0x0023, 0x136e: 0x0025, 0x136f: 0x0027,
+ 0x1370: 0x0029, 0x1371: 0x002b, 0x1372: 0x002d, 0x1373: 0x002f, 0x1374: 0x0031, 0x1375: 0x0033,
+ 0x1376: 0x0021, 0x1377: 0x0023, 0x1378: 0x0025, 0x1379: 0x0027, 0x137a: 0x0029, 0x137b: 0x002b,
+ 0x137c: 0x002d, 0x137d: 0x002f, 0x137e: 0x0031, 0x137f: 0x0033,
+ // Block 0x4e, offset 0x1380
+ 0x1380: 0x0239, 0x1381: 0x023c, 0x1382: 0x0248, 0x1383: 0x0251, 0x1385: 0x028a,
+ 0x1386: 0x025a, 0x1387: 0x024b, 0x1388: 0x0269, 0x1389: 0x0290, 0x138a: 0x027b, 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, 0x139c: 0x0293, 0x139d: 0x02e4,
+ 0x139e: 0x02cc, 0x139f: 0x0296, 0x13a1: 0x023c, 0x13a2: 0x0248,
+ 0x13a4: 0x0287, 0x13a7: 0x024b, 0x13a9: 0x0290,
+ 0x13aa: 0x027b, 0x13ab: 0x027e, 0x13ac: 0x0281, 0x13ad: 0x0284, 0x13ae: 0x025d, 0x13af: 0x026f,
+ 0x13b0: 0x0275, 0x13b1: 0x0263, 0x13b2: 0x0278, 0x13b4: 0x0260, 0x13b5: 0x0242,
+ 0x13b6: 0x0245, 0x13b7: 0x024e, 0x13b9: 0x0266, 0x13bb: 0x0272,
+ // Block 0x4f, offset 0x13c0
+ 0x13c2: 0x0248,
+ 0x13c7: 0x024b, 0x13c9: 0x0290, 0x13cb: 0x027e,
+ 0x13cd: 0x0284, 0x13ce: 0x025d, 0x13cf: 0x026f, 0x13d1: 0x0263,
+ 0x13d2: 0x0278, 0x13d4: 0x0260, 0x13d7: 0x024e,
+ 0x13d9: 0x0266, 0x13db: 0x0272, 0x13dd: 0x02e4,
+ 0x13df: 0x0296, 0x13e1: 0x023c, 0x13e2: 0x0248,
+ 0x13e4: 0x0287, 0x13e7: 0x024b, 0x13e8: 0x0269, 0x13e9: 0x0290,
+ 0x13ea: 0x027b, 0x13ec: 0x0281, 0x13ed: 0x0284, 0x13ee: 0x025d, 0x13ef: 0x026f,
+ 0x13f0: 0x0275, 0x13f1: 0x0263, 0x13f2: 0x0278, 0x13f4: 0x0260, 0x13f5: 0x0242,
+ 0x13f6: 0x0245, 0x13f7: 0x024e, 0x13f9: 0x0266, 0x13fa: 0x026c, 0x13fb: 0x0272,
+ 0x13fc: 0x0293, 0x13fe: 0x02cc,
+ // Block 0x50, offset 0x1400
+ 0x1400: 0x0239, 0x1401: 0x023c, 0x1402: 0x0248, 0x1403: 0x0251, 0x1404: 0x0287, 0x1405: 0x028a,
+ 0x1406: 0x025a, 0x1407: 0x024b, 0x1408: 0x0269, 0x1409: 0x0290, 0x140b: 0x027e,
+ 0x140c: 0x0281, 0x140d: 0x0284, 0x140e: 0x025d, 0x140f: 0x026f, 0x1410: 0x0275, 0x1411: 0x0263,
+ 0x1412: 0x0278, 0x1413: 0x0257, 0x1414: 0x0260, 0x1415: 0x0242, 0x1416: 0x0245, 0x1417: 0x024e,
+ 0x1418: 0x0254, 0x1419: 0x0266, 0x141a: 0x026c, 0x141b: 0x0272,
+ 0x1421: 0x023c, 0x1422: 0x0248, 0x1423: 0x0251,
+ 0x1425: 0x028a, 0x1426: 0x025a, 0x1427: 0x024b, 0x1428: 0x0269, 0x1429: 0x0290,
+ 0x142b: 0x027e, 0x142c: 0x0281, 0x142d: 0x0284, 0x142e: 0x025d, 0x142f: 0x026f,
+ 0x1430: 0x0275, 0x1431: 0x0263, 0x1432: 0x0278, 0x1433: 0x0257, 0x1434: 0x0260, 0x1435: 0x0242,
+ 0x1436: 0x0245, 0x1437: 0x024e, 0x1438: 0x0254, 0x1439: 0x0266, 0x143a: 0x026c, 0x143b: 0x0272,
+ // Block 0x51, offset 0x1440
+ 0x1440: 0x1879, 0x1441: 0x1876, 0x1442: 0x187c, 0x1443: 0x18a0, 0x1444: 0x18c4, 0x1445: 0x18e8,
+ 0x1446: 0x190c, 0x1447: 0x1915, 0x1448: 0x191b, 0x1449: 0x1921, 0x144a: 0x1927,
+ 0x1450: 0x1a8c, 0x1451: 0x1a90,
+ 0x1452: 0x1a94, 0x1453: 0x1a98, 0x1454: 0x1a9c, 0x1455: 0x1aa0, 0x1456: 0x1aa4, 0x1457: 0x1aa8,
+ 0x1458: 0x1aac, 0x1459: 0x1ab0, 0x145a: 0x1ab4, 0x145b: 0x1ab8, 0x145c: 0x1abc, 0x145d: 0x1ac0,
+ 0x145e: 0x1ac4, 0x145f: 0x1ac8, 0x1460: 0x1acc, 0x1461: 0x1ad0, 0x1462: 0x1ad4, 0x1463: 0x1ad8,
+ 0x1464: 0x1adc, 0x1465: 0x1ae0, 0x1466: 0x1ae4, 0x1467: 0x1ae8, 0x1468: 0x1aec, 0x1469: 0x1af0,
+ 0x146a: 0x271e, 0x146b: 0x0047, 0x146c: 0x0065, 0x146d: 0x193c, 0x146e: 0x19b1,
+ 0x1470: 0x0043, 0x1471: 0x0045, 0x1472: 0x0047, 0x1473: 0x0049, 0x1474: 0x004b, 0x1475: 0x004d,
+ 0x1476: 0x004f, 0x1477: 0x0051, 0x1478: 0x0053, 0x1479: 0x0055, 0x147a: 0x0057, 0x147b: 0x0059,
+ 0x147c: 0x005b, 0x147d: 0x005d, 0x147e: 0x005f, 0x147f: 0x0061,
+ // Block 0x52, offset 0x1480
+ 0x1480: 0x26ad, 0x1481: 0x26c2, 0x1482: 0x0503,
+ 0x1490: 0x0c0f, 0x1491: 0x0a47,
+ 0x1492: 0x08d3, 0x1493: 0x465a, 0x1494: 0x071b, 0x1495: 0x09ef, 0x1496: 0x132f, 0x1497: 0x09ff,
+ 0x1498: 0x0727, 0x1499: 0x0cd7, 0x149a: 0x0eaf, 0x149b: 0x0caf, 0x149c: 0x0827, 0x149d: 0x0b6b,
+ 0x149e: 0x07bf, 0x149f: 0x0cb7, 0x14a0: 0x0813, 0x14a1: 0x1117, 0x14a2: 0x0f83, 0x14a3: 0x138b,
+ 0x14a4: 0x09d3, 0x14a5: 0x090b, 0x14a6: 0x0e63, 0x14a7: 0x0c1b, 0x14a8: 0x0c47, 0x14a9: 0x06bf,
+ 0x14aa: 0x06cb, 0x14ab: 0x140b, 0x14ac: 0x0adb, 0x14ad: 0x06e7, 0x14ae: 0x08ef, 0x14af: 0x0c3b,
+ 0x14b0: 0x13b3, 0x14b1: 0x0c13, 0x14b2: 0x106f, 0x14b3: 0x10ab, 0x14b4: 0x08f7, 0x14b5: 0x0e43,
+ 0x14b6: 0x0d0b, 0x14b7: 0x0d07, 0x14b8: 0x0f97, 0x14b9: 0x082b, 0x14ba: 0x0957, 0x14bb: 0x1443,
+ // Block 0x53, offset 0x14c0
+ 0x14c0: 0x06fb, 0x14c1: 0x06f3, 0x14c2: 0x0703, 0x14c3: 0x1647, 0x14c4: 0x0747, 0x14c5: 0x0757,
+ 0x14c6: 0x075b, 0x14c7: 0x0763, 0x14c8: 0x076b, 0x14c9: 0x076f, 0x14ca: 0x077b, 0x14cb: 0x0773,
+ 0x14cc: 0x05b3, 0x14cd: 0x165b, 0x14ce: 0x078f, 0x14cf: 0x0793, 0x14d0: 0x0797, 0x14d1: 0x07b3,
+ 0x14d2: 0x164c, 0x14d3: 0x05b7, 0x14d4: 0x079f, 0x14d5: 0x07bf, 0x14d6: 0x1656, 0x14d7: 0x07cf,
+ 0x14d8: 0x07d7, 0x14d9: 0x0737, 0x14da: 0x07df, 0x14db: 0x07e3, 0x14dc: 0x1831, 0x14dd: 0x07ff,
+ 0x14de: 0x0807, 0x14df: 0x05bf, 0x14e0: 0x081f, 0x14e1: 0x0823, 0x14e2: 0x082b, 0x14e3: 0x082f,
+ 0x14e4: 0x05c3, 0x14e5: 0x0847, 0x14e6: 0x084b, 0x14e7: 0x0857, 0x14e8: 0x0863, 0x14e9: 0x0867,
+ 0x14ea: 0x086b, 0x14eb: 0x0873, 0x14ec: 0x0893, 0x14ed: 0x0897, 0x14ee: 0x089f, 0x14ef: 0x08af,
+ 0x14f0: 0x08b7, 0x14f1: 0x08bb, 0x14f2: 0x08bb, 0x14f3: 0x08bb, 0x14f4: 0x166a, 0x14f5: 0x0e93,
+ 0x14f6: 0x08cf, 0x14f7: 0x08d7, 0x14f8: 0x166f, 0x14f9: 0x08e3, 0x14fa: 0x08eb, 0x14fb: 0x08f3,
+ 0x14fc: 0x091b, 0x14fd: 0x0907, 0x14fe: 0x0913, 0x14ff: 0x0917,
+ // Block 0x54, offset 0x1500
+ 0x1500: 0x091f, 0x1501: 0x0927, 0x1502: 0x092b, 0x1503: 0x0933, 0x1504: 0x093b, 0x1505: 0x093f,
+ 0x1506: 0x093f, 0x1507: 0x0947, 0x1508: 0x094f, 0x1509: 0x0953, 0x150a: 0x095f, 0x150b: 0x0983,
+ 0x150c: 0x0967, 0x150d: 0x0987, 0x150e: 0x096b, 0x150f: 0x0973, 0x1510: 0x080b, 0x1511: 0x09cf,
+ 0x1512: 0x0997, 0x1513: 0x099b, 0x1514: 0x099f, 0x1515: 0x0993, 0x1516: 0x09a7, 0x1517: 0x09a3,
+ 0x1518: 0x09bb, 0x1519: 0x1674, 0x151a: 0x09d7, 0x151b: 0x09db, 0x151c: 0x09e3, 0x151d: 0x09ef,
+ 0x151e: 0x09f7, 0x151f: 0x0a13, 0x1520: 0x1679, 0x1521: 0x167e, 0x1522: 0x0a1f, 0x1523: 0x0a23,
+ 0x1524: 0x0a27, 0x1525: 0x0a1b, 0x1526: 0x0a2f, 0x1527: 0x05c7, 0x1528: 0x05cb, 0x1529: 0x0a37,
+ 0x152a: 0x0a3f, 0x152b: 0x0a3f, 0x152c: 0x1683, 0x152d: 0x0a5b, 0x152e: 0x0a5f, 0x152f: 0x0a63,
+ 0x1530: 0x0a6b, 0x1531: 0x1688, 0x1532: 0x0a73, 0x1533: 0x0a77, 0x1534: 0x0b4f, 0x1535: 0x0a7f,
+ 0x1536: 0x05cf, 0x1537: 0x0a8b, 0x1538: 0x0a9b, 0x1539: 0x0aa7, 0x153a: 0x0aa3, 0x153b: 0x1692,
+ 0x153c: 0x0aaf, 0x153d: 0x1697, 0x153e: 0x0abb, 0x153f: 0x0ab7,
+ // Block 0x55, offset 0x1540
+ 0x1540: 0x0abf, 0x1541: 0x0acf, 0x1542: 0x0ad3, 0x1543: 0x05d3, 0x1544: 0x0ae3, 0x1545: 0x0aeb,
+ 0x1546: 0x0aef, 0x1547: 0x0af3, 0x1548: 0x05d7, 0x1549: 0x169c, 0x154a: 0x05db, 0x154b: 0x0b0f,
+ 0x154c: 0x0b13, 0x154d: 0x0b17, 0x154e: 0x0b1f, 0x154f: 0x1863, 0x1550: 0x0b37, 0x1551: 0x16a6,
+ 0x1552: 0x16a6, 0x1553: 0x11d7, 0x1554: 0x0b47, 0x1555: 0x0b47, 0x1556: 0x05df, 0x1557: 0x16c9,
+ 0x1558: 0x179b, 0x1559: 0x0b57, 0x155a: 0x0b5f, 0x155b: 0x05e3, 0x155c: 0x0b73, 0x155d: 0x0b83,
+ 0x155e: 0x0b87, 0x155f: 0x0b8f, 0x1560: 0x0b9f, 0x1561: 0x05eb, 0x1562: 0x05e7, 0x1563: 0x0ba3,
+ 0x1564: 0x16ab, 0x1565: 0x0ba7, 0x1566: 0x0bbb, 0x1567: 0x0bbf, 0x1568: 0x0bc3, 0x1569: 0x0bbf,
+ 0x156a: 0x0bcf, 0x156b: 0x0bd3, 0x156c: 0x0be3, 0x156d: 0x0bdb, 0x156e: 0x0bdf, 0x156f: 0x0be7,
+ 0x1570: 0x0beb, 0x1571: 0x0bef, 0x1572: 0x0bfb, 0x1573: 0x0bff, 0x1574: 0x0c17, 0x1575: 0x0c1f,
+ 0x1576: 0x0c2f, 0x1577: 0x0c43, 0x1578: 0x16ba, 0x1579: 0x0c3f, 0x157a: 0x0c33, 0x157b: 0x0c4b,
+ 0x157c: 0x0c53, 0x157d: 0x0c67, 0x157e: 0x16bf, 0x157f: 0x0c6f,
+ // Block 0x56, offset 0x1580
+ 0x1580: 0x0c63, 0x1581: 0x0c5b, 0x1582: 0x05ef, 0x1583: 0x0c77, 0x1584: 0x0c7f, 0x1585: 0x0c87,
+ 0x1586: 0x0c7b, 0x1587: 0x05f3, 0x1588: 0x0c97, 0x1589: 0x0c9f, 0x158a: 0x16c4, 0x158b: 0x0ccb,
+ 0x158c: 0x0cff, 0x158d: 0x0cdb, 0x158e: 0x05ff, 0x158f: 0x0ce7, 0x1590: 0x05fb, 0x1591: 0x05f7,
+ 0x1592: 0x07c3, 0x1593: 0x07c7, 0x1594: 0x0d03, 0x1595: 0x0ceb, 0x1596: 0x11ab, 0x1597: 0x0663,
+ 0x1598: 0x0d0f, 0x1599: 0x0d13, 0x159a: 0x0d17, 0x159b: 0x0d2b, 0x159c: 0x0d23, 0x159d: 0x16dd,
+ 0x159e: 0x0603, 0x159f: 0x0d3f, 0x15a0: 0x0d33, 0x15a1: 0x0d4f, 0x15a2: 0x0d57, 0x15a3: 0x16e7,
+ 0x15a4: 0x0d5b, 0x15a5: 0x0d47, 0x15a6: 0x0d63, 0x15a7: 0x0607, 0x15a8: 0x0d67, 0x15a9: 0x0d6b,
+ 0x15aa: 0x0d6f, 0x15ab: 0x0d7b, 0x15ac: 0x16ec, 0x15ad: 0x0d83, 0x15ae: 0x060b, 0x15af: 0x0d8f,
+ 0x15b0: 0x16f1, 0x15b1: 0x0d93, 0x15b2: 0x060f, 0x15b3: 0x0d9f, 0x15b4: 0x0dab, 0x15b5: 0x0db7,
+ 0x15b6: 0x0dbb, 0x15b7: 0x16f6, 0x15b8: 0x168d, 0x15b9: 0x16fb, 0x15ba: 0x0ddb, 0x15bb: 0x1700,
+ 0x15bc: 0x0de7, 0x15bd: 0x0def, 0x15be: 0x0ddf, 0x15bf: 0x0dfb,
+ // Block 0x57, offset 0x15c0
+ 0x15c0: 0x0e0b, 0x15c1: 0x0e1b, 0x15c2: 0x0e0f, 0x15c3: 0x0e13, 0x15c4: 0x0e1f, 0x15c5: 0x0e23,
+ 0x15c6: 0x1705, 0x15c7: 0x0e07, 0x15c8: 0x0e3b, 0x15c9: 0x0e3f, 0x15ca: 0x0613, 0x15cb: 0x0e53,
+ 0x15cc: 0x0e4f, 0x15cd: 0x170a, 0x15ce: 0x0e33, 0x15cf: 0x0e6f, 0x15d0: 0x170f, 0x15d1: 0x1714,
+ 0x15d2: 0x0e73, 0x15d3: 0x0e87, 0x15d4: 0x0e83, 0x15d5: 0x0e7f, 0x15d6: 0x0617, 0x15d7: 0x0e8b,
+ 0x15d8: 0x0e9b, 0x15d9: 0x0e97, 0x15da: 0x0ea3, 0x15db: 0x1651, 0x15dc: 0x0eb3, 0x15dd: 0x1719,
+ 0x15de: 0x0ebf, 0x15df: 0x1723, 0x15e0: 0x0ed3, 0x15e1: 0x0edf, 0x15e2: 0x0ef3, 0x15e3: 0x1728,
+ 0x15e4: 0x0f07, 0x15e5: 0x0f0b, 0x15e6: 0x172d, 0x15e7: 0x1732, 0x15e8: 0x0f27, 0x15e9: 0x0f37,
+ 0x15ea: 0x061b, 0x15eb: 0x0f3b, 0x15ec: 0x061f, 0x15ed: 0x061f, 0x15ee: 0x0f53, 0x15ef: 0x0f57,
+ 0x15f0: 0x0f5f, 0x15f1: 0x0f63, 0x15f2: 0x0f6f, 0x15f3: 0x0623, 0x15f4: 0x0f87, 0x15f5: 0x1737,
+ 0x15f6: 0x0fa3, 0x15f7: 0x173c, 0x15f8: 0x0faf, 0x15f9: 0x16a1, 0x15fa: 0x0fbf, 0x15fb: 0x1741,
+ 0x15fc: 0x1746, 0x15fd: 0x174b, 0x15fe: 0x0627, 0x15ff: 0x062b,
+ // Block 0x58, offset 0x1600
+ 0x1600: 0x0ff7, 0x1601: 0x1755, 0x1602: 0x1750, 0x1603: 0x175a, 0x1604: 0x175f, 0x1605: 0x0fff,
+ 0x1606: 0x1003, 0x1607: 0x1003, 0x1608: 0x100b, 0x1609: 0x0633, 0x160a: 0x100f, 0x160b: 0x0637,
+ 0x160c: 0x063b, 0x160d: 0x1769, 0x160e: 0x1023, 0x160f: 0x102b, 0x1610: 0x1037, 0x1611: 0x063f,
+ 0x1612: 0x176e, 0x1613: 0x105b, 0x1614: 0x1773, 0x1615: 0x1778, 0x1616: 0x107b, 0x1617: 0x1093,
+ 0x1618: 0x0643, 0x1619: 0x109b, 0x161a: 0x109f, 0x161b: 0x10a3, 0x161c: 0x177d, 0x161d: 0x1782,
+ 0x161e: 0x1782, 0x161f: 0x10bb, 0x1620: 0x0647, 0x1621: 0x1787, 0x1622: 0x10cf, 0x1623: 0x10d3,
+ 0x1624: 0x064b, 0x1625: 0x178c, 0x1626: 0x10ef, 0x1627: 0x064f, 0x1628: 0x10ff, 0x1629: 0x10f7,
+ 0x162a: 0x1107, 0x162b: 0x1796, 0x162c: 0x111f, 0x162d: 0x0653, 0x162e: 0x112b, 0x162f: 0x1133,
+ 0x1630: 0x1143, 0x1631: 0x0657, 0x1632: 0x17a0, 0x1633: 0x17a5, 0x1634: 0x065b, 0x1635: 0x17aa,
+ 0x1636: 0x115b, 0x1637: 0x17af, 0x1638: 0x1167, 0x1639: 0x1173, 0x163a: 0x117b, 0x163b: 0x17b4,
+ 0x163c: 0x17b9, 0x163d: 0x118f, 0x163e: 0x17be, 0x163f: 0x1197,
+ // Block 0x59, offset 0x1640
+ 0x1640: 0x16ce, 0x1641: 0x065f, 0x1642: 0x11af, 0x1643: 0x11b3, 0x1644: 0x0667, 0x1645: 0x11b7,
+ 0x1646: 0x0a33, 0x1647: 0x17c3, 0x1648: 0x17c8, 0x1649: 0x16d3, 0x164a: 0x16d8, 0x164b: 0x11d7,
+ 0x164c: 0x11db, 0x164d: 0x13f3, 0x164e: 0x066b, 0x164f: 0x1207, 0x1650: 0x1203, 0x1651: 0x120b,
+ 0x1652: 0x083f, 0x1653: 0x120f, 0x1654: 0x1213, 0x1655: 0x1217, 0x1656: 0x121f, 0x1657: 0x17cd,
+ 0x1658: 0x121b, 0x1659: 0x1223, 0x165a: 0x1237, 0x165b: 0x123b, 0x165c: 0x1227, 0x165d: 0x123f,
+ 0x165e: 0x1253, 0x165f: 0x1267, 0x1660: 0x1233, 0x1661: 0x1247, 0x1662: 0x124b, 0x1663: 0x124f,
+ 0x1664: 0x17d2, 0x1665: 0x17dc, 0x1666: 0x17d7, 0x1667: 0x066f, 0x1668: 0x126f, 0x1669: 0x1273,
+ 0x166a: 0x127b, 0x166b: 0x17f0, 0x166c: 0x127f, 0x166d: 0x17e1, 0x166e: 0x0673, 0x166f: 0x0677,
+ 0x1670: 0x17e6, 0x1671: 0x17eb, 0x1672: 0x067b, 0x1673: 0x129f, 0x1674: 0x12a3, 0x1675: 0x12a7,
+ 0x1676: 0x12ab, 0x1677: 0x12b7, 0x1678: 0x12b3, 0x1679: 0x12bf, 0x167a: 0x12bb, 0x167b: 0x12cb,
+ 0x167c: 0x12c3, 0x167d: 0x12c7, 0x167e: 0x12cf, 0x167f: 0x067f,
+ // Block 0x5a, offset 0x1680
+ 0x1680: 0x12d7, 0x1681: 0x12db, 0x1682: 0x0683, 0x1683: 0x12eb, 0x1684: 0x12ef, 0x1685: 0x17f5,
+ 0x1686: 0x12fb, 0x1687: 0x12ff, 0x1688: 0x0687, 0x1689: 0x130b, 0x168a: 0x05bb, 0x168b: 0x17fa,
+ 0x168c: 0x17ff, 0x168d: 0x068b, 0x168e: 0x068f, 0x168f: 0x1337, 0x1690: 0x134f, 0x1691: 0x136b,
+ 0x1692: 0x137b, 0x1693: 0x1804, 0x1694: 0x138f, 0x1695: 0x1393, 0x1696: 0x13ab, 0x1697: 0x13b7,
+ 0x1698: 0x180e, 0x1699: 0x1660, 0x169a: 0x13c3, 0x169b: 0x13bf, 0x169c: 0x13cb, 0x169d: 0x1665,
+ 0x169e: 0x13d7, 0x169f: 0x13e3, 0x16a0: 0x1813, 0x16a1: 0x1818, 0x16a2: 0x1423, 0x16a3: 0x142f,
+ 0x16a4: 0x1437, 0x16a5: 0x181d, 0x16a6: 0x143b, 0x16a7: 0x1467, 0x16a8: 0x1473, 0x16a9: 0x1477,
+ 0x16aa: 0x146f, 0x16ab: 0x1483, 0x16ac: 0x1487, 0x16ad: 0x1822, 0x16ae: 0x1493, 0x16af: 0x0693,
+ 0x16b0: 0x149b, 0x16b1: 0x1827, 0x16b2: 0x0697, 0x16b3: 0x14d3, 0x16b4: 0x0ac3, 0x16b5: 0x14eb,
+ 0x16b6: 0x182c, 0x16b7: 0x1836, 0x16b8: 0x069b, 0x16b9: 0x069f, 0x16ba: 0x1513, 0x16bb: 0x183b,
+ 0x16bc: 0x06a3, 0x16bd: 0x1840, 0x16be: 0x152b, 0x16bf: 0x152b,
+ // Block 0x5b, offset 0x16c0
+ 0x16c0: 0x1533, 0x16c1: 0x1845, 0x16c2: 0x154b, 0x16c3: 0x06a7, 0x16c4: 0x155b, 0x16c5: 0x1567,
+ 0x16c6: 0x156f, 0x16c7: 0x1577, 0x16c8: 0x06ab, 0x16c9: 0x184a, 0x16ca: 0x158b, 0x16cb: 0x15a7,
+ 0x16cc: 0x15b3, 0x16cd: 0x06af, 0x16ce: 0x06b3, 0x16cf: 0x15b7, 0x16d0: 0x184f, 0x16d1: 0x06b7,
+ 0x16d2: 0x1854, 0x16d3: 0x1859, 0x16d4: 0x185e, 0x16d5: 0x15db, 0x16d6: 0x06bb, 0x16d7: 0x15ef,
+ 0x16d8: 0x15f7, 0x16d9: 0x15fb, 0x16da: 0x1603, 0x16db: 0x160b, 0x16dc: 0x1613, 0x16dd: 0x1868,
+}
+
+// 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: 0x5a, 0xc3: 0x01, 0xc4: 0x02, 0xc5: 0x03, 0xc6: 0x5b, 0xc7: 0x04,
+ 0xc8: 0x05, 0xca: 0x5c, 0xcb: 0x5d, 0xcc: 0x06, 0xcd: 0x07, 0xce: 0x08, 0xcf: 0x09,
+ 0xd0: 0x0a, 0xd1: 0x5e, 0xd2: 0x5f, 0xd3: 0x0b, 0xd6: 0x0c, 0xd7: 0x60,
+ 0xd8: 0x61, 0xd9: 0x0d, 0xdb: 0x62, 0xdc: 0x63, 0xdd: 0x64, 0xdf: 0x65,
+ 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: 0x66, 0x121: 0x67, 0x123: 0x68, 0x124: 0x69, 0x125: 0x6a, 0x126: 0x6b, 0x127: 0x6c,
+ 0x128: 0x6d, 0x129: 0x6e, 0x12a: 0x6f, 0x12b: 0x70, 0x12c: 0x6b, 0x12d: 0x71, 0x12e: 0x72, 0x12f: 0x73,
+ 0x131: 0x74, 0x132: 0x75, 0x133: 0x76, 0x134: 0x77, 0x135: 0x78, 0x137: 0x79,
+ 0x138: 0x7a, 0x139: 0x7b, 0x13a: 0x7c, 0x13b: 0x7d, 0x13c: 0x7e, 0x13d: 0x7f, 0x13e: 0x80, 0x13f: 0x81,
+ // Block 0x5, offset 0x140
+ 0x140: 0x82, 0x142: 0x83, 0x143: 0x84, 0x144: 0x85, 0x145: 0x86, 0x146: 0x87, 0x147: 0x88,
+ 0x14d: 0x89,
+ 0x15c: 0x8a, 0x15f: 0x8b,
+ 0x162: 0x8c, 0x164: 0x8d,
+ 0x168: 0x8e, 0x169: 0x8f, 0x16a: 0x90, 0x16c: 0x0e, 0x16d: 0x91, 0x16e: 0x92, 0x16f: 0x93,
+ 0x170: 0x94, 0x173: 0x95, 0x174: 0x96, 0x175: 0x0f, 0x176: 0x10, 0x177: 0x97,
+ 0x178: 0x11, 0x179: 0x12, 0x17a: 0x13, 0x17b: 0x14, 0x17c: 0x15, 0x17d: 0x16, 0x17e: 0x17, 0x17f: 0x18,
+ // Block 0x6, offset 0x180
+ 0x180: 0x98, 0x181: 0x99, 0x182: 0x9a, 0x183: 0x9b, 0x184: 0x19, 0x185: 0x1a, 0x186: 0x9c, 0x187: 0x9d,
+ 0x188: 0x9e, 0x189: 0x1b, 0x18a: 0x1c, 0x18b: 0x9f, 0x18c: 0xa0,
+ 0x191: 0x1d, 0x192: 0x1e, 0x193: 0xa1,
+ 0x1a8: 0xa2, 0x1a9: 0xa3, 0x1ab: 0xa4,
+ 0x1b1: 0xa5, 0x1b3: 0xa6, 0x1b5: 0xa7, 0x1b7: 0xa8,
+ 0x1ba: 0xa9, 0x1bb: 0xaa, 0x1bc: 0x1f, 0x1bd: 0x20, 0x1be: 0x21, 0x1bf: 0xab,
+ // Block 0x7, offset 0x1c0
+ 0x1c0: 0xac, 0x1c1: 0x22, 0x1c2: 0x23, 0x1c3: 0x24, 0x1c4: 0xad, 0x1c5: 0x25, 0x1c6: 0x26,
+ 0x1c8: 0x27, 0x1c9: 0x28, 0x1ca: 0x29, 0x1cb: 0x2a, 0x1cc: 0x2b, 0x1cd: 0x2c, 0x1ce: 0x2d, 0x1cf: 0x2e,
+ // Block 0x8, offset 0x200
+ 0x219: 0xae, 0x21a: 0xaf, 0x21b: 0xb0, 0x21d: 0xb1, 0x21f: 0xb2,
+ 0x220: 0xb3, 0x223: 0xb4, 0x224: 0xb5, 0x225: 0xb6, 0x226: 0xb7, 0x227: 0xb8,
+ 0x22a: 0xb9, 0x22b: 0xba, 0x22d: 0xbb, 0x22f: 0xbc,
+ 0x230: 0xbd, 0x231: 0xbe, 0x232: 0xbf, 0x233: 0xc0, 0x234: 0xc1, 0x235: 0xc2, 0x236: 0xc3, 0x237: 0xbd,
+ 0x238: 0xbe, 0x239: 0xbf, 0x23a: 0xc0, 0x23b: 0xc1, 0x23c: 0xc2, 0x23d: 0xc3, 0x23e: 0xbd, 0x23f: 0xbe,
+ // Block 0x9, offset 0x240
+ 0x240: 0xbf, 0x241: 0xc0, 0x242: 0xc1, 0x243: 0xc2, 0x244: 0xc3, 0x245: 0xbd, 0x246: 0xbe, 0x247: 0xbf,
+ 0x248: 0xc0, 0x249: 0xc1, 0x24a: 0xc2, 0x24b: 0xc3, 0x24c: 0xbd, 0x24d: 0xbe, 0x24e: 0xbf, 0x24f: 0xc0,
+ 0x250: 0xc1, 0x251: 0xc2, 0x252: 0xc3, 0x253: 0xbd, 0x254: 0xbe, 0x255: 0xbf, 0x256: 0xc0, 0x257: 0xc1,
+ 0x258: 0xc2, 0x259: 0xc3, 0x25a: 0xbd, 0x25b: 0xbe, 0x25c: 0xbf, 0x25d: 0xc0, 0x25e: 0xc1, 0x25f: 0xc2,
+ 0x260: 0xc3, 0x261: 0xbd, 0x262: 0xbe, 0x263: 0xbf, 0x264: 0xc0, 0x265: 0xc1, 0x266: 0xc2, 0x267: 0xc3,
+ 0x268: 0xbd, 0x269: 0xbe, 0x26a: 0xbf, 0x26b: 0xc0, 0x26c: 0xc1, 0x26d: 0xc2, 0x26e: 0xc3, 0x26f: 0xbd,
+ 0x270: 0xbe, 0x271: 0xbf, 0x272: 0xc0, 0x273: 0xc1, 0x274: 0xc2, 0x275: 0xc3, 0x276: 0xbd, 0x277: 0xbe,
+ 0x278: 0xbf, 0x279: 0xc0, 0x27a: 0xc1, 0x27b: 0xc2, 0x27c: 0xc3, 0x27d: 0xbd, 0x27e: 0xbe, 0x27f: 0xbf,
+ // Block 0xa, offset 0x280
+ 0x280: 0xc0, 0x281: 0xc1, 0x282: 0xc2, 0x283: 0xc3, 0x284: 0xbd, 0x285: 0xbe, 0x286: 0xbf, 0x287: 0xc0,
+ 0x288: 0xc1, 0x289: 0xc2, 0x28a: 0xc3, 0x28b: 0xbd, 0x28c: 0xbe, 0x28d: 0xbf, 0x28e: 0xc0, 0x28f: 0xc1,
+ 0x290: 0xc2, 0x291: 0xc3, 0x292: 0xbd, 0x293: 0xbe, 0x294: 0xbf, 0x295: 0xc0, 0x296: 0xc1, 0x297: 0xc2,
+ 0x298: 0xc3, 0x299: 0xbd, 0x29a: 0xbe, 0x29b: 0xbf, 0x29c: 0xc0, 0x29d: 0xc1, 0x29e: 0xc2, 0x29f: 0xc3,
+ 0x2a0: 0xbd, 0x2a1: 0xbe, 0x2a2: 0xbf, 0x2a3: 0xc0, 0x2a4: 0xc1, 0x2a5: 0xc2, 0x2a6: 0xc3, 0x2a7: 0xbd,
+ 0x2a8: 0xbe, 0x2a9: 0xbf, 0x2aa: 0xc0, 0x2ab: 0xc1, 0x2ac: 0xc2, 0x2ad: 0xc3, 0x2ae: 0xbd, 0x2af: 0xbe,
+ 0x2b0: 0xbf, 0x2b1: 0xc0, 0x2b2: 0xc1, 0x2b3: 0xc2, 0x2b4: 0xc3, 0x2b5: 0xbd, 0x2b6: 0xbe, 0x2b7: 0xbf,
+ 0x2b8: 0xc0, 0x2b9: 0xc1, 0x2ba: 0xc2, 0x2bb: 0xc3, 0x2bc: 0xbd, 0x2bd: 0xbe, 0x2be: 0xbf, 0x2bf: 0xc0,
+ // Block 0xb, offset 0x2c0
+ 0x2c0: 0xc1, 0x2c1: 0xc2, 0x2c2: 0xc3, 0x2c3: 0xbd, 0x2c4: 0xbe, 0x2c5: 0xbf, 0x2c6: 0xc0, 0x2c7: 0xc1,
+ 0x2c8: 0xc2, 0x2c9: 0xc3, 0x2ca: 0xbd, 0x2cb: 0xbe, 0x2cc: 0xbf, 0x2cd: 0xc0, 0x2ce: 0xc1, 0x2cf: 0xc2,
+ 0x2d0: 0xc3, 0x2d1: 0xbd, 0x2d2: 0xbe, 0x2d3: 0xbf, 0x2d4: 0xc0, 0x2d5: 0xc1, 0x2d6: 0xc2, 0x2d7: 0xc3,
+ 0x2d8: 0xbd, 0x2d9: 0xbe, 0x2da: 0xbf, 0x2db: 0xc0, 0x2dc: 0xc1, 0x2dd: 0xc2, 0x2de: 0xc4,
+ // Block 0xc, offset 0x300
+ 0x324: 0x2f, 0x325: 0x30, 0x326: 0x31, 0x327: 0x32,
+ 0x328: 0x33, 0x329: 0x34, 0x32a: 0x35, 0x32b: 0x36, 0x32c: 0x37, 0x32d: 0x38, 0x32e: 0x39, 0x32f: 0x3a,
+ 0x330: 0x3b, 0x331: 0x3c, 0x332: 0x3d, 0x333: 0x3e, 0x334: 0x3f, 0x335: 0x40, 0x336: 0x41, 0x337: 0x42,
+ 0x338: 0x43, 0x339: 0x44, 0x33a: 0x45, 0x33b: 0x46, 0x33c: 0xc5, 0x33d: 0x47, 0x33e: 0x48, 0x33f: 0x49,
+ // 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: 0xb7, 0x387: 0xce,
+ 0x388: 0xcf, 0x38b: 0xd0, 0x38c: 0x6b, 0x38d: 0xd1,
+ 0x391: 0xd2, 0x392: 0xd3, 0x393: 0xd4, 0x396: 0xd5, 0x397: 0xd6,
+ 0x398: 0xd7, 0x39a: 0xd8, 0x39c: 0xd9,
+ 0x3b0: 0xd7,
+ // Block 0xf, offset 0x3c0
+ 0x3eb: 0xda, 0x3ec: 0xdb,
+ // Block 0x10, offset 0x400
+ 0x432: 0xdc,
+ // Block 0x11, offset 0x440
+ 0x445: 0xdd, 0x446: 0xde, 0x447: 0xdf,
+ 0x449: 0xe0,
+ 0x450: 0xe1, 0x451: 0xe2, 0x452: 0xe3, 0x453: 0xe4, 0x454: 0xe5, 0x455: 0xe6, 0x456: 0xe7, 0x457: 0xe8,
+ 0x458: 0xe9, 0x459: 0xea, 0x45a: 0x4a, 0x45b: 0xeb, 0x45c: 0xec, 0x45d: 0xed, 0x45e: 0xee, 0x45f: 0x4b,
+ // Block 0x12, offset 0x480
+ 0x480: 0xef,
+ 0x4a3: 0xf0, 0x4a5: 0xf1,
+ 0x4b8: 0x4c, 0x4b9: 0x4d, 0x4ba: 0x4e,
+ // Block 0x13, offset 0x4c0
+ 0x4c4: 0x4f, 0x4c5: 0xf2, 0x4c6: 0xf3,
+ 0x4c8: 0x50, 0x4c9: 0xf4,
+ // Block 0x14, offset 0x500
+ 0x520: 0x51, 0x521: 0x52, 0x522: 0x53, 0x523: 0x54, 0x524: 0x55, 0x525: 0x56, 0x526: 0x57, 0x527: 0x58,
+ 0x528: 0x59,
+ // Block 0x15, offset 0x540
+ 0x550: 0x0b, 0x551: 0x0c, 0x556: 0x0d,
+ 0x55b: 0x0e, 0x55d: 0x0f, 0x55e: 0x10, 0x55f: 0x11,
+ 0x56f: 0x12,
+}
+
+// nfkcSparseOffset: 155 entries, 310 bytes
+var nfkcSparseOffset = []uint16{0x0, 0xe, 0x12, 0x1b, 0x25, 0x35, 0x37, 0x3c, 0x47, 0x56, 0x63, 0x6b, 0x6f, 0x74, 0x76, 0x87, 0x8f, 0x96, 0x99, 0xa0, 0xa4, 0xa8, 0xaa, 0xac, 0xb5, 0xb9, 0xc0, 0xc5, 0xc8, 0xd2, 0xd4, 0xdb, 0xe3, 0xe7, 0xe9, 0xec, 0xf0, 0xf6, 0x107, 0x113, 0x115, 0x11b, 0x11d, 0x11f, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12c, 0x12f, 0x131, 0x134, 0x137, 0x13b, 0x140, 0x149, 0x14b, 0x14e, 0x150, 0x15b, 0x166, 0x176, 0x184, 0x192, 0x1a2, 0x1b0, 0x1b7, 0x1bd, 0x1cc, 0x1d0, 0x1d2, 0x1d6, 0x1d8, 0x1db, 0x1dd, 0x1e0, 0x1e2, 0x1e5, 0x1e7, 0x1e9, 0x1eb, 0x1f7, 0x201, 0x20b, 0x20e, 0x212, 0x214, 0x216, 0x218, 0x21a, 0x21d, 0x21f, 0x221, 0x223, 0x225, 0x22b, 0x22e, 0x232, 0x234, 0x23b, 0x241, 0x247, 0x24f, 0x255, 0x25b, 0x261, 0x265, 0x267, 0x269, 0x26b, 0x26d, 0x273, 0x276, 0x279, 0x281, 0x288, 0x28b, 0x28e, 0x290, 0x298, 0x29b, 0x2a2, 0x2a5, 0x2ab, 0x2ad, 0x2af, 0x2b2, 0x2b4, 0x2b6, 0x2b8, 0x2ba, 0x2c7, 0x2d1, 0x2d3, 0x2d5, 0x2d9, 0x2de, 0x2ea, 0x2ef, 0x2f8, 0x2fe, 0x303, 0x307, 0x30c, 0x310, 0x320, 0x32e, 0x33c, 0x34a, 0x350, 0x352, 0x355, 0x35f, 0x361}
+
+// nfkcSparseValues: 875 entries, 3500 bytes
+var nfkcSparseValues = [875]valueRange{
+ // Block 0x0, offset 0x0
+ {value: 0x0002, lo: 0x0d},
+ {value: 0x0001, lo: 0xa0, hi: 0xa0},
+ {value: 0x4278, lo: 0xa8, hi: 0xa8},
+ {value: 0x0083, lo: 0xaa, hi: 0xaa},
+ {value: 0x4264, lo: 0xaf, hi: 0xaf},
+ {value: 0x0025, lo: 0xb2, hi: 0xb3},
+ {value: 0x425a, lo: 0xb4, hi: 0xb4},
+ {value: 0x01dc, lo: 0xb5, hi: 0xb5},
+ {value: 0x4291, lo: 0xb8, hi: 0xb8},
+ {value: 0x0023, lo: 0xb9, hi: 0xb9},
+ {value: 0x009f, lo: 0xba, hi: 0xba},
+ {value: 0x221c, lo: 0xbc, hi: 0xbc},
+ {value: 0x2210, lo: 0xbd, hi: 0xbd},
+ {value: 0x22b2, lo: 0xbe, hi: 0xbe},
+ // Block 0x1, offset 0xe
+ {value: 0x0091, lo: 0x03},
+ {value: 0x4778, lo: 0xa0, hi: 0xa1},
+ {value: 0x47aa, 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: 0x426e, lo: 0x98, hi: 0x98},
+ {value: 0x4273, lo: 0x99, hi: 0x9a},
+ {value: 0x4296, lo: 0x9b, hi: 0x9b},
+ {value: 0x425f, lo: 0x9c, hi: 0x9c},
+ {value: 0x4282, 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: 0x37a5, lo: 0x90, hi: 0x90},
+ {value: 0x37b1, lo: 0x91, hi: 0x91},
+ {value: 0x379f, lo: 0x93, hi: 0x93},
+ {value: 0xa000, lo: 0x96, hi: 0x96},
+ {value: 0x3817, lo: 0x97, hi: 0x97},
+ {value: 0x37e1, lo: 0x9c, hi: 0x9c},
+ {value: 0x37c9, lo: 0x9d, hi: 0x9d},
+ {value: 0x37f3, lo: 0x9e, hi: 0x9e},
+ {value: 0xa000, lo: 0xb4, hi: 0xb5},
+ {value: 0x381d, lo: 0xb6, hi: 0xb6},
+ {value: 0x3823, 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: 0x3841, lo: 0xa2, hi: 0xa2},
+ {value: 0x3847, lo: 0xa3, hi: 0xa3},
+ {value: 0x3853, lo: 0xa4, hi: 0xa4},
+ {value: 0x384d, lo: 0xa5, hi: 0xa5},
+ {value: 0x3859, lo: 0xa6, hi: 0xa6},
+ {value: 0xa000, lo: 0xa7, hi: 0xa7},
+ // Block 0x8, offset 0x47
+ {value: 0x0000, lo: 0x0e},
+ {value: 0x386b, lo: 0x80, hi: 0x80},
+ {value: 0xa000, lo: 0x81, hi: 0x81},
+ {value: 0x385f, lo: 0x82, hi: 0x82},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0x3865, 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: 0x10},
+ {value: 0x8132, lo: 0x94, hi: 0xa1},
+ {value: 0x812d, lo: 0xa3, hi: 0xa3},
+ {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 0x87
+ {value: 0x0000, lo: 0x07},
+ {value: 0xa000, lo: 0xa8, hi: 0xa8},
+ {value: 0x3ed8, lo: 0xa9, hi: 0xa9},
+ {value: 0xa000, lo: 0xb0, hi: 0xb0},
+ {value: 0x3ee0, lo: 0xb1, hi: 0xb1},
+ {value: 0xa000, lo: 0xb3, hi: 0xb3},
+ {value: 0x3ee8, lo: 0xb4, hi: 0xb4},
+ {value: 0x9902, lo: 0xbc, hi: 0xbc},
+ // Block 0x10, offset 0x8f
+ {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: 0x45b2, lo: 0x98, hi: 0x9f},
+ // Block 0x11, offset 0x96
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ {value: 0x9900, lo: 0xbe, hi: 0xbe},
+ // Block 0x12, offset 0x99
+ {value: 0x0008, lo: 0x06},
+ {value: 0xa000, lo: 0x87, hi: 0x87},
+ {value: 0x2c9e, lo: 0x8b, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x97, hi: 0x97},
+ {value: 0x45f2, lo: 0x9c, hi: 0x9d},
+ {value: 0x4602, lo: 0x9f, hi: 0x9f},
+ // Block 0x13, offset 0xa0
+ {value: 0x0000, lo: 0x03},
+ {value: 0x462a, lo: 0xb3, hi: 0xb3},
+ {value: 0x4632, lo: 0xb6, hi: 0xb6},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ // Block 0x14, offset 0xa4
+ {value: 0x0008, lo: 0x03},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x460a, lo: 0x99, hi: 0x9b},
+ {value: 0x4622, lo: 0x9e, hi: 0x9e},
+ // Block 0x15, offset 0xa8
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ // Block 0x16, offset 0xaa
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ // Block 0x17, offset 0xac
+ {value: 0x0000, lo: 0x08},
+ {value: 0xa000, lo: 0x87, hi: 0x87},
+ {value: 0x2cb6, lo: 0x88, hi: 0x88},
+ {value: 0x2cae, lo: 0x8b, hi: 0x8b},
+ {value: 0x2cbe, lo: 0x8c, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x96, hi: 0x97},
+ {value: 0x463a, lo: 0x9c, hi: 0x9c},
+ {value: 0x4642, lo: 0x9d, hi: 0x9d},
+ // Block 0x18, offset 0xb5
+ {value: 0x0000, lo: 0x03},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0x2cc6, lo: 0x94, hi: 0x94},
+ {value: 0x9900, lo: 0xbe, hi: 0xbe},
+ // Block 0x19, offset 0xb9
+ {value: 0x0000, lo: 0x06},
+ {value: 0xa000, lo: 0x86, hi: 0x87},
+ {value: 0x2cce, lo: 0x8a, hi: 0x8a},
+ {value: 0x2cde, lo: 0x8b, hi: 0x8b},
+ {value: 0x2cd6, lo: 0x8c, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x97, hi: 0x97},
+ // Block 0x1a, offset 0xc0
+ {value: 0x1801, lo: 0x04},
+ {value: 0xa000, lo: 0x86, hi: 0x86},
+ {value: 0x3ef0, lo: 0x88, hi: 0x88},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x8120, lo: 0x95, hi: 0x96},
+ // Block 0x1b, offset 0xc5
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ {value: 0xa000, lo: 0xbf, hi: 0xbf},
+ // Block 0x1c, offset 0xc8
+ {value: 0x0000, lo: 0x09},
+ {value: 0x2ce6, lo: 0x80, hi: 0x80},
+ {value: 0x9900, lo: 0x82, hi: 0x82},
+ {value: 0xa000, lo: 0x86, hi: 0x86},
+ {value: 0x2cee, lo: 0x87, hi: 0x87},
+ {value: 0x2cf6, lo: 0x88, hi: 0x88},
+ {value: 0x2f50, lo: 0x8a, hi: 0x8a},
+ {value: 0x2dd8, lo: 0x8b, hi: 0x8b},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x95, hi: 0x96},
+ // Block 0x1d, offset 0xd2
+ {value: 0x0000, lo: 0x01},
+ {value: 0x9900, lo: 0xbe, hi: 0xbe},
+ // Block 0x1e, offset 0xd4
+ {value: 0x0000, lo: 0x06},
+ {value: 0xa000, lo: 0x86, hi: 0x87},
+ {value: 0x2cfe, lo: 0x8a, hi: 0x8a},
+ {value: 0x2d0e, lo: 0x8b, hi: 0x8b},
+ {value: 0x2d06, lo: 0x8c, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x97, hi: 0x97},
+ // Block 0x1f, offset 0xdb
+ {value: 0x6bea, lo: 0x07},
+ {value: 0x9904, lo: 0x8a, hi: 0x8a},
+ {value: 0x9900, lo: 0x8f, hi: 0x8f},
+ {value: 0xa000, lo: 0x99, hi: 0x99},
+ {value: 0x3ef8, lo: 0x9a, hi: 0x9a},
+ {value: 0x2f58, lo: 0x9c, hi: 0x9c},
+ {value: 0x2de3, lo: 0x9d, hi: 0x9d},
+ {value: 0x2d16, lo: 0x9e, hi: 0x9f},
+ // Block 0x20, offset 0xe3
+ {value: 0x0000, lo: 0x03},
+ {value: 0x2621, lo: 0xb3, hi: 0xb3},
+ {value: 0x8122, lo: 0xb8, hi: 0xb9},
+ {value: 0x8104, lo: 0xba, hi: 0xba},
+ // Block 0x21, offset 0xe7
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8123, lo: 0x88, hi: 0x8b},
+ // Block 0x22, offset 0xe9
+ {value: 0x0000, lo: 0x02},
+ {value: 0x2636, lo: 0xb3, hi: 0xb3},
+ {value: 0x8124, lo: 0xb8, hi: 0xb9},
+ // Block 0x23, offset 0xec
+ {value: 0x0000, lo: 0x03},
+ {value: 0x8125, lo: 0x88, hi: 0x8b},
+ {value: 0x2628, lo: 0x9c, hi: 0x9c},
+ {value: 0x262f, lo: 0x9d, hi: 0x9d},
+ // Block 0x24, offset 0xf0
+ {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 0xf6
+ {value: 0x0000, lo: 0x10},
+ {value: 0x2644, lo: 0x83, hi: 0x83},
+ {value: 0x264b, lo: 0x8d, hi: 0x8d},
+ {value: 0x2652, lo: 0x92, hi: 0x92},
+ {value: 0x2659, lo: 0x97, hi: 0x97},
+ {value: 0x2660, lo: 0x9c, hi: 0x9c},
+ {value: 0x263d, lo: 0xa9, hi: 0xa9},
+ {value: 0x8126, lo: 0xb1, hi: 0xb1},
+ {value: 0x8127, lo: 0xb2, hi: 0xb2},
+ {value: 0x4a66, lo: 0xb3, hi: 0xb3},
+ {value: 0x8128, lo: 0xb4, hi: 0xb4},
+ {value: 0x4a6f, lo: 0xb5, hi: 0xb5},
+ {value: 0x464a, lo: 0xb6, hi: 0xb6},
+ {value: 0x468a, lo: 0xb7, hi: 0xb7},
+ {value: 0x4652, lo: 0xb8, hi: 0xb8},
+ {value: 0x4695, lo: 0xb9, hi: 0xb9},
+ {value: 0x8127, lo: 0xba, hi: 0xbd},
+ // Block 0x26, offset 0x107
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x8127, lo: 0x80, hi: 0x80},
+ {value: 0x4a78, lo: 0x81, hi: 0x81},
+ {value: 0x8132, lo: 0x82, hi: 0x83},
+ {value: 0x8104, lo: 0x84, hi: 0x84},
+ {value: 0x8132, lo: 0x86, hi: 0x87},
+ {value: 0x266e, lo: 0x93, hi: 0x93},
+ {value: 0x2675, lo: 0x9d, hi: 0x9d},
+ {value: 0x267c, lo: 0xa2, hi: 0xa2},
+ {value: 0x2683, lo: 0xa7, hi: 0xa7},
+ {value: 0x268a, lo: 0xac, hi: 0xac},
+ {value: 0x2667, lo: 0xb9, hi: 0xb9},
+ // Block 0x27, offset 0x113
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0x86, hi: 0x86},
+ // Block 0x28, offset 0x115
+ {value: 0x0000, lo: 0x05},
+ {value: 0xa000, lo: 0xa5, hi: 0xa5},
+ {value: 0x2d1e, 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 0x11b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0x8d, hi: 0x8d},
+ // Block 0x2a, offset 0x11d
+ {value: 0x0000, lo: 0x01},
+ {value: 0x030f, lo: 0xbc, hi: 0xbc},
+ // Block 0x2b, offset 0x11f
+ {value: 0x0000, lo: 0x01},
+ {value: 0xa000, lo: 0x80, hi: 0x92},
+ // Block 0x2c, offset 0x121
+ {value: 0x0000, lo: 0x01},
+ {value: 0xb900, lo: 0xa1, hi: 0xb5},
+ // Block 0x2d, offset 0x123
+ {value: 0x0000, lo: 0x01},
+ {value: 0x9900, lo: 0xa8, hi: 0xbf},
+ // Block 0x2e, offset 0x125
+ {value: 0x0000, lo: 0x01},
+ {value: 0x9900, lo: 0x80, hi: 0x82},
+ // Block 0x2f, offset 0x127
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0x9d, hi: 0x9f},
+ // Block 0x30, offset 0x129
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x94, hi: 0x94},
+ {value: 0x8104, lo: 0xb4, hi: 0xb4},
+ // Block 0x31, offset 0x12c
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x92, hi: 0x92},
+ {value: 0x8132, lo: 0x9d, hi: 0x9d},
+ // Block 0x32, offset 0x12f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8131, lo: 0xa9, hi: 0xa9},
+ // Block 0x33, offset 0x131
+ {value: 0x0004, lo: 0x02},
+ {value: 0x812e, lo: 0xb9, hi: 0xba},
+ {value: 0x812d, lo: 0xbb, hi: 0xbb},
+ // Block 0x34, offset 0x134
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0x97, hi: 0x97},
+ {value: 0x812d, lo: 0x98, hi: 0x98},
+ // Block 0x35, offset 0x137
+ {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 0x13b
+ {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 0x140
+ {value: 0x0000, lo: 0x08},
+ {value: 0x2d66, lo: 0x80, hi: 0x80},
+ {value: 0x2d6e, lo: 0x81, hi: 0x81},
+ {value: 0xa000, lo: 0x82, hi: 0x82},
+ {value: 0x2d76, 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 0x149
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xaa, hi: 0xab},
+ // Block 0x39, offset 0x14b
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8102, lo: 0xa6, hi: 0xa6},
+ {value: 0x8104, lo: 0xb2, hi: 0xb3},
+ // Block 0x3a, offset 0x14e
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0xb7, hi: 0xb7},
+ // Block 0x3b, offset 0x150
+ {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 0x15b
+ {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 0x166
+ {value: 0x0000, lo: 0x0f},
+ {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: 0x8132, lo: 0xbb, hi: 0xbb},
+ {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 0x176
+ {value: 0x0000, lo: 0x0d},
+ {value: 0x0001, lo: 0x80, hi: 0x8a},
+ {value: 0x043b, lo: 0x91, hi: 0x91},
+ {value: 0x429b, lo: 0x97, hi: 0x97},
+ {value: 0x001d, lo: 0xa4, hi: 0xa4},
+ {value: 0x1873, lo: 0xa5, hi: 0xa5},
+ {value: 0x1b5c, lo: 0xa6, hi: 0xa6},
+ {value: 0x0001, lo: 0xaf, hi: 0xaf},
+ {value: 0x2691, lo: 0xb3, hi: 0xb3},
+ {value: 0x27fe, lo: 0xb4, hi: 0xb4},
+ {value: 0x2698, lo: 0xb6, hi: 0xb6},
+ {value: 0x2808, lo: 0xb7, hi: 0xb7},
+ {value: 0x186d, lo: 0xbc, hi: 0xbc},
+ {value: 0x4269, lo: 0xbe, hi: 0xbe},
+ // Block 0x3f, offset 0x184
+ {value: 0x0002, lo: 0x0d},
+ {value: 0x1933, lo: 0x87, hi: 0x87},
+ {value: 0x1930, lo: 0x88, hi: 0x88},
+ {value: 0x1870, lo: 0x89, hi: 0x89},
+ {value: 0x298e, 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: 0x0467, 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 0x192
+ {value: 0x0002, lo: 0x0f},
+ {value: 0x0021, lo: 0x80, hi: 0x89},
+ {value: 0x0017, lo: 0x8a, hi: 0x8a},
+ {value: 0x0467, 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: 0x1999, lo: 0xa8, hi: 0xa8},
+ // Block 0x41, offset 0x1a2
+ {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 0x1b0
+ {value: 0x0007, lo: 0x06},
+ {value: 0x2180, lo: 0x89, hi: 0x89},
+ {value: 0xa000, lo: 0x90, hi: 0x90},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0xa000, lo: 0x94, hi: 0x94},
+ {value: 0x3bb9, lo: 0x9a, hi: 0x9b},
+ {value: 0x3bc7, lo: 0xae, hi: 0xae},
+ // Block 0x43, offset 0x1b7
+ {value: 0x000e, lo: 0x05},
+ {value: 0x3bce, lo: 0x8d, hi: 0x8e},
+ {value: 0x3bd5, 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 0x1bd
+ {value: 0x0173, lo: 0x0e},
+ {value: 0xa000, lo: 0x83, hi: 0x83},
+ {value: 0x3be3, lo: 0x84, hi: 0x84},
+ {value: 0xa000, lo: 0x88, hi: 0x88},
+ {value: 0x3bea, lo: 0x89, hi: 0x89},
+ {value: 0xa000, lo: 0x8b, hi: 0x8b},
+ {value: 0x3bf1, lo: 0x8c, hi: 0x8c},
+ {value: 0xa000, lo: 0xa3, hi: 0xa3},
+ {value: 0x3bf8, lo: 0xa4, hi: 0xa4},
+ {value: 0xa000, lo: 0xa5, hi: 0xa5},
+ {value: 0x3bff, lo: 0xa6, hi: 0xa6},
+ {value: 0x269f, lo: 0xac, hi: 0xad},
+ {value: 0x26a6, lo: 0xaf, hi: 0xaf},
+ {value: 0x281c, lo: 0xb0, hi: 0xb0},
+ {value: 0xa000, lo: 0xbc, hi: 0xbc},
+ // Block 0x45, offset 0x1cc
+ {value: 0x0007, lo: 0x03},
+ {value: 0x3c68, lo: 0xa0, hi: 0xa1},
+ {value: 0x3c92, lo: 0xa2, hi: 0xa3},
+ {value: 0x3cbc, lo: 0xaa, hi: 0xad},
+ // Block 0x46, offset 0x1d0
+ {value: 0x0004, lo: 0x01},
+ {value: 0x048b, lo: 0xa9, hi: 0xaa},
+ // Block 0x47, offset 0x1d2
+ {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 0x1d6
+ {value: 0x0000, lo: 0x01},
+ {value: 0x299b, lo: 0x8c, hi: 0x8c},
+ // Block 0x49, offset 0x1d8
+ {value: 0x0263, lo: 0x02},
+ {value: 0x1b8c, lo: 0xb4, hi: 0xb4},
+ {value: 0x192d, lo: 0xb5, hi: 0xb6},
+ // Block 0x4a, offset 0x1db
+ {value: 0x0000, lo: 0x01},
+ {value: 0x4573, lo: 0x9c, hi: 0x9c},
+ // Block 0x4b, offset 0x1dd
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0095, lo: 0xbc, hi: 0xbc},
+ {value: 0x006d, lo: 0xbd, hi: 0xbd},
+ // Block 0x4c, offset 0x1e0
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xaf, hi: 0xb1},
+ // Block 0x4d, offset 0x1e2
+ {value: 0x0000, lo: 0x02},
+ {value: 0x047f, lo: 0xaf, hi: 0xaf},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x4e, offset 0x1e5
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xa0, hi: 0xbf},
+ // Block 0x4f, offset 0x1e7
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0dc3, lo: 0x9f, hi: 0x9f},
+ // Block 0x50, offset 0x1e9
+ {value: 0x0000, lo: 0x01},
+ {value: 0x162f, lo: 0xb3, hi: 0xb3},
+ // Block 0x51, offset 0x1eb
+ {value: 0x0004, lo: 0x0b},
+ {value: 0x1597, lo: 0x80, hi: 0x82},
+ {value: 0x15af, lo: 0x83, hi: 0x83},
+ {value: 0x15c7, lo: 0x84, hi: 0x85},
+ {value: 0x15d7, lo: 0x86, hi: 0x89},
+ {value: 0x15eb, lo: 0x8a, hi: 0x8c},
+ {value: 0x15ff, lo: 0x8d, hi: 0x8d},
+ {value: 0x1607, lo: 0x8e, hi: 0x8e},
+ {value: 0x160f, lo: 0x8f, hi: 0x90},
+ {value: 0x161b, lo: 0x91, hi: 0x93},
+ {value: 0x162b, lo: 0x94, hi: 0x94},
+ {value: 0x1633, lo: 0x95, hi: 0x95},
+ // Block 0x52, offset 0x1f7
+ {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: 0x04b3, lo: 0xb6, hi: 0xb6},
+ {value: 0x0887, lo: 0xb8, hi: 0xba},
+ // Block 0x53, offset 0x201
+ {value: 0x0005, lo: 0x09},
+ {value: 0x0313, lo: 0xb1, hi: 0xb1},
+ {value: 0x0317, lo: 0xb2, hi: 0xb2},
+ {value: 0x4345, lo: 0xb3, hi: 0xb3},
+ {value: 0x031b, lo: 0xb4, hi: 0xb4},
+ {value: 0x434a, lo: 0xb5, hi: 0xb6},
+ {value: 0x031f, lo: 0xb7, hi: 0xb7},
+ {value: 0x0323, lo: 0xb8, hi: 0xb8},
+ {value: 0x0327, lo: 0xb9, hi: 0xb9},
+ {value: 0x4354, lo: 0xba, hi: 0xbf},
+ // Block 0x54, offset 0x20b
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0xaf, hi: 0xaf},
+ {value: 0x8132, lo: 0xb4, hi: 0xbd},
+ // Block 0x55, offset 0x20e
+ {value: 0x0000, lo: 0x03},
+ {value: 0x020f, lo: 0x9c, hi: 0x9c},
+ {value: 0x0212, lo: 0x9d, hi: 0x9d},
+ {value: 0x8132, lo: 0x9e, hi: 0x9f},
+ // Block 0x56, offset 0x212
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xb0, hi: 0xb1},
+ // Block 0x57, offset 0x214
+ {value: 0x0000, lo: 0x01},
+ {value: 0x163b, lo: 0xb0, hi: 0xb0},
+ // Block 0x58, offset 0x216
+ {value: 0x000c, lo: 0x01},
+ {value: 0x00d7, lo: 0xb8, hi: 0xb9},
+ // Block 0x59, offset 0x218
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x86, hi: 0x86},
+ // Block 0x5a, offset 0x21a
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x84, hi: 0x84},
+ {value: 0x8132, lo: 0xa0, hi: 0xb1},
+ // Block 0x5b, offset 0x21d
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0xab, hi: 0xad},
+ // Block 0x5c, offset 0x21f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x93, hi: 0x93},
+ // Block 0x5d, offset 0x221
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0xb3, hi: 0xb3},
+ // Block 0x5e, offset 0x223
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x80, hi: 0x80},
+ // Block 0x5f, offset 0x225
+ {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 0x60, offset 0x22b
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0x81, hi: 0x81},
+ {value: 0x8104, lo: 0xb6, hi: 0xb6},
+ // Block 0x61, offset 0x22e
+ {value: 0x0008, lo: 0x03},
+ {value: 0x1637, lo: 0x9c, hi: 0x9d},
+ {value: 0x0125, lo: 0x9e, hi: 0x9e},
+ {value: 0x1643, lo: 0x9f, hi: 0x9f},
+ // Block 0x62, offset 0x232
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xad, hi: 0xad},
+ // Block 0x63, offset 0x234
+ {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 0x64, offset 0x23b
+ {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 0x65, offset 0x241
+ {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 0x66, offset 0x247
+ {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 0x67, offset 0x24f
+ {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 0x68, offset 0x255
+ {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 0x69, offset 0x25b
+ {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 0x6a, offset 0x261
+ {value: 0x0000, lo: 0x03},
+ {value: 0xc600, lo: 0x80, hi: 0x87},
+ {value: 0xe500, lo: 0x88, hi: 0x88},
+ {value: 0xc600, lo: 0x89, hi: 0xa3},
+ // Block 0x6b, offset 0x265
+ {value: 0x0002, lo: 0x01},
+ {value: 0x0003, lo: 0x81, hi: 0xbf},
+ // Block 0x6c, offset 0x267
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0xbd, hi: 0xbd},
+ // Block 0x6d, offset 0x269
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0xa0, hi: 0xa0},
+ // Block 0x6e, offset 0x26b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xb6, hi: 0xba},
+ // Block 0x6f, offset 0x26d
+ {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 0x70, offset 0x273
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0xa5, hi: 0xa5},
+ {value: 0x812d, lo: 0xa6, hi: 0xa6},
+ // Block 0x71, offset 0x276
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x86, hi: 0x86},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x72, offset 0x279
+ {value: 0x17fe, lo: 0x07},
+ {value: 0xa000, lo: 0x99, hi: 0x99},
+ {value: 0x4238, lo: 0x9a, hi: 0x9a},
+ {value: 0xa000, lo: 0x9b, hi: 0x9b},
+ {value: 0x4242, lo: 0x9c, hi: 0x9c},
+ {value: 0xa000, lo: 0xa5, hi: 0xa5},
+ {value: 0x424c, lo: 0xab, hi: 0xab},
+ {value: 0x8104, lo: 0xb9, hi: 0xba},
+ // Block 0x73, offset 0x281
+ {value: 0x0000, lo: 0x06},
+ {value: 0x8132, lo: 0x80, hi: 0x82},
+ {value: 0x9900, lo: 0xa7, hi: 0xa7},
+ {value: 0x2d7e, lo: 0xae, hi: 0xae},
+ {value: 0x2d88, lo: 0xaf, hi: 0xaf},
+ {value: 0xa000, lo: 0xb1, hi: 0xb2},
+ {value: 0x8104, lo: 0xb3, hi: 0xb4},
+ // Block 0x74, offset 0x288
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x80, hi: 0x80},
+ {value: 0x8102, lo: 0x8a, hi: 0x8a},
+ // Block 0x75, offset 0x28b
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0xb5, hi: 0xb5},
+ {value: 0x8102, lo: 0xb6, hi: 0xb6},
+ // Block 0x76, offset 0x28e
+ {value: 0x0002, lo: 0x01},
+ {value: 0x8102, lo: 0xa9, hi: 0xaa},
+ // Block 0x77, offset 0x290
+ {value: 0x0000, lo: 0x07},
+ {value: 0xa000, lo: 0x87, hi: 0x87},
+ {value: 0x2d92, lo: 0x8b, hi: 0x8b},
+ {value: 0x2d9c, 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 0x298
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x82, hi: 0x82},
+ {value: 0x8102, lo: 0x86, hi: 0x86},
+ // Block 0x79, offset 0x29b
+ {value: 0x6b5a, lo: 0x06},
+ {value: 0x9900, lo: 0xb0, hi: 0xb0},
+ {value: 0xa000, lo: 0xb9, hi: 0xb9},
+ {value: 0x9900, lo: 0xba, hi: 0xba},
+ {value: 0x2db0, lo: 0xbb, hi: 0xbb},
+ {value: 0x2da6, lo: 0xbc, hi: 0xbd},
+ {value: 0x2dba, lo: 0xbe, hi: 0xbe},
+ // Block 0x7a, offset 0x2a2
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x82, hi: 0x82},
+ {value: 0x8102, lo: 0x83, hi: 0x83},
+ // Block 0x7b, offset 0x2a5
+ {value: 0x0000, lo: 0x05},
+ {value: 0x9900, lo: 0xaf, hi: 0xaf},
+ {value: 0xa000, lo: 0xb8, hi: 0xb9},
+ {value: 0x2dc4, lo: 0xba, hi: 0xba},
+ {value: 0x2dce, lo: 0xbb, hi: 0xbb},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x7c, offset 0x2ab
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0x80, hi: 0x80},
+ // Block 0x7d, offset 0x2ad
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x7e, offset 0x2af
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0xb6, hi: 0xb6},
+ {value: 0x8102, lo: 0xb7, hi: 0xb7},
+ // Block 0x7f, offset 0x2b2
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xab, hi: 0xab},
+ // Block 0x80, offset 0x2b4
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8101, lo: 0xb0, hi: 0xb4},
+ // Block 0x81, offset 0x2b6
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xb0, hi: 0xb6},
+ // Block 0x82, offset 0x2b8
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8101, lo: 0x9e, hi: 0x9e},
+ // Block 0x83, offset 0x2ba
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x4662, lo: 0x9e, hi: 0x9e},
+ {value: 0x466c, lo: 0x9f, hi: 0x9f},
+ {value: 0x46a0, lo: 0xa0, hi: 0xa0},
+ {value: 0x46ae, lo: 0xa1, hi: 0xa1},
+ {value: 0x46bc, lo: 0xa2, hi: 0xa2},
+ {value: 0x46ca, lo: 0xa3, hi: 0xa3},
+ {value: 0x46d8, 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 0x84, offset 0x2c7
+ {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: 0x4676, lo: 0xbb, hi: 0xbb},
+ {value: 0x4680, lo: 0xbc, hi: 0xbc},
+ {value: 0x46e6, lo: 0xbd, hi: 0xbd},
+ {value: 0x4702, lo: 0xbe, hi: 0xbe},
+ {value: 0x46f4, lo: 0xbf, hi: 0xbf},
+ // Block 0x85, offset 0x2d1
+ {value: 0x0000, lo: 0x01},
+ {value: 0x4710, lo: 0x80, hi: 0x80},
+ // Block 0x86, offset 0x2d3
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0x82, hi: 0x84},
+ // Block 0x87, offset 0x2d5
+ {value: 0x0002, lo: 0x03},
+ {value: 0x0043, lo: 0x80, hi: 0x99},
+ {value: 0x0083, lo: 0x9a, hi: 0xb3},
+ {value: 0x0043, lo: 0xb4, hi: 0xbf},
+ // Block 0x88, offset 0x2d9
+ {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 0x89, offset 0x2de
+ {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 0x8a, offset 0x2ea
+ {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 0x8b, offset 0x2ef
+ {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 0x8c, offset 0x2f8
+ {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 0x8d, offset 0x2fe
+ {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 0x8e, offset 0x303
+ {value: 0x0002, lo: 0x03},
+ {value: 0x008f, lo: 0x80, hi: 0x93},
+ {value: 0x0043, lo: 0x94, hi: 0xad},
+ {value: 0x0083, lo: 0xae, hi: 0xbf},
+ // Block 0x8f, offset 0x307
+ {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 0x90, offset 0x30c
+ {value: 0x0002, lo: 0x03},
+ {value: 0x004b, lo: 0x80, hi: 0x95},
+ {value: 0x0083, lo: 0x96, hi: 0xaf},
+ {value: 0x0043, lo: 0xb0, hi: 0xbf},
+ // Block 0x91, offset 0x310
+ {value: 0x0003, lo: 0x0f},
+ {value: 0x01b8, lo: 0x80, hi: 0x80},
+ {value: 0x045f, lo: 0x81, hi: 0x81},
+ {value: 0x01bb, lo: 0x82, hi: 0x9a},
+ {value: 0x045b, 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: 0x045f, lo: 0xbb, hi: 0xbb},
+ {value: 0x01bb, lo: 0xbc, hi: 0xbf},
+ // Block 0x92, offset 0x320
+ {value: 0x0003, lo: 0x0d},
+ {value: 0x01c7, lo: 0x80, hi: 0x94},
+ {value: 0x045b, 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: 0x045f, lo: 0xb5, hi: 0xb5},
+ {value: 0x01bb, lo: 0xb6, hi: 0xbf},
+ // Block 0x93, offset 0x32e
+ {value: 0x0003, lo: 0x0d},
+ {value: 0x01d9, lo: 0x80, hi: 0x8e},
+ {value: 0x045b, 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: 0x045f, lo: 0xaf, hi: 0xaf},
+ {value: 0x01bb, lo: 0xb0, hi: 0xbf},
+ // Block 0x94, offset 0x33c
+ {value: 0x0003, lo: 0x0d},
+ {value: 0x01eb, lo: 0x80, hi: 0x88},
+ {value: 0x045b, 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: 0x045f, lo: 0xa9, hi: 0xa9},
+ {value: 0x01bb, lo: 0xaa, hi: 0xbf},
+ // Block 0x95, offset 0x34a
+ {value: 0x0000, lo: 0x05},
+ {value: 0x8132, lo: 0x80, hi: 0x86},
+ {value: 0x8132, lo: 0x88, hi: 0x98},
+ {value: 0x8132, lo: 0x9b, hi: 0xa1},
+ {value: 0x8132, lo: 0xa3, hi: 0xa4},
+ {value: 0x8132, lo: 0xa6, hi: 0xaa},
+ // Block 0x96, offset 0x350
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0x90, hi: 0x96},
+ // Block 0x97, offset 0x352
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0x84, hi: 0x89},
+ {value: 0x8102, lo: 0x8a, hi: 0x8a},
+ // Block 0x98, offset 0x355
+ {value: 0x0002, lo: 0x09},
+ {value: 0x0063, lo: 0x80, hi: 0x89},
+ {value: 0x1951, lo: 0x8a, hi: 0x8a},
+ {value: 0x1981, lo: 0x8b, hi: 0x8b},
+ {value: 0x199c, lo: 0x8c, hi: 0x8c},
+ {value: 0x19a2, lo: 0x8d, hi: 0x8d},
+ {value: 0x1bc0, lo: 0x8e, hi: 0x8e},
+ {value: 0x19ae, lo: 0x8f, hi: 0x8f},
+ {value: 0x197b, lo: 0xaa, hi: 0xaa},
+ {value: 0x197e, lo: 0xab, hi: 0xab},
+ // Block 0x99, offset 0x35f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x193f, lo: 0x90, hi: 0x90},
+ // Block 0x9a, offset 0x361
+ {value: 0x0028, lo: 0x09},
+ {value: 0x2862, lo: 0x80, hi: 0x80},
+ {value: 0x2826, lo: 0x81, hi: 0x81},
+ {value: 0x2830, lo: 0x82, hi: 0x82},
+ {value: 0x2844, lo: 0x83, hi: 0x84},
+ {value: 0x284e, lo: 0x85, hi: 0x86},
+ {value: 0x283a, lo: 0x87, hi: 0x87},
+ {value: 0x2858, lo: 0x88, hi: 0x88},
+ {value: 0x0b6f, lo: 0x90, hi: 0x90},
+ {value: 0x08e7, 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: 53KB (53976 bytes)
diff --git a/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/transform.go b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/transform.go
new file mode 100644
index 0000000..8589067
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/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/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/transform_test.go b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/transform_test.go
new file mode 100644
index 0000000..987d680
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/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/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/trie.go b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/trie.go
new file mode 100644
index 0000000..423386b
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/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/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/triegen.go b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/triegen.go
new file mode 100644
index 0000000..45d7119
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/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/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/ucd_test.go b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/ucd_test.go
new file mode 100644
index 0000000..29205a6
--- /dev/null
+++ b/cmd/ponzu/vendor/golang.org/x/text/unicode/norm/ucd_test.go
@@ -0,0 +1,275 @@
+// 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 (
+ "bufio"
+ "bytes"
+ "fmt"
+ "regexp"
+ "runtime"
+ "strconv"
+ "strings"
+ "sync"
+ "testing"
+ "time"
+ "unicode/utf8"
+
+ "golang.org/x/text/internal/gen"
+ "golang.org/x/text/internal/testtext"
+)
+
+var once sync.Once
+
+func skipShort(t *testing.T) {
+ testtext.SkipIfNotLong(t)
+
+ once.Do(func() { loadTestData(t) })
+}
+
+// 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(t *testing.T) {
+ f := gen.OpenUCDFile("NormalizationTest.txt")
+ 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 {
+ t.Fatal("Failed to parse Part: ", line)
+ }
+ i, err := strconv.Atoi(m[1])
+ if err != nil {
+ t.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 {
+ t.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 {
+ t.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 {
+ t.Fatal(scanner.Err())
+ }
+}
+
+func cmpResult(t *testing.T, tc *Test, name string, f Form, gold, test, result string) {
+ if gold != result {
+ t.Errorf("%s:%s: %s(%+q)=%+q; want %+q: %s",
+ tc.Name(), name, fstr[f], test, result, gold, tc.name)
+ }
+}
+
+func cmpIsNormal(t *testing.T, tc *Test, name string, f Form, test string, result, want bool) {
+ if result != want {
+ t.Errorf("%s:%s: %s(%+q)=%v; want %v", tc.Name(), name, fstr[f], test, result, want)
+ }
+}
+
+func doTest(t *testing.T, tc *Test, f Form, gold, test string) {
+ testb := []byte(test)
+ result := f.Bytes(testb)
+ cmpResult(t, tc, "Bytes", f, gold, test, string(result))
+
+ sresult := f.String(test)
+ cmpResult(t, tc, "String", f, gold, test, sresult)
+
+ acc := []byte{}
+ i := Iter{}
+ i.InitString(f, test)
+ for !i.Done() {
+ acc = append(acc, i.Next()...)
+ }
+ cmpResult(t, tc, "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, tc, "Transform", f, gold, test, string(acc))
+
+ for i := range test {
+ out := f.Append(f.Bytes([]byte(test[:i])), []byte(test[i:])...)
+ cmpResult(t, tc, fmt.Sprintf(":Append:%d", i), f, gold, test, string(out))
+ }
+ cmpIsNormal(t, tc, "IsNormal", f, test, f.IsNormal([]byte(test)), test == gold)
+ cmpIsNormal(t, tc, "IsNormalString", f, test, f.IsNormalString(test), test == gold)
+}
+
+func doConformanceTests(t *testing.T, tc *Test, partn int) {
+ for i := 0; i <= 2; i++ {
+ doTest(t, tc, NFC, tc.cols[1], tc.cols[i])
+ doTest(t, tc, NFD, tc.cols[2], tc.cols[i])
+ doTest(t, tc, NFKC, tc.cols[3], tc.cols[i])
+ doTest(t, tc, NFKD, tc.cols[4], tc.cols[i])
+ }
+ for i := 3; i <= 4; i++ {
+ doTest(t, tc, NFC, tc.cols[3], tc.cols[i])
+ doTest(t, tc, NFD, tc.cols[4], tc.cols[i])
+ doTest(t, tc, NFKC, tc.cols[3], tc.cols[i])
+ doTest(t, tc, NFKD, tc.cols[4], tc.cols[i])
+ }
+}
+
+func TestCharacterByCharacter(t *testing.T) {
+ skipShort(t)
+ 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.
+ tc := &Test{partnr: 1, number: -1}
+ char := string(last)
+ doTest(t, tc, NFC, char, char)
+ doTest(t, tc, NFD, char, char)
+ doTest(t, tc, NFKC, char, char)
+ doTest(t, tc, NFKD, char, char)
+ }
+ if i < len(tests) {
+ doConformanceTests(t, &tests[i], 1)
+ }
+ }
+}
+
+func TestStandardTests(t *testing.T) {
+ skipShort(t)
+ for _, j := range []int{0, 2, 3} {
+ for _, test := range part[j].tests {
+ doConformanceTests(t, &test, j)
+ }
+ }
+}
+
+// TestPerformance 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 TestPerformance(t *testing.T) {
+ skipShort(t)
+ runtime.GOMAXPROCS(2)
+ success := make(chan bool, 1)
+ go func() {
+ buf := bytes.Repeat([]byte("\u035D"), 1024*1024)
+ buf = append(buf, "\u035B"...)
+ NFC.Append(nil, buf...)
+ success <- true
+ }()
+ timeout := time.After(1 * time.Second)
+ select {
+ case <-success:
+ // test completed before the timeout
+ case <-timeout:
+ t.Errorf(`unexpectedly long time to complete PerformanceTest`)
+ }
+}