Full Code of Ed-von-Schleck/shoco for AI

master 7c92fa9c4161 cached
21 files
1.4 MB
390.8k tokens
128 symbols
1 requests
Download .txt
Showing preview only (1,460K chars total). Download the full file or copy to clipboard to get everything.
Repository: Ed-von-Schleck/shoco
Branch: master
Commit: 7c92fa9c4161
Files: 21
Total size: 1.4 MB

Directory structure:
gitextract_i2kqoeob/

├── LICENSE
├── Makefile
├── README.md
├── generate_compressor_model.py
├── models/
│   ├── dictionary.h
│   ├── filepaths.h
│   ├── text_en.h
│   └── words_en.h
├── pre.js
├── shoco-bin.c
├── shoco.c
├── shoco.h
├── shoco.html
├── shoco.js
├── shoco_model.h
├── shoco_table.h
├── test_input.c
├── tests.c
└── training_data/
    ├── dorian_gray.txt
    ├── metamorphosis.txt
    └── pride_and_prejudice.txt

================================================
FILE CONTENTS
================================================

================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2014 Christian Schramm <christian.h.m.schramm@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.



================================================
FILE: Makefile
================================================
FLAGS=$(CFLAGS) -std=c99 -O3 -Wall
SOURCES=shoco.c
OBJECTS=$(SOURCES:.c=.o)
HEADERS=shoco.h shoco_model.h
GENERATOR=generate_compressor_model.py
TRAINING_DATA_DIR=training_data
TRAINING_DATA=$(wildcard training_data/*.txt)
TABLES_DIR=models
TABLES=$(TABLES_DIR)/text_en.h $(TABLES_DIR)/words_en.h $(TABLES_DIR)/filepaths.h

.PHONY: all
all: shoco

shoco: shoco-bin.o $(OBJECTS) $(HEADERS)
	$(CC) $(LDFLAGS) $(OBJECTS) -s $< -o $@

test_input: test_input.o $(OBJECTS) $(HEADERS)
	$(CC) $(LDFLAGS) $(OBJECTS) -s $< -o $@

$(OBJECTS): %.o: %.c $(HEADERS)
	$(CC) $(FLAGS) $< -c

shoco_model.h: $(TABLES_DIR)/words_en.h
	cp $< $@

.PHONY: models
models: $(TABLES)

$(TABLES_DIR)/text_en.h: $(TRAINING_DATA) $(GENERATOR)
	python $(GENERATOR) $(TRAINING_DATA) -o $@

$(TABLES_DIR)/words_en.h: $(TRAINING_DATA) $(GENERATOR)
	python $(GENERATOR) --split=whitespace --strip=punctuation $(TRAINING_DATA) -o $@

$(TABLES_DIR)/dictionary.h: /usr/share/dict/words $(GENERATOR)
	python $(GENERATOR) $< -o $@

# Warning: This is *slow*! Use pypy when possible
$(TABLES_DIR)/filepaths.h: $(GENERATOR)
	find / -print 2>/dev/null | pypy $(GENERATOR) --optimize-encoding -o $@

.PHONY: check
check: tests

tests: tests.o $(OBJECTS) $(HEADERS)
	$(CC) $(LDFLAGS) $(OBJECTS) $< -o $@
	./tests

.PHONY: clean
clean:
	rm *.o

.PHONY: js
js: shoco.js

shoco.js: $(OBJECTS) $(HEADERS) pre.js
	emcc shoco.c -O3 -o $@ --closure 1 -s EXPORTED_FUNCTIONS="['_shoco_compress', '_shoco_decompress']" --pre-js pre.js


================================================
FILE: README.md
================================================
**Note: This project is unmaintained. You should use ZStandard nowadays**

**shoco**: a fast compressor for short strings
--------------------------------------------

**shoco** is a C library to compress and decompress short strings. It is [very fast](#comparisons-with-other-compressors) and [easy to use](#api). The default compression model is optimized for english words, but you can [generate your own compression model](#generating-compression-models) based on *your specific* input data.

**shoco** is free software, distributed under the [MIT license](https://raw.githubusercontent.com/Ed-von-Schleck/shoco/master/LICENSE).

## Quick Start

Copy [shoco.c](https://raw.githubusercontent.com/Ed-von-Schleck/shoco/master/shoco.c), [shoco.h](https://raw.githubusercontent.com/Ed-von-Schleck/shoco/master/shoco.h) and [shoco_model.h](https://raw.githubusercontent.com/Ed-von-Schleck/shoco/master/shoco_model.h) from [github/shoco](https://github.com/Ed-von-Schleck/shoco) over to your project. Include `shoco.h` and you are ready to use the [API](#api)!

### API

Here is all of it:

```C
size_t shoco_compress(const char * in, size_t len, char * out, size_t bufsize);
size_t shoco_decompress(const char * in, size_t len, char * out, size_t bufsize);
```

If the `len` argument for `shoco_compress` is 0, the input char is assumed to be null-terminated. If it’s a positive integer, parsing the input will stop after this length, or at a null-char, whatever comes first. `shoco_decompress` however will need a positive integer for `len` (most likely you should pass the return value of `shoco_compress`).

The return value is the number of bytes written. If it is less than `bufsize`, all is well. In case of decompression, a null-terminator is written. If the return value is exactly `bufsize`, the output is all there, but _not_ null-terminated. It is up to you to decide if that’s an error or not. If the buffer is not large enough for the output, the return value will be `bufsize` + 1. You might want to allocate a bigger output buffer. The compressed string will never be null-terminated.

If you are sure that the input data is plain ASCII, your `out` buffer for `shoco_compress` only needs to be as large as the input string. Otherwise, the output buffer may need to be up to 2x as large as the input, if it’s a 1-byte encoding, or even larger for multi-byte or variable-width encodings like UTF-8.

For the standard values of _shoco_, maximum compression is 50%, so the `out` buffer for `shoco_decompress` needs to be a maximum of twice the size of the compressed string.

## How It Works

Have you ever tried compressing the string “hello world” with **gzip**? Let’s do it now:

```bash
$ echo "hello world" | gzip -c | wc -c
32
```

So the output is actually *larger* than the input string. And **gzip** is quite good with short input: **xz** produces an output size of 68 bytes. Of course, compressing short strings is not what they are made for, because you rarely need to make small strings even smaller – except when you do. That’s why **shoco** was written.

**shoco** works best if your input is ASCII. In fact, the most remarkable property of **shoco** is that the compressed size will *never* exceed the size of your input string, provided it is plain ASCII. What is more: An ASCII string is suitable input for the decompressor (which will return the exact same string, of course). That property comes at a cost, however: If your input string is not entirely (or mostly) ASCII, the output may grow. For some inputs, it can grow quite a lot. That is especially true for multibyte encodings such as UTF-8. Latin-1 and comparable encodings fare better, but will still increase your output size, if you don’t happen to hit a common character. Why is that so?

In every language, some characters are used more often than others. English is no exception to this rule. So if one simply makes a list of the, say, sixteen most common characters, four bits would be sufficient to refer to them (as opposed to eight bits – one byte – used by ASCII). But what if the input string includes an uncommon character, that is not in this list? Here’s the trick: We use the first bit of a `char` to indicate if the following bits refer to a short common character index, or a normal ASCII byte. Since the first bit in plain ASCII is always 0, setting the first bit to 1 says “the next bits represent short indices for common chars”. But what if our character is not ASCII (meaning the first bit of the input `char` is not 0)? Then we insert a marker that says “copy the next byte over as-is”, and we’re done. That explains the growth for non-ASCII characters: This marker takes up a byte, doubling the effective size of the character.

How **shoco** actually marks these packed representations is a bit more complicated than that (e.g., we also need to specify *how many* packed characters follow, so a single leading bit won’t be sufficient), but the principle still holds.

But **shoco** is a bit smarter than just to abbreviate characters based on absolute frequency – languages have more regularities than that. Some characters are more likely to be encountered next to others; the canonical example would be **q**, that’s *almost always* followed by a **u**. In english, *the*, *she*, *he*, *then* are all very common words – and all have a **h** followed by a **e**. So if we’d assemble a list of common characters *following common characters*, we can do with even less bits to represent these *successor* characters, and still have a good hit rate. That’s the idea of **shoco**: Provide short representations of characters based on the previous character.

This does not allow for optimal compression – by far. But if one carefully aligns the representation packs to byte boundaries, and uses the ASCII-first-bit-trick above to encode the indices, it works well enough. Moreover, it is blazingly fast. You wouldn’t want to use **shoco** for strings larger than, say, a hundred bytes, because then the overhead of a full-blown compressor like **gzip** begins to be dwarfed by the advantages of the much more efficient algorithms it uses.

If one would want to classify **shoco**, it would be an [entropy encoder](http://en.wikipedia.org/wiki/Entropy_encoding), because the length of the representation of a character is determined by the probability of encountering it in a given input string. That’s opposed to [dictionary coders](http://en.wikipedia.org/wiki/Dictionary_coder) that maintain a dictionary of common substrings. An optimal compression for short strings could probably be achieved using an [arithmetic coder](http://en.wikipedia.org/wiki/Arithmetic_coding) (also a type of entropy encoder), but most likely one could not achieve the same kind of performance that **shoco** delivers.

How does **shoco** get the information about character frequencies? They are not pulled out of thin air, but instead generated by analyzing text with a relatively simple script. It counts all *bigrams* – two successive characters – in the text and orders them by frequency. If wished for, it also tests for best encodings (like: Is it better to spend more bits on the leading character or on the successor character?), and then outputs its findings as a header file for `shoco.c` to include. That means the statistical model is compiled in; we simply can’t add it to the compressed string without blowing it out of proportions (and defeating the whole purpose of this exercise). This script is shipped with **shoco**, and the [next section](#generating-compression-models) is about how *you* can use it to generate a model that’s optimized for *your* kind of data. Just remember that, with **shoco**, you need to control both ends of the chain (compression **and** decompression), because you can’t decompress data correctly if you’re not sure that the compressor has used the same model.

## Generating Compression Models

Maybe your typical input isn’t english words. Maybe it’s german or french – or whole sentences. Or file system paths. Or URLs. While the standard compression model of **shoco** should work for all of these, it might be worthwile to train **shoco** for this specific type of input data.

Fortunately, that’s really easy: **shoco** includes a python script called `generate_compression_model.py` that takes one or more text files and ouputs a header file ready for **shoco** to use. Here’s an example that trains **shoco** with a dictionary (btw., not the best kind of training data, because it’s dominated by uncommon words):

```bash
$ ./generate_compression_model.py /usr/share/dict/words -o shoco_model.h
```

There are options on how to chunk and strip the input data – for example, if we want to train **shoco** with the words in a readme file, but without punctuation and whitespace, we could do

```bash
$ ./generate_compression_model.py --split=whitespace --strip=punctuation README.md
```

Since we haven’t specified an output file, the resulting table file is printed on stdout.

This is most likely all you’ll need to generate a good model, but if you are adventurous, you might want to play around with all the options of the script: Type `generate_compression_model.py --help` to get a friendly help message. We won’t dive into the details here, though – just one word of warning: Generating tables can be slow if your input data is large, and _especially_ so if you use the `--optimize-encoding` option. Using [pypy](http://pypy.org/) can significantly speed up the process.

## Comparisons With Other Compressors

### smaz

There’s another good small string compressor out there: [**smaz**](https://github.com/antirez/**smaz**). **smaz** seems to be dictionary based, while **shoco** is an entropy encoder. As a result, **smaz** will often do better than **shoco** when compressing common english terms. However, **shoco** typically beats **smaz** for more obscure input, as long as it’s ASCII. **smaz** may enlarge your string for uncommon words (like numbers), **shoco** will never do that for ASCII strings.

Performance-wise, **shoco** is typically faster by at least a factor of 2. As an example, compressing and decompressing all words in `/usr/dict/share/words` with **smaz** takes around 0.325s on my computer and compresses on average by 28%, while **shoco** has a compression average of 33% (with the standard model; an optimized model will be even better) and takes around 0.145s. **shoco** is _especially_ fast at decompression.

**shoco** can be trained with user data, while **smaz**’s dictionary is built-in. That said, the maximum compression rate of **smaz** is hard to reach for **shoco**, so depending on your input type, you might fare better with **smaz** (there’s no way around it: You have to measure it yourself).

### gzip, xz

As mentioned, **shoco**’s compression ratio can’t (and doesn’t want to) compete with gzip et al. for strings larger than a few bytes. But for very small strings, it will always be better than standard compressors.

The performance of **shoco** should always be several times faster than about any standard compression tool. For testing purposes, there’s a binary inlcuded (unsurprisingly called `shoco`) that compresses and decompresses single files. The following timings were made with this command line tool. The data is `/usr/share/dict/words` (size: 4,953,680), compressing it as a whole (not a strong point of **shoco**):

compressor | compression time | decompression time | compressed size
-----------|------------------|--------------------|----------------
shoco      | 0.070s           | 0.010s             | 3,393,975
gzip       | 0.470s           | 0.048s             | 1,476,083
xz         | 3.300s           | 0.148s             | 1,229,980

This demonstates quite clearly that **shoco**’s compression rate sucks, but also that it’s _very_ fast.

## Javascript Version

For showing off, **shoco** ships with a Javascript version (`shoco.js`) that’s generated with [emscripten](https://github.com/kripken/emscripten). If you change the default compression model, you need to re-generate it by typing `make js`. You do need to have emscripten installed. The output is [asm.js](http://asmjs.org/) with a small shim to provide a convenient API:

```js
compressed = shoco.compress(input_string);
output_string = shoco.decompress(compressed);
```

The compressed string is really a [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/API/Uint8Array), since that resembles a C string more closely. The Javascript version is not as furiously fast as the C version because there’s dynamic (heap) memory allocation involved, but I guess there’s no way around it.

`shoco.js` should be usable as a node.js module.

## Tools And Other Included Extras

Most of them have been mentioned already, but for the sake of completeness – let’s have a quick overview over what you’ll find in the repo:

#### `shoco.c`, `shoco.h`, `shoco_model.h`

The heart of the project. If you don’t want to bother with nitty-gritty details, and the compression works for you, it’s all you’ll ever need.

#### `models/*`

As examples, there are more models included. Feel free to use one of them instead of the default model: Just copy it over `shoco_model.h` and you’re all set. Re-build them with `make models`.

#### `training_data/*`

Some books from [Project Gutenberg](http://www.gutenberg.org/ebooks/) used for generating the default model.

#### `shoco.js`

Javascript library, generated by **emscripten**. Also usable as a [node.js](http://nodejs.org/) module (put it in `node_modules` and `require` it). Re-build with `make js`.

#### `shoco.html`

A example of how to use `shoco.js` in a website.

#### `shoco`

A testing tool for compressing and decompressing files. Build it with `make shoco` or just `make`. Use it like this:

```bash
$ shoco compress file-to-compress.txt compressed-file.shoco
$ shoco decompress compressed-file.shoco decompressed-file.txt
```

It’s not meant for production use, because I can’t image why one would want to use **shoco** on entire files.

#### `test_input`

Another testing tool for compressing and decompressing every line in the input file. Build it with `make test_input`. Usage example:

```bash
$ time ./test_input < /usr/share/dict/words 
Number of compressed strings: 479828, average compression ratio: 33%

real   0m0.158s
user   0m0.145s
sys    0m0.013s
```

Adding the command line switch `-v` gives line-by-line information about the compression ratios.

#### `Makefile`

It’s not the cleanest or l33test Makefile ever, but it should give you hints for integrating **shoco** into your project.

#### `tests`

Invoke them with `make check`. They should pass.

## Things Still To Do

**shoco** is stable, and it works well – but I’d have only tested it with gcc/clang on x86_64 Linux. Feedback on how it runs on other OSes, compilers and architectures would be highly appreciated! If it fails, it’s a bug (and given the size of the project, it should be easy to fix). Other than that, there’s a few issues that could stand some improvements:

* There should be more tests, because there’s _never_ enough tests. Ever. Patches are very welcome!
* Tests should include model generation. As that involves re-compilation, these should probably written as a Makefile, or in bash or Python (maybe using `ctypes` to call the **shoco**-functions directly).
* The Python script for model generation should see some clean-up, as well as documentation. Also it should utilize all cpu cores (presumably via the `multiprocess`-module). This is a good task for new contributers!
* Again for model generation: Investigate why **pypy** isn’t as fast as should be expected ([jitviewer](https://bitbucket.org/pypy/jitviewer/) might be of help here).
* Make a real **node.js** module.
* The current SSE2 optimization is probably not optimal. Anyone who loves to tinker with these kinds of micro-optimizations is invited to try his or her hand here.
* Publishing/packaging it as a real library probably doesn’t make much sense, as the model is compiled-in, but maybe we should be making it easier to use **shoco** as a git submodule (even if it’s just about adding documentation), or finding other ways to avoid the copy&paste installation.

## Feedback

If you use **shoco**, or like it for whatever reason, I’d really love to [hear from you](mailto:christian.h.m.schramm at gmail.com - replace the 'at' with @ and delete this sentence-)! If wished for, I can provide integration with **shoco** for your commercial services (at a price, of course), or for your totally awesome free and open source software (for free, if I find the time). Also, a nice way of saying thanks is to support me financially via
[git tip](https://www.gittip.com/Ed-von-Schleck/) or [flattr](https://flattr.com/submit/auto?user_id=Christian.Schramm&url=https://ed-von-schleck.github.io/shoco&language=C&tags=github&category=software).

If you find a bug, or have a feature request, [file it](https://github.com/Ed-von-Schleck/shoco/issues/new)! If you have a question about usage or internals of **shoco**, ask it on [stackoverflow](https://stackoverflow.com/questions/ask) for good exposure – and write me a mail, so that I don’t miss it.

## Authors

**shoco** is written by [Christian Schramm](mailto:christian.h.m.schramm at gmail.com - replace the 'at' with @ and delete this sentence).


================================================
FILE: generate_compressor_model.py
================================================
#!/usr/bin/python

from __future__ import print_function

import collections
import argparse
import itertools
import re
import sys

WHITESPACE = b" \t\n\r\x0b\x0c\xc2\xad"
PUNCTUATION = b"!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
TABLE_C = """#ifndef _SHOCO_INTERNAL
#error This header file is only to be included by 'shoco.c'.
#endif
#pragma once
/*
This file was generated by 'generate_compressor_model.py'
so don't edit this by hand. Also, do not include this file
anywhere. It is internal to 'shoco.c'. Include 'shoco.h'
if you want to use shoco in your project.
*/

#define MIN_CHR {min_chr}
#define MAX_CHR {max_chr}

static const char chrs_by_chr_id[{chrs_count}] = {{
  {chrs}
}};

static const int8_t chr_ids_by_chr[256] = {{
  {chrs_reversed}
}};

static const int8_t successor_ids_by_chr_id_and_chr_id[{chrs_count}][{chrs_count}] = {{
  {{{successors_reversed}}}
}};

static const int8_t chrs_by_chr_and_successor_id[MAX_CHR - MIN_CHR][{successors_count}] = {{
  {{{chrs_by_chr_and_successor_id}}}
}};

#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4324)    // structure was padded due to __declspec(align())
#endif

typedef struct Pack {{
  const uint32_t word;
  const unsigned int bytes_packed;
  const unsigned int bytes_unpacked;
  const unsigned int offsets[{max_elements_len}];
  const int16_t _ALIGNED masks[{max_elements_len}];
  const char header_mask;
  const char header;
}} Pack;

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#define PACK_COUNT {pack_count}
#define MAX_SUCCESSOR_N {max_successor_len}

static const Pack packs[PACK_COUNT] = {{
  {pack_lines}
}};
"""

PACK_LINE = "{{ {word:#x}, {packed}, {unpacked}, {{ {offsets} }}, {{ {masks} }}, {header_mask:#x}, {header:#x} }}"

def accumulate(seq, start=0):
    total = start
    for elem in seq:
        total += elem
        yield total

class Structure(object):
    def __init__(self, datalist):
        self.datalist = list(datalist)

    @property
    def header(self):
        return self.datalist[0]

    @property
    def lead(self):
        return self.datalist[1]

    @property
    def successors(self):
        return self.datalist[2:]

    @property
    def consecutive(self):
        return self.datalist[1:]


class Bits(Structure):
    def __init__(self, bitlist):
        Structure.__init__(self, bitlist)

class Masks(Structure):
    def __init__(self, bitlist):
        Structure.__init__(self, [((1 << bits) -1) for bits in bitlist])

class Offsets(Structure):
    def __init__(self, bitlist):
        inverse = accumulate(bitlist)
        offsets = [32 - offset for offset in inverse]
        Structure.__init__(self, offsets)


class Encoding(object):
    def __init__(self, bitlist):
        self.bits = Bits(bitlist)
        self.masks = Masks(bitlist)
        self.offsets = Offsets(bitlist)
        self.packed = sum(bitlist) / 8
        self.size = len([bits for bits in bitlist if bits])
        self.unpacked = self.size - 1
        self._hash = tuple(bitlist).__hash__()

    @property
    def header_code(self):
        return ((1 << self.bits.header) - 2) << (8 - self.bits.header)

    @property
    def header_mask(self):
        return self.masks.header << (8 - self.bits.header)

    @property
    def word(self):
        return ((1 << self.bits.header) - 2) << self.offsets.header

    def __hash__(self):
        return self._hash

    def can_encode(self, part, successors, chrs_indices):
        lead_index = chrs_indices.get(part[0], -1)
        if lead_index < 0:
            return False
        if lead_index > (1 << self.bits.header):
            return False
        last_index = lead_index
        last_char = part[0]
        for bits, char in zip(self.bits.consecutive, part[1:]):
            if char not in successors[last_char]:
                return False
            successor_index = successors[last_char].index(char)
            if successor_index > (1 << bits):
                return False
            last_index = successor_index
            last_char = part[0]
            return True

PACK_STRUCTURES = (
    (1, (
        (2, 4, 2),
        (2, 3, 3),
        (2, 4, 1, 1),
        (2, 3, 2, 1),
        (2, 2, 2, 2),
        (2, 3, 1, 1, 1),
        (2, 2, 2, 1, 1),
        (2, 2, 1, 1, 1, 1),
        (2, 1, 1, 1, 1, 1, 1),
    )),
    (2, (
        (3, 5, 4, 2, 2),
        (3, 5, 3, 3, 2),
        (3, 4, 4, 3, 2),
        (3, 4, 3, 3, 3),
        (3, 5, 3, 2, 2, 1),
        (3, 5, 2, 2, 2, 2),
        (3, 4, 4, 2, 2, 1),
        (3, 4, 3, 2, 2, 2),
        (3, 4, 3, 3, 2, 1),
        (3, 4, 2, 2, 2, 2),
        (3, 3, 3, 3, 2, 2),
        (3, 4, 3, 2, 2, 1, 1),
        (3, 4, 2, 2, 2, 2, 1),
        (3, 3, 3, 2, 2, 2, 1),
        (3, 3, 2, 2, 2, 2, 2),
        (3, 2, 2, 2, 2, 2, 2),
        (3, 3, 3, 2, 2, 1, 1, 1),
        (3, 3, 2, 2, 2, 2, 1, 1),
        (3, 2, 2, 2, 2, 2, 2, 1),
    )),
    (4, (
        (4, 5, 4, 4, 4, 3, 3, 3, 2),
        (4, 5, 5, 4, 4, 3, 3, 2, 2),
        (4, 4, 4, 4, 4, 4, 3, 3, 2),
        (4, 4, 4, 4, 4, 3, 3, 3, 3),
    ))

)

ENCODINGS = [(packed, [Encoding(bitlist) for bitlist in bitlists]) for packed, bitlists in PACK_STRUCTURES]

MAX_CONSECUTIVES = 8

def make_log(output):
    if output is None:
        def _(*args, **kwargs):
            pass
        return _
    return print


def bigrams(sequence):
    sequence = iter(sequence)
    last = next(sequence)
    for item in sequence:
        yield last, item
        last = item


def format_int_line(items):
    return r", ".join([r"{}".format(k) for k in items])


def escape(char):
    return r"'\''" if char == "'" else repr(char)


def format_chr_line(items):
    return r", ".join([r"{}".format(escape(k)) for k in items])

def chunkinator(files, split, strip):
    if files:
        all_in = (open(filename, "rb").read() for filename in files)
    else:
        all_in = [sys.stdin.read()]

    split = split.lower()
    if split == "none":
        chunks = all_in
    elif split == "newline":
        chunks = itertools.chain.from_iterable(data.splitlines() for data in all_in)
    elif split == "whitespace":
        chunks = itertools.chain.from_iterable(re.split(b"[" + WHITESPACE + "]", data) for data in all_in)

    strip = strip.lower()
    for chunk in chunks:
        if strip == "whitespace":
            chunk = chunk.strip()
        elif strip == "punctuation":
            chunk = chunk.strip(PUNCTUATION + WHITESPACE)

        if chunk:
            yield chunk


def nearest_lg(number):
    lg = 0
    while (number > 0):
        number >>= 1
        lg += 1
    return lg


def main():
    parser = argparse.ArgumentParser(description="Generate a succession table for 'shoco'.")
    parser.add_argument("file", nargs="*", help="The training data file(s). If no input file is specified, the input is read from STDIN.")
    parser.add_argument("-o", "--output", type=str, help="Output file for the resulting succession table.")
    parser.add_argument("--split", choices=["newline", "whitespace", "none"], default="newline", help=r"Split the input into chunks at this separator. Default: newline")
    parser.add_argument("--strip", choices=["whitespace", "punctuation", "none"], default="whitespace", help="Remove leading and trailing characters from each chunk. Default: whitespace")

    generation_group = parser.add_argument_group("table and encoding generation arguments", "Higher values may provide for better compression ratios, but will make compression/decompression slower. Likewise, lower numbers make compression/decompression faster, but will likely make hurt the compression ratio. The default values are mostly a good compromise.")
    generation_group.add_argument("--max-leading-char-bits", type=int, default=5, help="The maximum amount of bits that may be used for representing a leading character. Default: 5")
    generation_group.add_argument("--max-successor-bits", type=int, default=4, help="The maximum amount of bits that may be used for representing a successor character. Default: 4")
    generation_group.add_argument("--encoding-types", type=int, default=3, choices=[1, 2, 3], help="The number of different encoding schemes. If your input strings are very short, consider lower values. Default: 3")
    generation_group.add_argument("--optimize-encoding", action="store_true", default=False, help="Find the optimal packing structure for the training data. This rarely leads to different results than the default values, and it is *slow*. Use it for very unusual input strings, or when you use non-default table generation arguments.")
    args = parser.parse_args()

    log = make_log(args.output)

    chars_count = 1 << args.max_leading_char_bits
    successors_count = 1 << args.max_successor_bits


    log("finding bigrams ... ", end="")
    sys.stdout.flush()
    bigram_counters = collections.OrderedDict()
    first_char_counter = collections.Counter()
    chunks = list(chunkinator(args.file, args.split, args.strip))
    for chunk in chunks:
        bgs = bigrams(chunk)
        for bg in bgs:
            a, b = bg
            first_char_counter[a] += 1
            if a not in bigram_counters:
                bigram_counters[a] = collections.Counter()
            bigram_counters[a][b] += 1


    log("done.")
    # generate list of most common chars
    successors = collections.OrderedDict()
    for char, freq in first_char_counter.most_common(1 << args.max_leading_char_bits):
        successors[char] = [successor for successor, freq in bigram_counters[char].most_common(1 << args.max_successor_bits)]
        successors[char] += ['\0'] * ((1 << args.max_successor_bits) - len(successors[char]))

    max_chr = ord(max(successors.keys())) + 1
    min_chr = ord(min(successors.keys()))

    chrs_indices = collections.OrderedDict(zip(successors.keys(), range(chars_count)))
    chrs_reversed = [chrs_indices.get(chr(i), -1) for i in range(256)]

    successors_reversed = collections.OrderedDict()
    for char, successor_list in successors.items():
        successors_reversed[char] = [None] * chars_count
        s_indices = collections.OrderedDict(zip(successor_list, range(chars_count)))
        for i, s in enumerate(successors.keys()):
            successors_reversed[char][i] = s_indices.get(s, -1)

    zeros_line = ['\0'] * (1 << args.max_successor_bits)
    chrs_by_chr_and_successor_id = [successors.get(chr(i), zeros_line) for i in range(min_chr, max_chr)]


    if args.optimize_encoding:
        log("finding best packing structures ... ", end="")
        sys.stdout.flush()
        counters = {}

        for packed, _ in ENCODINGS[:args.encoding_types]:
            counters[packed] = collections.Counter()

        for chunk in chunks:
            for i in range(len(chunk)):
                for packed, encodings in ENCODINGS[:args.encoding_types]:
                    for encoding in encodings:
                        if (encoding.bits.lead > args.max_leading_char_bits) or (max(encoding.bits.consecutive) > args.max_successor_bits):
                            continue
                        if encoding.can_encode(chunk[i:], successors, chrs_indices):
                            counters[packed][encoding] += packed / float(encoding.unpacked)

        best_encodings_raw = [(packed, counter.most_common(1)[0][0]) for packed, counter in counters.items()]
        max_encoding_len = max(encoding.size for _, encoding in best_encodings_raw)
        best_encodings = [Encoding(encoding.bits.datalist + [0] * (MAX_CONSECUTIVES - encoding.size)) for packed, encoding in best_encodings_raw]
        log("done.")
    else:
        max_encoding_len = 8
        best_encodings = [Encoding([2, 4, 2, 0, 0, 0, 0, 0, 0]),
                          Encoding([3, 4, 3, 3, 3, 0, 0, 0, 0]),
                          Encoding([4, 5, 4, 4, 4, 3, 3, 3, 2])][:args.encoding_types]

    log("formating table file ... ", end="")
    sys.stdout.flush()

    pack_lines_formated = ",\n  ".join(
        PACK_LINE.format(
            word=best_encodings[i].word,
            packed=best_encodings[i].packed,
            unpacked=best_encodings[i].unpacked,
            offsets=format_int_line(best_encodings[i].offsets.consecutive),
            masks=format_int_line(best_encodings[i].masks.consecutive),
            header_mask=best_encodings[i].header_mask,
            header=best_encodings[i].header_code,
        )
        for i in range(args.encoding_types)
    )
    out = TABLE_C.format(
        chrs_count=chars_count,
        successors_count=successors_count,
        chrs=format_chr_line(successors.keys()),
        chrs_reversed=format_int_line(chrs_reversed),
        successors_reversed="},\n  {".join(format_int_line(l) for l in successors_reversed.values()),
        chrs_by_chr_and_successor_id="},\n  {".join(format_chr_line(l) for l in chrs_by_chr_and_successor_id),

        pack_lines=pack_lines_formated,
        max_successor_len=max_encoding_len - 1,
        max_elements_len=MAX_CONSECUTIVES,
        pack_count=args.encoding_types,
        max_chr=max_chr,
        min_chr=min_chr
    )
    log("done.")

    log("writing table file ... ", end="")
    sys.stdout.flush()
    if args.output is None:
        print(out)
    else:
        with open(args.output, "wb") as f:
            f.write(out)
            log("done.")

if __name__ == "__main__":
    main()


================================================
FILE: models/dictionary.h
================================================
#ifdef _SHOCO_INTERNAL
/*
This file was generated by 'generate_successor_table.py',
so don't edit this by hand. Also, do not include this file
anywhere. It is internal to 'shoco.c'. Include 'shoco.h'
if you want to use shoco in your project.
*/

static const char chrs[32] = {
  'e', 'i', 'o', 't', 'a', 'r', 'l', 's', 'n', 'u', 'c', 'd', 'h', 'm', 'v', 'p', 'g', 'b', 'k', 'f', 'q', 'z', 'w', '-', 'y', 'x', 'M', 'C', 'j', 'B', 'S', 'P'
};

static const char successors[32][16] = {
  {'r', 's', 'n', 'd', 'l', 't', 'a', 'c', 'm', 'e', 'p', '-', 'o', 'x', 'i', 'u'},
  {'n', 's', 'c', 't', 'a', 'o', 'l', 'e', 'd', 'm', 'r', 'v', 'g', 'z', 'p', 'f'},
  {'n', 'r', 'u', 'l', 'm', 's', 'p', 't', 'c', 'g', 'o', 'd', 'v', 'w', 'i', 'b'},
  {'i', 'e', 'o', 'a', 'r', 'h', 'u', 't', 'y', 's', 'l', '-', 'c', 'w', 'm', 'n'},
  {'n', 't', 'l', 'r', 's', 'c', 'b', 'm', 'd', 'p', 'g', 'i', 'u', 'e', 'v', 'k'},
  {'e', 'i', 'a', 'o', 's', 't', 'y', 'm', 'd', 'u', 'r', 'c', 'n', 'g', 'l', 'p'},
  {'e', 'i', 'a', 'l', 'o', 'y', 'u', 't', 'd', '-', 's', 'f', 'm', 'p', 'v', 'c'},
  {'t', 'e', 's', 'i', 'h', 'u', 'o', 'a', 'c', 'p', 'm', 'l', 'y', 'n', 'k', 'w'},
  {'e', 'g', 't', 'i', 'o', 'a', 'd', 's', 'c', 'n', 'u', 'f', '-', 'k', 'p', 'y'},
  {'n', 's', 'r', 'l', 't', 'm', 'b', 'a', 'p', 'c', 'i', 'd', 'e', 'g', 'f', 'o'},
  {'o', 'a', 'h', 'e', 'i', 't', 'k', 'r', 'u', 'l', 'y', 'c', 's', 'n', 'q', '-'},
  {'e', 'i', 'a', 'o', 'r', 'u', 'l', '-', 's', 'd', 'y', 'n', 'g', 'm', 'w', 'h'},
  {'e', 'a', 'i', 'o', 'y', 'r', 't', 'u', 'l', '-', 'n', 'm', 's', 'w', 'b', 'f'},
  {'a', 'e', 'i', 'o', 'p', 'b', 'u', 'm', 'y', 's', 'n', '-', 'l', 'f', 'r', 't'},
  {'e', 'i', 'a', 'o', 'u', 'y', 'r', 's', 'v', 'l', 'n', 'k', 'd', 't', '-', 'g'},
  {'e', 'h', 'r', 'o', 'a', 'i', 'l', 't', 'p', 'u', 's', 'y', '-', 'n', 'm', 'b'},
  {'e', 'i', 'a', 'r', 'l', 'o', 'h', 'u', 'n', 'g', 'y', 's', '-', 'm', 't', 'w'},
  {'l', 'e', 'a', 'i', 'o', 'r', 'u', 'b', 's', 'y', 't', 'd', 'c', 'j', '-', 'm'},
  {'e', 'i', 'a', 's', 'l', '-', 'o', 'n', 'y', 'h', 'u', 'r', 'w', 't', 'm', 'b'},
  {'i', 'o', 'e', 'l', 'a', 'u', 'f', 'r', '-', 't', 'y', 's', 'm', 'n', 'b', 'h'},
  {'u', 'a', 'i', 't', 'r', 'q', 'e', 's', 'l', 'w', 'o', 'p', 'v', 'h', 'n', '-'},
  {'e', 'a', 'i', 'o', 'z', 'y', 'l', 'u', 'h', 'b', 'm', '-', 'k', 't', 's', 'n'},
  {'e', 'a', 'i', 'o', 'h', 'n', '-', 'r', 's', 'l', 'd', 'b', 'k', 'y', 't', 'm'},
  {'s', 'b', 'c', 'f', 'p', 't', 'd', 'h', 'l', 'e', 'a', 'm', 'r', 'w', 'g', 'o'},
  {'l', 's', 'p', 'n', 'e', 'm', '-', 'a', 'c', 't', 'r', 'o', 'i', 'd', 'g', 'b'},
  {'i', 't', 'e', 'a', 'p', 'o', 'y', 'c', 'u', '-', 'h', 's', 'l', 'b', 'f', 'm'},
  {'a', 'e', 'o', 'i', 'u', 'c', 'y', 'S', 'P', 'C', 'M', 'r', 'B', 'n', 'g', '-'},
  {'a', 'o', 'h', 'r', 'l', 'e', 'u', 'y', 'i', 'S', 'C', 'M', 'P', 'B', 'z', 't'},
  {'a', 'u', 'o', 'e', 'i', 'n', 'r', 'd', 'k', 'c', 'j', 's', 'y', 'h', 'm', 'p'},
  {'a', 'e', 'r', 'o', 'u', 'i', 'l', 'S', 'y', 'h', 'M', 'C', 'P', 'B', '-', 'd'},
  {'a', 't', 'e', 'h', 'c', 'i', 'o', 'p', 'u', 'y', 'w', 'l', 'S', 'C', 'P', 'k'},
  {'a', 'e', 'r', 'o', 'h', 'i', 'l', 'u', 's', 'y', 'S', 't', 'C', 'P', 'M', 'B'}
};

static const int chrs_reversed[256] = {
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29, 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, -1, -1, 31, -1, -1, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 17, 10, 11, 0, 19, 16, 12, 1, 28, 18, 6, 13, 8, 2, 15, 20, 5, 7, 3, 9, 14, 22, 25, 24, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};

static const int successors_reversed[32][32] = {
  {9, 14, 12, 5, 6, 0, 4, 1, 2, 15, 7, 3, -1, 8, -1, 10, -1, -1, -1, -1, -1, -1, -1, 11, -1, 13, -1, -1, -1, -1, -1, -1},
  {7, -1, 5, 3, 4, 10, 6, 1, 0, -1, 2, 8, -1, 9, 11, 14, 12, -1, -1, 15, -1, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {-1, 14, 10, 7, -1, 1, 3, 5, 0, 2, 8, 11, -1, 4, 12, 6, 9, 15, -1, -1, -1, -1, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {1, 0, 2, 7, 3, 4, 10, 9, 15, 6, 12, -1, 5, 14, -1, -1, -1, -1, -1, -1, -1, -1, 13, 11, 8, -1, -1, -1, -1, -1, -1, -1},
  {13, 11, -1, 1, -1, 3, 2, 4, 0, 12, 5, 8, -1, 7, 14, 9, 10, 6, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, 1, 3, 5, 2, 10, 14, 4, 12, 9, 11, 8, -1, 7, -1, 15, 13, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1},
  {0, 1, 4, 7, 2, -1, 3, 10, -1, 6, 15, 8, -1, 12, 14, 13, -1, -1, -1, 11, -1, -1, -1, 9, 5, -1, -1, -1, -1, -1, -1, -1},
  {1, 3, 6, 0, 7, -1, 11, 2, 13, 5, 8, -1, 4, 10, -1, 9, -1, -1, 14, -1, -1, -1, 15, -1, 12, -1, -1, -1, -1, -1, -1, -1},
  {0, 3, 4, 2, 5, -1, -1, 7, 9, 10, 8, 6, -1, -1, -1, 14, 1, -1, 13, 11, -1, -1, -1, 12, 15, -1, -1, -1, -1, -1, -1, -1},
  {12, 10, 15, 4, 7, 2, 3, 1, 0, -1, 9, 11, -1, 5, -1, 8, 13, 6, -1, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {3, 4, 0, 5, 1, 7, 9, 12, 13, 8, 11, -1, 2, -1, -1, -1, -1, -1, 6, -1, 14, -1, -1, 15, 10, -1, -1, -1, -1, -1, -1, -1},
  {0, 1, 3, -1, 2, 4, 6, 8, 11, 5, -1, 9, 15, 13, -1, -1, 12, -1, -1, -1, -1, -1, 14, 7, 10, -1, -1, -1, -1, -1, -1, -1},
  {0, 2, 3, 6, 1, 5, 8, 12, 10, 7, -1, -1, -1, 11, -1, -1, -1, 14, -1, 15, -1, -1, 13, 9, 4, -1, -1, -1, -1, -1, -1, -1},
  {1, 2, 3, 15, 0, 14, 12, 9, 10, 6, -1, -1, -1, 7, -1, 4, -1, 5, -1, 13, -1, -1, -1, 11, 8, -1, -1, -1, -1, -1, -1, -1},
  {0, 1, 3, 13, 2, 6, 9, 7, 10, 4, -1, 12, -1, -1, 8, -1, 15, -1, 11, -1, -1, -1, -1, 14, 5, -1, -1, -1, -1, -1, -1, -1},
  {0, 5, 3, 7, 4, 2, 6, 10, 13, 9, -1, -1, 1, 14, -1, 8, -1, 15, -1, -1, -1, -1, -1, 12, 11, -1, -1, -1, -1, -1, -1, -1},
  {0, 1, 5, 14, 2, 3, 4, 11, 8, 7, -1, -1, 6, 13, -1, -1, 9, -1, -1, -1, -1, -1, 15, 12, 10, -1, -1, -1, -1, -1, -1, -1},
  {1, 3, 4, 10, 2, 5, 0, 8, -1, 6, 12, 11, -1, 15, -1, -1, -1, 7, -1, -1, -1, -1, -1, 14, 9, -1, -1, -1, 13, -1, -1, -1},
  {0, 1, 6, 13, 2, 11, 4, 3, 7, 10, -1, -1, 9, 14, -1, -1, -1, 15, -1, -1, -1, -1, 12, 5, 8, -1, -1, -1, -1, -1, -1, -1},
  {2, 0, 1, 9, 4, 7, 3, 11, 13, 5, -1, -1, 15, 12, -1, -1, -1, 14, -1, 6, -1, -1, -1, 8, 10, -1, -1, -1, -1, -1, -1, -1},
  {6, 2, 10, 3, 1, 4, 8, 7, 14, 0, -1, -1, 13, -1, 12, 11, -1, -1, -1, -1, 5, -1, 9, 15, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, 2, 3, 13, 1, -1, 6, 14, 15, 7, -1, -1, 8, 10, -1, -1, -1, 9, 12, -1, -1, 4, -1, 11, 5, -1, -1, -1, -1, -1, -1, -1},
  {0, 2, 3, 14, 1, 7, 9, 8, 5, -1, -1, 10, 4, 15, -1, -1, -1, 11, 12, -1, -1, -1, -1, 6, 13, -1, -1, -1, -1, -1, -1, -1},
  {9, -1, 15, 5, 10, 12, 8, 0, -1, -1, 2, 6, 7, 11, -1, 4, 14, 1, -1, 3, -1, -1, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {4, 12, 11, 9, 7, 10, 0, 1, 3, -1, 8, 13, -1, 5, -1, 2, 14, 15, -1, -1, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1},
  {2, 0, 5, 1, 3, -1, 12, 11, -1, 8, 7, -1, 10, 15, -1, 4, -1, 13, -1, 14, -1, -1, -1, 9, 6, -1, -1, -1, -1, -1, -1, -1},
  {1, 3, 2, -1, 0, 11, -1, -1, 13, 4, 5, -1, -1, -1, -1, -1, 14, -1, -1, -1, -1, -1, -1, 15, 6, -1, 10, 9, -1, 12, 7, 8},
  {5, 8, 1, 15, 0, 3, 4, -1, -1, 6, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, 14, -1, -1, 7, -1, 11, 10, -1, 13, 9, 12},
  {3, 4, 2, -1, 0, 6, -1, 11, 5, 1, 9, 7, 13, 14, -1, 15, -1, -1, 8, -1, -1, -1, -1, -1, 12, -1, -1, -1, 10, -1, -1, -1},
  {1, 5, 3, -1, 0, 2, 6, -1, -1, 4, -1, 15, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, 8, -1, 10, 11, -1, 13, 7, 12},
  {2, 5, 6, 1, 0, -1, 11, -1, -1, 8, 4, -1, 3, -1, -1, 7, -1, -1, 15, -1, -1, -1, 10, -1, 9, -1, -1, 13, -1, -1, 12, 14},
  {1, 5, 3, 11, 0, 2, 6, 8, -1, 7, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, -1, 14, 12, -1, 15, 10, 13}
};


typedef struct Pack {
  uint32_t word;
  unsigned int bytes_packed;
  unsigned int bytes_unpacked;
  unsigned int n_successors;
  unsigned const int offsets[8];
  const int masks[8];
  char header_mask;
  char header;
} Pack;

#define PACK_COUNT 3
#define MAX_SUCCESSOR_N 7

static const Pack packs[PACK_COUNT] = {
  { 0x80000000, 1, 2, 1, { 26, 24, 24, 24, 24, 24, 24, 24 }, { 15, 3, 0, 0, 0, 0, 0, 0 }, 0xc0, 0x80 },
  { 0xc0000000, 2, 4, 3, { 25, 22, 19, 16, 16, 16, 16, 16 }, { 15, 7, 7, 7, 0, 0, 0, 0 }, 0xe0, 0xc0 },
  { 0xe0000000, 4, 8, 7, { 23, 19, 15, 11, 8, 5, 2, 0 }, { 31, 15, 15, 15, 7, 7, 7, 3 }, 0xf0, 0xe0 }
};

#endif


================================================
FILE: models/filepaths.h
================================================
#ifndef _SHOCO_INTERNAL
#error This header file is only to be included by 'shoco.c'.
#endif
#pragma once
/*
This file was generated by 'generate_compressor_model.py'
so don't edit this by hand. Also, do not include this file
anywhere. It is internal to 'shoco.c'. Include 'shoco.h'
if you want to use shoco in your project.
*/

#define MIN_CHR 45
#define MAX_CHR 121

static const char chrs_by_chr_id[32] = {
  '/', 'e', 's', 'r', 'o', 'i', 't', 'c', 'a', 'n', 'm', 'l', 'h', '.', 'u', 'd', 'g', 'b', 'p', '-', 'f', '2', 'k', '0', '_', '1', '3', 'v', '4', 'x', '6', 'w'
};

static const int8_t chr_ids_by_chr[256] = {
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 19, 13, 0, 23, 25, 21, 26, 28, -1, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24, -1, 8, 17, 7, 15, 1, 20, 16, 12, 5, -1, 22, 11, 10, 9, 4, 18, -1, 3, 2, 6, 14, 27, 31, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};

static const int8_t successor_ids_by_chr_id_and_chr_id[32][32] = {
  {-1, -1, 0, -1, -1, 9, 4, 1, -1, -1, 12, 6, 2, 11, 5, 10, 3, -1, 7, -1, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8},
  {0, -1, 2, 1, -1, -1, 10, 7, 12, 5, 9, 6, -1, 13, -1, 11, -1, 3, 15, 8, -1, -1, -1, -1, 14, -1, -1, -1, -1, 4, -1, -1},
  {1, 5, 6, 2, 3, 9, 0, 7, -1, -1, -1, -1, 4, 8, 13, -1, -1, -1, 12, 10, -1, -1, 14, -1, -1, -1, -1, 15, -1, -1, -1, -1},
  {3, 1, 9, -1, 4, 0, 6, 2, 5, 12, 7, 15, -1, 8, 11, 14, -1, -1, -1, 13, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, -1, -1},
  {7, -1, 12, 2, 8, -1, 11, 5, 9, 3, 0, 6, -1, -1, 1, 4, 15, 10, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14},
  {14, 15, 0, 13, 8, -1, 2, 5, 1, 4, 12, 6, -1, -1, -1, 9, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, -1},
  {2, 1, 5, 7, 8, 0, -1, 15, 4, -1, 14, -1, 9, 10, -1, -1, 6, -1, -1, 11, 12, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {3, 1, 11, 8, 2, -1, 5, 12, 4, -1, -1, 7, 0, 13, 14, -1, -1, 15, 10, -1, -1, 9, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {12, -1, 4, 1, -1, 10, 2, 5, -1, 0, 11, 3, -1, -1, 15, 9, 6, 13, 8, 7, -1, -1, -1, -1, -1, -1, -1, 14, -1, -1, -1, -1},
  {0, 6, 4, -1, 1, 10, 2, 7, 12, -1, -1, -1, -1, 13, 11, 5, 3, -1, -1, 8, 9, -1, 14, -1, -1, -1, 15, -1, -1, -1, -1, -1},
  {4, 0, 8, -1, 3, 9, -1, -1, 1, -1, 12, 6, -1, 14, 15, 7, -1, 11, 2, 13, 5, -1, -1, -1, 10, -1, -1, -1, -1, -1, -1, -1},
  {4, 1, 7, -1, 3, 0, 11, -1, 2, -1, -1, 5, -1, 12, 6, 9, -1, -1, 8, 10, -1, -1, 13, -1, -1, -1, -1, 14, -1, -1, -1, -1},
  {6, 3, -1, 1, 0, 5, 4, -1, 2, -1, 13, -1, -1, 8, 15, -1, 10, -1, 9, 11, -1, -1, -1, -1, 12, -1, -1, -1, -1, -1, -1, -1},
  {-1, -1, -1, -1, 12, -1, -1, 5, -1, -1, 13, 4, 2, -1, -1, 9, 7, -1, 0, -1, 10, 14, -1, 8, -1, 3, 1, -1, 11, -1, -1, -1},
  {12, 14, 1, 0, -1, 7, 5, -1, 15, 3, 2, 4, -1, -1, -1, 6, 9, 10, 8, -1, 11, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1},
  {3, 0, 6, 13, 2, 1, -1, -1, 4, -1, -1, 12, -1, 10, 7, 15, -1, 5, -1, 8, 14, -1, -1, -1, 11, -1, -1, -1, -1, -1, -1, -1},
  {4, 2, 6, 5, 8, 3, 1, -1, -1, 0, -1, 7, 10, 9, 12, 14, -1, 15, -1, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {1, 5, 6, -1, 11, 13, -1, 15, 3, -1, -1, 8, -1, -1, 4, -1, 14, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, 12, -1},
  {5, 2, 8, 7, 6, 10, 9, 13, 0, 3, 15, 1, 14, -1, 12, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {-1, 15, 2, -1, -1, -1, 4, 6, -1, 14, 12, 9, -1, -1, -1, 1, 8, 13, 3, -1, 7, 0, -1, 11, -1, 5, -1, -1, -1, 10, -1, -1},
  {7, 5, 11, 9, 0, 1, -1, 2, 4, -1, 6, -1, -1, 13, -1, 10, -1, 12, -1, 3, 8, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {2, -1, -1, -1, -1, -1, -1, 15, 14, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, 8, -1, 4, -1, 1, -1, 12, 11, -1, 3, 13, 7, -1},
  {3, 2, 6, -1, 10, 0, 12, -1, 5, 8, -1, 11, -1, 7, -1, 13, -1, 15, -1, 1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1},
  {2, -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, 3, -1, 6, -1, 1, 5, 4, 8, -1, 9, -1, 12, -1},
  {-1, -1, 4, 10, -1, -1, 8, 11, -1, -1, 6, 0, -1, -1, -1, 14, -1, 15, 3, -1, -1, -1, -1, 2, 13, 9, 5, -1, -1, -1, 1, 12},
  {0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 14, -1, 15, -1, 9, -1, 5, -1, 2, 13, 4, 3, -1, 7, -1, 6, -1},
  {1, -1, -1, -1, -1, -1, -1, -1, 14, -1, -1, -1, -1, 0, -1, 15, -1, -1, -1, 13, -1, 2, -1, 5, 3, 6, 7, -1, 9, -1, 11, -1},
  {8, 0, 13, -1, 3, 2, -1, 9, 1, 6, 5, -1, -1, 10, -1, 15, 4, -1, 14, 12, 7, -1, -1, -1, 11, -1, -1, -1, -1, -1, -1, -1},
  {0, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 13, -1, 2, 15, 10, -1, 3, -1, 5, 7, -1, 8, -1, 12, -1},
  {3, 9, -1, -1, -1, -1, 4, -1, 8, -1, 0, 1, -1, 10, -1, -1, -1, -1, 11, 5, -1, 6, -1, -1, 14, 13, 15, -1, 12, -1, -1, -1},
  {2, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, -1, -1, 4, -1, 15, -1, 14, -1, -1, -1, 3, -1, 5, 1, 9, 7, -1, 0, -1, 6, -1},
  {11, 0, 10, 9, 3, 1, 12, 15, 2, 4, 6, -1, 13, 7, -1, 14, -1, -1, -1, 8, -1, -1, -1, -1, 5, -1, -1, -1, -1, -1, -1, -1}
};

static const int8_t chrs_by_chr_and_successor_id[MAX_CHR - MIN_CHR][16] = {
  {'2', 'd', 's', 'p', 't', '1', 'c', 'f', 'g', 'l', 'x', '0', 'm', 'b', 'n', 'e'},
  {'p', '3', 'h', '1', 'l', 'c', '9', 'g', '0', 'd', 'f', '4', 'o', 'm', '2', 'P'},
  {'s', 'c', 'h', 'g', 't', 'u', 'l', 'p', 'w', 'i', 'd', '.', 'm', 'S', 'W', 'f'},
  {'.', '0', '/', '-', '1', '_', '2', '9', '3', '4', '7', '8', '6', '5', ':', 'a'},
  {'/', '.', '0', '3', '1', '2', '6', '4', '5', '-', '7', '8', '9', '_', 'd', 'b'},
  {'.', '0', '/', '4', '2', '8', '5', '6', '-', '7', '9', '3', '1', 'x', 'a', 'c'},
  {'.', '/', '2', '_', '7', '0', '1', '3', '8', '4', '5', '6', '9', '-', 'a', 'd'},
  {'/', '.', '-', '0', '8', '1', '5', '3', '4', '9', '2', '7', '6', 'b', 'e', 'f'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'4', '_', '/', '2', '.', '0', '6', '3', '8', '1', '7', '9', '5', 'a', 'b', 'd'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'l', '6', '0', 'p', 's', '3', 'm', 'M', 't', '1', 'r', 'c', 'w', '_', 'd', 'b'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'n', 'r', 't', 'l', 's', 'c', 'g', '-', 'p', 'd', 'i', 'm', '/', 'b', 'v', 'u'},
  {'k', '/', 'C', 'a', 'u', 'e', 's', 'j', 'l', 'K', 'W', 'o', '6', 'i', 'g', 'c'},
  {'h', 'e', 'o', '/', 'a', 't', 'k', 'l', 'r', '2', 'p', 's', 'c', '.', 'u', 'b'},
  {'e', 'i', 'o', '/', 'a', 'b', 's', 'u', '-', 'S', '.', '_', 'l', 'r', 'f', 'd'},
  {'/', 'r', 's', 'b', 'x', 'n', 'l', 'c', '-', 'm', 't', 'd', 'a', '.', '_', 'p'},
  {'o', 'i', 'c', '-', 'a', 'e', 'm', '/', 'f', 'r', 'd', 's', 'b', '.', '8', '2'},
  {'n', 't', 'e', 'i', '/', 'r', 's', 'l', 'o', '.', 'h', 'z', 'u', '-', 'd', 'b'},
  {'o', 'r', 'a', 'e', 't', 'i', '/', 'y', '.', 'p', 'g', '-', '_', 'm', 'C', 'u'},
  {'s', 'a', 't', 'b', 'n', 'c', 'l', 'v', 'o', 'd', 'p', 'g', 'm', 'r', '/', 'e'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'i', '-', 'e', '/', '_', 'a', 's', '.', 'n', '+', 'o', 'l', 't', 'd', 'M', 'b'},
  {'i', 'e', 'a', 'o', '/', 'l', 'u', 's', 'p', 'd', '-', 't', '.', 'k', 'v', 'y'},
  {'e', 'a', 'p', 'o', '/', 'f', 'l', 'd', 's', 'i', '_', 'b', 'm', '-', '.', 'u'},
  {'/', 'o', 't', 'g', 's', 'd', 'e', 'c', '-', 'f', 'i', 'u', 'a', '.', 'k', '3'},
  {'m', 'u', 'r', 'n', 'd', 'c', 'l', '/', 'o', 'a', 'b', 't', 's', 'p', 'w', 'g'},
  {'a', 'l', 'e', 'n', 'p', '/', 'o', 'r', 's', 't', 'i', 'y', 'u', 'c', 'h', 'm'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'i', 'e', 'c', '/', 'o', 'a', 't', 'm', '.', 's', 'v', 'u', 'n', '-', 'd', 'l'},
  {'t', '/', 'r', 'o', 'h', 'e', 's', 'c', '.', 'i', '-', 'y', 'p', 'u', 'k', 'v'},
  {'i', 'e', '/', 'k', 'a', 's', 'g', 'r', 'o', 'h', '.', '-', 'f', 'y', 'm', 'c'},
  {'r', 's', 'm', 'n', 'l', 't', 'd', 'i', 'p', 'g', 'b', 'f', '/', 'x', 'e', 'a'},
  {'e', 'a', 'i', 'o', 'g', 'm', 'n', 'f', '/', 'c', '.', '_', '-', 's', 'p', 'd'},
  {'e', 'i', 'a', 'o', 'n', '_', 'm', '.', '-', 'r', 's', '/', 't', 'h', 'd', 'c'},
  {'m', 'l', '8', '/', 't', '-', '2', 'y', 'a', 'e', '.', 'p', '4', '1', '_', '3'}
};


typedef struct Pack {
  const uint32_t word;
  const unsigned int bytes_packed;
  const unsigned int bytes_unpacked;
  const unsigned int offsets[8];
  const int16_t _ALIGNED masks[8];
  const char header_mask;
  const char header;
} Pack;

#define PACK_COUNT 3
#define MAX_SUCCESSOR_N 8

static const Pack packs[PACK_COUNT] = {
  { 0x80000000, 1, 2, { 26, 24, 24, 24, 24, 24, 24 }, { 15, 3, 0, 0, 0, 0, 0 }, 0xc0, 0x80 },
  { 0xc0000000, 2, 4, { 25, 21, 18, 16, 16, 16, 16 }, { 15, 15, 7, 3, 0, 0, 0 }, 0xe0, 0xc0 },
  { 0xe0000000, 4, 8, { 24, 20, 16, 12, 9, 6, 3, 0 }, { 15, 15, 15, 15, 7, 7, 7, 7 }, 0xf0, 0xe0 }
};


================================================
FILE: models/text_en.h
================================================
#ifndef _SHOCO_INTERNAL
#error This header file is only to be included by 'shoco.c'.
#endif
#pragma once
/*
This file was generated by 'generate_compressor_model.py'
so don't edit this by hand. Also, do not include this file
anywhere. It is internal to 'shoco.c'. Include 'shoco.h'
if you want to use shoco in your project.
*/

#define MIN_CHR 32
#define MAX_CHR 122

static const char chrs_by_chr_id[32] = {
  ' ', 'e', 't', 'a', 'o', 'n', 'i', 'h', 's', 'r', 'd', 'l', 'u', 'm', 'c', 'w', 'y', 'f', 'g', ',', 'p', 'b', '.', 'v', 'k', 'I', '"', '-', 'H', 'M', 'T', '\''
};

static const int8_t chr_ids_by_chr[256] = {
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 26, -1, -1, -1, -1, 31, -1, -1, -1, -1, 19, 27, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 28, 25, -1, -1, -1, 29, -1, -1, -1, -1, -1, -1, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 21, 14, 10, 1, 17, 18, 7, 6, -1, 24, 11, 13, 5, 4, 20, -1, 9, 8, 2, 12, 23, 15, -1, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};

static const int8_t successor_ids_by_chr_id_and_chr_id[32][32] = {
  {12, -1, 0, 1, 5, 13, 6, 2, 4, -1, 11, 14, -1, 7, 10, 3, -1, 9, -1, -1, 15, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, 8, 7, 5, -1, 2, 15, -1, 4, 1, 3, 6, -1, 10, 11, -1, 14, -1, -1, 9, -1, -1, 13, 12, -1, -1, -1, -1, -1, -1, -1, -1},
  {1, 3, 6, 5, 2, -1, 4, 0, 13, 7, -1, 12, 9, -1, 15, 14, 11, -1, -1, 8, -1, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {6, -1, 1, -1, -1, 0, 7, -1, 2, 3, 5, 4, -1, 10, 12, -1, 8, -1, 13, -1, 14, 11, -1, 9, 15, -1, -1, -1, -1, -1, -1, -1},
  {2, -1, 6, -1, 8, 1, 15, -1, 9, 3, 12, 10, 0, 5, -1, 7, -1, 4, -1, -1, 13, -1, -1, 11, 14, -1, -1, -1, -1, -1, -1, -1},
  {0, 3, 4, 10, 5, 11, 8, -1, 7, -1, 1, 14, -1, -1, 6, -1, 12, -1, 2, 9, -1, -1, 13, -1, 15, -1, -1, -1, -1, -1, -1, -1},
  {-1, 9, 2, 11, 4, 0, -1, -1, 1, 8, 7, 5, -1, 3, 6, -1, -1, 12, 10, -1, -1, 15, -1, 13, -1, -1, -1, -1, -1, -1, -1, -1},
  {3, 0, 5, 1, 4, -1, 2, -1, 13, 7, -1, 14, 8, 12, -1, -1, 10, -1, -1, 6, -1, 15, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, 1, 2, 7, 5, -1, 4, 3, 6, -1, -1, 13, 8, 15, 12, 14, -1, -1, -1, 9, 11, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {1, 0, 7, 4, 3, 12, 2, -1, 5, 11, 9, 15, -1, 14, 13, -1, 6, -1, -1, 10, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, 1, -1, 6, 3, -1, 2, -1, 7, 9, 11, 12, 10, -1, -1, -1, 8, -1, 15, 4, -1, -1, 5, -1, -1, -1, -1, 14, -1, -1, -1, -1},
  {3, 0, 11, 7, 6, -1, 2, -1, 12, -1, 5, 1, 9, -1, -1, 15, 4, 8, -1, 10, -1, -1, 14, -1, 13, -1, -1, -1, -1, -1, -1, -1},
  {5, 9, 1, 11, -1, 4, 10, -1, 3, 0, 12, 2, -1, 13, 7, -1, -1, -1, 6, 15, 8, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {1, 0, -1, 2, 3, -1, 4, -1, 8, -1, -1, -1, 5, 12, -1, -1, 7, 14, -1, 9, 6, 11, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {12, 1, 4, 3, 0, -1, 6, 2, 15, 7, -1, 8, 9, -1, 11, -1, 10, -1, -1, -1, -1, -1, 14, -1, 5, -1, -1, -1, -1, -1, -1, -1},
  {5, 3, -1, 0, 4, 6, 1, 2, 9, 7, 12, 10, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, 11, -1, 15, -1, -1, 14, -1, -1, -1, -1},
  {0, 4, 6, -1, 1, -1, 7, -1, 5, -1, 8, 12, -1, -1, -1, -1, -1, -1, -1, 2, -1, 14, 3, -1, -1, -1, -1, 15, -1, -1, -1, 10},
  {0, 2, 8, 4, 1, -1, 5, -1, -1, 3, -1, 9, 7, -1, -1, -1, 13, 6, -1, 10, -1, -1, 11, -1, -1, -1, -1, 12, -1, -1, -1, -1},
  {0, 2, -1, 4, 3, 12, 6, 1, 9, 5, -1, 7, 11, -1, -1, -1, -1, -1, 13, 8, -1, 15, 10, -1, -1, -1, -1, 14, -1, -1, -1, -1},
  {0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 3, -1, -1, -1, 2},
  {7, 0, 8, 2, 3, -1, 6, 11, 10, 1, -1, 4, 9, -1, -1, -1, 12, -1, -1, 13, 5, 15, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {12, 0, 10, 5, 2, -1, 7, 15, 8, 6, -1, 1, 3, -1, -1, -1, 4, -1, -1, -1, -1, 11, 14, 13, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, 2, -1, -1, -1, 1, 4, -1, -1, -1, 3},
  {-1, 0, -1, 2, 3, -1, 1, -1, -1, 6, -1, -1, 5, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {1, 0, -1, 13, -1, 2, 3, 5, 4, -1, -1, 8, -1, -1, -1, 14, 10, 9, -1, 6, -1, -1, 7, -1, -1, -1, -1, 11, -1, -1, -1, -1},
  {0, -1, 1, -1, -1, 2, -1, -1, 4, -1, -1, -1, -1, 7, -1, -1, -1, 3, -1, 6, -1, -1, 14, -1, -1, 8, -1, -1, -1, -1, -1, 5},
  {0, -1, 12, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, -1, -1, -1, -1, 1, -1, -1, 7, 6, 4, -1},
  {8, -1, 1, 2, -1, 9, 15, 5, 4, 7, 14, 13, -1, 12, 6, 10, -1, -1, -1, -1, 11, 3, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1},
  {-1, 0, -1, 1, 2, -1, 3, -1, -1, -1, -1, -1, 4, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {8, 4, -1, 3, 5, -1, 1, -1, -1, 0, -1, -1, 6, -1, -1, -1, 2, -1, -1, -1, -1, -1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {9, 2, -1, 8, 1, -1, 4, 0, -1, 6, -1, -1, 5, -1, -1, 7, 13, -1, -1, 11, -1, -1, 12, -1, -1, -1, -1, -1, 10, -1, -1, -1},
  {2, 15, 1, 6, -1, -1, -1, -1, 0, 8, 7, 4, -1, 5, 3, -1, -1, -1, -1, 14, -1, -1, -1, 9, -1, -1, 13, -1, -1, -1, 10, -1}
};

static const int8_t chrs_by_chr_and_successor_id[MAX_CHR - MIN_CHR][16] = {
  {'t', 'a', 'h', 'w', 's', 'o', 'i', 'm', 'b', 'f', 'c', 'd', ' ', 'n', 'l', 'p'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {' ', 'I', 'Y', 'W', 'T', 'A', 'M', 'H', 'O', 'B', 'N', 'D', 't', 'S', 'a', ','},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'s', 't', ' ', 'c', 'l', 'm', 'a', 'd', 'r', 'v', 'T', 'A', 'L', '"', ',', 'e'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {' ', '"', '\'', '-', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'-', 't', 'a', 'b', 's', 'h', 'c', 'r', ' ', 'n', 'w', 'p', 'm', 'l', 'd', 'i'},
  {' ', '"', '.', '\'', '-', ',', '?', ';', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'e', 'a', 'o', 'i', 'u', 'A', 'y', 'E', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {' ', 't', 'n', 'f', 's', '\'', ',', 'm', 'I', 'N', '_', 'A', 'E', 'L', '.', 'R'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'r', 'i', 'y', 'a', 'e', 'o', 'u', 'Y', ' ', '.', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'h', 'o', 'e', 'E', 'i', 'u', 'r', 'w', 'a', ' ', 'H', ',', '.', 'y', 'R', 'Z'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'n', 't', 's', 'r', 'l', 'd', ' ', 'i', 'y', 'v', 'm', 'b', 'c', 'g', 'p', 'k'},
  {'e', 'l', 'o', 'u', 'y', 'a', 'r', 'i', 's', 'j', 't', 'b', ' ', 'v', '.', 'h'},
  {'o', 'e', 'h', 'a', 't', 'k', 'i', 'r', 'l', 'u', 'y', 'c', ' ', 'q', '.', 's'},
  {' ', 'e', 'i', 'o', ',', '.', 'a', 's', 'y', 'r', 'u', 'd', 'l', ';', '-', 'g'},
  {' ', 'r', 'n', 'd', 's', 'a', 'l', 't', 'e', ',', 'm', 'c', 'v', '.', 'y', 'i'},
  {' ', 'o', 'e', 'r', 'a', 'i', 'f', 'u', 't', 'l', ',', '.', '-', 'y', ';', '?'},
  {' ', 'h', 'e', 'o', 'a', 'r', 'i', 'l', ',', 's', '.', 'u', 'n', 'g', '-', 'b'},
  {'e', 'a', 'i', ' ', 'o', 't', ',', 'r', 'u', '.', 'y', '!', 'm', 's', 'l', 'b'},
  {'n', 's', 't', 'm', 'o', 'l', 'c', 'd', 'r', 'e', 'g', 'a', 'f', 'v', 'z', 'b'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'e', ' ', 'n', 'i', 's', 'h', ',', '.', 'l', 'f', 'y', '-', ';', 'a', 'w', '!'},
  {'e', 'l', 'i', ' ', 'y', 'd', 'o', 'a', 'f', 'u', ',', 't', 's', 'k', '.', 'w'},
  {'e', ' ', 'a', 'o', 'i', 'u', 'p', 'y', 's', ',', '.', 'b', 'm', ';', 'f', '?'},
  {' ', 'd', 'g', 'e', 't', 'o', 'c', 's', 'i', ',', 'a', 'n', 'y', '.', 'l', 'k'},
  {'u', 'n', ' ', 'r', 'f', 'm', 't', 'w', 'o', 's', 'l', 'v', 'd', 'p', 'k', 'i'},
  {'e', 'r', 'a', 'o', 'l', 'p', 'i', ' ', 't', 'u', 's', 'h', 'y', ',', '.', 'b'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'e', ' ', 'i', 'o', 'a', 's', 'y', 't', '.', 'd', ',', 'r', 'n', 'c', 'm', 'l'},
  {' ', 'e', 't', 'h', 'i', 'o', 's', 'a', 'u', ',', '.', 'p', 'c', 'l', 'w', 'm'},
  {'h', ' ', 'o', 'e', 'i', 'a', 't', 'r', ',', 'u', '.', 'y', 'l', 's', 'w', 'c'},
  {'r', 't', 'l', 's', 'n', ' ', 'g', 'c', 'p', 'e', 'i', 'a', 'd', 'm', 'b', ','},
  {'e', 'i', 'a', 'o', 'y', 'u', 'r', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'a', 'i', 'h', 'e', 'o', ' ', 'n', 'r', ',', 's', 'l', '.', 'd', ';', '-', 'k'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {' ', 'o', ',', '.', 'e', 's', 't', 'i', 'd', ';', '\'', '?', 'l', '!', 'b', '-'}
};


typedef struct Pack {
  const uint32_t word;
  const unsigned int bytes_packed;
  const unsigned int bytes_unpacked;
  const unsigned int offsets[8];
  const int16_t _ALIGNED masks[8];
  const char header_mask;
  const char header;
} Pack;

#define PACK_COUNT 3
#define MAX_SUCCESSOR_N 7

static const Pack packs[PACK_COUNT] = {
  { 0x80000000, 1, 2, { 26, 24, 24, 24, 24, 24, 24, 24 }, { 15, 3, 0, 0, 0, 0, 0, 0 }, 0xc0, 0x80 },
  { 0xc0000000, 2, 4, { 25, 22, 19, 16, 16, 16, 16, 16 }, { 15, 7, 7, 7, 0, 0, 0, 0 }, 0xe0, 0xc0 },
  { 0xe0000000, 4, 8, { 23, 19, 15, 11, 8, 5, 2, 0 }, { 31, 15, 15, 15, 7, 7, 7, 3 }, 0xf0, 0xe0 }
};


================================================
FILE: models/words_en.h
================================================
#ifndef _SHOCO_INTERNAL
#error This header file is only to be included by 'shoco.c'.
#endif
#pragma once
/*
This file was generated by 'generate_compressor_model.py'
so don't edit this by hand. Also, do not include this file
anywhere. It is internal to 'shoco.c'. Include 'shoco.h'
if you want to use shoco in your project.
*/

#define MIN_CHR 39
#define MAX_CHR 122

static const char chrs_by_chr_id[32] = {
  'e', 'a', 'i', 'o', 't', 'h', 'n', 'r', 's', 'l', 'u', 'c', 'w', 'm', 'd', 'b', 'p', 'f', 'g', 'v', 'y', 'k', '-', 'H', 'M', 'T', '\'', 'B', 'x', 'I', 'W', 'L'
};

static const int8_t chr_ids_by_chr[256] = {
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, 23, 29, -1, -1, 31, 24, -1, -1, -1, -1, -1, -1, 25, -1, -1, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 15, 11, 14, 0, 17, 18, 5, 2, -1, 21, 9, 13, 6, 3, 16, -1, 7, 8, 4, 10, 19, 12, 28, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};

static const int8_t successor_ids_by_chr_id_and_chr_id[32][32] = {
  {7, 4, 12, -1, 6, -1, 1, 0, 3, 5, -1, 9, -1, 8, 2, -1, 15, 14, -1, 10, 11, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, -1},
  {-1, -1, 6, -1, 1, -1, 0, 3, 2, 4, 15, 11, -1, 9, 5, 10, 13, -1, 12, 8, 7, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {9, 11, -1, 4, 2, -1, 0, 8, 1, 5, -1, 6, -1, 3, 7, 15, -1, 12, 10, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {-1, -1, 14, 7, 5, -1, 1, 2, 8, 9, 0, 15, 6, 4, 11, -1, 12, 3, -1, 10, -1, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {2, 4, 3, 1, 5, 0, -1, 6, 10, 9, 7, 12, 11, -1, -1, -1, -1, 13, -1, -1, 8, -1, 15, -1, -1, -1, 14, -1, -1, -1, -1, -1},
  {0, 1, 2, 3, 4, -1, -1, 5, 9, 10, 6, -1, -1, 8, 15, 11, -1, 14, -1, -1, 7, -1, 13, -1, -1, -1, 12, -1, -1, -1, -1, -1},
  {2, 8, 7, 4, 3, -1, 9, -1, 6, 11, -1, 5, -1, -1, 0, -1, -1, 14, 1, 15, 10, 12, -1, -1, -1, -1, 13, -1, -1, -1, -1, -1},
  {0, 3, 1, 2, 6, -1, 9, 8, 4, 12, 13, 10, -1, 11, 7, -1, -1, 15, 14, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, 6, 3, 4, 1, 2, -1, -1, 5, 10, 7, 9, 11, 12, -1, -1, 8, 14, -1, -1, 15, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, 6, 2, 5, 9, -1, -1, -1, 10, 1, 8, -1, 12, 14, 4, -1, 15, 7, -1, 13, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {8, 10, 9, 15, 1, -1, 4, 0, 3, 2, -1, 6, -1, 12, 11, 13, 7, 14, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {1, 3, 6, 0, 4, 2, -1, 7, 13, 8, 9, 11, -1, -1, 15, -1, -1, -1, -1, -1, 10, 5, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {3, 0, 1, 4, -1, 2, 5, 6, 7, 8, -1, 14, -1, -1, 9, 15, -1, 12, -1, -1, -1, 10, 11, -1, -1, -1, 13, -1, -1, -1, -1, -1},
  {0, 1, 3, 2, 15, -1, 12, -1, 7, 14, 4, -1, -1, 9, -1, 8, 5, 10, -1, -1, 6, -1, 13, -1, -1, -1, 11, -1, -1, -1, -1, -1},
  {0, 3, 1, 2, -1, -1, 12, 6, 4, 9, 7, -1, -1, 14, 8, -1, -1, 15, 11, 13, 5, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, 5, 7, 2, 10, 13, -1, 6, 8, 1, 3, -1, -1, 14, 15, 11, -1, -1, -1, 12, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, 2, 6, 3, 7, 10, -1, 1, 9, 4, 8, -1, -1, 15, -1, 12, 5, -1, -1, -1, 11, -1, 13, -1, -1, -1, 14, -1, -1, -1, -1, -1},
  {1, 3, 4, 0, 7, -1, 12, 2, 11, 8, 6, 13, -1, -1, -1, -1, -1, 5, -1, -1, 10, 15, 9, -1, -1, -1, 14, -1, -1, -1, -1, -1},
  {1, 3, 5, 2, 13, 0, 9, 4, 7, 6, 8, -1, -1, 15, -1, 11, -1, -1, 10, -1, 14, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, 2, 1, 3, -1, -1, -1, 6, -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {1, 11, 4, 0, 3, -1, 13, 12, 2, 7, -1, -1, 15, 10, 5, 8, 14, -1, -1, -1, -1, -1, 9, -1, -1, -1, 6, -1, -1, -1, -1, -1},
  {0, 9, 2, 14, 15, 4, 1, 13, 3, 5, -1, -1, 10, -1, -1, -1, -1, 6, 12, -1, 7, -1, 8, -1, -1, -1, 11, -1, -1, -1, -1, -1},
  {-1, 2, 14, -1, 1, 5, 8, 7, 4, 12, -1, 6, 9, 11, 13, 3, 10, 15, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, 1, 3, 2, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {4, 3, 1, 5, -1, -1, -1, 0, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {2, 8, 4, 1, -1, 0, -1, 6, -1, -1, 5, -1, 7, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, 9, -1, -1, -1, -1, -1, -1, -1, -1},
  {12, 5, -1, -1, 1, -1, -1, 7, 0, 3, -1, 2, -1, 4, 6, -1, -1, -1, -1, 8, -1, -1, 15, -1, 13, 9, -1, -1, -1, -1, -1, 11},
  {1, 3, 2, 4, -1, -1, -1, 5, -1, 7, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1},
  {5, 3, 4, 12, 1, 6, -1, -1, -1, -1, 8, 2, -1, -1, -1, -1, 0, 9, -1, -1, 11, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {-1, -1, -1, -1, 0, -1, 1, 12, 3, -1, -1, -1, -1, 5, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, 6, -1, 10},
  {2, 3, 1, 4, -1, 0, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1},
  {5, 1, 3, 0, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, 9, -1, -1, 6, -1, 7}
};

static const int8_t chrs_by_chr_and_successor_id[MAX_CHR - MIN_CHR][16] = {
  {'s', 't', 'c', 'l', 'm', 'a', 'd', 'r', 'v', 'T', 'A', 'L', 'e', 'M', 'Y', '-'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'-', 't', 'a', 'b', 's', 'h', 'c', 'r', 'n', 'w', 'p', 'm', 'l', 'd', 'i', 'f'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'u', 'e', 'i', 'a', 'o', 'r', 'y', 'l', 'I', 'E', 'R', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'e', 'a', 'o', 'i', 'u', 'A', 'y', 'E', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'t', 'n', 'f', 's', '\'', 'm', 'I', 'N', 'A', 'E', 'L', 'Z', 'r', 'V', 'R', 'C'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'o', 'a', 'y', 'i', 'u', 'e', 'I', 'L', 'D', '\'', 'E', 'Y', '\x00', '\x00', '\x00', '\x00'},
  {'r', 'i', 'y', 'a', 'e', 'o', 'u', 'Y', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'h', 'o', 'e', 'E', 'i', 'u', 'r', 'w', 'a', 'H', 'y', 'R', 'Z', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'h', 'i', 'e', 'a', 'o', 'r', 'I', 'y', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'n', 't', 's', 'r', 'l', 'd', 'i', 'y', 'v', 'm', 'b', 'c', 'g', 'p', 'k', 'u'},
  {'e', 'l', 'o', 'u', 'y', 'a', 'r', 'i', 's', 'j', 't', 'b', 'v', 'h', 'm', 'd'},
  {'o', 'e', 'h', 'a', 't', 'k', 'i', 'r', 'l', 'u', 'y', 'c', 'q', 's', '-', 'd'},
  {'e', 'i', 'o', 'a', 's', 'y', 'r', 'u', 'd', 'l', '-', 'g', 'n', 'v', 'm', 'f'},
  {'r', 'n', 'd', 's', 'a', 'l', 't', 'e', 'm', 'c', 'v', 'y', 'i', 'x', 'f', 'p'},
  {'o', 'e', 'r', 'a', 'i', 'f', 'u', 't', 'l', '-', 'y', 's', 'n', 'c', '\'', 'k'},
  {'h', 'e', 'o', 'a', 'r', 'i', 'l', 's', 'u', 'n', 'g', 'b', '-', 't', 'y', 'm'},
  {'e', 'a', 'i', 'o', 't', 'r', 'u', 'y', 'm', 's', 'l', 'b', '\'', '-', 'f', 'd'},
  {'n', 's', 't', 'm', 'o', 'l', 'c', 'd', 'r', 'e', 'g', 'a', 'f', 'v', 'z', 'b'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'e', 'n', 'i', 's', 'h', 'l', 'f', 'y', '-', 'a', 'w', '\'', 'g', 'r', 'o', 't'},
  {'e', 'l', 'i', 'y', 'd', 'o', 'a', 'f', 'u', 't', 's', 'k', 'w', 'v', 'm', 'p'},
  {'e', 'a', 'o', 'i', 'u', 'p', 'y', 's', 'b', 'm', 'f', '\'', 'n', '-', 'l', 't'},
  {'d', 'g', 'e', 't', 'o', 'c', 's', 'i', 'a', 'n', 'y', 'l', 'k', '\'', 'f', 'v'},
  {'u', 'n', 'r', 'f', 'm', 't', 'w', 'o', 's', 'l', 'v', 'd', 'p', 'k', 'i', 'c'},
  {'e', 'r', 'a', 'o', 'l', 'p', 'i', 't', 'u', 's', 'h', 'y', 'b', '-', '\'', 'm'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'e', 'i', 'o', 'a', 's', 'y', 't', 'd', 'r', 'n', 'c', 'm', 'l', 'u', 'g', 'f'},
  {'e', 't', 'h', 'i', 'o', 's', 'a', 'u', 'p', 'c', 'l', 'w', 'm', 'k', 'f', 'y'},
  {'h', 'o', 'e', 'i', 'a', 't', 'r', 'u', 'y', 'l', 's', 'w', 'c', 'f', '\'', '-'},
  {'r', 't', 'l', 's', 'n', 'g', 'c', 'p', 'e', 'i', 'a', 'd', 'm', 'b', 'f', 'o'},
  {'e', 'i', 'a', 'o', 'y', 'u', 'r', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'a', 'i', 'h', 'e', 'o', 'n', 'r', 's', 'l', 'd', 'k', '-', 'f', '\'', 'c', 'b'},
  {'p', 't', 'c', 'a', 'i', 'e', 'h', 'q', 'u', 'f', '-', 'y', 'o', '\x00', '\x00', '\x00'},
  {'o', 'e', 's', 't', 'i', 'd', '\'', 'l', 'b', '-', 'm', 'a', 'r', 'n', 'p', 'w'}
};


typedef struct Pack {
  const uint32_t word;
  const unsigned int bytes_packed;
  const unsigned int bytes_unpacked;
  const unsigned int offsets[8];
  const int16_t _ALIGNED masks[8];
  const char header_mask;
  const char header;
} Pack;

#define PACK_COUNT 3
#define MAX_SUCCESSOR_N 7

static const Pack packs[PACK_COUNT] = {
  { 0x80000000, 1, 2, { 26, 24, 24, 24, 24, 24, 24, 24 }, { 15, 3, 0, 0, 0, 0, 0, 0 }, 0xc0, 0x80 },
  { 0xc0000000, 2, 4, { 25, 22, 19, 16, 16, 16, 16, 16 }, { 15, 7, 7, 7, 0, 0, 0, 0 }, 0xe0, 0xc0 },
  { 0xe0000000, 4, 8, { 23, 19, 15, 11, 8, 5, 2, 0 }, { 31, 15, 15, 15, 7, 7, 7, 3 }, 0xf0, 0xe0 }
};


================================================
FILE: pre.js
================================================
var Module = {
  'preRun': function() {
    var _shoco_compress = Module['cwrap']('shoco_compress', 'number', ['string', 'number', 'number', 'number']);
    var _shoco_decompress = Module['cwrap']('shoco_decompress', 'number', ['number', 'number', 'number', 'number']);

    var shoco = {
      'compress': function(str_in) {
        var out_heap = Module['_malloc'](str_in.length * 8);
        var out_buffer = new Uint8Array(Module['HEAPU8']['buffer'], out_heap, str_in.length * 8);

        var len = _shoco_compress(str_in, 0, out_buffer.byteOffset, out_buffer.byteLength);
        var result = new Uint8Array(out_buffer.subarray(0, len));

        Module['_free'](out_buffer.byteOffset);
        return result;
      },
      'decompress': function(cmp) {
        var out_heap = Module['_malloc'](cmp.length * 8);
        var out_buffer = new Uint8Array(Module['HEAPU8']['buffer'], out_heap, cmp.length * 8);

        var in_heap = Module['_malloc'](cmp.length);
        var in_buffer = new Uint8Array(Module['HEAPU8']['buffer'], in_heap, cmp.length);
        in_buffer.set(new Uint8Array(cmp.buffer));

        var len = _shoco_decompress(in_buffer.byteOffset, cmp.length, out_buffer.byteOffset, out_buffer.byteLength);
        var result = decodeURIComponent(escape(String.fromCharCode.apply(null, out_buffer.subarray(0, len))));

        Module['_free'](in_buffer.byteOffset);
        Module['_free'](out_buffer.byteOffset);
        return result;
      }
    }

    // node.js
    if (typeof module !== "undefined")
      module.exports = shoco;
    // browser
    else
      window['shoco'] = shoco;
  }
};


================================================
FILE: shoco-bin.c
================================================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "shoco.h"

static const char USAGE[] = "compresses or decompresses your (presumably short) data.\n"
"usage: shoco {c(ompress),d(ecompress)} <file-to-(de)compress> <output-filename>\n";

typedef enum {
  JOB_COMPRESS,
  JOB_DECOMPRESS,
} Job;

#define MAX_STACK_ALLOCATION_SIZE 65536

int main(int argc, char **argv) {
  Job job; 
  unsigned long in_size;
  char *in_buffer;
  char *out_buffer;
  FILE *fin;
  FILE *fout;
  int len;

  if (argc < 4) {
    puts(USAGE);
    return 1;
  }
  if (argv[1][0] == 'c')
    job = JOB_COMPRESS;
  else if (argv[1][0] == 'd')
    job = JOB_DECOMPRESS;
  else {
    puts(USAGE);
    return 1;
  }
  char *infile = argv[2];
  char *outfile = argv[3];

  fin = fopen (infile, "rb" );
  if (fin == NULL) {
    fputs("Something went wrong opening the file. Does it even exist?", stderr);
    exit(1);
  }

  // obtain file size:
  fseek(fin, 0, SEEK_END);
  in_size = ftell(fin);
  rewind(fin);

  if (in_size > MAX_STACK_ALLOCATION_SIZE) {
    in_buffer = (char *)malloc(sizeof(char) * in_size);
    out_buffer = (char *)malloc(sizeof(char) * in_size * 4);
    if ((in_buffer == NULL) || (out_buffer == NULL)) {
      fputs("Memory error. This really shouldn't happen.", stderr);
      exit(2);
    }
  } else {
    in_buffer = (char *)alloca(sizeof(char) * in_size);
    out_buffer = (char *)alloca(sizeof(char) * in_size * 4);
  }

  if (fread(in_buffer, sizeof(char), in_size, fin) != in_size) {
    fputs("Error reading the input file.", stderr);
    exit(3);
  }
  fclose(fin);

  if (job == JOB_COMPRESS)
    len = shoco_compress(in_buffer, in_size, out_buffer, in_size * 4);
  else
    len = shoco_decompress(in_buffer, in_size, out_buffer, in_size * 4);

  fout = fopen(outfile, "wb");
  fwrite(out_buffer , sizeof(char), len, fout);
  fclose(fout);

  if (in_size > MAX_STACK_ALLOCATION_SIZE) {
    free(in_buffer);
    free(out_buffer);
  }

  return 0;
}


================================================
FILE: shoco.c
================================================
#include <stdint.h>

#if (defined (__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || __BIG_ENDIAN__)
  #define swap(x) (x)
#else
  #if defined(_MSC_VER)
    #include <stdlib.h>
    #define swap(x) _byteswap_ulong(x)
  #elif defined (__GNUC__)
    #if defined(__builtin_bswap32)
      #define swap(x) __builtin_bswap32(x)
    #else
      #define swap(x) ((x<<24) + ((x&0x0000FF00)<<8) + ((x&0x00FF0000)>>8) + (x>>24))
    #endif
  #else
    #include <byteswap.h>
    #define swap(x) bswap_32(x)
  #endif
#endif

#if defined(_MSC_VER)
  #define _ALIGNED __declspec(align(16))
  #define inline __inline
#elif defined(__GNUC__)
  #define _ALIGNED __attribute__ ((aligned(16)))
#else
  #define _ALIGNED
#endif

#if defined(_M_X64) || defined (_M_AMD64) || defined (__x86_64__)
  #include "emmintrin.h"
  #define HAVE_SSE2
#endif

#include "shoco.h"
#define _SHOCO_INTERNAL
#include "shoco_model.h"

static inline int decode_header(unsigned char val) {
  int i = -1;
  while ((signed char)val < 0) {
    val <<= 1;
    ++i;
  }
  return i;
}

union Code {
  uint32_t word;
  char bytes[4];
};

#ifdef HAVE_SSE2
static inline int check_indices(const int16_t * shoco_restrict indices, int pack_n) {
  __m128i zero = _mm_setzero_si128();
  __m128i indis = _mm_load_si128 ((__m128i *)indices);
  __m128i masks = _mm_load_si128 ((__m128i *)packs[pack_n].masks);
  __m128i cmp = _mm_cmpgt_epi16 (indis, masks);
  __m128i mmask = _mm_cmpgt_epi16 (masks, zero);
  cmp = _mm_and_si128 (cmp, mmask);
  int result = _mm_movemask_epi8 (cmp);
  return (result == 0);
}
#else
static inline int check_indices(const int16_t * shoco_restrict indices, int pack_n) {
  for (unsigned int i = 0; i < packs[pack_n].bytes_unpacked; ++i)
    if (indices[i] > packs[pack_n].masks[i])
      return 0;
  return 1;
}
#endif

static inline int find_best_encoding(const int16_t * shoco_restrict indices, unsigned int n_consecutive) {
  for (int p = PACK_COUNT - 1; p >= 0; --p)
    if ((n_consecutive >= packs[p].bytes_unpacked) && (check_indices(indices, p)))
      return p;
  return -1;
}

size_t shoco_compress(const char * const shoco_restrict original, size_t strlen, char * const shoco_restrict out, size_t bufsize) {
  char *o = out;
  char * const out_end = out + bufsize;
  const char *in = original;
  int16_t _ALIGNED indices[MAX_SUCCESSOR_N + 1] = { 0 };
  int last_chr_index;
  int current_index;
  int successor_index;
  unsigned int n_consecutive;
  union Code code;
  int pack_n;
  unsigned int rest;
  const char * const in_end = original + strlen;

  while ((*in != '\0')) {
    if (strlen && (in == in_end))
      break;

    // find the longest string of known successors
    indices[0] = chr_ids_by_chr[(unsigned char)in[0]];
    last_chr_index = indices[0];
    if (last_chr_index < 0)
      goto last_resort;

    rest = in_end - in;
    for (n_consecutive = 1; n_consecutive <= MAX_SUCCESSOR_N; ++n_consecutive) {
      if (strlen && (n_consecutive == rest))
        break;

      current_index = chr_ids_by_chr[(unsigned char)in[n_consecutive]];
      if (current_index < 0)  // '\0' is always -1
        break;

      successor_index = successor_ids_by_chr_id_and_chr_id[last_chr_index][current_index];
      if (successor_index < 0)
        break;

      indices[n_consecutive] = (int16_t)successor_index;
      last_chr_index = current_index;
    }
    if (n_consecutive < 2)
      goto last_resort;

    pack_n = find_best_encoding(indices, n_consecutive);
    if (pack_n >= 0) {
      if (o + packs[pack_n].bytes_packed > out_end)
        return bufsize + 1;

      code.word = packs[pack_n].word;
      for (unsigned int i = 0; i < packs[pack_n].bytes_unpacked; ++i)
        code.word |= indices[i] << packs[pack_n].offsets[i];

      // In the little-endian world, we need to swap what's
      // in the register to match the memory representation.
      // On big-endian systems, this is a dummy.
      code.word = swap(code.word);

      // if we'd just copy the word, we might write over the end
      // of the output string
      for (unsigned int i = 0; i < packs[pack_n].bytes_packed; ++i)
        o[i] = code.bytes[i];

      o += packs[pack_n].bytes_packed;
      in += packs[pack_n].bytes_unpacked;
    } else {
last_resort:
      if (*in & 0x80) {
        // non-ascii case
        if (o + 2 > out_end)
          return bufsize + 1;
        // put in a sentinel byte
        *o++ = 0x00;
      } else {
        // an ascii byte
        if (o + 1 > out_end)
          return bufsize + 1;
      }
      *o++ = *in++;
    }
  }

  return o - out;
}

size_t shoco_decompress(const char * const shoco_restrict original, size_t complen, char * const shoco_restrict out, size_t bufsize) {
  char *o = out;
  char * const out_end = out + bufsize;
  const char *in = original;
  char last_chr;
  union Code code = { 0 };
  int offset;
  int mask;
  int mark;
  const char * const in_end = original + complen;

  while (in < in_end) {
    mark = decode_header(*in);
    if (mark < 0) {
      if (o >= out_end)
        return bufsize + 1;

      // ignore the sentinel value for non-ascii chars
      if (*in == 0x00) {
        if (++in >= in_end)
          return SIZE_MAX;
      }

      *o++ = *in++;
    } else {
      if (o + packs[mark].bytes_unpacked > out_end)
        return bufsize + 1;
      else if (in + packs[mark].bytes_packed > in_end)
        return SIZE_MAX;

      // This should be OK as well, but it fails with emscripten.
      // Test this with new versions of emcc.
      //code.word = swap(*(uint32_t *)in);
      for (unsigned int i = 0; i < packs[mark].bytes_packed; ++i)
        code.bytes[i] = in[i];
      code.word = swap(code.word);

      // unpack the leading char
      offset = packs[mark].offsets[0];
      mask = packs[mark].masks[0];
      last_chr = o[0] = chrs_by_chr_id[(code.word >> offset) & mask];

      // unpack the successor chars
      for (unsigned int i = 1; i < packs[mark].bytes_unpacked; ++i) {
        offset = packs[mark].offsets[i];
        mask = packs[mark].masks[i];
        last_chr = o[i] = chrs_by_chr_and_successor_id[(unsigned char)last_chr - MIN_CHR][(code.word >> offset) & mask];
      }

      o += packs[mark].bytes_unpacked;
      in += packs[mark].bytes_packed;
    }
  }

  // append a 0-terminator if it fits
  if (o < out_end)
    *o = '\0';

  return o - out;
}


================================================
FILE: shoco.h
================================================
#pragma once

#include <stddef.h>

#if defined(_MSC_VER)
#define shoco_restrict __restrict
#elif __GNUC__
#define shoco_restrict __restrict__
#else
#define shoco_restrict restrict
#endif

#ifdef __cplusplus
extern "C" {
#endif

size_t shoco_compress(const char * const shoco_restrict in, size_t len, char * const shoco_restrict out, size_t bufsize);
size_t shoco_decompress(const char * const shoco_restrict in, size_t len, char * const shoco_restrict out, size_t bufsize);

#ifdef __cplusplus
}
#endif




================================================
FILE: shoco.html
================================================
<!doctype html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>shoco example</title>
    <style>
    </style>
  </head>
  <body>
    <script async type="text/javascript" src="shoco.js"></script>
    <script type="text/javascript">
       window.onload = function() {
         in_str_input = document.getElementById('in_str');
         ratio_span =  document.getElementById('ratio');
         out_str_span =  document.getElementById('out_str');
         on_in_str_change = function() {
           compressed = shoco.compress(in_str_input.value); 
           out_str_span.innerHTML = shoco.decompress(compressed);
           ratio_span.innerHTML = (((in_str_input.value.length - compressed.length) / in_str_input.value.length) * 100) | 0;
         }
         in_str_input.addEventListener("keyup", on_in_str_change);
         on_in_str_change();
         in_str_input.focus();
         in_str_input.select();
       }
    </script>
    <h1>see <em>shoco</em> in action</h1>
    <input type="text" autofocus="true" id="in_str" value="test"></input>
    compression ratio: <span id="ratio"></span>%
    output: <span id="out_str"></span>
    </body>
    </html>


================================================
FILE: shoco.js
================================================
function e(a){throw a;}var i=void 0,j=!0,l=null,m=!1;function n(){return function(){}}
var p={preRun:function(){var a=p.cwrap("shoco_compress","number",["string","number","number","number"]),b=p.cwrap("shoco_decompress","number",["number","number","number","number"]),c={compress:function(b){var c=p._malloc(8*b.length),c=new Uint8Array(p.HEAPU8.buffer,c,8*b.length),b=a(b,0,c.byteOffset,c.byteLength),b=new Uint8Array(c.subarray(0,b));p._free(c.byteOffset);return b},decompress:function(a){var c=p._malloc(8*a.length),c=new Uint8Array(p.HEAPU8.buffer,c,8*a.length),g=p._malloc(a.length),
g=new Uint8Array(p.HEAPU8.buffer,g,a.length);g.set(new Uint8Array(a.buffer));a=b(g.byteOffset,a.length,c.byteOffset,c.byteLength);a=decodeURIComponent(escape(String.fromCharCode.apply(l,c.subarray(0,a))));p._free(g.byteOffset);p._free(c.byteOffset);return a}};"undefined"!==typeof module?module.Wd=c:window.shoco=c}},aa={},q;for(q in p)p.hasOwnProperty(q)&&(aa[q]=p[q]);
var ba="object"===typeof process&&"function"===typeof require,ca="object"===typeof window,da="function"===typeof importScripts,fa=!ca&&!ba&&!da;
if(ba){p.print||(p.print=function(a){process.stdout.write(a+"\n")});p.printErr||(p.printErr=function(a){process.stderr.write(a+"\n")});var ga=require("fs"),ha=require("path");p.read=function(a,b){var a=ha.normalize(a),c=ga.readFileSync(a);!c&&a!=ha.resolve(a)&&(a=path.join(__dirname,"..","src",a),c=ga.readFileSync(a));c&&!b&&(c=c.toString());return c};p.readBinary=function(a){return p.read(a,j)};p.load=function(a){ia(read(a))};p.arguments=process.argv.slice(2);module.exports=p}else fa?(p.print||(p.print=
print),"undefined"!=typeof printErr&&(p.printErr=printErr),p.read="undefined"!=typeof read?read:function(){e("no read() available (jsc?)")},p.readBinary=function(a){return read(a,"binary")},"undefined"!=typeof scriptArgs?p.arguments=scriptArgs:"undefined"!=typeof arguments&&(p.arguments=arguments),this.Module=p,eval("if (typeof gc === 'function' && gc.toString().indexOf('[native code]') > 0) var gc = undefined")):ca||da?(p.read=function(a){var b=new XMLHttpRequest;b.open("GET",a,m);b.send(l);return b.responseText},
"undefined"!=typeof arguments&&(p.arguments=arguments),"undefined"!==typeof console?(p.print||(p.print=function(a){console.log(a)}),p.printErr||(p.printErr=function(a){console.log(a)})):p.print||(p.print=n()),ca?window.Module=p:p.load=importScripts):e("Unknown runtime environment. Where are we?");function ia(a){eval.call(l,a)}"undefined"==!p.load&&p.read&&(p.load=function(a){ia(p.read(a))});p.print||(p.print=n());p.printErr||(p.printErr=p.print);p.arguments||(p.arguments=[]);p.print=p.print;p.I=p.printErr;
p.preRun=[];p.postRun=[];for(q in aa)aa.hasOwnProperty(q)&&(p[q]=aa[q]);
var v={Xa:function(){return r},Wa:function(a){r=a},Xd:function(a,b){b=b||4;return 1==b?a:isNumber(a)&&isNumber(b)?Math.ceil(a/b)*b:isNumber(b)&&isPowerOfTwo(b)?"((("+a+")+"+(b-1)+")&"+-b+")":"Math.ceil(("+a+")/"+b+")*"+b},vb:function(a){return a in v.ib||a in v.gb},wb:function(a){return"*"==a[a.length-1]},xb:function(a){return isPointerType(a)?m:isArrayType(a)||/<?\{ ?[^}]* ?\}>?/.test(a)?j:"%"==a[0]},ib:{i1:0,i8:0,i16:0,i32:0,i64:0},gb:{"float":0,"double":0},ne:function(a,b){return(a|0|b|0)+4294967296*
(Math.round(a/4294967296)|Math.round(b/4294967296))},Od:function(a,b){return((a|0)&(b|0))+4294967296*(Math.round(a/4294967296)&Math.round(b/4294967296))},te:function(a,b){return((a|0)^(b|0))+4294967296*(Math.round(a/4294967296)^Math.round(b/4294967296))},pa:function(a){switch(a){case "i1":case "i8":return 1;case "i16":return 2;case "i32":return 4;case "i64":return 8;case "float":return 4;case "double":return 8;default:return"*"===a[a.length-1]?v.D:"i"===a[0]?(a=parseInt(a.substr(1)),w(0===a%8),a/
8):0}},qb:function(a){return Math.max(v.pa(a),v.D)},ob:function(a,b){var c={};return b?a.filter(function(a){return c[a[b]]?m:c[a[b]]=j}):a.filter(function(a){return c[a]?m:c[a]=j})},set:function(){for(var a="object"===typeof arguments[0]?arguments[0]:arguments,b={},c=0;c<a.length;c++)b[a[c]]=0;return b},Ed:8,oa:function(a,b,c){return!c&&("i64"==a||"double"==a)?8:!a?Math.min(b,8):Math.min(b||(a?v.qb(a):0),v.D)},mb:function(a){a.u=0;a.N=0;var b=[],c=-1,d=0;a.Ma=a.la.map(function(f){d++;var g,h;v.vb(f)||
v.wb(f)?(g=v.pa(f),h=v.oa(f,g)):v.xb(f)?"0"===f[1]?(g=0,h=Types.types[f]?v.oa(l,Types.types[f].N):a.N||QUANTUM_SIZE):(g=Types.types[f].u,h=v.oa(l,Types.types[f].N)):"b"==f[0]?(g=f.substr(1)|0,h=1):"<"===f[0]?g=h=Types.types[f].u:"i"===f[0]?(g=h=parseInt(f.substr(1))/8,w(0===g%1,"cannot handle non-byte-size field "+f)):w(m,"invalid type for calculateStructAlignment");a.oe&&(h=1);a.N=Math.max(a.N,h);f=v.M(a.u,h);a.u=f+g;0<=c&&b.push(f-c);return c=f});a.Sa&&"["===a.Sa[0]&&(a.u=parseInt(a.Sa.substr(1))*
a.u/2);a.u=v.M(a.u,a.N);0==b.length?a.La=a.u:1==v.ob(b).length&&(a.La=b[0]);a.je=1!=a.La;return a.Ma},pb:function(a,b,c){var d,f;if(b){c=c||0;d=("undefined"===typeof Types?v.se:Types.types)[b];if(!d)return l;if(d.la.length!=a.length)return printErr("Number of named fields must match the type for "+b+": possibly duplicate struct names. Cannot return structInfo"),l;f=d.Ma}else d={la:a.map(function(a){return a[0]})},f=v.mb(d);var g={Gd:d.u};b?a.forEach(function(a,b){if("string"===typeof a)g[a]=f[b]+
c;else{var s,u;for(u in a)s=u;g[s]=v.pb(a[s],d.la[b],f[b])}}):a.forEach(function(a,b){g[a[1]]=f[b]});return g},ja:function(a,b,c){return c&&c.length?(c.splice||(c=Array.prototype.slice.call(c)),c.splice(0,0,b),p["dynCall_"+a].apply(l,c)):p["dynCall_"+a].call(l,b)},W:[],Hd:function(a){for(var b=0;b<v.W.length;b++)if(!v.W[b])return v.W[b]=a,2*(1+b);e("Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.")},qe:function(a){v.W[(a-2)/2]=l},Yd:function(a,b){v.ia||
(v.ia={});var c=v.ia[a];if(c)return c;for(var c=[],d=0;d<b;d++)c.push(String.fromCharCode(36)+d);d=ja(a);'"'===d[0]&&(d.indexOf('"',1)===d.length-1?d=d.substr(1,d.length-2):z("invalid EM_ASM input |"+d+"|. Please use EM_ASM(..code..) (no quotes) or EM_ASM({ ..code($0).. }, input) (to input values)"));try{var f=eval("(function("+c.join(",")+"){ "+d+" })")}catch(g){p.I("error in executing inline EM_ASM code: "+g+" on: \n\n"+d+"\n\nwith args |"+c+"| (make sure to use the right one out of EM_ASM, EM_ASM_ARGS, etc.)"),
e(g)}return v.ia[a]=f},S:function(a){v.S.va||(v.S.va={});v.S.va[a]||(v.S.va[a]=1,p.I(a))},na:{},$d:function(a,b){w(b);v.na[a]||(v.na[a]=function(){return v.ja(b,a,arguments)});return v.na[a]},ga:function(){var a=[],b=0;this.sa=function(c){c&=255;if(0==a.length){if(0==(c&128))return String.fromCharCode(c);a.push(c);b=192==(c&224)?1:224==(c&240)?2:3;return""}if(b&&(a.push(c),b--,0<b))return"";var c=a[0],d=a[1],f=a[2],g=a[3];2==a.length?c=String.fromCharCode((c&31)<<6|d&63):3==a.length?c=String.fromCharCode((c&
15)<<12|(d&63)<<6|f&63):(c=(c&7)<<18|(d&63)<<12|(f&63)<<6|g&63,c=String.fromCharCode(Math.floor((c-65536)/1024)+55296,(c-65536)%1024+56320));a.length=0;return c};this.Bb=function(a){for(var a=unescape(encodeURIComponent(a)),b=[],f=0;f<a.length;f++)b.push(a.charCodeAt(f));return b}},Zd:function(){e("You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work")},wa:function(a){var b=r;r=r+a|0;r=r+7&-8;return b},Ya:function(a){var b=B;B=
B+a|0;B=B+7&-8;return b},Ja:function(a){var b=C;C=C+a|0;C=C+7&-8;C>=D&&z("Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value "+D+", (2) compile with ALLOW_MEMORY_GROWTH which adjusts the size at runtime but prevents some optimizations, or (3) set Module.TOTAL_MEMORY before the program runs.");return b},M:function(a,b){return Math.ceil(a/(b?b:8))*(b?b:8)},he:function(a,b,c){return c?+(a>>>0)+4294967296*+(b>>>0):+(a>>>0)+4294967296*+(b|0)},hb:8,
D:4,Fd:0};p.Runtime=v;var ka=m,F,la;function w(a,b){a||z("Assertion failed: "+b)}p.ccall=function(a,b,c,d){return ma(na(a),b,c,d)};function na(a){try{var b=p["_"+a];b||(b=eval("_"+a))}catch(c){}w(b,"Cannot call unknown function "+a+" (perhaps LLVM optimizations or closure removed it?)");return b}
function ma(a,b,c,d){function f(a,b){if("string"==b){if(a===l||a===i||0===a)return 0;a=G(a);b="array"}if("array"==b){g||(g=v.Xa());var c=v.wa(a.length);oa(a,c);return c}return a}var g=0,h=0,d=d?d.map(function(a){return f(a,c[h++])}):[];a=a.apply(l,d);"string"==b?b=ja(a):(w("array"!=b),b=a);g&&v.Wa(g);return b}p.cwrap=function(a,b,c){var d=na(a);return function(){return ma(d,b,c,Array.prototype.slice.call(arguments))}};
function pa(a,b,c){c=c||"i8";"*"===c.charAt(c.length-1)&&(c="i32");switch(c){case "i1":H[a]=b;break;case "i8":H[a]=b;break;case "i16":I[a>>1]=b;break;case "i32":J[a>>2]=b;break;case "i64":la=[b>>>0,(F=b,1<=+qa(F)?0<F?(ra(+sa(F/4294967296),4294967295)|0)>>>0:~~+ta((F-+(~~F>>>0))/4294967296)>>>0:0)];J[a>>2]=la[0];J[a+4>>2]=la[1];break;case "float":ua[a>>2]=b;break;case "double":va[a>>3]=b;break;default:z("invalid type for setValue: "+c)}}p.setValue=pa;
p.getValue=function(a,b){b=b||"i8";"*"===b.charAt(b.length-1)&&(b="i32");switch(b){case "i1":return H[a];case "i8":return H[a];case "i16":return I[a>>1];case "i32":return J[a>>2];case "i64":return J[a>>2];case "float":return ua[a>>2];case "double":return va[a>>3];default:z("invalid type for setValue: "+b)}return l};var L=2,wa=4;p.ALLOC_NORMAL=0;p.ALLOC_STACK=1;p.ALLOC_STATIC=L;p.ALLOC_DYNAMIC=3;p.ALLOC_NONE=wa;
function M(a,b,c,d){var f,g;"number"===typeof a?(f=j,g=a):(f=m,g=a.length);var h="string"===typeof b?b:l,c=c==wa?d:[xa,v.wa,v.Ya,v.Ja][c===i?L:c](Math.max(g,h?1:b.length));if(f){d=c;w(0==(c&3));for(a=c+(g&-4);d<a;d+=4)J[d>>2]=0;for(a=c+g;d<a;)H[d++|0]=0;return c}if("i8"===h)return a.subarray||a.slice?N.set(a,c):N.set(new Uint8Array(a),c),c;for(var d=0,x,s;d<g;){var u=a[d];"function"===typeof u&&(u=v.ae(u));f=h||b[d];0===f?d++:("i64"==f&&(f="i32"),pa(c+d,u,f),s!==f&&(x=v.pa(f),s=f),d+=x)}return c}
p.allocate=M;function ja(a,b){for(var c=m,d,f=0;;){d=N[a+f|0];if(128<=d)c=j;else if(0==d&&!b)break;f++;if(b&&f==b)break}b||(b=f);var g="";if(!c){for(;0<b;)d=String.fromCharCode.apply(String,N.subarray(a,a+Math.min(b,1024))),g=g?g+d:d,a+=1024,b-=1024;return g}c=new v.ga;for(f=0;f<b;f++)d=N[a+f|0],g+=c.sa(d);return g}p.Pointer_stringify=ja;p.UTF16ToString=function(a){for(var b=0,c="";;){var d=I[a+2*b>>1];if(0==d)return c;++b;c+=String.fromCharCode(d)}};
p.stringToUTF16=function(a,b){for(var c=0;c<a.length;++c)I[b+2*c>>1]=a.charCodeAt(c);I[b+2*a.length>>1]=0};p.UTF32ToString=function(a){for(var b=0,c="";;){var d=J[a+4*b>>2];if(0==d)return c;++b;65536<=d?(d-=65536,c+=String.fromCharCode(55296|d>>10,56320|d&1023)):c+=String.fromCharCode(d)}};p.stringToUTF32=function(a,b){for(var c=0,d=0;d<a.length;++d){var f=a.charCodeAt(d);if(55296<=f&&57343>=f)var g=a.charCodeAt(++d),f=65536+((f&1023)<<10)|g&1023;J[b+4*c>>2]=f;++c}J[b+4*c>>2]=0};
function ya(a){function b(h,s,u){var s=s||Infinity,t="",A=[],k;if("N"===a[c]){c++;"K"===a[c]&&c++;for(k=[];"E"!==a[c];)if("S"===a[c]){c++;var y=a.indexOf("_",c);k.push(f[a.substring(c,y)||0]||"?");c=y+1}else if("C"===a[c])k.push(k[k.length-1]),c+=2;else{var y=parseInt(a.substr(c)),E=y.toString().length;if(!y||!E){c--;break}var ea=a.substr(c+E,y);k.push(ea);f.push(ea);c+=E+y}c++;k=k.join("::");s--;if(0===s)return h?[k]:k}else if(("K"===a[c]||g&&"L"===a[c])&&c++,y=parseInt(a.substr(c)))E=y.toString().length,
k=a.substr(c+E,y),c+=E+y;g=m;"I"===a[c]?(c++,y=b(j),E=b(j,1,j),t+=E[0]+" "+k+"<"+y.join(", ")+">"):t=k;a:for(;c<a.length&&0<s--;)if(k=a[c++],k in d)A.push(d[k]);else switch(k){case "P":A.push(b(j,1,j)[0]+"*");break;case "R":A.push(b(j,1,j)[0]+"&");break;case "L":c++;y=a.indexOf("E",c)-c;A.push(a.substr(c,y));c+=y+2;break;case "A":y=parseInt(a.substr(c));c+=y.toString().length;"_"!==a[c]&&e("?");c++;A.push(b(j,1,j)[0]+" ["+y+"]");break;case "E":break a;default:t+="?"+k;break a}!u&&(1===A.length&&"void"===
A[0])&&(A=[]);return h?(t&&A.push(t+"?"),A):t+("("+A.join(", ")+")")}var c=3,d={v:"void",b:"bool",c:"char",s:"short",i:"int",l:"long",f:"float",d:"double",w:"wchar_t",a:"signed char",h:"unsigned char",t:"unsigned short",j:"unsigned int",m:"unsigned long",x:"long long",y:"unsigned long long",z:"..."},f=[],g=j;try{if("Object._main"==a||"_main"==a)return"main()";"number"===typeof a&&(a=ja(a));if("_"!==a[0]||"_"!==a[1]||"Z"!==a[2])return a;switch(a[3]){case "n":return"operator new()";case "d":return"operator delete()"}return b()}catch(h){return a}}
function za(){var a=Error().stack;return a?a.replace(/__Z[\w\d_]+/g,function(a){var c=ya(a);return a===c?a:a+" ["+c+"]"}):"(no stack trace available)"}for(var H,N,I,Aa,J,Ba,ua,va,Ca=0,B=0,Da=0,r=0,Ea=0,Fa=0,C=0,Ga=p.TOTAL_STACK||5242880,D=p.TOTAL_MEMORY||16777216,O=4096;O<D||O<2*Ga;)O=16777216>O?2*O:O+16777216;O!==D&&(p.I("increasing TOTAL_MEMORY to "+O+" to be more reasonable"),D=O);
w("undefined"!==typeof Int32Array&&"undefined"!==typeof Float64Array&&!!(new Int32Array(1)).subarray&&!!(new Int32Array(1)).set,"JS engine does not provide full typed array support");var P=new ArrayBuffer(D);H=new Int8Array(P);I=new Int16Array(P);J=new Int32Array(P);N=new Uint8Array(P);Aa=new Uint16Array(P);Ba=new Uint32Array(P);ua=new Float32Array(P);va=new Float64Array(P);J[0]=255;w(255===N[0]&&0===N[3],"Typed arrays 2 must be run on a little-endian system");p.HEAP=i;p.HEAP8=H;p.HEAP16=I;
p.HEAP32=J;p.HEAPU8=N;p.HEAPU16=Aa;p.HEAPU32=Ba;p.HEAPF32=ua;p.HEAPF64=va;function Q(a){for(;0<a.length;){var b=a.shift();if("function"==typeof b)b();else{var c=b.Q;"number"===typeof c?b.ha===i?v.ja("v",c):v.ja("vi",c,[b.ha]):c(b.ha===i?l:b.ha)}}}var Ha=[],Ia=[],Ja=[],Ka=[],La=[],Ma=m;function Na(a){Ha.unshift(a)}p.addOnPreRun=p.Md=Na;p.addOnInit=p.Jd=function(a){Ia.unshift(a)};p.addOnPreMain=p.Ld=function(a){Ja.unshift(a)};p.addOnExit=p.Id=function(a){Ka.unshift(a)};
function Pa(a){La.unshift(a)}p.addOnPostRun=p.Kd=Pa;function G(a,b,c){a=(new v.ga).Bb(a);c&&(a.length=c);b||a.push(0);return a}p.intArrayFromString=G;p.intArrayToString=function(a){for(var b=[],c=0;c<a.length;c++){var d=a[c];255<d&&(d&=255);b.push(String.fromCharCode(d))}return b.join("")};p.writeStringToMemory=function(a,b,c){a=G(a,c);for(c=0;c<a.length;)H[b+c|0]=a[c],c+=1};function oa(a,b){for(var c=0;c<a.length;c++)H[b+c|0]=a[c]}p.writeArrayToMemory=oa;
p.writeAsciiToMemory=function(a,b,c){for(var d=0;d<a.length;d++)H[b+d|0]=a.charCodeAt(d);c||(H[b+a.length|0]=0)};if(!Math.imul||-5!==Math.imul(4294967295,5))Math.imul=function(a,b){var c=a&65535,d=b&65535;return c*d+((a>>>16)*d+c*(b>>>16)<<16)|0};Math.ce=Math.imul;var qa=Math.abs,ta=Math.ceil,sa=Math.floor,ra=Math.min,R=0,Qa=l,Ra=l;function Sa(){R++;p.monitorRunDependencies&&p.monitorRunDependencies(R)}p.addRunDependency=Sa;
function Ta(){R--;p.monitorRunDependencies&&p.monitorRunDependencies(R);if(0==R&&(Qa!==l&&(clearInterval(Qa),Qa=l),Ra)){var a=Ra;Ra=l;a()}}p.removeRunDependency=Ta;p.preloadedImages={};p.preloadedAudios={};Ca=8;B=Ca+v.M(2883);Ia.push();
M([255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,26,255,255,255,255,255,22,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,27,255,255,255,255,255,23,29,255,255,31,24,255,255,255,255,255,255,25,255,255,30,255,255,255,255,255,255,255,255,255,1,15,11,14,0,17,18,5,2,255,21,9,13,6,3,16,255,7,8,4,10,19,12,28,20,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,7,4,12,255,6,255,
1,0,3,5,255,9,255,8,2,255,15,14,255,10,11,255,255,255,255,255,255,255,13,255,255,255,255,255,6,255,1,255,0,3,2,4,15,11,255,9,5,10,13,255,12,8,7,14,255,255,255,255,255,255,255,255,255,255,9,11,255,4,2,255,0,8,1,5,255,6,255,3,7,15,255,12,10,13,255,255,255,255,255,255,255,255,255,255,255,255,255,255,14,7,5,255,1,2,8,9,0,15,6,4,11,255,12,3,255,10,255,13,255,255,255,255,255,255,255,255,255,255,2,4,3,1,5,0,255,6,10,9,7,12,11,255,255,255,255,13,255,255,8,255,15,255,255,255,14,255,255,255,255,255,0,1,2,3,
4,255,255,5,9,10,6,255,255,8,15,11,255,14,255,255,7,255,13,255,255,255,12,255,255,255,255,255,2,8,7,4,3,255,9,255,6,11,255,5,255,255,0,255,255,14,1,15,10,12,255,255,255,255,13,255,255,255,255,255,0,3,1,2,6,255,9,8,4,12,13,10,255,11,7,255,255,15,14,255,5,255,255,255,255,255,255,255,255,255,255,255,0,6,3,4,1,2,255,255,5,10,7,9,11,12,255,255,8,14,255,255,15,13,255,255,255,255,255,255,255,255,255,255,0,6,2,5,9,255,255,255,10,1,8,255,12,14,4,255,15,7,255,13,3,11,255,255,255,255,255,255,255,255,255,255,
8,10,9,15,1,255,4,0,3,2,255,6,255,12,11,13,7,14,5,255,255,255,255,255,255,255,255,255,255,255,255,255,1,3,6,0,4,2,255,7,13,8,9,11,255,255,15,255,255,255,255,255,10,5,14,255,255,255,255,255,255,255,255,255,3,0,1,4,255,2,5,6,7,8,255,14,255,255,9,15,255,12,255,255,255,10,11,255,255,255,13,255,255,255,255,255,0,1,3,2,15,255,12,255,7,14,4,255,255,9,255,8,5,10,255,255,6,255,13,255,255,255,11,255,255,255,255,255,0,3,1,2,255,255,12,6,4,9,7,255,255,14,8,255,255,15,11,13,5,255,10,255,255,255,255,255,255,255,
255,255,0,5,7,2,10,13,255,6,8,1,3,255,255,14,15,11,255,255,255,12,4,255,255,255,255,255,255,255,255,255,255,255,0,2,6,3,7,10,255,1,9,4,8,255,255,15,255,12,5,255,255,255,11,255,13,255,255,255,14,255,255,255,255,255,1,3,4,0,7,255,12,2,11,8,6,13,255,255,255,255,255,5,255,255,10,15,9,255,255,255,14,255,255,255,255,255,1,3,5,2,13,0,9,4,7,6,8,255,255,15,255,11,255,255,10,255,14,255,12,255,255,255,255,255,255,255,255,255,0,2,1,3,255,255,255,6,255,255,5,255,255,255,255,255,255,255,255,255,4,255,255,255,255,
255,255,255,255,255,255,255,1,11,4,0,3,255,13,12,2,7,255,255,15,10,5,8,14,255,255,255,255,255,9,255,255,255,6,255,255,255,255,255,0,9,2,14,15,4,1,13,3,5,255,255,10,255,255,255,255,6,12,255,7,255,8,255,255,255,11,255,255,255,255,255,255,2,14,255,1,5,8,7,4,12,255,6,9,11,13,3,10,15,255,255,255,255,0,255,255,255,255,255,255,255,255,255,0,1,3,2,255,255,255,255,255,255,4,255,255,255,255,255,255,255,255,255,6,255,255,255,255,255,255,255,255,255,255,255,4,3,1,5,255,255,255,0,255,255,6,255,255,255,255,255,
255,255,255,255,2,255,255,255,255,255,255,255,255,255,255,255,2,8,4,1,255,0,255,6,255,255,5,255,7,255,255,255,255,255,255,255,10,255,255,9,255,255,255,255,255,255,255,255,12,5,255,255,1,255,255,7,0,3,255,2,255,4,6,255,255,255,255,8,255,255,15,255,13,9,255,255,255,255,255,11,1,3,2,4,255,255,255,5,255,7,0,255,255,255,255,255,255,255,255,255,6,255,255,255,255,255,255,255,255,8,255,255,5,3,4,12,1,6,255,255,255,255,8,2,255,255,255,255,0,9,255,255,11,255,10,255,255,255,255,255,255,255,255,255,255,255,255,
255,0,255,1,12,3,255,255,255,255,5,255,255,255,2,255,255,255,255,255,255,255,255,4,255,255,6,255,10,2,3,1,4,255,0,255,5,255,255,255,255,255,255,255,255,255,255,255,255,7,255,255,255,255,255,255,255,255,6,255,255,5,1,3,0,255,255,255,255,255,255,4,255,255,255,255,255,255,255,255,255,2,255,255,255,255,255,9,255,255,6,255,7,0,0,0,128,1,0,0,0,2,0,0,0,26,0,0,0,24,0,0,0,24,0,0,0,24,0,0,0,24,0,0,0,24,0,0,0,24,0,0,0,24,0,0,0,0,0,0,0,15,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,192,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,192,2,0,0,0,4,0,0,0,25,0,0,0,22,0,0,0,19,0,0,0,16,0,0,0,16,0,0,0,16,0,0,0,16,0,0,0,16,0,0,0,0,0,0,0,15,0,7,0,7,0,7,0,0,0,0,0,0,0,0,0,224,192,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,224,4,0,0,0,8,0,0,0,23,0,0,0,19,0,0,0,15,0,0,0,11,0,0,0,8,0,0,0,5,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,31,0,15,0,15,0,15,0,7,0,7,0,7,0,3,0,240,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,101,97,105,111,116,104,110,114,115,108,117,99,119,109,100,98,112,102,103,118,121,107,45,72,77,84,39,66,120,73,87,76,115,116,99,108,109,97,100,114,118,84,65,
76,101,77,89,45,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,116,97,98,115,104,99,114,110,119,112,109,108,100,105,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,101,105,97,111,114,121,108,73,69,82,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,101,97,111,105,117,65,121,69,0,0,0,0,0,0,0,0,116,110,102,115,39,109,73,78,65,69,76,90,114,86,82,67,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,111,97,121,105,117,101,73,76,68,39,69,89,0,0,0,0,114,105,121,97,101,111,117,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,104,111,101,69,105,117,114,119,97,72,121,82,90,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,104,105,101,97,111,114,73,121,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,110,116,115,114,108,
100,105,121,118,109,98,99,103,112,107,117,101,108,111,117,121,97,114,105,115,106,116,98,118,104,109,100,111,101,104,97,116,107,105,114,108,117,121,99,113,115,45,100,101,105,111,97,115,121,114,117,100,108,45,103,110,118,109,102,114,110,100,115,97,108,116,101,109,99,118,121,105,120,102,112,111,101,114,97,105,102,117,116,108,45,121,115,110,99,39,107,104,101,111,97,114,105,108,115,117,110,103,98,45,116,121,109,101,97,105,111,116,114,117,121,109,115,108,98,39,45,102,100,110,115,116,109,111,108,99,100,
114,101,103,97,102,118,122,98,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,101,110,105,115,104,108,102,121,45,97,119,39,103,114,111,116,101,108,105,121,100,111,97,102,117,116,115,107,119,118,109,112,101,97,111,105,117,112,121,115,98,109,102,39,110,45,108,116,100,103,101,116,111,99,115,105,97,110,121,108,107,39,102,118,117,110,114,102,109,116,119,111,115,108,118,100,112,107,105,99,101,114,97,111,108,112,105,116,117,115,104,121,98,45,39,109,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,101,105,111,97,115,121,116,100,114,110,
99,109,108,117,103,102,101,116,104,105,111,115,97,117,112,99,108,119,109,107,102,121,104,111,101,105,97,116,114,117,121,108,115,119,99,102,39,45,114,116,108,115,110,103,99,112,101,105,97,100,109,98,102,111,101,105,97,111,121,117,114,0,0,0,0,0,0,0,0,0,97,105,104,101,111,110,114,115,108,100,107,45,102,39,99,98,112,116,99,97,105,101,104,113,117,102,45,121,111,0,0,0,111,101,115,116,105,100,39,108,98,45,109,97,114,110,112,119],"i8",wa,v.hb);var Ua=v.M(M(12,"i8",L),8);w(0==Ua%8);
function xa(a){return v.Ja(a+8)+8&4294967288}p._malloc=xa;
var S={O:1,T:2,rd:3,mc:4,C:5,Ea:6,Gb:7,Kc:8,bb:9,Ub:10,za:11,Bd:11,eb:12,ab:13,fc:14,Wc:15,Aa:16,Ba:17,Cd:18,Ca:19,fb:20,da:21,L:22,Fc:23,cb:24,ad:25,yd:26,gc:27,Sc:28,fa:29,od:30,yc:31,gd:32,cc:33,ld:34,Oc:42,jc:43,Vb:44,pc:45,qc:46,rc:47,xc:48,zd:49,Ic:50,oc:51,$b:35,Lc:37,Mb:52,Pb:53,Dd:54,Gc:55,Qb:56,Rb:57,ac:35,Sb:59,Uc:60,Jc:61,vd:62,Tc:63,Pc:64,Qc:65,nd:66,Mc:67,Jb:68,sd:69,Wb:70,hd:71,Ac:72,dc:73,Ob:74,bd:76,Nb:77,md:78,sc:79,tc:80,wc:81,vc:82,uc:83,Vc:38,Da:39,Bc:36,ea:40,cd:95,fd:96,Zb:104,
Hc:105,Kb:97,kd:91,Zc:88,Rc:92,pd:108,Yb:111,Hb:98,Xb:103,Ec:101,Cc:100,wd:110,hc:112,ic:113,lc:115,Lb:114,bc:89,zc:90,jd:93,qd:94,Ib:99,Dc:102,nc:106,Xc:107,xd:109,Ad:87,ec:122,td:116,$c:95,Nc:123,kc:84,dd:75,Tb:125,Yc:131,ed:130,ud:86},Va={"0":"Success",1:"Not super-user",2:"No such file or directory",3:"No such process",4:"Interrupted system call",5:"I/O error",6:"No such device or address",7:"Arg list too long",8:"Exec format error",9:"Bad file number",10:"No children",11:"No more processes",
12:"Not enough core",13:"Permission denied",14:"Bad address",15:"Block device required",16:"Mount device busy",17:"File exists",18:"Cross-device link",19:"No such device",20:"Not a directory",21:"Is a directory",22:"Invalid argument",23:"Too many open files in system",24:"Too many open files",25:"Not a typewriter",26:"Text file busy",27:"File too large",28:"No space left on device",29:"Illegal seek",30:"Read only file system",31:"Too many links",32:"Broken pipe",33:"Math arg out of domain of func",
34:"Math result not representable",35:"File locking deadlock error",36:"File or path name too long",37:"No record locks available",38:"Function not implemented",39:"Directory not empty",40:"Too many symbolic links",42:"No message of desired type",43:"Identifier removed",44:"Channel number out of range",45:"Level 2 not synchronized",46:"Level 3 halted",47:"Level 3 reset",48:"Link number out of range",49:"Protocol driver not attached",50:"No CSI structure available",51:"Level 2 halted",52:"Invalid exchange",
53:"Invalid request descriptor",54:"Exchange full",55:"No anode",56:"Invalid request code",57:"Invalid slot",59:"Bad font file fmt",60:"Device not a stream",61:"No data (for no delay io)",62:"Timer expired",63:"Out of streams resources",64:"Machine is not on the network",65:"Package not installed",66:"The object is remote",67:"The link has been severed",68:"Advertise error",69:"Srmount error",70:"Communication error on send",71:"Protocol error",72:"Multihop attempted",73:"Cross mount point (not really error)",
74:"Trying to read unreadable message",75:"Value too large for defined data type",76:"Given log. name not unique",77:"f.d. invalid for this operation",78:"Remote address changed",79:"Can   access a needed shared lib",80:"Accessing a corrupted shared lib",81:".lib section in a.out corrupted",82:"Attempting to link in too many libs",83:"Attempting to exec a shared library",84:"Illegal byte sequence",86:"Streams pipe error",87:"Too many users",88:"Socket operation on non-socket",89:"Destination address required",
90:"Message too long",91:"Protocol wrong type for socket",92:"Protocol not available",93:"Unknown protocol",94:"Socket type not supported",95:"Not supported",96:"Protocol family not supported",97:"Address family not supported by protocol family",98:"Address already in use",99:"Address not available",100:"Network interface is not configured",101:"Network is unreachable",102:"Connection reset by network",103:"Connection aborted",104:"Connection reset by peer",105:"No buffer space available",106:"Socket is already connected",
107:"Socket is not connected",108:"Can't send after socket shutdown",109:"Too many references",110:"Connection timed out",111:"Connection refused",112:"Host is down",113:"Host is unreachable",114:"Socket already connected",115:"Connection already in progress",116:"Stale file handle",122:"Quota exceeded",123:"No medium (in tape drive)",125:"Operation canceled",130:"Previous owner died",131:"State not recoverable"},Wa=0;function Xa(a){return J[Wa>>2]=a}var Ya=[];
function Za(a,b){Ya[a]={input:[],H:[],R:b};$a[a]={k:ab}}
var ab={open:function(a){var b=Ya[a.e.$];b||e(new T(S.Ca));a.p=b;a.seekable=m},close:function(a){a.p.H.length&&a.p.R.Z(a.p,10)},J:function(a,b,c,d){(!a.p||!a.p.R.Pa)&&e(new T(S.Ea));for(var f=0,g=0;g<d;g++){var h;try{h=a.p.R.Pa(a.p)}catch(x){e(new T(S.C))}h===i&&0===f&&e(new T(S.za));if(h===l||h===i)break;f++;b[c+g]=h}f&&(a.e.timestamp=Date.now());return f},write:function(a,b,c,d){(!a.p||!a.p.R.Z)&&e(new T(S.Ea));for(var f=0;f<d;f++)try{a.p.R.Z(a.p,b[c+f])}catch(g){e(new T(S.C))}d&&(a.e.timestamp=
Date.now());return f}},U={A:l,$a:1,ca:2,ya:3,G:function(){return U.createNode(l,"/",16895,0)},createNode:function(a,b,c,d){(24576===(c&61440)||4096===(c&61440))&&e(new T(S.O));U.A||(U.A={dir:{e:{B:U.g.B,o:U.g.o,ra:U.g.ra,X:U.g.X,rename:U.g.rename,Za:U.g.Za,Va:U.g.Va,Ua:U.g.Ua,ba:U.g.ba},K:{F:U.k.F}},file:{e:{B:U.g.B,o:U.g.o},K:{F:U.k.F,J:U.k.J,write:U.k.write,Fa:U.k.Fa,Ra:U.k.Ra}},link:{e:{B:U.g.B,o:U.g.o,aa:U.g.aa},K:{}},Ia:{e:{B:U.g.B,o:U.g.o},K:bb}});cb||(cb=function(a,b,c,d){a||(a=this);this.parent=
a;this.G=a.G;this.Y=l;this.id=db++;this.name=b;this.mode=c;this.g={};this.k={};this.$=d},cb.prototype={},Object.defineProperties(cb.prototype,{J:{get:function(){return 365===(this.mode&365)},set:function(a){a?this.mode|=365:this.mode&=-366}},write:{get:function(){return 146===(this.mode&146)},set:function(a){a?this.mode|=146:this.mode&=-147}},ub:{get:function(){return 16384===(this.mode&61440)}},tb:{get:function(){return 8192===(this.mode&61440)}}}));c=new cb(a,b,c,d);d=eb(c.parent.id,c.name);c.Ab=
fb[d];fb[d]=c;16384===(c.mode&61440)?(c.g=U.A.dir.e,c.k=U.A.dir.K,c.n={}):32768===(c.mode&61440)?(c.g=U.A.file.e,c.k=U.A.file.K,c.n=[],c.V=U.ca):40960===(c.mode&61440)?(c.g=U.A.link.e,c.k=U.A.link.K):8192===(c.mode&61440)&&(c.g=U.A.Ia.e,c.k=U.A.Ia.K);c.timestamp=Date.now();a&&(a.n[b]=c);return c},ka:function(a){a.V!==U.ca&&(a.n=Array.prototype.slice.call(a.n),a.V=U.ca)},g:{B:function(a){var b={};b.Td=8192===(a.mode&61440)?a.id:1;b.de=a.id;b.mode=a.mode;b.ke=1;b.uid=0;b.be=0;b.$=a.$;b.size=16384===
(a.mode&61440)?4096:32768===(a.mode&61440)?a.n.length:40960===(a.mode&61440)?a.link.length:0;b.Pd=new Date(a.timestamp);b.ie=new Date(a.timestamp);b.Sd=new Date(a.timestamp);b.lb=4096;b.Qd=Math.ceil(b.size/b.lb);return b},o:function(a,b){b.mode!==i&&(a.mode=b.mode);b.timestamp!==i&&(a.timestamp=b.timestamp);if(b.size!==i){U.ka(a);var c=a.n;if(b.size<c.length)c.length=b.size;else for(;b.size>c.length;)c.push(0)}},ra:function(){e(gb[S.T])},X:function(a,b,c,d){return U.createNode(a,b,c,d)},rename:function(a,
b,c){if(16384===(a.mode&61440)){var d;try{d=hb(b,c)}catch(f){}if(d)for(var g in d.n)e(new T(S.Da))}delete a.parent.n[a.name];a.name=c;b.n[c]=a;a.parent=b},Za:function(a,b){delete a.n[b]},Va:function(a,b){var c=hb(a,b),d;for(d in c.n)e(new T(S.Da));delete a.n[b]},Ua:function(a){var b=[".",".."],c;for(c in a.n)a.n.hasOwnProperty(c)&&b.push(c);return b},ba:function(a,b,c){a=U.createNode(a,b,41471,0);a.link=c;return a},aa:function(a){40960!==(a.mode&61440)&&e(new T(S.L));return a.link}},k:{J:function(a,
b,c,d,f){a=a.e.n;if(f>=a.length)return 0;d=Math.min(a.length-f,d);w(0<=d);if(8<d&&a.subarray)b.set(a.subarray(f,f+d),c);else for(var g=0;g<d;g++)b[c+g]=a[f+g];return d},write:function(a,b,c,d,f,g){var h=a.e;h.timestamp=Date.now();a=h.n;if(d&&0===a.length&&0===f&&b.subarray)return g&&0===c?(h.n=b,h.V=b.buffer===H.buffer?U.$a:U.ya):(h.n=new Uint8Array(b.subarray(c,c+d)),h.V=U.ya),d;U.ka(h);for(a=h.n;a.length<f;)a.push(0);for(g=0;g<d;g++)a[f+g]=b[c+g];return d},F:function(a,b,c){1===c?b+=a.position:
2===c&&32768===(a.e.mode&61440)&&(b+=a.e.n.length);0>b&&e(new T(S.L));a.Eb=[];return a.position=b},Fa:function(a,b,c){U.ka(a.e);a=a.e.n;for(b+=c;b>a.length;)a.push(0)},Ra:function(a,b,c,d,f,g,h){32768!==(a.e.mode&61440)&&e(new T(S.Ca));a=a.e.n;if(!(h&2)&&(a.buffer===b||a.buffer===b.buffer))f=m,d=a.byteOffset;else{if(0<f||f+d<a.length)a=a.subarray?a.subarray(f,f+d):Array.prototype.slice.call(a,f,f+d);f=j;(d=xa(d))||e(new T(S.eb));b.set(a,d)}return{pe:d,Nd:f}}}},ib=M(1,"i32*",L),jb=M(1,"i32*",L),kb=
M(1,"i32*",L),lb=l,$a=[l],mb=[],db=1,fb=l,nb=j,T=l,gb={};
function V(a,b){var a=ob("/",a),b=b||{},c={Na:j,ta:0},d;for(d in c)b[d]===i&&(b[d]=c[d]);8<b.ta&&e(new T(S.ea));var c=pb(a.split("/").filter(function(a){return!!a}),m),f=lb,g="/";for(d=0;d<c.length;d++){var h=d===c.length-1;if(h&&b.parent)break;f=hb(f,c[d]);g=W(g+"/"+c[d]);if(f.Y&&(!h||h&&b.Na))f=f.Y.root;if(!h||b.ma)for(h=0;40960===(f.mode&61440);){f=V(g).e;f.g.aa||e(new T(S.L));var f=f.g.aa(f),x=ob;var s=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/.exec(g).slice(1),g=s[0],s=s[1];
!g&&!s?g=".":(s&&(s=s.substr(0,s.length-1)),g+=s);g=x(g,f);f=V(g,{ta:b.ta}).e;40<h++&&e(new T(S.ea))}}return{path:g,e:f}}function X(a){for(var b;;){if(a===a.parent)return a=a.G.yb,!b?a:"/"!==a[a.length-1]?a+"/"+b:a+b;b=b?a.name+"/"+b:a.name;a=a.parent}}function eb(a,b){for(var c=0,d=0;d<b.length;d++)c=(c<<5)-c+b.charCodeAt(d)|0;return(a+c>>>0)%fb.length}
function hb(a,b){var c=qb(a,"x");c&&e(new T(c));for(c=fb[eb(a.id,b)];c;c=c.Ab){var d=c.name;if(c.parent.id===a.id&&d===b)return c}return a.g.ra(a,b)}var rb={r:0,rs:1052672,"r+":2,w:577,wx:705,xw:705,"w+":578,"wx+":706,"xw+":706,a:1089,ax:1217,xa:1217,"a+":1090,"ax+":1218,"xa+":1218};function qb(a,b){return nb?0:-1!==b.indexOf("r")&&!(a.mode&292)||-1!==b.indexOf("w")&&!(a.mode&146)||-1!==b.indexOf("x")&&!(a.mode&73)?S.ab:0}function sb(a,b){try{return hb(a,b),S.Ba}catch(c){}return qb(a,"wx")}
var bb={open:function(a){a.k=$a[a.e.$].k;a.k.open&&a.k.open(a)},F:function(){e(new T(S.fa))}};function tb(a,b,c){var d=V(a,{parent:j}).e,a=ub(a),f=sb(d,a);f&&e(new T(f));d.g.X||e(new T(S.O));return d.g.X(d,a,b,c)}function vb(a,b){b=(b!==i?b:438)&4095;b|=32768;return tb(a,b,0)}function wb(a,b){b=(b!==i?b:511)&1023;b|=16384;return tb(a,b,0)}function xb(a,b,c){"undefined"===typeof c&&(c=b,b=438);return tb(a,b|8192,c)}
function yb(a,b){var c=V(b,{parent:j}).e,d=ub(b),f=sb(c,d);f&&e(new T(f));c.g.ba||e(new T(S.O));return c.g.ba(c,d,a)}function zb(a,b){var c;c="string"===typeof a?V(a,{ma:j}).e:a;c.g.o||e(new T(S.O));c.g.o(c,{mode:b&4095|c.mode&-4096,timestamp:Date.now()})}
function Ab(a,b){var c,d;"string"===typeof b?(d=rb[b],"undefined"===typeof d&&e(Error("Unknown file open mode: "+b))):d=b;b=d;c=b&64?("undefined"===typeof c?438:c)&4095|32768:0;var f;if("object"===typeof a)f=a;else{a=W(a);try{f=V(a,{ma:!(b&131072)}).e}catch(g){}}b&64&&(f?b&128&&e(new T(S.Ba)):f=tb(a,c,0));f||e(new T(S.T));8192===(f.mode&61440)&&(b&=-513);f?40960===(f.mode&61440)?c=S.ea:16384===(f.mode&61440)&&(0!==(b&2097155)||b&512)?c=S.da:(c=["r","w","rw"][b&2097155],b&512&&(c+="w"),c=qb(f,c)):
c=S.T;c&&e(new T(c));b&512&&(c=f,c="string"===typeof c?V(c,{ma:j}).e:c,c.g.o||e(new T(S.O)),16384===(c.mode&61440)&&e(new T(S.da)),32768!==(c.mode&61440)&&e(new T(S.L)),(d=qb(c,"w"))&&e(new T(d)),c.g.o(c,{size:0,timestamp:Date.now()}));var b=b&-641,h;f={e:f,path:X(f),P:b,seekable:j,position:0,k:f.k,Eb:[],error:m};Bb||(Bb=n(),Bb.prototype={},Object.defineProperties(Bb.prototype,{object:{get:function(){return this.e},set:function(a){this.e=a}},fe:{get:function(){return 1!==(this.P&2097155)}},ge:{get:function(){return 0!==
(this.P&2097155)}},ee:{get:function(){return this.P&1024}}}));c=new Bb;for(var x in f)c[x]=f[x];f=c;a:{x=i||4096;for(c=i||0;c<=x;c++)if(!mb[c]){h=c;break a}e(new T(S.cb))}f.q=h;h=mb[h]=f;h.k.open&&h.k.open(h);p.logReadFiles&&!(b&1)&&(Cb||(Cb={}),a in Cb||(Cb[a]=1,p.printErr("read file: "+a)));return h}function Db(a){try{a.k.close&&a.k.close(a)}catch(b){e(b)}finally{mb[a.q]=l}}
function Eb(){T||(T=function(a){this.Ud=a;for(var b in S)if(S[b]===a){this.code=b;break}this.message=Va[a]},T.prototype=Error(),[S.T].forEach(function(a){gb[a]=new T(a);gb[a].stack="<generic error, no stack>"}))}var Fb;function Gb(a,b){var c=0;a&&(c|=365);b&&(c|=146);return c}
function Hb(a,b,c,d,f,g){a=b?W(("string"===typeof a?a:X(a))+"/"+b):a;d=Gb(d,f);f=vb(a,d);if(c){if("string"===typeof c){for(var a=Array(c.length),b=0,h=c.length;b<h;++b)a[b]=c.charCodeAt(b);c=a}zb(f,d|146);var a=Ab(f,"w"),b=c,h=c.length,x=0;(0>h||0>x)&&e(new T(S.L));0===(a.P&2097155)&&e(new T(S.bb));16384===(a.e.mode&61440)&&e(new T(S.da));a.k.write||e(new T(S.L));c=j;"undefined"===typeof x?(x=a.position,c=m):a.seekable||e(new T(S.fa));a.P&1024&&((!a.seekable||!a.k.F)&&e(new T(S.fa)),a.k.F(a,0,2));
g=a.k.write(a,b,0,h,x,g);c||(a.position+=g);Db(a);zb(f,d)}return f}
function Y(a,b,c,d){a=W(("string"===typeof a?a:X(a))+"/"+b);b=Gb(!!c,!!d);Y.Qa||(Y.Qa=64);var f;f=Y.Qa++<<8|0;$a[f]={k:{open:function(a){a.seekable=m},close:function(){d&&(d.buffer&&d.buffer.length)&&d(10)},J:function(a,b,d,f){for(var u=0,t=0;t<f;t++){var A;try{A=c()}catch(k){e(new T(S.C))}A===i&&0===u&&e(new T(S.za));if(A===l||A===i)break;u++;b[d+t]=A}u&&(a.e.timestamp=Date.now());return u},write:function(a,b,c,f){for(var u=0;u<f;u++)try{d(b[c+u])}catch(t){e(new T(S.C))}f&&(a.e.timestamp=Date.now());
return u}}};return xb(a,b,f)}function Ib(a){if(a.tb||a.ub||a.link||a.n)return j;var b=j;"undefined"!==typeof XMLHttpRequest&&e(Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread."));if(p.read)try{a.n=G(p.read(a.url),j)}catch(c){b=m}else e(Error("Cannot load without read() or XMLHttpRequest."));b||Xa(S.C);return b}var cb,Bb,Cb;
function pb(a,b){for(var c=0,d=a.length-1;0<=d;d--){var f=a[d];"."===f?a.splice(d,1):".."===f?(a.splice(d,1),c++):c&&(a.splice(d,1),c--)}if(b)for(;c--;c)a.unshift("..");return a}function W(a){var b="/"===a.charAt(0),c="/"===a.substr(-1),a=pb(a.split("/").filter(function(a){return!!a}),!b).join("/");!a&&!b&&(a=".");a&&c&&(a+="/");return(b?"/":"")+a}function ub(a){if("/"===a)return"/";var b=a.lastIndexOf("/");return-1===b?a:a.substr(b+1)}
function ob(){for(var a="",b=m,c=arguments.length-1;-1<=c&&!b;c--){var d=0<=c?arguments[c]:"/";"string"!==typeof d&&e(new TypeError("Arguments to path.resolve must be strings"));d&&(a=d+"/"+a,b="/"===d.charAt(0))}a=pb(a.split("/").filter(function(a){return!!a}),!b).join("/");return(b?"/":"")+a||"."}var Jb=m,Kb=m,Lb=m,Mb=m,Nb=i,Ob=i;
function Pb(a){return{jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",bmp:"image/bmp",ogg:"audio/ogg",wav:"audio/wav",mp3:"audio/mpeg"}[a.substr(a.lastIndexOf(".")+1)]}var Qb=[];function Rb(){var a=p.canvas;Qb.forEach(function(b){b(a.width,a.height)})}
function Sb(a,b,c){b&&c?(a.Fb=b,a.sb=c):(b=a.Fb,c=a.sb);var d=b,f=c;p.forcedAspectRatio&&0<p.forcedAspectRatio&&(d/f<p.forcedAspectRatio?d=Math.round(f*p.forcedAspectRatio):f=Math.round(d/p.forcedAspectRatio));if((document.webkitFullScreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.mozFullscreenElement||document.fullScreenElement||document.fullscreenElement||document.msFullScreenElement||document.msFullscreenElement||document.webkitCurrentFullScreenElement)===
a.parentNode&&"undefined"!=typeof screen)var g=Math.min(screen.width/d,screen.height/f),d=Math.round(d*g),f=Math.round(f*g);Ob?(a.width!=d&&(a.width=d),a.height!=f&&(a.height=f),"undefined"!=typeof a.style&&(a.style.removeProperty("width"),a.style.removeProperty("height"))):(a.width!=b&&(a.width=b),a.height!=c&&(a.height=c),"undefined"!=typeof a.style&&(d!=b||f!=c?(a.style.setProperty("width",d+"px","important"),a.style.setProperty("height",f+"px","important")):(a.style.removeProperty("width"),a.style.removeProperty("height"))))}
var Tb,Ub,Vb,Wb;p._memset=Xb;p._strlen=Yb;p._memcpy=Zb;function $b(){}p._free=$b;
p.requestFullScreen=function(a,b){function c(){Kb=m;var a=d.parentNode;(document.webkitFullScreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.mozFullscreenElement||document.fullScreenElement||document.fullscreenElement||document.msFullScreenElement||document.msFullscreenElement||document.webkitCurrentFullScreenElement)===a?(d.Ha=document.cancelFullScreen||document.mozCancelFullScreen||document.webkitCancelFullScreen||document.msExitFullscreen||document.exitFullscreen||
n(),d.Ha=d.Ha.bind(document),Nb&&d.ua(),Kb=j,Ob&&("undefined"!=typeof SDL&&(a=Ba[SDL.screen+0*v.D>>2],J[SDL.screen+0*v.D>>2]=a|8388608),Rb())):(a.parentNode.insertBefore(d,a),a.parentNode.removeChild(a),Ob&&("undefined"!=typeof SDL&&(a=Ba[SDL.screen+0*v.D>>2],J[SDL.screen+0*v.D>>2]=a&-8388609),Rb()));if(p.onFullScreen)p.onFullScreen(Kb);Sb(d)}Nb=a;Ob=b;"undefined"===typeof Nb&&(Nb=j);"undefined"===typeof Ob&&(Ob=m);var d=p.canvas;Mb||(Mb=j,document.addEventListener("fullscreenchange",c,m),document.addEventListener("mozfullscreenchange",
c,m),document.addEventListener("webkitfullscreenchange",c,m),document.addEventListener("MSFullscreenChange",c,m));var f=document.createElement("div");d.parentNode.insertBefore(f,d);f.appendChild(d);f.Cb=f.requestFullScreen||f.mozRequestFullScreen||f.msRequestFullscreen||(f.webkitRequestFullScreen?function(){f.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT)}:l);f.Cb()};
p.requestAnimationFrame=function(a){"undefined"===typeof window?setTimeout(a,1E3/60):(window.requestAnimationFrame||(window.requestAnimationFrame=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame||window.setTimeout),window.requestAnimationFrame(a))};p.setCanvasSize=function(a,b,c){Sb(p.canvas,a,b);c||Rb()};p.pauseMainLoop=n();p.resumeMainLoop=function(){Jb&&(Jb=m,l())};
p.getUserMedia=function(){window.Oa||(window.Oa=navigator.getUserMedia||navigator.mozGetUserMedia);window.Oa(i)};Eb();var fb=Array(4096),ac=U,bc="/",cc="/"===bc,dc=!bc,Z;cc&&lb&&e(new T(S.Aa));if(!cc&&!dc){var ec=V(bc,{Na:m}),bc=ec.path;Z=ec.e;Z.Y&&e(new T(S.Aa));16384!==(Z.mode&61440)&&e(new T(S.fb))}var fc={type:ac,me:{},yb:bc,zb:[]},gc=ac.G(fc);gc.G=fc;fc.root=gc;cc?lb=gc:Z&&(Z.Y=fc,Z.G&&Z.G.zb.push(fc));wb("/tmp");wb("/dev");$a[259]={k:{J:function(){return 0},write:function(){return 0}}};
xb("/dev/null",259);Za(1280,{Pa:function(a){if(!a.input.length){var b=l;if(ba){if(b=process.stdin.read(),!b){if(process.stdin._readableState&&process.stdin._readableState.ended)return l;return}}else"undefined"!=typeof window&&"function"==typeof window.prompt?(b=window.prompt("Input: "),b!==l&&(b+="\n")):"function"==typeof readline&&(b=readline(),b!==l&&(b+="\n"));if(!b)return l;a.input=G(b,j)}return a.input.shift()},Z:function(a,b){b===l||10===b?(p.print(a.H.join("")),a.H=[]):a.H.push(hc.sa(b))}});
Za(1536,{Z:function(a,b){b===l||10===b?(p.printErr(a.H.join("")),a.H=[]):a.H.push(hc.sa(b))}});xb("/dev/tty",1280);xb("/dev/tty1",1536);wb("/dev/shm");wb("/dev/shm/tmp");
Ia.unshift({Q:function(){if(!p.noFSInit&&!Fb){w(!Fb,"FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)");Fb=j;Eb();p.stdin=p.stdin;p.stdout=p.stdout;p.stderr=p.stderr;p.stdin?Y("/dev","stdin",p.stdin):yb("/dev/tty","/dev/stdin");p.stdout?Y("/dev","stdout",l,p.stdout):yb("/dev/tty","/dev/stdout");p.stderr?Y("/dev","stderr",l,p.stderr):yb("/dev/tty1","/dev/stderr");var a=Ab("/dev/stdin",
"r");J[ib>>2]=a?a.q+1:0;w(0===a.q,"invalid handle for stdin ("+a.q+")");a=Ab("/dev/stdout","w");J[jb>>2]=a?a.q+1:0;w(1===a.q,"invalid handle for stdout ("+a.q+")");a=Ab("/dev/stderr","w");J[kb>>2]=a?a.q+1:0;w(2===a.q,"invalid handle for stderr ("+a.q+")")}}});Ja.push({Q:function(){nb=m}});Ka.push({Q:function(){Fb=m;for(var a=0;a<mb.length;a++){var b=mb[a];b&&Db(b)}}});p.FS_createFolder=function(a,b,c,d){a=W(("string"===typeof a?a:X(a))+"/"+b);return wb(a,Gb(c,d))};
p.FS_createPath=function(a,b){for(var a="string"===typeof a?a:X(a),c=b.split("/").reverse();c.length;){var d=c.pop();if(d){var f=W(a+"/"+d);try{wb(f)}catch(g){}a=f}}return f};p.FS_createDataFile=Hb;
p.FS_createPreloadedFile=function(a,b,c,d,f,g,h,x,s){function u(){Lb=document.pointerLockElement===k||document.mozPointerLockElement===k||document.webkitPointerLockElement===k||document.msPointerLockElement===k}function t(c){function t(c){x||Hb(a,b,c,d,f,s);g&&g();Ta()}var k=m;p.preloadPlugins.forEach(function(a){!k&&a.canHandle(y)&&(a.handle(c,y,t,function(){h&&h();Ta()}),k=j)});k||t(c)}p.preloadPlugins||(p.preloadPlugins=[]);if(!Tb&&!da){Tb=j;try{new Blob,Ub=j}catch(A){Ub=m,console.log("warning: no blob constructor, cannot create blobs with mimetypes")}Vb=
"undefined"!=typeof MozBlobBuilder?MozBlobBuilder:"undefined"!=typeof WebKitBlobBuilder?WebKitBlobBuilder:!Ub?console.log("warning: no BlobBuilder"):l;Wb="undefined"!=typeof window?window.URL?window.URL:window.webkitURL:i;!p.Ta&&"undefined"===typeof Wb&&(console.log("warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available."),p.Ta=j);p.preloadPlugins.push({canHandle:function(a){return!p.Ta&&/\.(jpg|jpeg|png|bmp)$/i.test(a)},handle:function(a,b,
c,d){var f=l;if(Ub)try{f=new Blob([a],{type:Pb(b)}),f.size!==a.length&&(f=new Blob([(new Uint8Array(a)).buffer],{type:Pb(b)}))}catch(g){v.S("Blob constructor present but fails: "+g+"; falling back to blob builder")}f||(f=new Vb,f.append((new Uint8Array(a)).buffer),f=f.getBlob());var h=Wb.createObjectURL(f),t=new Image;t.onload=function(){w(t.complete,"Image "+b+" could not be decoded");var d=document.createElement("canvas");d.width=t.width;d.height=t.height;d.getContext("2d").drawImage(t,0,0);p.preloadedImages[b]=
d;Wb.revokeObjectURL(h);c&&c(a)};t.onerror=function(){console.log("Image "+h+" could not be decoded");d&&d()};t.src=h}});p.preloadPlugins.push({canHandle:function(a){return!p.le&&a.substr(-4)in{".ogg":1,".wav":1,".mp3":1}},handle:function(a,b,c,d){function f(d){h||(h=j,p.preloadedAudios[b]=d,c&&c(a))}function g(){h||(h=j,p.preloadedAudios[b]=new Audio,d&&d())}var h=m;if(Ub){try{var t=new Blob([a],{type:Pb(b)})}catch(k){return g()}var t=Wb.createObjectURL(t),s=new Audio;s.addEventListener("canplaythrough",
function(){f(s)},m);s.onerror=function(){if(!h){console.log("warning: browser could not fully decode audio "+b+", trying slower base64 approach");for(var c="",d=0,g=0,t=0;t<a.length;t++){d=d<<8|a[t];for(g+=8;6<=g;)var k=d>>g-6&63,g=g-6,c=c+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[k]}2==g?(c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(d&3)<<4],c+="=="):4==g&&(c+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(d&15)<<2],c+="=");
s.src="data:audio/x-"+b.substr(-3)+";base64,"+c;f(s)}};s.src=t;setTimeout(function(){ka||f(s)},1E4)}else return g()}});var k=p.canvas;k.ua=k.requestPointerLock||k.mozRequestPointerLock||k.webkitRequestPointerLock||k.msRequestPointerLock||n();k.Ka=document.exitPointerLock||document.mozExitPointerLock||document.webkitExitPointerLock||document.msExitPointerLock||n();k.Ka=k.Ka.bind(document);document.addEventListener("pointerlockchange",u,m);document.addEventListener("mozpointerlockchange",u,m);document.addEventListener("webkitpointerlockchange",
u,m);document.addEventListener("mspointerlockchange",u,m);p.elementPointerLock&&k.addEventListener("click",function(a){!Lb&&k.ua&&(k.ua(),a.preventDefault())},m)}var y=b?ob(W(a+"/"+b)):a;Sa();if("string"==typeof c){var E=h,ea=function(){E?E():e('Loading data file "'+c+'" failed.')},K=new XMLHttpRequest;K.open("GET",c,j);K.responseType="arraybuffer";K.onload=function(){if(200==K.status||0==K.status&&K.response){var a=K.response;w(a,'Loading data file "'+c+'" failed (no arrayBuffer).');a=new Uint8Array(a);
t(a);Ta()}else ea()};K.onerror=ea;K.send(l);Sa()}else t(c)};
p.FS_createLazyFile=function(a,b,c,d,f){var g,h;function x(){this.qa=m;this.U=[]}x.prototype.get=function(a){if(!(a>this.length-1||0>a)){var b=a%this.nb;return this.rb(Math.floor(a/this.nb))[b]}};x.prototype.Db=function(a){this.rb=a};x.prototype.Ga=function(){var a=new XMLHttpRequest;a.open("HEAD",c,m);a.send(l);200<=a.status&&300>a.status||304===a.status||e(Error("Couldn't load "+c+". Status: "+a.status));var b=Number(a.getResponseHeader("Content-length")),d,f=1048576;if(!((d=a.getResponseHeader("Accept-Ranges"))&&
"bytes"===d))f=b;var g=this;g.Db(function(a){var d=a*f,h=(a+1)*f-1,h=Math.min(h,b-1);if("undefined"===typeof g.U[a]){var t=g.U;d>h&&e(Error("invalid range ("+d+", "+h+") or no bytes requested!"));h>b-1&&e(Error("only "+b+" bytes available! programmer error!"));var k=new XMLHttpRequest;k.open("GET",c,m);b!==f&&k.setRequestHeader("Range","bytes="+d+"-"+h);"undefined"!=typeof Uint8Array&&(k.responseType="arraybuffer");k.overrideMimeType&&k.overrideMimeType("text/plain; charset=x-user-defined");k.send(l);
200<=k.status&&300>k.status||304===k.status||e(Error("Couldn't load "+c+". Status: "+k.status));d=k.response!==i?new Uint8Array(k.response||[]):G(k.responseText||"",j);t[a]=d}"undefined"===typeof g.U[a]&&e(Error("doXHR failed!"));return g.U[a]});this.kb=b;this.jb=f;this.qa=j};"undefined"!==typeof XMLHttpRequest?(da||e("Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc"),g=new x,Object.defineProperty(g,"length",{get:function(){this.qa||
this.Ga();return this.kb}}),Object.defineProperty(g,"chunkSize",{get:function(){this.qa||this.Ga();return this.jb}}),h=i):(h=c,g=i);var s,a=W(("string"===typeof a?a:X(a))+"/"+b);s=vb(a,Gb(d,f));g?s.n=g:h&&(s.n=l,s.url=h);var u={};Object.keys(s.k).forEach(function(a){var b=s.k[a];u[a]=function(){Ib(s)||e(new T(S.C));return b.apply(l,arguments)}});u.J=function(a,b,c,d,f){Ib(s)||e(new T(S.C));a=a.e.n;if(f>=a.length)return 0;d=Math.min(a.length-f,d);w(0<=d);if(a.slice)for(var g=0;g<d;g++)b[c+g]=a[f+g];
else for(g=0;g<d;g++)b[c+g]=a.get(f+g);return d};s.k=u;return s};p.FS_createLink=function(a,b,c){a=W(("string"===typeof a?a:X(a))+"/"+b);return yb(c,a)};p.FS_createDevice=Y;Wa=v.Ya(4);J[Wa>>2]=0;Ia.unshift({Q:n()});Ka.push({Q:n()});var hc=new v.ga;ba&&(require("fs"),process.platform.match(/^win/));Da=r=v.M(B);Ea=Da+5242880;Fa=C=v.M(Ea);w(Fa<D,"TOTAL_MEMORY not big enough for stack");ra=Math.min;
var $=(function(global,env,buffer) {
// EMSCRIPTEN_START_ASM
"use asm";var a=new global.Int8Array(buffer);var b=new global.Int16Array(buffer);var c=new global.Int32Array(buffer);var d=new global.Uint8Array(buffer);var e=new global.Uint16Array(buffer);var f=new global.Uint32Array(buffer);var g=new global.Float32Array(buffer);var h=new global.Float64Array(buffer);var i=env.STACKTOP|0;var j=env.STACK_MAX|0;var k=env.tempDoublePtr|0;var l=env.ABORT|0;var m=0;var n=0;var o=0;var p=0;var q=+env.NaN,r=+env.Infinity;var s=0,t=0,u=0,v=0,w=0.0,x=0,y=0,z=0,A=0.0;var B=0;var C=0;var D=0;var E=0;var F=0;var G=0;var H=0;var I=0;var J=0;var K=0;var L=global.Math.floor;var M=global.Math.abs;var N=global.Math.sqrt;var O=global.Math.pow;var P=global.Math.cos;var Q=global.Math.sin;var R=global.Math.tan;var S=global.Math.acos;var T=global.Math.asin;var U=global.Math.atan;var V=global.Math.atan2;var W=global.Math.exp;var X=global.Math.log;var Y=global.Math.ceil;var Z=global.Math.imul;var _=env.abort;var $=env.assert;var aa=env.asmPrintInt;var ba=env.asmPrintFloat;var ca=env.min;var da=env._fflush;var ea=env.___setErrNo;var fa=env._malloc;var ga=env._emscripten_memcpy_big;var ha=env._free;var ia=env._llvm_bswap_i32;var ja=0.0;
// EMSCRIPTEN_START_FUNCS
function ka(a){a=a|0;var b=0;b=i;i=i+a|0;i=i+7&-8;return b|0}function la(){return i|0}function ma(a){a=a|0;i=a}function na(a,b){a=a|0;b=b|0;if((m|0)==0){m=a;n=b}}function oa(b){b=b|0;a[k]=a[b];a[k+1|0]=a[b+1|0];a[k+2|0]=a[b+2|0];a[k+3|0]=a[b+3|0]}function pa(b){b=b|0;a[k]=a[b];a[k+1|0]=a[b+1|0];a[k+2|0]=a[b+2|0];a[k+3|0]=a[b+3|0];a[k+4|0]=a[b+4|0];a[k+5|0]=a[b+5|0];a[k+6|0]=a[b+6|0];a[k+7|0]=a[b+7|0]}function qa(a){a=a|0;B=a}function ra(a){a=a|0;C=a}function sa(a){a=a|0;D=a}function ta(a){a=a|0;E=a}function ua(a){a=a|0;F=a}function va(a){a=a|0;G=a}function wa(a){a=a|0;H=a}function xa(a){a=a|0;I=a}function ya(a){a=a|0;J=a}function za(a){a=a|0;K=a}function Aa(e,f,g,h){e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0,u=0,v=0,w=0;j=i;i=i+32|0;o=j;l=j+16|0;n=g+h|0;c[o+0>>2]=0;c[o+4>>2]=0;c[o+8>>2]=0;c[o+12>>2]=0;m=e+f|0;r=a[e]|0;a:do{if(!(r<<24>>24==0)){p=(f|0)!=0;f=m;q=g;b:while(1){if(p&e>>>0>m>>>0){break a}r=a[8+(r&255)|0]|0;b[o>>1]=r<<24>>24;c:do{if(!(r<<24>>24<0)){t=r<<24>>24;r=f-e|0;d:do{if(p){u=1;while(1){if((u|0)>(r|0)){k=13;break d}w=a[8+(d[e+u|0]|0)|0]|0;s=w<<24>>24;if(w<<24>>24<0){k=13;break d}t=a[264+(t<<5)+s|0]|0;if(t<<24>>24<0){k=13;break d}b[o+(u<<1)>>1]=t<<24>>24;u=u+1|0;if((u|0)<8){t=s}else{break}}}else{u=1;while(1){w=a[8+(d[e+u|0]|0)|0]|0;r=w<<24>>24;if(w<<24>>24<0){k=13;break d}s=a[264+(t<<5)+r|0]|0;if(s<<24>>24<0){k=13;break d}b[o+(u<<1)>>1]=s<<24>>24;u=u+1|0;if((u|0)<8){t=r}else{break}}}}while(0);if((k|0)==13){k=0;if((u|0)<2){k=27;break}}s=2;e:while(1){r=c[1296+(s*80|0)>>2]|0;f:do{if(!(r>>>0>u>>>0)){t=0;while(1){v=t+1|0;if((b[o+(t<<1)>>1]|0)>(b[1288+(s*80|0)+(t<<1)+48>>1]|0)){break f}if(v>>>0<r>>>0){t=v}else{break e}}}}while(0);if((s|0)>0){s=s+ -1|0}else{k=27;break c}}if((s|0)>-1){u=c[1292+(s*80|0)>>2]|0;t=q+u|0;if(t>>>0>n>>>0){k=21;break b}w=c[1288+(s*80|0)>>2]|0;c[l>>2]=w;v=0;do{w=w|b[o+(v<<1)>>1]<<c[1288+(s*80|0)+(v<<2)+12>>2];v=v+1|0}while(v>>>0<r>>>0);c[l>>2]=ia(w|0)|0;s=0;do{a[q+s|0]=a[l+s|0]|0;s=s+1|0}while(s>>>0<u>>>0);e=e+r|0;q=t}else{k=27}}else{k=27}}while(0);if((k|0)==27){k=0;r=a[e]|0;if(!(r<<24>>24<0)){if((q+1|0)>>>0>n>>>0){k=32;break}}else{if((q+2|0)>>>0>n>>>0){k=29;break}a[q]=0;r=a[e]|0;q=q+1|0}a[q]=r;e=e+1|0;q=q+1|0}r=a[e]|0;if(r<<24>>24==0){break a}}if((k|0)==21){w=h+1|0;i=j;return w|0}else if((k|0)==29){w=h+1|0;i=j;return w|0}else if((k|0)==32){w=h+1|0;i=j;return w|0}}else{q=g}}while(0);w=q-g|0;i=j;return w|0}function Ba(d,e,f,g){d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0,o=0,p=0,q=0,r=0,s=0,t=0;k=i;i=i+16|0;l=k;j=f+g|0;m=d+e|0;a:do{if((e|0)>0){e=f;while(1){s=a[d]|0;if(s<<24>>24<0){n=s;o=-1;do{n=(n&255)<<1&255;o=o+1|0}while(n<<24>>24<0);if((o|0)>=0){p=c[1296+(o*80|0)>>2]|0;n=e+p|0;if(n>>>0>j>>>0){h=11;break}q=1292+(o*80|0)|0;r=c[q>>2]|0;t=0;while(1){a[l+t|0]=s;t=t+1|0;if(!(t>>>0<r>>>0)){break}s=a[d+t|0]|0}r=ia(c[l>>2]|0)|0;c[l>>2]=r;r=a[1528+(b[1336+(o*80|0)>>1]&r>>>(c[1300+(o*80|0)>>2]|0))|0]|0;a[e]=r;s=1;do{r=a[((c[l>>2]|0)>>>(c[1288+(o*80|0)+(s<<2)+12>>2]|0)&b[1288+(o*80|0)+(s<<1)+48>>1])+(1560+((r&255)+ -39<<4))|0]|0;a[e+s|0]=r;s=s+1|0}while(s>>>0<p>>>0);d=d+(c[q>>2]|0)|0;e=n}else{h=6}}else{h=6}if((h|0)==6){h=0;if(!(e>>>0<j>>>0)){h=7;break}d=s<<24>>24==0?d+1|0:d;a[e]=a[d]|0;d=d+1|0;e=e+1|0}if(!(d>>>0<m>>>0)){break a}}if((h|0)==7){t=g+1|0;i=k;return t|0}else if((h|0)==11){t=g+1|0;i=k;return t|0}}else{e=f}}while(0);if(e>>>0<j>>>0){a[e]=0}t=e-f|0;i=k;return t|0}function Ca(){}function Da(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;f=b+e|0;if((e|0)>=20){d=d&255;i=b&3;h=d|d<<8|d<<16|d<<24;g=f&~3;if(i){i=b+4-i|0;while((b|0)<(i|0)){a[b]=d;b=b+1|0}}while((b|0)<(g|0)){c[b>>2]=h;b=b+4|0}}while((b|0)<(f|0)){a[b]=d;b=b+1|0}return b-e|0}function Ea(b){b=b|0;var c=0;c=b;while(a[c]|0){c=c+1|0}return c-b|0}function Fa(b,d,e){b=b|0;d=d|0;e=e|0;var f=0;if((e|0)>=4096)return ga(b|0,d|0,e|0)|0;f=b|0;if((b&3)==(d&3)){while(b&3){if((e|0)==0)return f|0;a[b]=a[d]|0;b=b+1|0;d=d+1|0;e=e-1|0}while((e|0)>=4){c[b>>2]=c[d>>2];b=b+4|0;d=d+4|0;e=e-4|0}}while((e|0)>0){a[b]=a[d]|0;b=b+1|0;d=d+1|0;e=e-1|0}return f|0}




// EMSCRIPTEN_END_FUNCS
return{_shoco_decompress:Ba,_memcpy:Fa,_strlen:Ea,_shoco_compress:Aa,_memset:Da,runPostSets:Ca,stackAlloc:ka,stackSave:la,stackRestore:ma,setThrew:na,setTempRet0:qa,setTempRet1:ra,setTempRet2:sa,setTempRet3:ta,setTempRet4:ua,setTempRet5:va,setTempRet6:wa,setTempRet7:xa,setTempRet8:ya,setTempRet9:za}
// EMSCRIPTEN_END_ASM

})({Math:Math,Int8Array:Int8Array,Int16Array:Int16Array,Int32Array:Int32Array,Uint8Array:Uint8Array,Uint16Array:Uint16Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array},{abort:z,assert:w,asmPrintInt:function(a,b){p.print("int "+a+","+b)},asmPrintFloat:function(a,b){p.print("float "+a+","+b)},min:ra,_fflush:n(),___setErrNo:Xa,_malloc:xa,_emscripten_memcpy_big:function(a,b,c){N.set(N.subarray(b,b+c),a);return a},_free:$b,_llvm_bswap_i32:function(a){return(a&
255)<<24|(a>>8&255)<<16|(a>>16&255)<<8|a>>>24},STACKTOP:r,STACK_MAX:Ea,tempDoublePtr:Ua,ABORT:ka,NaN:NaN,Infinity:Infinity},P);p._shoco_decompress=$._shoco_decompress;var Zb=p._memcpy=$._memcpy,Yb=p._strlen=$._strlen;p._shoco_compress=$._shoco_compress;var Xb=p._memset=$._memset;p.runPostSets=$.runPostSets;v.wa=function(a){return $.stackAlloc(a)};v.Xa=function(){return $.stackSave()};v.Wa=function(a){$.stackRestore(a)};
function ic(a){this.name="ExitStatus";this.message="Program terminated with exit("+a+")";this.status=a}ic.prototype=Error();var jc,kc=l,Ra=function lc(){!p.calledRun&&mc&&nc();p.calledRun||(Ra=lc)};
p.callMain=p.Rd=function(a){function b(){for(var a=0;3>a;a++)d.push(0)}w(0==R,"cannot call main when async dependencies remain! (listen on __ATMAIN__)");w(0==Ha.length,"cannot call main when preRun functions remain to be called");a=a||[];Ma||(Ma=j,Q(Ia));var c=a.length+1,d=[M(G("/bin/this.program"),"i8",0)];b();for(var f=0;f<c-1;f+=1)d.push(M(G(a[f]),"i8",0)),b();d.push(0);d=M(d,"i32",0);jc=r;try{var g=p._main(c,d,0);p.noExitRuntime||oc(g)}catch(h){h instanceof ic||("SimulateInfiniteLoop"==h?p.noExitRuntime=
j:(h&&("object"===typeof h&&h.stack)&&p.I("exception thrown: "+[h,h.stack]),e(h)))}finally{}};
function nc(a){function b(){if(!p.calledRun){p.calledRun=j;Ma||(Ma=j,Q(Ia));Q(Ja);ca&&kc!==l&&p.I("pre-main prep time: "+(Date.now()-kc)+" ms");p._main&&mc&&p.callMain(a);if(p.postRun)for("function"==typeof p.postRun&&(p.postRun=[p.postRun]);p.postRun.length;)Pa(p.postRun.shift());Q(La)}}a=a||p.arguments;kc===l&&(kc=Date.now());if(0<R)p.I("run() called, but dependencies remain, so not running");else{if(p.preRun)for("function"==typeof p.preRun&&(p.preRun=[p.preRun]);p.preRun.length;)Na(p.preRun.shift());
Q(Ha);!(0<R)&&!p.calledRun&&(p.setStatus?(p.setStatus("Running..."),setTimeout(function(){setTimeout(function(){p.setStatus("")},1);ka||b()},1)):b())}}p.run=p.re=nc;function oc(a){ka=j;r=jc;Q(Ka);e(new ic(a))}p.exit=p.Vd=oc;function z(a){a&&(p.print(a),p.I(a));ka=j;e("abort() at "+za()+"\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.")}p.abort=p.abort=z;if(p.preInit)for("function"==typeof p.preInit&&(p.preInit=[p.preInit]);0<p.preInit.length;)p.preInit.pop()();
var mc=j;p.noInitialRun&&(mc=m);nc();



================================================
FILE: shoco_model.h
================================================
#ifndef _SHOCO_INTERNAL
#error This header file is only to be included by 'shoco.c'.
#endif
#pragma once
/*
This file was generated by 'generate_compressor_model.py'
so don't edit this by hand. Also, do not include this file
anywhere. It is internal to 'shoco.c'. Include 'shoco.h'
if you want to use shoco in your project.
*/

#define MIN_CHR 39
#define MAX_CHR 122

static const char chrs_by_chr_id[32] = {
  'e', 'a', 'i', 'o', 't', 'h', 'n', 'r', 's', 'l', 'u', 'c', 'w', 'm', 'd', 'b', 'p', 'f', 'g', 'v', 'y', 'k', '-', 'H', 'M', 'T', '\'', 'B', 'x', 'I', 'W', 'L'
};

static const int8_t chr_ids_by_chr[256] = {
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, 23, 29, -1, -1, 31, 24, -1, -1, -1, -1, -1, -1, 25, -1, -1, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 15, 11, 14, 0, 17, 18, 5, 2, -1, 21, 9, 13, 6, 3, 16, -1, 7, 8, 4, 10, 19, 12, 28, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};

static const int8_t successor_ids_by_chr_id_and_chr_id[32][32] = {
  {7, 4, 12, -1, 6, -1, 1, 0, 3, 5, -1, 9, -1, 8, 2, -1, 15, 14, -1, 10, 11, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, -1},
  {-1, -1, 6, -1, 1, -1, 0, 3, 2, 4, 15, 11, -1, 9, 5, 10, 13, -1, 12, 8, 7, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {9, 11, -1, 4, 2, -1, 0, 8, 1, 5, -1, 6, -1, 3, 7, 15, -1, 12, 10, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {-1, -1, 14, 7, 5, -1, 1, 2, 8, 9, 0, 15, 6, 4, 11, -1, 12, 3, -1, 10, -1, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {2, 4, 3, 1, 5, 0, -1, 6, 10, 9, 7, 12, 11, -1, -1, -1, -1, 13, -1, -1, 8, -1, 15, -1, -1, -1, 14, -1, -1, -1, -1, -1},
  {0, 1, 2, 3, 4, -1, -1, 5, 9, 10, 6, -1, -1, 8, 15, 11, -1, 14, -1, -1, 7, -1, 13, -1, -1, -1, 12, -1, -1, -1, -1, -1},
  {2, 8, 7, 4, 3, -1, 9, -1, 6, 11, -1, 5, -1, -1, 0, -1, -1, 14, 1, 15, 10, 12, -1, -1, -1, -1, 13, -1, -1, -1, -1, -1},
  {0, 3, 1, 2, 6, -1, 9, 8, 4, 12, 13, 10, -1, 11, 7, -1, -1, 15, 14, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, 6, 3, 4, 1, 2, -1, -1, 5, 10, 7, 9, 11, 12, -1, -1, 8, 14, -1, -1, 15, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, 6, 2, 5, 9, -1, -1, -1, 10, 1, 8, -1, 12, 14, 4, -1, 15, 7, -1, 13, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {8, 10, 9, 15, 1, -1, 4, 0, 3, 2, -1, 6, -1, 12, 11, 13, 7, 14, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {1, 3, 6, 0, 4, 2, -1, 7, 13, 8, 9, 11, -1, -1, 15, -1, -1, -1, -1, -1, 10, 5, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {3, 0, 1, 4, -1, 2, 5, 6, 7, 8, -1, 14, -1, -1, 9, 15, -1, 12, -1, -1, -1, 10, 11, -1, -1, -1, 13, -1, -1, -1, -1, -1},
  {0, 1, 3, 2, 15, -1, 12, -1, 7, 14, 4, -1, -1, 9, -1, 8, 5, 10, -1, -1, 6, -1, 13, -1, -1, -1, 11, -1, -1, -1, -1, -1},
  {0, 3, 1, 2, -1, -1, 12, 6, 4, 9, 7, -1, -1, 14, 8, -1, -1, 15, 11, 13, 5, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, 5, 7, 2, 10, 13, -1, 6, 8, 1, 3, -1, -1, 14, 15, 11, -1, -1, -1, 12, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, 2, 6, 3, 7, 10, -1, 1, 9, 4, 8, -1, -1, 15, -1, 12, 5, -1, -1, -1, 11, -1, 13, -1, -1, -1, 14, -1, -1, -1, -1, -1},
  {1, 3, 4, 0, 7, -1, 12, 2, 11, 8, 6, 13, -1, -1, -1, -1, -1, 5, -1, -1, 10, 15, 9, -1, -1, -1, 14, -1, -1, -1, -1, -1},
  {1, 3, 5, 2, 13, 0, 9, 4, 7, 6, 8, -1, -1, 15, -1, 11, -1, -1, 10, -1, 14, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, 2, 1, 3, -1, -1, -1, 6, -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {1, 11, 4, 0, 3, -1, 13, 12, 2, 7, -1, -1, 15, 10, 5, 8, 14, -1, -1, -1, -1, -1, 9, -1, -1, -1, 6, -1, -1, -1, -1, -1},
  {0, 9, 2, 14, 15, 4, 1, 13, 3, 5, -1, -1, 10, -1, -1, -1, -1, 6, 12, -1, 7, -1, 8, -1, -1, -1, 11, -1, -1, -1, -1, -1},
  {-1, 2, 14, -1, 1, 5, 8, 7, 4, 12, -1, 6, 9, 11, 13, 3, 10, 15, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, 1, 3, 2, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {4, 3, 1, 5, -1, -1, -1, 0, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {2, 8, 4, 1, -1, 0, -1, 6, -1, -1, 5, -1, 7, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, 9, -1, -1, -1, -1, -1, -1, -1, -1},
  {12, 5, -1, -1, 1, -1, -1, 7, 0, 3, -1, 2, -1, 4, 6, -1, -1, -1, -1, 8, -1, -1, 15, -1, 13, 9, -1, -1, -1, -1, -1, 11},
  {1, 3, 2, 4, -1, -1, -1, 5, -1, 7, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1},
  {5, 3, 4, 12, 1, 6, -1, -1, -1, -1, 8, 2, -1, -1, -1, -1, 0, 9, -1, -1, 11, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {-1, -1, -1, -1, 0, -1, 1, 12, 3, -1, -1, -1, -1, 5, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, 6, -1, 10},
  {2, 3, 1, 4, -1, 0, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1},
  {5, 1, 3, 0, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, 9, -1, -1, 6, -1, 7}
};

static const int8_t chrs_by_chr_and_successor_id[MAX_CHR - MIN_CHR][16] = {
  {'s', 't', 'c', 'l', 'm', 'a', 'd', 'r', 'v', 'T', 'A', 'L', 'e', 'M', 'Y', '-'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'-', 't', 'a', 'b', 's', 'h', 'c', 'r', 'n', 'w', 'p', 'm', 'l', 'd', 'i', 'f'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'u', 'e', 'i', 'a', 'o', 'r', 'y', 'l', 'I', 'E', 'R', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'e', 'a', 'o', 'i', 'u', 'A', 'y', 'E', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'t', 'n', 'f', 's', '\'', 'm', 'I', 'N', 'A', 'E', 'L', 'Z', 'r', 'V', 'R', 'C'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'o', 'a', 'y', 'i', 'u', 'e', 'I', 'L', 'D', '\'', 'E', 'Y', '\x00', '\x00', '\x00', '\x00'},
  {'r', 'i', 'y', 'a', 'e', 'o', 'u', 'Y', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'h', 'o', 'e', 'E', 'i', 'u', 'r', 'w', 'a', 'H', 'y', 'R', 'Z', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'h', 'i', 'e', 'a', 'o', 'r', 'I', 'y', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'n', 't', 's', 'r', 'l', 'd', 'i', 'y', 'v', 'm', 'b', 'c', 'g', 'p', 'k', 'u'},
  {'e', 'l', 'o', 'u', 'y', 'a', 'r', 'i', 's', 'j', 't', 'b', 'v', 'h', 'm', 'd'},
  {'o', 'e', 'h', 'a', 't', 'k', 'i', 'r', 'l', 'u', 'y', 'c', 'q', 's', '-', 'd'},
  {'e', 'i', 'o', 'a', 's', 'y', 'r', 'u', 'd', 'l', '-', 'g', 'n', 'v', 'm', 'f'},
  {'r', 'n', 'd', 's', 'a', 'l', 't', 'e', 'm', 'c', 'v', 'y', 'i', 'x', 'f', 'p'},
  {'o', 'e', 'r', 'a', 'i', 'f', 'u', 't', 'l', '-', 'y', 's', 'n', 'c', '\'', 'k'},
  {'h', 'e', 'o', 'a', 'r', 'i', 'l', 's', 'u', 'n', 'g', 'b', '-', 't', 'y', 'm'},
  {'e', 'a', 'i', 'o', 't', 'r', 'u', 'y', 'm', 's', 'l', 'b', '\'', '-', 'f', 'd'},
  {'n', 's', 't', 'm', 'o', 'l', 'c', 'd', 'r', 'e', 'g', 'a', 'f', 'v', 'z', 'b'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'e', 'n', 'i', 's', 'h', 'l', 'f', 'y', '-', 'a', 'w', '\'', 'g', 'r', 'o', 't'},
  {'e', 'l', 'i', 'y', 'd', 'o', 'a', 'f', 'u', 't', 's', 'k', 'w', 'v', 'm', 'p'},
  {'e', 'a', 'o', 'i', 'u', 'p', 'y', 's', 'b', 'm', 'f', '\'', 'n', '-', 'l', 't'},
  {'d', 'g', 'e', 't', 'o', 'c', 's', 'i', 'a', 'n', 'y', 'l', 'k', '\'', 'f', 'v'},
  {'u', 'n', 'r', 'f', 'm', 't', 'w', 'o', 's', 'l', 'v', 'd', 'p', 'k', 'i', 'c'},
  {'e', 'r', 'a', 'o', 'l', 'p', 'i', 't', 'u', 's', 'h', 'y', 'b', '-', '\'', 'm'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'e', 'i', 'o', 'a', 's', 'y', 't', 'd', 'r', 'n', 'c', 'm', 'l', 'u', 'g', 'f'},
  {'e', 't', 'h', 'i', 'o', 's', 'a', 'u', 'p', 'c', 'l', 'w', 'm', 'k', 'f', 'y'},
  {'h', 'o', 'e', 'i', 'a', 't', 'r', 'u', 'y', 'l', 's', 'w', 'c', 'f', '\'', '-'},
  {'r', 't', 'l', 's', 'n', 'g', 'c', 'p', 'e', 'i', 'a', 'd', 'm', 'b', 'f', 'o'},
  {'e', 'i', 'a', 'o', 'y', 'u', 'r', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'a', 'i', 'h', 'e', 'o', 'n', 'r', 's', 'l', 'd', 'k', '-', 'f', '\'', 'c', 'b'},
  {'p', 't', 'c', 'a', 'i', 'e', 'h', 'q', 'u', 'f', '-', 'y', 'o', '\x00', '\x00', '\x00'},
  {'o', 'e', 's', 't', 'i', 'd', '\'', 'l', 'b', '-', 'm', 'a', 'r', 'n', 'p', 'w'}
};


typedef struct Pack {
  const uint32_t word;
  const unsigned int bytes_packed;
  const unsigned int bytes_unpacked;
  const unsigned int offsets[8];
  const int16_t _ALIGNED masks[8];
  const char header_mask;
  const char header;
} Pack;

#define PACK_COUNT 3
#define MAX_SUCCESSOR_N 7

static const Pack packs[PACK_COUNT] = {
  { 0x80000000, 1, 2, { 26, 24, 24, 24, 24, 24, 24, 24 }, { 15, 3, 0, 0, 0, 0, 0, 0 }, 0xc0, 0x80 },
  { 0xc0000000, 2, 4, { 25, 22, 19, 16, 16, 16, 16, 16 }, { 15, 7, 7, 7, 0, 0, 0, 0 }, 0xe0, 0xc0 },
  { 0xe0000000, 4, 8, { 23, 19, 15, 11, 8, 5, 2, 0 }, { 31, 15, 15, 15, 7, 7, 7, 3 }, 0xf0, 0xe0 }
};


================================================
FILE: shoco_table.h
================================================
#ifndef _SHOCO_INTERNAL
#error This header file is only to be included by 'shoco.c'.
#endif
#pragma once
/*
This file was generated by 'generate_successor_table.py',
so don't edit this by hand. Also, do not include this file
anywhere. It is internal to 'shoco.c'. Include 'shoco.h'
if you want to use shoco in your project.
*/

#define MIN_CHR 39
#define MAX_CHR 122

static const char chrs_by_chr_id[32] = {
  'e', 'a', 'i', 'o', 't', 'h', 'n', 'r', 's', 'l', 'u', 'c', 'w', 'm', 'd', 'b', 'p', 'f', 'g', 'v', 'y', 'k', '-', 'H', 'M', 'T', '\'', 'B', 'x', 'I', 'W', 'L'
};

static const int8_t chr_ids_by_chr[256] = {
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, 23, 29, -1, -1, 31, 24, -1, -1, -1, -1, -1, -1, 25, -1, -1, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 15, 11, 14, 0, 17, 18, 5, 2, -1, 21, 9, 13, 6, 3, 16, -1, 7, 8, 4, 10, 19, 12, 28, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};

static const int8_t successor_ids_by_chr_id_and_chr_id[32][32] = {
  {7, 4, 12, -1, 6, -1, 1, 0, 3, 5, -1, 9, -1, 8, 2, -1, 15, 14, -1, 10, 11, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, -1},
  {-1, -1, 6, -1, 1, -1, 0, 3, 2, 4, 15, 11, -1, 9, 5, 10, 13, -1, 12, 8, 7, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {9, 11, -1, 4, 2, -1, 0, 8, 1, 5, -1, 6, -1, 3, 7, 15, -1, 12, 10, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {-1, -1, 14, 7, 5, -1, 1, 2, 8, 9, 0, 15, 6, 4, 11, -1, 12, 3, -1, 10, -1, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {2, 4, 3, 1, 5, 0, -1, 6, 10, 9, 7, 12, 11, -1, -1, -1, -1, 13, -1, -1, 8, -1, 15, -1, -1, -1, 14, -1, -1, -1, -1, -1},
  {0, 1, 2, 3, 4, -1, -1, 5, 9, 10, 6, -1, -1, 8, 15, 11, -1, 14, -1, -1, 7, -1, 13, -1, -1, -1, 12, -1, -1, -1, -1, -1},
  {2, 8, 7, 4, 3, -1, 9, -1, 6, 11, -1, 5, -1, -1, 0, -1, -1, 14, 1, 15, 10, 12, -1, -1, -1, -1, 13, -1, -1, -1, -1, -1},
  {0, 3, 1, 2, 6, -1, 9, 8, 4, 12, 13, 10, -1, 11, 7, -1, -1, 15, 14, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, 6, 3, 4, 1, 2, -1, -1, 5, 10, 7, 9, 11, 12, -1, -1, 8, 14, -1, -1, 15, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, 6, 2, 5, 9, -1, -1, -1, 10, 1, 8, -1, 12, 14, 4, -1, 15, 7, -1, 13, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {8, 10, 9, 15, 1, -1, 4, 0, 3, 2, -1, 6, -1, 12, 11, 13, 7, 14, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {1, 3, 6, 0, 4, 2, -1, 7, 13, 8, 9, 11, -1, -1, 15, -1, -1, -1, -1, -1, 10, 5, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {3, 0, 1, 4, -1, 2, 5, 6, 7, 8, -1, 14, -1, -1, 9, 15, -1, 12, -1, -1, -1, 10, 11, -1, -1, -1, 13, -1, -1, -1, -1, -1},
  {0, 1, 3, 2, 15, -1, 12, -1, 7, 14, 4, -1, -1, 9, -1, 8, 5, 10, -1, -1, 6, -1, 13, -1, -1, -1, 11, -1, -1, -1, -1, -1},
  {0, 3, 1, 2, -1, -1, 12, 6, 4, 9, 7, -1, -1, 14, 8, -1, -1, 15, 11, 13, 5, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, 5, 7, 2, 10, 13, -1, 6, 8, 1, 3, -1, -1, 14, 15, 11, -1, -1, -1, 12, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, 2, 6, 3, 7, 10, -1, 1, 9, 4, 8, -1, -1, 15, -1, 12, 5, -1, -1, -1, 11, -1, 13, -1, -1, -1, 14, -1, -1, -1, -1, -1},
  {1, 3, 4, 0, 7, -1, 12, 2, 11, 8, 6, 13, -1, -1, -1, -1, -1, 5, -1, -1, 10, 15, 9, -1, -1, -1, 14, -1, -1, -1, -1, -1},
  {1, 3, 5, 2, 13, 0, 9, 4, 7, 6, 8, -1, -1, 15, -1, 11, -1, -1, 10, -1, 14, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, 2, 1, 3, -1, -1, -1, 6, -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {1, 11, 4, 0, 3, -1, 13, 12, 2, 7, -1, -1, 15, 10, 5, 8, 14, -1, -1, -1, -1, -1, 9, -1, -1, -1, 6, -1, -1, -1, -1, -1},
  {0, 9, 2, 14, 15, 4, 1, 13, 3, 5, -1, -1, 10, -1, -1, -1, -1, 6, 12, -1, 7, -1, 8, -1, -1, -1, 11, -1, -1, -1, -1, -1},
  {-1, 2, 14, -1, 1, 5, 8, 7, 4, 12, -1, 6, 9, 11, 13, 3, 10, 15, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {0, 1, 3, 2, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {4, 3, 1, 5, -1, -1, -1, 0, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {2, 8, 4, 1, -1, 0, -1, 6, -1, -1, 5, -1, 7, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, 9, -1, -1, -1, -1, -1, -1, -1, -1},
  {12, 5, -1, -1, 1, -1, -1, 7, 0, 3, -1, 2, -1, 4, 6, -1, -1, -1, -1, 8, -1, -1, 15, -1, 13, 9, -1, -1, -1, -1, -1, 11},
  {1, 3, 2, 4, -1, -1, -1, 5, -1, 7, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1},
  {5, 3, 4, 12, 1, 6, -1, -1, -1, -1, 8, 2, -1, -1, -1, -1, 0, 9, -1, -1, 11, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1},
  {-1, -1, -1, -1, 0, -1, 1, 12, 3, -1, -1, -1, -1, 5, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, 6, -1, 10},
  {2, 3, 1, 4, -1, 0, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1},
  {5, 1, 3, 0, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, 9, -1, -1, 6, -1, 7}
};

static const int8_t chrs_by_chr_and_successor_id[MAX_CHR - MIN_CHR][16] = {
  {'s', 't', 'c', 'l', 'm', 'a', 'd', 'r', 'v', 'T', 'A', 'L', 'e', 'M', 'Y', '-'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'-', 't', 'a', 'b', 's', 'h', 'c', 'r', 'n', 'w', 'p', 'm', 'l', 'd', 'i', 'f'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'u', 'e', 'i', 'a', 'o', 'r', 'y', 'l', 'I', 'E', 'R', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'e', 'a', 'o', 'i', 'u', 'A', 'y', 'E', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'t', 'n', 'f', 's', '\'', 'm', 'I', 'N', 'A', 'E', 'L', 'Z', 'r', 'V', 'R', 'C'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'o', 'a', 'y', 'i', 'u', 'e', 'I', 'L', 'D', '\'', 'E', 'Y', '\x00', '\x00', '\x00', '\x00'},
  {'r', 'i', 'y', 'a', 'e', 'o', 'u', 'Y', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'h', 'o', 'e', 'E', 'i', 'u', 'r', 'w', 'a', 'H', 'y', 'R', 'Z', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'h', 'i', 'e', 'a', 'o', 'r', 'I', 'y', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'n', 't', 's', 'r', 'l', 'd', 'i', 'y', 'v', 'm', 'b', 'c', 'g', 'p', 'k', 'u'},
  {'e', 'l', 'o', 'u', 'y', 'a', 'r', 'i', 's', 'j', 't', 'b', 'v', 'h', 'm', 'd'},
  {'o', 'e', 'h', 'a', 't', 'k', 'i', 'r', 'l', 'u', 'y', 'c', 'q', 's', '-', 'd'},
  {'e', 'i', 'o', 'a', 's', 'y', 'r', 'u', 'd', 'l', '-', 'g', 'n', 'v', 'm', 'f'},
  {'r', 'n', 'd', 's', 'a', 'l', 't', 'e', 'm', 'c', 'v', 'y', 'i', 'x', 'f', 'p'},
  {'o', 'e', 'r', 'a', 'i', 'f', 'u', 't', 'l', '-', 'y', 's', 'n', 'c', '\'', 'k'},
  {'h', 'e', 'o', 'a', 'r', 'i', 'l', 's', 'u', 'n', 'g', 'b', '-', 't', 'y', 'm'},
  {'e', 'a', 'i', 'o', 't', 'r', 'u', 'y', 'm', 's', 'l', 'b', '\'', '-', 'f', 'd'},
  {'n', 's', 't', 'm', 'o', 'l', 'c', 'd', 'r', 'e', 'g', 'a', 'f', 'v', 'z', 'b'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'e', 'n', 'i', 's', 'h', 'l', 'f', 'y', '-', 'a', 'w', '\'', 'g', 'r', 'o', 't'},
  {'e', 'l', 'i', 'y', 'd', 'o', 'a', 'f', 'u', 't', 's', 'k', 'w', 'v', 'm', 'p'},
  {'e', 'a', 'o', 'i', 'u', 'p', 'y', 's', 'b', 'm', 'f', '\'', 'n', '-', 'l', 't'},
  {'d', 'g', 'e', 't', 'o', 'c', 's', 'i', 'a', 'n', 'y', 'l', 'k', '\'', 'f', 'v'},
  {'u', 'n', 'r', 'f', 'm', 't', 'w', 'o', 's', 'l', 'v', 'd', 'p', 'k', 'i', 'c'},
  {'e', 'r', 'a', 'o', 'l', 'p', 'i', 't', 'u', 's', 'h', 'y', 'b', '-', '\'', 'm'},
  {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'e', 'i', 'o', 'a', 's', 'y', 't', 'd', 'r', 'n', 'c', 'm', 'l', 'u', 'g', 'f'},
  {'e', 't', 'h', 'i', 'o', 's', 'a', 'u', 'p', 'c', 'l', 'w', 'm', 'k', 'f', 'y'},
  {'h', 'o', 'e', 'i', 'a', 't', 'r', 'u', 'y', 'l', 's', 'w', 'c', 'f', '\'', '-'},
  {'r', 't', 'l', 's', 'n', 'g', 'c', 'p', 'e', 'i', 'a', 'd', 'm', 'b', 'f', 'o'},
  {'e', 'i', 'a', 'o', 'y', 'u', 'r', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'},
  {'a', 'i', 'h', 'e', 'o', 'n', 'r', 's', 'l', 'd', 'k', '-', 'f', '\'', 'c', 'b'},
  {'p', 't', 'c', 'a', 'i', 'e', 'h', 'q', 'u', 'f', '-', 'y', 'o', '\x00', '\x00', '\x00'},
  {'o', 'e', 's', 't', 'i', 'd', '\'', 'l', 'b', '-', 'm', 'a', 'r', 'n', 'p', 'w'}
};


typedef struct Pack {
  const uint32_t word;
  const unsigned int bytes_packed;
  const unsigned int bytes_unpacked;
  const unsigned int offsets[8];
  const int16_t _ALIGNED masks[8];
  const char header_mask;
  const char header;
} Pack;

#define PACK_COUNT 3
#define MAX_SUCCESSOR_N 7

static const Pack packs[PACK_COUNT] = {
  { 0x80000000, 1, 2, { 26, 24, 24, 24, 24, 24, 24, 24 }, { 15, 3, 0, 0, 0, 0, 0, 0 }, 0xc0, 0x80 },
  { 0xc0000000, 2, 4, { 25, 22, 19, 16, 16, 16, 16, 16 }, { 15, 7, 7, 7, 0, 0, 0, 0 }, 0xe0, 0xc0 },
  { 0xe0000000, 4, 8, { 23, 19, 15, 11, 8, 5, 2, 0 }, { 31, 15, 15, 15, 7, 7, 7, 3 }, 0xf0, 0xe0 }
};


================================================
FILE: test_input.c
================================================
#include <stdio.h>
#include <string.h>
#include <assert.h>

#include "shoco.h"

#define BUFFER_SIZE 1024

static double ratio(int original, int compressed) {
  return ((double)(original - compressed) / (double)original);
}

static int percent(double ratio) {
  return ratio * 100;
}

static void print(char *in, double ratio) {
  printf("'%s' (%d%%)\n", in, percent(ratio));
}

int main(int argc, char ** argv) {
  char buffer[BUFFER_SIZE] = { 0 };
  char comp[BUFFER_SIZE] = { 0 };
  char out[BUFFER_SIZE] = { 0 };
  int count = 0;
  double ratios = 0;
  double rat = 0;
  int inlen, complen, outlen;

  while (fgets(buffer, BUFFER_SIZE, stdin) != NULL) {
    char *end = strchr(buffer, '\n');
    if (end != NULL)
      *end = '\0';
    else
      break;

    inlen = strlen(buffer);
    complen = shoco_compress(buffer, 0, comp, BUFFER_SIZE);
    outlen = shoco_decompress(comp, complen, out, BUFFER_SIZE);
    rat = ratio(inlen, complen);
    if (complen != 0) {
      ++count;
      ratios += rat;
    }
    if ((argc > 1) && ((strcmp(argv[1], "-v") == 0) || (strcmp(argv[1], "--verbose") == 0))) {
      print(buffer, rat);
    }
    assert(inlen == outlen);
    assert(strcmp(buffer, out) == 0);
  }
  printf("Number of compressed strings: %d, average compression ratio: %d%%\n", count, percent(ratios / count));
  return 0;
}


================================================
FILE: tests.c
================================================
#include "stdint.h"
#include "stdio.h"
#include "assert.h"
#include "string.h"

#include "shoco.h"

static const char LARGE_STR[] = "This is a large string that won't possibly fit into a small buffer";
static const char NON_ASCII_STR[] = "Übergrößenträger";

int main() {
  char buf_1[1];
  char buf_2[2];
  char buf_4[4];
  char buf_large[4096];
  size_t ret;

  // test compression
  ret = shoco_compress(LARGE_STR, 0, buf_2, 2);
  assert(ret == 3); // bufsize + 1 if buffer too small

  ret = shoco_compress(LARGE_STR, 0, buf_large, 4096);
  assert(ret <= strlen(LARGE_STR));

  ret = shoco_compress("a", 0, buf_1, 1);
  assert(ret == 1); // bufsize if null byte didn't fit

  buf_2[1] = 'x';
  ret = shoco_compress("a", 0, buf_2, 2);
  assert(ret == 1); // compressed string length without null byte
  assert(buf_2[1] == 'x'); // Canary is still alive

  ret = shoco_compress("a", 0, buf_4, 4);
  assert(ret == 1);

  ret = shoco_compress("test", 0, buf_4, 4);
  assert(ret <= 4);

  buf_4[1] = 'x';
  ret = shoco_compress("test", 1, buf_4, 4); // buffer large enough, but strlen said "just compress first char"
  assert(ret == 1);
  assert(buf_4[1] == 'x');

  ret = shoco_compress("t\x80", 1, buf_4, 4);
  assert(ret == 1);
  assert(buf_4[1] == 'x');

  buf_4[1] = 'y';
  ret = shoco_compress("test", 1, buf_4, 1);
  assert(ret == 1);
  assert(buf_4[1] == 'y'); // no null byte written

  buf_4[1] = 'z';
  ret = shoco_compress("a", 1, buf_4, 4);
  assert(ret == 1);
  assert(buf_4[1] == 'z');

  buf_4[1] = 'b';
  ret = shoco_compress("a", 2, buf_4, 4);
  assert(ret == 1);
  assert(buf_4[1] == 'b');

  ret = shoco_compress("ä", 0, buf_1, 1); // this assumes that 'ä' is not in the frequent chars table
  assert(ret == 2);

  
  //test decompression
  char compressed_large[4096];
  int large_len = strlen(LARGE_STR);
  int comp_len;
  comp_len = shoco_compress(LARGE_STR, 0, compressed_large, 4096);

  buf_large[large_len] = 'x';
  ret = shoco_decompress(compressed_large, comp_len, buf_large, 4096);
  assert(ret == large_len);
  assert(strcmp(buf_large, LARGE_STR) == 0);
  assert(buf_large[large_len] == '\0'); // null byte written
  
  ret = shoco_decompress(compressed_large, comp_len, buf_2, 2);
  assert(ret == 3); // ret = bufsize + 1, because buffer too small

  buf_large[large_len] = 'x';
  ret = shoco_decompress(compressed_large, comp_len, buf_large, large_len);
  assert(ret == large_len);
  assert(buf_large[large_len] != '\0'); // no null byte written

  ret = shoco_decompress(compressed_large, 5, buf_large, 4096);
  assert((ret < large_len) || (ret == 4097)); // either fail (bufsize + 1) or it happened to work


  char compressed_non_ascii[256];
  int non_ascii_len = strlen(NON_ASCII_STR);
  comp_len = shoco_compress(NON_ASCII_STR, 0, compressed_non_ascii, 256);

  buf_large[non_ascii_len] = 'x';
  ret = shoco_decompress(compressed_non_ascii, comp_len, buf_large, 4096);
  assert(ret == non_ascii_len);
  assert(strcmp(buf_large, NON_ASCII_STR) == 0);
  assert(buf_large[non_ascii_len] == '\0'); // null byte written

  ret = shoco_decompress("\x00", 1, buf_large, 4096);
  assert(ret == SIZE_MAX);

  ret = shoco_decompress("\xe0""ab", 3, buf_large, 4096);
  assert(ret == SIZE_MAX);

  puts("All tests passed.");
  return 0;
}


================================================
FILE: training_data/dorian_gray.txt
================================================
The Picture of Dorian Gray

by

Oscar Wilde




THE PREFACE

The artist is the creator of beautiful things.  To reveal art and
conceal the artist is art's aim.  The critic is he who can translate
into another manner or a new material his impression of beautiful
things.

The highest as the lowest form of criticism is a mode of autobiography.
Those who find ugly meanings in beautiful things are corrupt without
being charming.  This is a fault.

Those who find beautiful meanings in beautiful things are the
cultivated.  For these there is hope.  They are the elect to whom
beautiful things mean only beauty.

There is no such thing as a moral or an immoral book.  Books are well
written, or badly written.  That is all.

The nineteenth century dislike of realism is the rage of Caliban seeing
his own face in a glass.

The nineteenth century dislike of romanticism is the rage of Caliban
not seeing his own face in a glass.  The moral life of man forms part
of the subject-matter of the artist, but the morality of art consists
in the perfect use of an imperfect medium.  No artist desires to prove
anything.  Even things that are true can be proved.  No artist has
ethical sympathies.  An ethical sympathy in an artist is an
unpardonable mannerism of style.  No artist is ever morbid.  The artist
can express everything.  Thought and language are to the artist
instruments of an art.  Vice and virtue are to the artist materials for
an art.  From the point of view of form, the type of all the arts is
the art of the musician.  From the point of view of feeling, the
actor's craft is the type.  All art is at once surface and symbol.
Those who go beneath the surface do so at their peril.  Those who read
the symbol do so at their peril.  It is the spectator, and not life,
that art really mirrors.  Diversity of opinion about a work of art
shows that the work is new, complex, and vital.  W
Download .txt
gitextract_i2kqoeob/

├── LICENSE
├── Makefile
├── README.md
├── generate_compressor_model.py
├── models/
│   ├── dictionary.h
│   ├── filepaths.h
│   ├── text_en.h
│   └── words_en.h
├── pre.js
├── shoco-bin.c
├── shoco.c
├── shoco.h
├── shoco.html
├── shoco.js
├── shoco_model.h
├── shoco_table.h
├── test_input.c
├── tests.c
└── training_data/
    ├── dorian_gray.txt
    ├── metamorphosis.txt
    └── pride_and_prejudice.txt
Download .txt
SYMBOL INDEX (128 symbols across 12 files)

FILE: generate_compressor_model.py
  function accumulate (line 72) | def accumulate(seq, start=0):
  class Structure (line 78) | class Structure(object):
    method __init__ (line 79) | def __init__(self, datalist):
    method header (line 83) | def header(self):
    method lead (line 87) | def lead(self):
    method successors (line 91) | def successors(self):
    method consecutive (line 95) | def consecutive(self):
  class Bits (line 99) | class Bits(Structure):
    method __init__ (line 100) | def __init__(self, bitlist):
  class Masks (line 103) | class Masks(Structure):
    method __init__ (line 104) | def __init__(self, bitlist):
  class Offsets (line 107) | class Offsets(Structure):
    method __init__ (line 108) | def __init__(self, bitlist):
  class Encoding (line 114) | class Encoding(object):
    method __init__ (line 115) | def __init__(self, bitlist):
    method header_code (line 125) | def header_code(self):
    method header_mask (line 129) | def header_mask(self):
    method word (line 133) | def word(self):
    method __hash__ (line 136) | def __hash__(self):
    method can_encode (line 139) | def can_encode(self, part, successors, chrs_indices):
  function make_log (line 203) | def make_log(output):
  function bigrams (line 211) | def bigrams(sequence):
  function format_int_line (line 219) | def format_int_line(items):
  function escape (line 223) | def escape(char):
  function format_chr_line (line 227) | def format_chr_line(items):
  function chunkinator (line 230) | def chunkinator(files, split, strip):
  function nearest_lg (line 255) | def nearest_lg(number):
  function main (line 263) | def main():

FILE: models/dictionary.h
  type Pack (line 88) | typedef struct Pack {

FILE: models/filepaths.h
  type Pack (line 138) | typedef struct Pack {

FILE: models/text_en.h
  type Pack (line 152) | typedef struct Pack {

FILE: models/words_en.h
  type Pack (line 145) | typedef struct Pack {

FILE: shoco-bin.c
  type Job (line 10) | typedef enum {
  function main (line 17) | int main(int argc, char **argv) {

FILE: shoco.c
  function decode_header (line 39) | static inline int decode_header(unsigned char val) {
  function check_indices (line 54) | static inline int check_indices(const int16_t * shoco_restrict indices, ...
  function check_indices (line 65) | static inline int check_indices(const int16_t * shoco_restrict indices, ...
  function find_best_encoding (line 73) | static inline int find_best_encoding(const int16_t * shoco_restrict indi...
  function shoco_compress (line 80) | size_t shoco_compress(const char * const shoco_restrict original, size_t...
  function shoco_decompress (line 164) | size_t shoco_decompress(const char * const shoco_restrict original, size...

FILE: shoco.js
  function e (line 1) | function e(a){throw a;}
  function n (line 1) | function n(){return function(){}}
  function ia (line 7) | function ia(a){eval.call(l,a)}
  function w (line 19) | function w(a,b){a||z("Assertion failed: "+b)}
  function na (line 19) | function na(a){try{var b=p["_"+a];b||(b=eval("_"+a))}catch(c){}w(b,"Cann...
  function ma (line 20) | function ma(a,b,c,d){function f(a,b){if("string"==b){if(a===l||a===i||0=...
  function pa (line 21) | function pa(a,b,c){c=c||"i8";"*"===c.charAt(c.length-1)&&(c="i32");switc...
  function M (line 23) | function M(a,b,c,d){var f,g;"number"===typeof a?(f=j,g=a):(f=m,g=a.lengt...
  function ja (line 24) | function ja(a,b){for(var c=m,d,f=0;;){d=N[a+f|0];if(128<=d)c=j;else if(0...
  function ya (line 26) | function ya(a){function b(h,s,u){var s=s||Infinity,t="",A=[],k;if("N"===...
  function za (line 29) | function za(){var a=Error().stack;return a?a.replace(/__Z[\w\d_]+/g,func...
  function Q (line 31) | function Q(a){for(;0<a.length;){var b=a.shift();if("function"==typeof b)...
  function Na (line 31) | function Na(a){Ha.unshift(a)}
  function Pa (line 32) | function Pa(a){La.unshift(a)}
  function G (line 32) | function G(a,b,c){a=(new v.ga).Bb(a);c&&(a.length=c);b||a.push(0);return a}
  function oa (line 32) | function oa(a,b){for(var c=0;c<a.length;c++)H[b+c|0]=a[c]}
  function Sa (line 33) | function Sa(){R++;p.monitorRunDependencies&&p.monitorRunDependencies(R)}
  function Ta (line 34) | function Ta(){R--;p.monitorRunDependencies&&p.monitorRunDependencies(R);...
  function xa (line 52) | function xa(a){return v.Ja(a+8)+8&4294967288}
  function Xa (line 60) | function Xa(a){return J[Wa>>2]=a}
  function Za (line 61) | function Za(a,b){Ya[a]={input:[],H:[],R:b};$a[a]={k:ab}}
  function V (line 71) | function V(a,b){var a=ob("/",a),b=b||{},c={Na:j,ta:0},d;for(d in c)b[d]=...
  function X (line 72) | function X(a){for(var b;;){if(a===a.parent)return a=a.G.yb,!b?a:"/"!==a[...
  function eb (line 72) | function eb(a,b){for(var c=0,d=0;d<b.length;d++)c=(c<<5)-c+b.charCodeAt(...
  function hb (line 73) | function hb(a,b){var c=qb(a,"x");c&&e(new T(c));for(c=fb[eb(a.id,b)];c;c...
  function qb (line 73) | function qb(a,b){return nb?0:-1!==b.indexOf("r")&&!(a.mode&292)||-1!==b....
  function sb (line 73) | function sb(a,b){try{return hb(a,b),S.Ba}catch(c){}return qb(a,"wx")}
  function tb (line 74) | function tb(a,b,c){var d=V(a,{parent:j}).e,a=ub(a),f=sb(d,a);f&&e(new T(...
  function vb (line 74) | function vb(a,b){b=(b!==i?b:438)&4095;b|=32768;return tb(a,b,0)}
  function wb (line 74) | function wb(a,b){b=(b!==i?b:511)&1023;b|=16384;return tb(a,b,0)}
  function xb (line 74) | function xb(a,b,c){"undefined"===typeof c&&(c=b,b=438);return tb(a,b|819...
  function yb (line 75) | function yb(a,b){var c=V(b,{parent:j}).e,d=ub(b),f=sb(c,d);f&&e(new T(f)...
  function zb (line 75) | function zb(a,b){var c;c="string"===typeof a?V(a,{ma:j}).e:a;c.g.o||e(ne...
  function Ab (line 76) | function Ab(a,b){var c,d;"string"===typeof b?(d=rb[b],"undefined"===type...
  function Db (line 78) | function Db(a){try{a.k.close&&a.k.close(a)}catch(b){e(b)}finally{mb[a.q]...
  function Eb (line 79) | function Eb(){T||(T=function(a){this.Ud=a;for(var b in S)if(S[b]===a){th...
  function Gb (line 79) | function Gb(a,b){var c=0;a&&(c|=365);b&&(c|=146);return c}
  function Hb (line 80) | function Hb(a,b,c,d,f,g){a=b?W(("string"===typeof a?a:X(a))+"/"+b):a;d=G...
  function Y (line 82) | function Y(a,b,c,d){a=W(("string"===typeof a?a:X(a))+"/"+b);b=Gb(!!c,!!d...
  function Ib (line 83) | function Ib(a){if(a.tb||a.ub||a.link||a.n)return j;var b=j;"undefined"!=...
  function pb (line 84) | function pb(a,b){for(var c=0,d=a.length-1;0<=d;d--){var f=a[d];"."===f?a...
  function W (line 84) | function W(a){var b="/"===a.charAt(0),c="/"===a.substr(-1),a=pb(a.split(...
  function ub (line 84) | function ub(a){if("/"===a)return"/";var b=a.lastIndexOf("/");return-1===...
  function ob (line 85) | function ob(){for(var a="",b=m,c=arguments.length-1;-1<=c&&!b;c--){var d...
  function Pb (line 86) | function Pb(a){return{jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png"...
  function Rb (line 86) | function Rb(){var a=p.canvas;Qb.forEach(function(b){b(a.width,a.height)})}
  function Sb (line 87) | function Sb(a,b,c){b&&c?(a.Fb=b,a.sb=c):(b=a.Fb,c=a.sb);var d=b,f=c;p.fo...
  function $b (line 89) | function $b(){}
  function c (line 90) | function c(){Kb=m;var a=d.parentNode;(document.webkitFullScreenElement||...
  function u (line 100) | function u(){Lb=document.pointerLockElement===k||document.mozPointerLock...
  function t (line 100) | function t(c){function t(c){x||Hb(a,b,c,d,f,s);g&&g();Ta()}var k=m;p.pre...
  function f (line 103) | function f(d){h||(h=j,p.preloadedAudios[b]=d,c&&c(a))}
  function g (line 103) | function g(){h||(h=j,p.preloadedAudios[b]=new Audio,d&&d())}
  function x (line 108) | function x(){this.qa=m;this.U=[]}
  function ka (line 117) | function ka(a){a=a|0;var b=0;b=i;i=i+a|0;i=i+7&-8;return b|0}
  function la (line 117) | function la(){return i|0}
  function ma (line 117) | function ma(a){a=a|0;i=a}
  function na (line 117) | function na(a,b){a=a|0;b=b|0;if((m|0)==0){m=a;n=b}}
  function oa (line 117) | function oa(b){b=b|0;a[k]=a[b];a[k+1|0]=a[b+1|0];a[k+2|0]=a[b+2|0];a[k+3...
  function pa (line 117) | function pa(b){b=b|0;a[k]=a[b];a[k+1|0]=a[b+1|0];a[k+2|0]=a[b+2|0];a[k+3...
  function qa (line 117) | function qa(a){a=a|0;B=a}
  function ra (line 117) | function ra(a){a=a|0;C=a}
  function sa (line 117) | function sa(a){a=a|0;D=a}
  function ta (line 117) | function ta(a){a=a|0;E=a}
  function ua (line 117) | function ua(a){a=a|0;F=a}
  function va (line 117) | function va(a){a=a|0;G=a}
  function wa (line 117) | function wa(a){a=a|0;H=a}
  function xa (line 117) | function xa(a){a=a|0;I=a}
  function ya (line 117) | function ya(a){a=a|0;J=a}
  function za (line 117) | function za(a){a=a|0;K=a}
  function Aa (line 117) | function Aa(e,f,g,h){e=e|0;f=f|0;g=g|0;h=h|0;var j=0,k=0,l=0,m=0,n=0,o=0...
  function Ba (line 117) | function Ba(d,e,f,g){d=d|0;e=e|0;f=f|0;g=g|0;var h=0,j=0,k=0,l=0,m=0,n=0...
  function Ca (line 117) | function Ca(){}
  function Da (line 117) | function Da(b,d,e){b=b|0;d=d|0;e=e|0;var f=0,g=0,h=0,i=0;f=b+e|0;if((e|0...
  function Ea (line 117) | function Ea(b){b=b|0;var c=0;c=b;while(a[c]|0){c=c+1|0}return c-b|0}
  function Fa (line 117) | function Fa(b,d,e){b=b|0;d=d|0;e=e|0;var f=0;if((e|0)>=4096)return ga(b|...
  function ic (line 128) | function ic(a){this.name="ExitStatus";this.message="Program terminated w...
  function b (line 129) | function b(){for(var a=0;3>a;a++)d.push(0)}
  function nc (line 131) | function nc(a){function b(){if(!p.calledRun){p.calledRun=j;Ma||(Ma=j,Q(I...
  function oc (line 132) | function oc(a){ka=j;r=jc;Q(Ka);e(new ic(a))}
  function z (line 132) | function z(a){a&&(p.print(a),p.I(a));ka=j;e("abort() at "+za()+"\nIf thi...

FILE: shoco_model.h
  type Pack (line 145) | typedef struct Pack {

FILE: shoco_table.h
  type Pack (line 145) | typedef struct Pack {

FILE: test_input.c
  function ratio (line 9) | static double ratio(int original, int compressed) {
  function percent (line 13) | static int percent(double ratio) {
  function print (line 17) | static void print(char *in, double ratio) {
  function main (line 21) | int main(int argc, char ** argv) {

FILE: tests.c
  function main (line 11) | int main() {
Condensed preview — 21 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,520K chars).
[
  {
    "path": "LICENSE",
    "chars": 1119,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2014 Christian Schramm <christian.h.m.schramm@gmail.com>\n\nPermission is hereby gran"
  },
  {
    "path": "Makefile",
    "chars": 1482,
    "preview": "FLAGS=$(CFLAGS) -std=c99 -O3 -Wall\nSOURCES=shoco.c\nOBJECTS=$(SOURCES:.c=.o)\nHEADERS=shoco.h shoco_model.h\nGENERATOR=gene"
  },
  {
    "path": "README.md",
    "chars": 17391,
    "preview": "**Note: This project is unmaintained. You should use ZStandard nowadays**\n\n**shoco**: a fast compressor for short string"
  },
  {
    "path": "generate_compressor_model.py",
    "chars": 13315,
    "preview": "#!/usr/bin/python\n\nfrom __future__ import print_function\n\nimport collections\nimport argparse\nimport itertools\nimport re\n"
  },
  {
    "path": "models/dictionary.h",
    "chars": 8826,
    "preview": "#ifdef _SHOCO_INTERNAL\n/*\nThis file was generated by 'generate_successor_table.py',\nso don't edit this by hand. Also, do"
  },
  {
    "path": "models/filepaths.h",
    "chars": 14828,
    "preview": "#ifndef _SHOCO_INTERNAL\n#error This header file is only to be included by 'shoco.c'.\n#endif\n#pragma once\n/*\nThis file wa"
  },
  {
    "path": "models/text_en.h",
    "chars": 16829,
    "preview": "#ifndef _SHOCO_INTERNAL\n#error This header file is only to be included by 'shoco.c'.\n#endif\n#pragma once\n/*\nThis file wa"
  },
  {
    "path": "models/words_en.h",
    "chars": 15920,
    "preview": "#ifndef _SHOCO_INTERNAL\n#error This header file is only to be included by 'shoco.c'.\n#endif\n#pragma once\n/*\nThis file wa"
  },
  {
    "path": "pre.js",
    "chars": 1617,
    "preview": "var Module = {\n  'preRun': function() {\n    var _shoco_compress = Module['cwrap']('shoco_compress', 'number', ['string',"
  },
  {
    "path": "shoco-bin.c",
    "chars": 1970,
    "preview": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"shoco.h\"\n\nstatic const char USAGE[] = \"compresses "
  },
  {
    "path": "shoco.c",
    "chars": 6349,
    "preview": "#include <stdint.h>\n\n#if (defined (__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || __BIG_ENDIAN__)\n  #def"
  },
  {
    "path": "shoco.h",
    "chars": 505,
    "preview": "#pragma once\n\n#include <stddef.h>\n\n#if defined(_MSC_VER)\n#define shoco_restrict __restrict\n#elif __GNUC__\n#define shoco_"
  },
  {
    "path": "shoco.html",
    "chars": 1250,
    "preview": "<!doctype html>\n<html lang=\"en-us\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"Content-Type\" content=\"tex"
  },
  {
    "path": "shoco.js",
    "chars": 57946,
    "preview": "function e(a){throw a;}var i=void 0,j=!0,l=null,m=!1;function n(){return function(){}}\nvar p={preRun:function(){var a=p."
  },
  {
    "path": "shoco_model.h",
    "chars": 15920,
    "preview": "#ifndef _SHOCO_INTERNAL\n#error This header file is only to be included by 'shoco.c'.\n#endif\n#pragma once\n/*\nThis file wa"
  },
  {
    "path": "shoco_table.h",
    "chars": 15920,
    "preview": "#ifndef _SHOCO_INTERNAL\n#error This header file is only to be included by 'shoco.c'.\n#endif\n#pragma once\n/*\nThis file wa"
  },
  {
    "path": "test_input.c",
    "chars": 1334,
    "preview": "#include <stdio.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"shoco.h\"\n\n#define BUFFER_SIZE 1024\n\nstatic double "
  },
  {
    "path": "tests.c",
    "chars": 3264,
    "preview": "#include \"stdint.h\"\n#include \"stdio.h\"\n#include \"assert.h\"\n#include \"string.h\"\n\n#include \"shoco.h\"\n\nstatic const char LA"
  },
  {
    "path": "training_data/dorian_gray.txt",
    "chars": 442055,
    "preview": "The Picture of Dorian Gray\r\n\r\nby\r\n\r\nOscar Wilde\r\n\r\n\r\n\r\n\r\nTHE PREFACE\r\n\r\nThe artist is the creator of beautiful things.  "
  },
  {
    "path": "training_data/metamorphosis.txt",
    "chars": 121228,
    "preview": "Copyright (C) 2002 David Wyllie.\r\n\r\n\r\n\r\n\r\n\r\n  Metamorphosis\r\n  Franz Kafka\r\n\r\nTranslated by David Wyllie\r\n\r\n\r\n\r\nI\r\n\r\n\r\nO"
  },
  {
    "path": "training_data/pride_and_prejudice.txt",
    "chars": 697793,
    "preview": "PRIDE AND PREJUDICE\r\n\r\nBy Jane Austen\r\n\r\n\r\n\r\nChapter 1\r\n\r\n\r\nIt is a truth universally acknowledged, that a single man in"
  }
]

About this extraction

This page contains the full source code of the Ed-von-Schleck/shoco GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 21 files (1.4 MB), approximately 390.8k tokens, and a symbol index with 128 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!