]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: hpack: implement the HPACK Huffman table decoder
authorWilly Tarreau <w@1wt.eu>
Tue, 30 May 2017 15:22:18 +0000 (17:22 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 31 Oct 2017 17:03:24 +0000 (18:03 +0100)
The code was borrowed from the HPACK experimental implementations
available here :

    https://github.com/wtarreau/http2-exp

It contains the Huffman table as specified in RFC7541 Appendix B, and a
set of reverse tables used to decode a Huffman byte stream, and produced
by contrib/h2/gen-rht. The encoder is not finalized, it doesn't emit the
byte stream but this is not needed for now.

Makefile
include/common/hpack-huff.h [new file with mode: 0644]
src/hpack-huff.c [new file with mode: 0644]

index 5a33991a6cd202dcceda68ede82f80ac9ad610cb..fdad03a48d8b9bb4481127f2479df2d4812c079d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -848,6 +848,7 @@ OBJS = src/cfgparse.o src/proto_http.o src/stats.o src/server.o src/stream.o \
        src/haproxy.o src/stream_interface.o src/tcp_rules.o src/proxy.o \
        src/listener.o src/acl.o src/flt_http_comp.o src/filters.o src/dns.o \
        src/cli.o src/flt_trace.o src/connection.o src/session.o src/vars.o \
+       src/hpack-huff.o \
        src/map.o src/payload.o src/namespace.o src/compression.o \
        src/mailers.o src/auth.o src/proto_udp.o src/memory.o src/freq_ctr.o \
        src/signal.o src/uri_auth.o src/buffer.o src/task.o src/chunk.o \
diff --git a/include/common/hpack-huff.h b/include/common/hpack-huff.h
new file mode 100644 (file)
index 0000000..85ca417
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Huffman decoding and encoding for HPACK (RFC7541)
+ *
+ * Copyright (C) 2014-2017 Willy Tarreau <willy@haproxy.org>
+ * Copyright (C) 2017 HAProxy Technologies
+ *
+ * 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.
+ */
+#ifndef _PROTO_HPACK_HUFF_H
+#define _PROTO_HPACK_HUFF_H
+
+#include <stdint.h>
+
+int huff_enc(const char *s, char *out);
+int huff_dec(const uint8_t *huff, int hlen, char *out, int olen);
+
+#endif
diff --git a/src/hpack-huff.c b/src/hpack-huff.c
new file mode 100644 (file)
index 0000000..23aa541
--- /dev/null
@@ -0,0 +1,1530 @@
+/*
+ * Huffman decoding and encoding for HPACK (RFC7541)
+ *
+ * Copyright (C) 2014-2017 Willy Tarreau <willy@haproxy.org>
+ * Copyright (C) 2017 HAProxy Technologies
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <common/config.h>
+#include <common/hpack-huff.h>
+
+struct huff {
+       uint32_t c; /* code point */
+       int b;      /* bits */
+};
+
+struct rht {
+       uint8_t c; // code or 0 if length > 8 + position*8
+       uint8_t l; // length in bits
+};
+
+/* huffman table as per RFC7541 appendix B */
+static const struct huff ht[257] = {
+       [  0] = { .c = 0x00001ff8, .b = 13 },
+       [  1] = { .c = 0x007fffd8, .b = 23 },
+       [  2] = { .c = 0x0fffffe2, .b = 28 },
+       [  3] = { .c = 0x0fffffe3, .b = 28 },
+       [  4] = { .c = 0x0fffffe4, .b = 28 },
+       [  5] = { .c = 0x0fffffe5, .b = 28 },
+       [  6] = { .c = 0x0fffffe6, .b = 28 },
+       [  7] = { .c = 0x0fffffe7, .b = 28 },
+       [  8] = { .c = 0x0fffffe8, .b = 28 },
+       [  9] = { .c = 0x00ffffea, .b = 24 },
+       [ 10] = { .c = 0x3ffffffc, .b = 30 },
+       [ 11] = { .c = 0x0fffffe9, .b = 28 },
+       [ 12] = { .c = 0x0fffffea, .b = 28 },
+       [ 13] = { .c = 0x3ffffffd, .b = 30 },
+       [ 14] = { .c = 0x0fffffeb, .b = 28 },
+       [ 15] = { .c = 0x0fffffec, .b = 28 },
+       [ 16] = { .c = 0x0fffffed, .b = 28 },
+       [ 17] = { .c = 0x0fffffee, .b = 28 },
+       [ 18] = { .c = 0x0fffffef, .b = 28 },
+       [ 19] = { .c = 0x0ffffff0, .b = 28 },
+       [ 20] = { .c = 0x0ffffff1, .b = 28 },
+       [ 21] = { .c = 0x0ffffff2, .b = 28 },
+       [ 22] = { .c = 0x3ffffffe, .b = 30 },
+       [ 23] = { .c = 0x0ffffff3, .b = 28 },
+       [ 24] = { .c = 0x0ffffff4, .b = 28 },
+       [ 25] = { .c = 0x0ffffff5, .b = 28 },
+       [ 26] = { .c = 0x0ffffff6, .b = 28 },
+       [ 27] = { .c = 0x0ffffff7, .b = 28 },
+       [ 28] = { .c = 0x0ffffff8, .b = 28 },
+       [ 29] = { .c = 0x0ffffff9, .b = 28 },
+       [ 30] = { .c = 0x0ffffffa, .b = 28 },
+       [ 31] = { .c = 0x0ffffffb, .b = 28 },
+       [ 32] = { .c = 0x00000014, .b =  6 },
+       [ 33] = { .c = 0x000003f8, .b = 10 },
+       [ 34] = { .c = 0x000003f9, .b = 10 },
+       [ 35] = { .c = 0x00000ffa, .b = 12 },
+       [ 36] = { .c = 0x00001ff9, .b = 13 },
+       [ 37] = { .c = 0x00000015, .b =  6 },
+       [ 38] = { .c = 0x000000f8, .b =  8 },
+       [ 39] = { .c = 0x000007fa, .b = 11 },
+       [ 40] = { .c = 0x000003fa, .b = 10 },
+       [ 41] = { .c = 0x000003fb, .b = 10 },
+       [ 42] = { .c = 0x000000f9, .b =  8 },
+       [ 43] = { .c = 0x000007fb, .b = 11 },
+       [ 44] = { .c = 0x000000fa, .b =  8 },
+       [ 45] = { .c = 0x00000016, .b =  6 },
+       [ 46] = { .c = 0x00000017, .b =  6 },
+       [ 47] = { .c = 0x00000018, .b =  6 },
+       [ 48] = { .c = 0x00000000, .b =  5 },
+       [ 49] = { .c = 0x00000001, .b =  5 },
+       [ 50] = { .c = 0x00000002, .b =  5 },
+       [ 51] = { .c = 0x00000019, .b =  6 },
+       [ 52] = { .c = 0x0000001a, .b =  6 },
+       [ 53] = { .c = 0x0000001b, .b =  6 },
+       [ 54] = { .c = 0x0000001c, .b =  6 },
+       [ 55] = { .c = 0x0000001d, .b =  6 },
+       [ 56] = { .c = 0x0000001e, .b =  6 },
+       [ 57] = { .c = 0x0000001f, .b =  6 },
+       [ 58] = { .c = 0x0000005c, .b =  7 },
+       [ 59] = { .c = 0x000000fb, .b =  8 },
+       [ 60] = { .c = 0x00007ffc, .b = 15 },
+       [ 61] = { .c = 0x00000020, .b =  6 },
+       [ 62] = { .c = 0x00000ffb, .b = 12 },
+       [ 63] = { .c = 0x000003fc, .b = 10 },
+       [ 64] = { .c = 0x00001ffa, .b = 13 },
+       [ 65] = { .c = 0x00000021, .b =  6 },
+       [ 66] = { .c = 0x0000005d, .b =  7 },
+       [ 67] = { .c = 0x0000005e, .b =  7 },
+       [ 68] = { .c = 0x0000005f, .b =  7 },
+       [ 69] = { .c = 0x00000060, .b =  7 },
+       [ 70] = { .c = 0x00000061, .b =  7 },
+       [ 71] = { .c = 0x00000062, .b =  7 },
+       [ 72] = { .c = 0x00000063, .b =  7 },
+       [ 73] = { .c = 0x00000064, .b =  7 },
+       [ 74] = { .c = 0x00000065, .b =  7 },
+       [ 75] = { .c = 0x00000066, .b =  7 },
+       [ 76] = { .c = 0x00000067, .b =  7 },
+       [ 77] = { .c = 0x00000068, .b =  7 },
+       [ 78] = { .c = 0x00000069, .b =  7 },
+       [ 79] = { .c = 0x0000006a, .b =  7 },
+       [ 80] = { .c = 0x0000006b, .b =  7 },
+       [ 81] = { .c = 0x0000006c, .b =  7 },
+       [ 82] = { .c = 0x0000006d, .b =  7 },
+       [ 83] = { .c = 0x0000006e, .b =  7 },
+       [ 84] = { .c = 0x0000006f, .b =  7 },
+       [ 85] = { .c = 0x00000070, .b =  7 },
+       [ 86] = { .c = 0x00000071, .b =  7 },
+       [ 87] = { .c = 0x00000072, .b =  7 },
+       [ 88] = { .c = 0x000000fc, .b =  8 },
+       [ 89] = { .c = 0x00000073, .b =  7 },
+       [ 90] = { .c = 0x000000fd, .b =  8 },
+       [ 91] = { .c = 0x00001ffb, .b = 13 },
+       [ 92] = { .c = 0x0007fff0, .b = 19 },
+       [ 93] = { .c = 0x00001ffc, .b = 13 },
+       [ 94] = { .c = 0x00003ffc, .b = 14 },
+       [ 95] = { .c = 0x00000022, .b =  6 },
+       [ 96] = { .c = 0x00007ffd, .b = 15 },
+       [ 97] = { .c = 0x00000003, .b =  5 },
+       [ 98] = { .c = 0x00000023, .b =  6 },
+       [ 99] = { .c = 0x00000004, .b =  5 },
+       [100] = { .c = 0x00000024, .b =  6 },
+       [101] = { .c = 0x00000005, .b =  5 },
+       [102] = { .c = 0x00000025, .b =  6 },
+       [103] = { .c = 0x00000026, .b =  6 },
+       [104] = { .c = 0x00000027, .b =  6 },
+       [105] = { .c = 0x00000006, .b =  5 },
+       [106] = { .c = 0x00000074, .b =  7 },
+       [107] = { .c = 0x00000075, .b =  7 },
+       [108] = { .c = 0x00000028, .b =  6 },
+       [109] = { .c = 0x00000029, .b =  6 },
+       [110] = { .c = 0x0000002a, .b =  6 },
+       [111] = { .c = 0x00000007, .b =  5 },
+       [112] = { .c = 0x0000002b, .b =  6 },
+       [113] = { .c = 0x00000076, .b =  7 },
+       [114] = { .c = 0x0000002c, .b =  6 },
+       [115] = { .c = 0x00000008, .b =  5 },
+       [116] = { .c = 0x00000009, .b =  5 },
+       [117] = { .c = 0x0000002d, .b =  6 },
+       [118] = { .c = 0x00000077, .b =  7 },
+       [119] = { .c = 0x00000078, .b =  7 },
+       [120] = { .c = 0x00000079, .b =  7 },
+       [121] = { .c = 0x0000007a, .b =  7 },
+       [122] = { .c = 0x0000007b, .b =  7 },
+       [123] = { .c = 0x00007ffe, .b = 15 },
+       [124] = { .c = 0x000007fc, .b = 11 },
+       [125] = { .c = 0x00003ffd, .b = 14 },
+       [126] = { .c = 0x00001ffd, .b = 13 },
+       [127] = { .c = 0x0ffffffc, .b = 28 },
+       [128] = { .c = 0x000fffe6, .b = 20 },
+       [129] = { .c = 0x003fffd2, .b = 22 },
+       [130] = { .c = 0x000fffe7, .b = 20 },
+       [131] = { .c = 0x000fffe8, .b = 20 },
+       [132] = { .c = 0x003fffd3, .b = 22 },
+       [133] = { .c = 0x003fffd4, .b = 22 },
+       [134] = { .c = 0x003fffd5, .b = 22 },
+       [135] = { .c = 0x007fffd9, .b = 23 },
+       [136] = { .c = 0x003fffd6, .b = 22 },
+       [137] = { .c = 0x007fffda, .b = 23 },
+       [138] = { .c = 0x007fffdb, .b = 23 },
+       [139] = { .c = 0x007fffdc, .b = 23 },
+       [140] = { .c = 0x007fffdd, .b = 23 },
+       [141] = { .c = 0x007fffde, .b = 23 },
+       [142] = { .c = 0x00ffffeb, .b = 24 },
+       [143] = { .c = 0x007fffdf, .b = 23 },
+       [144] = { .c = 0x00ffffec, .b = 24 },
+       [145] = { .c = 0x00ffffed, .b = 24 },
+       [146] = { .c = 0x003fffd7, .b = 22 },
+       [147] = { .c = 0x007fffe0, .b = 23 },
+       [148] = { .c = 0x00ffffee, .b = 24 },
+       [149] = { .c = 0x007fffe1, .b = 23 },
+       [150] = { .c = 0x007fffe2, .b = 23 },
+       [151] = { .c = 0x007fffe3, .b = 23 },
+       [152] = { .c = 0x007fffe4, .b = 23 },
+       [153] = { .c = 0x001fffdc, .b = 21 },
+       [154] = { .c = 0x003fffd8, .b = 22 },
+       [155] = { .c = 0x007fffe5, .b = 23 },
+       [156] = { .c = 0x003fffd9, .b = 22 },
+       [157] = { .c = 0x007fffe6, .b = 23 },
+       [158] = { .c = 0x007fffe7, .b = 23 },
+       [159] = { .c = 0x00ffffef, .b = 24 },
+       [160] = { .c = 0x003fffda, .b = 22 },
+       [161] = { .c = 0x001fffdd, .b = 21 },
+       [162] = { .c = 0x000fffe9, .b = 20 },
+       [163] = { .c = 0x003fffdb, .b = 22 },
+       [164] = { .c = 0x003fffdc, .b = 22 },
+       [165] = { .c = 0x007fffe8, .b = 23 },
+       [166] = { .c = 0x007fffe9, .b = 23 },
+       [167] = { .c = 0x001fffde, .b = 21 },
+       [168] = { .c = 0x007fffea, .b = 23 },
+       [169] = { .c = 0x003fffdd, .b = 22 },
+       [170] = { .c = 0x003fffde, .b = 22 },
+       [171] = { .c = 0x00fffff0, .b = 24 },
+       [172] = { .c = 0x001fffdf, .b = 21 },
+       [173] = { .c = 0x003fffdf, .b = 22 },
+       [174] = { .c = 0x007fffeb, .b = 23 },
+       [175] = { .c = 0x007fffec, .b = 23 },
+       [176] = { .c = 0x001fffe0, .b = 21 },
+       [177] = { .c = 0x001fffe1, .b = 21 },
+       [178] = { .c = 0x003fffe0, .b = 22 },
+       [179] = { .c = 0x001fffe2, .b = 21 },
+       [180] = { .c = 0x007fffed, .b = 23 },
+       [181] = { .c = 0x003fffe1, .b = 22 },
+       [182] = { .c = 0x007fffee, .b = 23 },
+       [183] = { .c = 0x007fffef, .b = 23 },
+       [184] = { .c = 0x000fffea, .b = 20 },
+       [185] = { .c = 0x003fffe2, .b = 22 },
+       [186] = { .c = 0x003fffe3, .b = 22 },
+       [187] = { .c = 0x003fffe4, .b = 22 },
+       [188] = { .c = 0x007ffff0, .b = 23 },
+       [189] = { .c = 0x003fffe5, .b = 22 },
+       [190] = { .c = 0x003fffe6, .b = 22 },
+       [191] = { .c = 0x007ffff1, .b = 23 },
+       [192] = { .c = 0x03ffffe0, .b = 26 },
+       [193] = { .c = 0x03ffffe1, .b = 26 },
+       [194] = { .c = 0x000fffeb, .b = 20 },
+       [195] = { .c = 0x0007fff1, .b = 19 },
+       [196] = { .c = 0x003fffe7, .b = 22 },
+       [197] = { .c = 0x007ffff2, .b = 23 },
+       [198] = { .c = 0x003fffe8, .b = 22 },
+       [199] = { .c = 0x01ffffec, .b = 25 },
+       [200] = { .c = 0x03ffffe2, .b = 26 },
+       [201] = { .c = 0x03ffffe3, .b = 26 },
+       [202] = { .c = 0x03ffffe4, .b = 26 },
+       [203] = { .c = 0x07ffffde, .b = 27 },
+       [204] = { .c = 0x07ffffdf, .b = 27 },
+       [205] = { .c = 0x03ffffe5, .b = 26 },
+       [206] = { .c = 0x00fffff1, .b = 24 },
+       [207] = { .c = 0x01ffffed, .b = 25 },
+       [208] = { .c = 0x0007fff2, .b = 19 },
+       [209] = { .c = 0x001fffe3, .b = 21 },
+       [210] = { .c = 0x03ffffe6, .b = 26 },
+       [211] = { .c = 0x07ffffe0, .b = 27 },
+       [212] = { .c = 0x07ffffe1, .b = 27 },
+       [213] = { .c = 0x03ffffe7, .b = 26 },
+       [214] = { .c = 0x07ffffe2, .b = 27 },
+       [215] = { .c = 0x00fffff2, .b = 24 },
+       [216] = { .c = 0x001fffe4, .b = 21 },
+       [217] = { .c = 0x001fffe5, .b = 21 },
+       [218] = { .c = 0x03ffffe8, .b = 26 },
+       [219] = { .c = 0x03ffffe9, .b = 26 },
+       [220] = { .c = 0x0ffffffd, .b = 28 },
+       [221] = { .c = 0x07ffffe3, .b = 27 },
+       [222] = { .c = 0x07ffffe4, .b = 27 },
+       [223] = { .c = 0x07ffffe5, .b = 27 },
+       [224] = { .c = 0x000fffec, .b = 20 },
+       [225] = { .c = 0x00fffff3, .b = 24 },
+       [226] = { .c = 0x000fffed, .b = 20 },
+       [227] = { .c = 0x001fffe6, .b = 21 },
+       [228] = { .c = 0x003fffe9, .b = 22 },
+       [229] = { .c = 0x001fffe7, .b = 21 },
+       [230] = { .c = 0x001fffe8, .b = 21 },
+       [231] = { .c = 0x007ffff3, .b = 23 },
+       [232] = { .c = 0x003fffea, .b = 22 },
+       [233] = { .c = 0x003fffeb, .b = 22 },
+       [234] = { .c = 0x01ffffee, .b = 25 },
+       [235] = { .c = 0x01ffffef, .b = 25 },
+       [236] = { .c = 0x00fffff4, .b = 24 },
+       [237] = { .c = 0x00fffff5, .b = 24 },
+       [238] = { .c = 0x03ffffea, .b = 26 },
+       [239] = { .c = 0x007ffff4, .b = 23 },
+       [240] = { .c = 0x03ffffeb, .b = 26 },
+       [241] = { .c = 0x07ffffe6, .b = 27 },
+       [242] = { .c = 0x03ffffec, .b = 26 },
+       [243] = { .c = 0x03ffffed, .b = 26 },
+       [244] = { .c = 0x07ffffe7, .b = 27 },
+       [245] = { .c = 0x07ffffe8, .b = 27 },
+       [246] = { .c = 0x07ffffe9, .b = 27 },
+       [247] = { .c = 0x07ffffea, .b = 27 },
+       [248] = { .c = 0x07ffffeb, .b = 27 },
+       [249] = { .c = 0x0ffffffe, .b = 28 },
+       [250] = { .c = 0x07ffffec, .b = 27 },
+       [251] = { .c = 0x07ffffed, .b = 27 },
+       [252] = { .c = 0x07ffffee, .b = 27 },
+       [253] = { .c = 0x07ffffef, .b = 27 },
+       [254] = { .c = 0x07fffff0, .b = 27 },
+       [255] = { .c = 0x03ffffee, .b = 26 },
+       [256] = { .c = 0x3fffffff, .b = 30 }, /* EOS */
+};
+
+
+/* Reversed huffman codes, generated by contrib/h2/gen-rht.c from the table
+ * above.
+ *
+ * The codes are aligned on the MSB since that's how they appear in the stream.
+ *
+ * Quick summary below of the way the tables work. They're based on how the
+ * prefixes are organized, starting from the MSB.
+ *
+ * These codes fit in a single octet (5 to 8 bits) :
+ *   00/5 08/5 10/5 18/5  20/5 28/5 30/5 38/5
+ *   40/5 48/5
+ *
+ *   50/6 54/6 58/6 5c/6  60/6 64/6 68/6 6c/6
+ *   70/6 74/6 78/6 7c/6  80/6 84/6 88/6 8c/6
+ *   90/6 94/6 98/6 9c/6  a0/6 a4/6 a8/6 ac/6
+ *   b0/6 b4/6
+ *
+ *   b8/7 ba/7 bc/7 be/7  c0/7 c2/7 c4/7 c6/7
+ *   c8/7 ca/7 cc/7 ce/7  d0/7 d2/7 d4/7 d6/7
+ *   d8/7 da/7 dc/7 de/7  e0/7 e2/7 e4/7 e6/7
+ *   e8/7 ea/7 ec/7 ee/7  f0/7 f2/7 f4/7 f6/7
+ *
+ *   f8/8 f9/8 fa/8 fb/8  fc/8 fd/8
+ *
+ * ==> a single 256-symbol table based on the full byte provides a direct
+ *     access and the bit count
+ *
+ * These codes fit in two octets (10 to 15 bits, neither 9 nor 16 bits code) :
+ *
+ * fe + 2 bits:
+ *   00/2 40/2 80/2 c0/2
+ *
+ * ff + 2..7 bits :
+ *   00/2
+ *   40/3 60/3 80/3
+ *   a0/4 b0/4
+ *   c0/5 c8/5 d0/5 d8/5  e0/5 e8/5
+ *   f0/6 f4/6
+ *   f8/7 fa/7 fc/7
+ *
+ *  ==> a single 256-symbol table made of b0.0 and b1.7-1 provides a direct
+ *      access and the bit count after a miss on the first one above.
+ *
+ * These ones fit in three octets :
+ * ff fe + 3..5 bits :
+ *   00/3 20/3 40/3 60/4  70/4 80/4 90/4 a0/4
+ *   b0/4 c0/4 d0/4
+ *   e0/5 e8/5 f0/5 f8/5
+ *
+ * ff ff + 5..8 bits :
+ *   00/5 08/5 10/5 18/5  20/5 28/5 30/5 38/5
+ *   40/5
+ *   48/6 4c/6 50/6 54/6  58/6 5c/6 60/6 64/6
+ *   68/6 6c/6 70/6 74/6  78/6 7c/6 80/6 84/6
+ *   88/6 8c/6 90/6 94/6  98/6 9c/6 a0/6 a4/6
+ *   a8/6 ac/6
+ *   b0/7 b2/7 b4/7 b6/7  b8/7 ba/7 bc/7 be/7
+ *   c0/7 c2/7 c4/7 c6/7  c8/7 ca/7 cc/7 ce/7
+ *   d0/7 d2/7 d4/7 d6/7  d8/7 da/7 dc/7 de/7
+ *   e0/7 e2/7 e4/7 e6/7  e8/7
+ *   ea/8 eb/8 ec/8 ed/8  ee/8 ef/8 f0/8 f1/8
+ *   f2/8 f3/8 f4/8 f5/8
+ *
+ * ==> a 32-symbol table has to be applied to 0xfffe
+ * ==> a 256-symbol table has to be applied to 0xffff
+ *
+ * The other ones fit in four octets with 1 to 6 bits in the last one :
+ * ff ff f6 :  00/1 80/1
+ * ff ff f7 :  00/1 80/1
+ * ff ff f8 :  00/2 40/2 80/2 c0/2
+ * ff ff f9 :  00/2 40/2 80/2 c0/2
+ * ff ff fa :  00/2 40/2 80/2 c0/2
+ * ff ff fb :  00/2 40/2 80/2
+ * ff ff fb :  c0/3 e0/3
+ * ff ff fc :  00/3 20/3 40/3 60/3 80/3 a0/3 c0/3 e0/3
+ * ff ff fd :  00/3 20/3 40/3 60/3 80/3 a0/3 c0/3 e0/3
+ * ff ff fe :  00/3
+ * ff ff fe :  20/4 30/4 40/4 50/4 60/4 70/4 80/4 90/4 a0/4 b0/4 c0/4 d0/4 e0/4 f0/4
+ * ff ff ff :  00/4 10/4 20/4 30/4 40/4 50/4 60/4 70/4 80/4 90/4 a0/4 b0/4 c0/4 d0/4 e0/4
+ * ff ff ff :  f0/6 f4/6 f8/6 fc/6
+ *
+ * ==> a 256-symbol table with b2.0-3,b3.7-4 gives all of them except the
+ *     distinction between ffffff{f0,f4,f8,fc} which is rare enough
+ *     and can be done by hand when bit count == 30.
+ *
+ *
+ * Code lengths :
+ *   5..8 : 0x00..0xfe
+ *   10..15 : 0xfe
+ *            0xff 0x00..0xfe
+ *   19..20 : 0xff 0xfe 0x00..0xdf
+ *   21     : 0xff 0xfe 0xe0..0xff
+ *   21     : 0xff 0xff 0x00..0x40
+ *   22..24 : 0xff 0xff 0x00..0xf5
+ *   24..28 : 0xff 0xff 0xf5..0xff
+ *   30     : 0xff 0xff 0xff 0xf0..0xff
+ *
+ *
+ * if b0  < 0xfe ==> 5..8 bits (74 codes)
+ * if b0 == 0xfe or 0xff : 10..15
+ *    => if b0 == 0xfe || b1 < 0xfe : lookup (b0:0|b1:7..1)  (21 codes)
+ *
+ * -- b0 = 0xff --
+ * if b1 == 0xfe : 19..21 bits
+ *    => lookup b2:7..3 (15 codes)
+ *
+ * -- b0 = 0xff, b1 = 0xff : 147 codes --
+ * if b2  < 0xf6 : 21..24 bits (76 codes)
+ * if b2 >= 0xf6 : 25..30 bits (71 codes)
+ *
+ * Algorithm:
+ *   - if > 24 and < 32, read missing bits.
+ *   - if less than 24 bits, read 1 byte. If past end, insert 0xff instead.
+ *   - if b0 < 0xfe lookup b0 in table0[0..255]
+ *   - else if b0 == 0xfe, manual lookup
+ *   - else if b0 == 0xff, lookup b1 in table1[0..255]
+ * ...
+ */
+
+struct rht rht_bit31_24[256] = {
+       [0x00] = { .c = 0x30, .l = 5 },
+       [0x01] = { .c = 0x30, .l = 5 },
+       [0x02] = { .c = 0x30, .l = 5 },
+       [0x03] = { .c = 0x30, .l = 5 },
+       [0x04] = { .c = 0x30, .l = 5 },
+       [0x05] = { .c = 0x30, .l = 5 },
+       [0x06] = { .c = 0x30, .l = 5 },
+       [0x07] = { .c = 0x30, .l = 5 },
+       [0x08] = { .c = 0x31, .l = 5 },
+       [0x09] = { .c = 0x31, .l = 5 },
+       [0x0a] = { .c = 0x31, .l = 5 },
+       [0x0b] = { .c = 0x31, .l = 5 },
+       [0x0c] = { .c = 0x31, .l = 5 },
+       [0x0d] = { .c = 0x31, .l = 5 },
+       [0x0e] = { .c = 0x31, .l = 5 },
+       [0x0f] = { .c = 0x31, .l = 5 },
+       [0x10] = { .c = 0x32, .l = 5 },
+       [0x11] = { .c = 0x32, .l = 5 },
+       [0x12] = { .c = 0x32, .l = 5 },
+       [0x13] = { .c = 0x32, .l = 5 },
+       [0x14] = { .c = 0x32, .l = 5 },
+       [0x15] = { .c = 0x32, .l = 5 },
+       [0x16] = { .c = 0x32, .l = 5 },
+       [0x17] = { .c = 0x32, .l = 5 },
+       [0x18] = { .c = 0x61, .l = 5 },
+       [0x19] = { .c = 0x61, .l = 5 },
+       [0x1a] = { .c = 0x61, .l = 5 },
+       [0x1b] = { .c = 0x61, .l = 5 },
+       [0x1c] = { .c = 0x61, .l = 5 },
+       [0x1d] = { .c = 0x61, .l = 5 },
+       [0x1e] = { .c = 0x61, .l = 5 },
+       [0x1f] = { .c = 0x61, .l = 5 },
+       [0x20] = { .c = 0x63, .l = 5 },
+       [0x21] = { .c = 0x63, .l = 5 },
+       [0x22] = { .c = 0x63, .l = 5 },
+       [0x23] = { .c = 0x63, .l = 5 },
+       [0x24] = { .c = 0x63, .l = 5 },
+       [0x25] = { .c = 0x63, .l = 5 },
+       [0x26] = { .c = 0x63, .l = 5 },
+       [0x27] = { .c = 0x63, .l = 5 },
+       [0x28] = { .c = 0x65, .l = 5 },
+       [0x29] = { .c = 0x65, .l = 5 },
+       [0x2a] = { .c = 0x65, .l = 5 },
+       [0x2b] = { .c = 0x65, .l = 5 },
+       [0x2c] = { .c = 0x65, .l = 5 },
+       [0x2d] = { .c = 0x65, .l = 5 },
+       [0x2e] = { .c = 0x65, .l = 5 },
+       [0x2f] = { .c = 0x65, .l = 5 },
+       [0x30] = { .c = 0x69, .l = 5 },
+       [0x31] = { .c = 0x69, .l = 5 },
+       [0x32] = { .c = 0x69, .l = 5 },
+       [0x33] = { .c = 0x69, .l = 5 },
+       [0x34] = { .c = 0x69, .l = 5 },
+       [0x35] = { .c = 0x69, .l = 5 },
+       [0x36] = { .c = 0x69, .l = 5 },
+       [0x37] = { .c = 0x69, .l = 5 },
+       [0x38] = { .c = 0x6f, .l = 5 },
+       [0x39] = { .c = 0x6f, .l = 5 },
+       [0x3a] = { .c = 0x6f, .l = 5 },
+       [0x3b] = { .c = 0x6f, .l = 5 },
+       [0x3c] = { .c = 0x6f, .l = 5 },
+       [0x3d] = { .c = 0x6f, .l = 5 },
+       [0x3e] = { .c = 0x6f, .l = 5 },
+       [0x3f] = { .c = 0x6f, .l = 5 },
+       [0x40] = { .c = 0x73, .l = 5 },
+       [0x41] = { .c = 0x73, .l = 5 },
+       [0x42] = { .c = 0x73, .l = 5 },
+       [0x43] = { .c = 0x73, .l = 5 },
+       [0x44] = { .c = 0x73, .l = 5 },
+       [0x45] = { .c = 0x73, .l = 5 },
+       [0x46] = { .c = 0x73, .l = 5 },
+       [0x47] = { .c = 0x73, .l = 5 },
+       [0x48] = { .c = 0x74, .l = 5 },
+       [0x49] = { .c = 0x74, .l = 5 },
+       [0x4a] = { .c = 0x74, .l = 5 },
+       [0x4b] = { .c = 0x74, .l = 5 },
+       [0x4c] = { .c = 0x74, .l = 5 },
+       [0x4d] = { .c = 0x74, .l = 5 },
+       [0x4e] = { .c = 0x74, .l = 5 },
+       [0x4f] = { .c = 0x74, .l = 5 },
+       [0x50] = { .c = 0x20, .l = 6 },
+       [0x51] = { .c = 0x20, .l = 6 },
+       [0x52] = { .c = 0x20, .l = 6 },
+       [0x53] = { .c = 0x20, .l = 6 },
+       [0x54] = { .c = 0x25, .l = 6 },
+       [0x55] = { .c = 0x25, .l = 6 },
+       [0x56] = { .c = 0x25, .l = 6 },
+       [0x57] = { .c = 0x25, .l = 6 },
+       [0x58] = { .c = 0x2d, .l = 6 },
+       [0x59] = { .c = 0x2d, .l = 6 },
+       [0x5a] = { .c = 0x2d, .l = 6 },
+       [0x5b] = { .c = 0x2d, .l = 6 },
+       [0x5c] = { .c = 0x2e, .l = 6 },
+       [0x5d] = { .c = 0x2e, .l = 6 },
+       [0x5e] = { .c = 0x2e, .l = 6 },
+       [0x5f] = { .c = 0x2e, .l = 6 },
+       [0x60] = { .c = 0x2f, .l = 6 },
+       [0x61] = { .c = 0x2f, .l = 6 },
+       [0x62] = { .c = 0x2f, .l = 6 },
+       [0x63] = { .c = 0x2f, .l = 6 },
+       [0x64] = { .c = 0x33, .l = 6 },
+       [0x65] = { .c = 0x33, .l = 6 },
+       [0x66] = { .c = 0x33, .l = 6 },
+       [0x67] = { .c = 0x33, .l = 6 },
+       [0x68] = { .c = 0x34, .l = 6 },
+       [0x69] = { .c = 0x34, .l = 6 },
+       [0x6a] = { .c = 0x34, .l = 6 },
+       [0x6b] = { .c = 0x34, .l = 6 },
+       [0x6c] = { .c = 0x35, .l = 6 },
+       [0x6d] = { .c = 0x35, .l = 6 },
+       [0x6e] = { .c = 0x35, .l = 6 },
+       [0x6f] = { .c = 0x35, .l = 6 },
+       [0x70] = { .c = 0x36, .l = 6 },
+       [0x71] = { .c = 0x36, .l = 6 },
+       [0x72] = { .c = 0x36, .l = 6 },
+       [0x73] = { .c = 0x36, .l = 6 },
+       [0x74] = { .c = 0x37, .l = 6 },
+       [0x75] = { .c = 0x37, .l = 6 },
+       [0x76] = { .c = 0x37, .l = 6 },
+       [0x77] = { .c = 0x37, .l = 6 },
+       [0x78] = { .c = 0x38, .l = 6 },
+       [0x79] = { .c = 0x38, .l = 6 },
+       [0x7a] = { .c = 0x38, .l = 6 },
+       [0x7b] = { .c = 0x38, .l = 6 },
+       [0x7c] = { .c = 0x39, .l = 6 },
+       [0x7d] = { .c = 0x39, .l = 6 },
+       [0x7e] = { .c = 0x39, .l = 6 },
+       [0x7f] = { .c = 0x39, .l = 6 },
+       [0x80] = { .c = 0x3d, .l = 6 },
+       [0x81] = { .c = 0x3d, .l = 6 },
+       [0x82] = { .c = 0x3d, .l = 6 },
+       [0x83] = { .c = 0x3d, .l = 6 },
+       [0x84] = { .c = 0x41, .l = 6 },
+       [0x85] = { .c = 0x41, .l = 6 },
+       [0x86] = { .c = 0x41, .l = 6 },
+       [0x87] = { .c = 0x41, .l = 6 },
+       [0x88] = { .c = 0x5f, .l = 6 },
+       [0x89] = { .c = 0x5f, .l = 6 },
+       [0x8a] = { .c = 0x5f, .l = 6 },
+       [0x8b] = { .c = 0x5f, .l = 6 },
+       [0x8c] = { .c = 0x62, .l = 6 },
+       [0x8d] = { .c = 0x62, .l = 6 },
+       [0x8e] = { .c = 0x62, .l = 6 },
+       [0x8f] = { .c = 0x62, .l = 6 },
+       [0x90] = { .c = 0x64, .l = 6 },
+       [0x91] = { .c = 0x64, .l = 6 },
+       [0x92] = { .c = 0x64, .l = 6 },
+       [0x93] = { .c = 0x64, .l = 6 },
+       [0x94] = { .c = 0x66, .l = 6 },
+       [0x95] = { .c = 0x66, .l = 6 },
+       [0x96] = { .c = 0x66, .l = 6 },
+       [0x97] = { .c = 0x66, .l = 6 },
+       [0x98] = { .c = 0x67, .l = 6 },
+       [0x99] = { .c = 0x67, .l = 6 },
+       [0x9a] = { .c = 0x67, .l = 6 },
+       [0x9b] = { .c = 0x67, .l = 6 },
+       [0x9c] = { .c = 0x68, .l = 6 },
+       [0x9d] = { .c = 0x68, .l = 6 },
+       [0x9e] = { .c = 0x68, .l = 6 },
+       [0x9f] = { .c = 0x68, .l = 6 },
+       [0xa0] = { .c = 0x6c, .l = 6 },
+       [0xa1] = { .c = 0x6c, .l = 6 },
+       [0xa2] = { .c = 0x6c, .l = 6 },
+       [0xa3] = { .c = 0x6c, .l = 6 },
+       [0xa4] = { .c = 0x6d, .l = 6 },
+       [0xa5] = { .c = 0x6d, .l = 6 },
+       [0xa6] = { .c = 0x6d, .l = 6 },
+       [0xa7] = { .c = 0x6d, .l = 6 },
+       [0xa8] = { .c = 0x6e, .l = 6 },
+       [0xa9] = { .c = 0x6e, .l = 6 },
+       [0xaa] = { .c = 0x6e, .l = 6 },
+       [0xab] = { .c = 0x6e, .l = 6 },
+       [0xac] = { .c = 0x70, .l = 6 },
+       [0xad] = { .c = 0x70, .l = 6 },
+       [0xae] = { .c = 0x70, .l = 6 },
+       [0xaf] = { .c = 0x70, .l = 6 },
+       [0xb0] = { .c = 0x72, .l = 6 },
+       [0xb1] = { .c = 0x72, .l = 6 },
+       [0xb2] = { .c = 0x72, .l = 6 },
+       [0xb3] = { .c = 0x72, .l = 6 },
+       [0xb4] = { .c = 0x75, .l = 6 },
+       [0xb5] = { .c = 0x75, .l = 6 },
+       [0xb6] = { .c = 0x75, .l = 6 },
+       [0xb7] = { .c = 0x75, .l = 6 },
+       [0xb8] = { .c = 0x3a, .l = 7 },
+       [0xb9] = { .c = 0x3a, .l = 7 },
+       [0xba] = { .c = 0x42, .l = 7 },
+       [0xbb] = { .c = 0x42, .l = 7 },
+       [0xbc] = { .c = 0x43, .l = 7 },
+       [0xbd] = { .c = 0x43, .l = 7 },
+       [0xbe] = { .c = 0x44, .l = 7 },
+       [0xbf] = { .c = 0x44, .l = 7 },
+       [0xc0] = { .c = 0x45, .l = 7 },
+       [0xc1] = { .c = 0x45, .l = 7 },
+       [0xc2] = { .c = 0x46, .l = 7 },
+       [0xc3] = { .c = 0x46, .l = 7 },
+       [0xc4] = { .c = 0x47, .l = 7 },
+       [0xc5] = { .c = 0x47, .l = 7 },
+       [0xc6] = { .c = 0x48, .l = 7 },
+       [0xc7] = { .c = 0x48, .l = 7 },
+       [0xc8] = { .c = 0x49, .l = 7 },
+       [0xc9] = { .c = 0x49, .l = 7 },
+       [0xca] = { .c = 0x4a, .l = 7 },
+       [0xcb] = { .c = 0x4a, .l = 7 },
+       [0xcc] = { .c = 0x4b, .l = 7 },
+       [0xcd] = { .c = 0x4b, .l = 7 },
+       [0xce] = { .c = 0x4c, .l = 7 },
+       [0xcf] = { .c = 0x4c, .l = 7 },
+       [0xd0] = { .c = 0x4d, .l = 7 },
+       [0xd1] = { .c = 0x4d, .l = 7 },
+       [0xd2] = { .c = 0x4e, .l = 7 },
+       [0xd3] = { .c = 0x4e, .l = 7 },
+       [0xd4] = { .c = 0x4f, .l = 7 },
+       [0xd5] = { .c = 0x4f, .l = 7 },
+       [0xd6] = { .c = 0x50, .l = 7 },
+       [0xd7] = { .c = 0x50, .l = 7 },
+       [0xd8] = { .c = 0x51, .l = 7 },
+       [0xd9] = { .c = 0x51, .l = 7 },
+       [0xda] = { .c = 0x52, .l = 7 },
+       [0xdb] = { .c = 0x52, .l = 7 },
+       [0xdc] = { .c = 0x53, .l = 7 },
+       [0xdd] = { .c = 0x53, .l = 7 },
+       [0xde] = { .c = 0x54, .l = 7 },
+       [0xdf] = { .c = 0x54, .l = 7 },
+       [0xe0] = { .c = 0x55, .l = 7 },
+       [0xe1] = { .c = 0x55, .l = 7 },
+       [0xe2] = { .c = 0x56, .l = 7 },
+       [0xe3] = { .c = 0x56, .l = 7 },
+       [0xe4] = { .c = 0x57, .l = 7 },
+       [0xe5] = { .c = 0x57, .l = 7 },
+       [0xe6] = { .c = 0x59, .l = 7 },
+       [0xe7] = { .c = 0x59, .l = 7 },
+       [0xe8] = { .c = 0x6a, .l = 7 },
+       [0xe9] = { .c = 0x6a, .l = 7 },
+       [0xea] = { .c = 0x6b, .l = 7 },
+       [0xeb] = { .c = 0x6b, .l = 7 },
+       [0xec] = { .c = 0x71, .l = 7 },
+       [0xed] = { .c = 0x71, .l = 7 },
+       [0xee] = { .c = 0x76, .l = 7 },
+       [0xef] = { .c = 0x76, .l = 7 },
+       [0xf0] = { .c = 0x77, .l = 7 },
+       [0xf1] = { .c = 0x77, .l = 7 },
+       [0xf2] = { .c = 0x78, .l = 7 },
+       [0xf3] = { .c = 0x78, .l = 7 },
+       [0xf4] = { .c = 0x79, .l = 7 },
+       [0xf5] = { .c = 0x79, .l = 7 },
+       [0xf6] = { .c = 0x7a, .l = 7 },
+       [0xf7] = { .c = 0x7a, .l = 7 },
+       [0xf8] = { .c = 0x26, .l = 8 },
+       [0xf9] = { .c = 0x2a, .l = 8 },
+       [0xfa] = { .c = 0x2c, .l = 8 },
+       [0xfb] = { .c = 0x3b, .l = 8 },
+       [0xfc] = { .c = 0x58, .l = 8 },
+       [0xfd] = { .c = 0x5a, .l = 8 },
+};
+
+struct rht rht_bit24_17[256] = {
+       [0x00] = { .c = 0x21, .l = 10 },
+       [0x01] = { .c = 0x21, .l = 10 },
+       [0x02] = { .c = 0x21, .l = 10 },
+       [0x03] = { .c = 0x21, .l = 10 },
+       [0x04] = { .c = 0x21, .l = 10 },
+       [0x05] = { .c = 0x21, .l = 10 },
+       [0x06] = { .c = 0x21, .l = 10 },
+       [0x07] = { .c = 0x21, .l = 10 },
+       [0x08] = { .c = 0x21, .l = 10 },
+       [0x09] = { .c = 0x21, .l = 10 },
+       [0x0a] = { .c = 0x21, .l = 10 },
+       [0x0b] = { .c = 0x21, .l = 10 },
+       [0x0c] = { .c = 0x21, .l = 10 },
+       [0x0d] = { .c = 0x21, .l = 10 },
+       [0x0e] = { .c = 0x21, .l = 10 },
+       [0x0f] = { .c = 0x21, .l = 10 },
+       [0x10] = { .c = 0x21, .l = 10 },
+       [0x11] = { .c = 0x21, .l = 10 },
+       [0x12] = { .c = 0x21, .l = 10 },
+       [0x13] = { .c = 0x21, .l = 10 },
+       [0x14] = { .c = 0x21, .l = 10 },
+       [0x15] = { .c = 0x21, .l = 10 },
+       [0x16] = { .c = 0x21, .l = 10 },
+       [0x17] = { .c = 0x21, .l = 10 },
+       [0x18] = { .c = 0x21, .l = 10 },
+       [0x19] = { .c = 0x21, .l = 10 },
+       [0x1a] = { .c = 0x21, .l = 10 },
+       [0x1b] = { .c = 0x21, .l = 10 },
+       [0x1c] = { .c = 0x21, .l = 10 },
+       [0x1d] = { .c = 0x21, .l = 10 },
+       [0x1e] = { .c = 0x21, .l = 10 },
+       [0x1f] = { .c = 0x21, .l = 10 },
+       [0x20] = { .c = 0x22, .l = 10 },
+       [0x21] = { .c = 0x22, .l = 10 },
+       [0x22] = { .c = 0x22, .l = 10 },
+       [0x23] = { .c = 0x22, .l = 10 },
+       [0x24] = { .c = 0x22, .l = 10 },
+       [0x25] = { .c = 0x22, .l = 10 },
+       [0x26] = { .c = 0x22, .l = 10 },
+       [0x27] = { .c = 0x22, .l = 10 },
+       [0x28] = { .c = 0x22, .l = 10 },
+       [0x29] = { .c = 0x22, .l = 10 },
+       [0x2a] = { .c = 0x22, .l = 10 },
+       [0x2b] = { .c = 0x22, .l = 10 },
+       [0x2c] = { .c = 0x22, .l = 10 },
+       [0x2d] = { .c = 0x22, .l = 10 },
+       [0x2e] = { .c = 0x22, .l = 10 },
+       [0x2f] = { .c = 0x22, .l = 10 },
+       [0x30] = { .c = 0x22, .l = 10 },
+       [0x31] = { .c = 0x22, .l = 10 },
+       [0x32] = { .c = 0x22, .l = 10 },
+       [0x33] = { .c = 0x22, .l = 10 },
+       [0x34] = { .c = 0x22, .l = 10 },
+       [0x35] = { .c = 0x22, .l = 10 },
+       [0x36] = { .c = 0x22, .l = 10 },
+       [0x37] = { .c = 0x22, .l = 10 },
+       [0x38] = { .c = 0x22, .l = 10 },
+       [0x39] = { .c = 0x22, .l = 10 },
+       [0x3a] = { .c = 0x22, .l = 10 },
+       [0x3b] = { .c = 0x22, .l = 10 },
+       [0x3c] = { .c = 0x22, .l = 10 },
+       [0x3d] = { .c = 0x22, .l = 10 },
+       [0x3e] = { .c = 0x22, .l = 10 },
+       [0x3f] = { .c = 0x22, .l = 10 },
+       [0x40] = { .c = 0x28, .l = 10 },
+       [0x41] = { .c = 0x28, .l = 10 },
+       [0x42] = { .c = 0x28, .l = 10 },
+       [0x43] = { .c = 0x28, .l = 10 },
+       [0x44] = { .c = 0x28, .l = 10 },
+       [0x45] = { .c = 0x28, .l = 10 },
+       [0x46] = { .c = 0x28, .l = 10 },
+       [0x47] = { .c = 0x28, .l = 10 },
+       [0x48] = { .c = 0x28, .l = 10 },
+       [0x49] = { .c = 0x28, .l = 10 },
+       [0x4a] = { .c = 0x28, .l = 10 },
+       [0x4b] = { .c = 0x28, .l = 10 },
+       [0x4c] = { .c = 0x28, .l = 10 },
+       [0x4d] = { .c = 0x28, .l = 10 },
+       [0x4e] = { .c = 0x28, .l = 10 },
+       [0x4f] = { .c = 0x28, .l = 10 },
+       [0x50] = { .c = 0x28, .l = 10 },
+       [0x51] = { .c = 0x28, .l = 10 },
+       [0x52] = { .c = 0x28, .l = 10 },
+       [0x53] = { .c = 0x28, .l = 10 },
+       [0x54] = { .c = 0x28, .l = 10 },
+       [0x55] = { .c = 0x28, .l = 10 },
+       [0x56] = { .c = 0x28, .l = 10 },
+       [0x57] = { .c = 0x28, .l = 10 },
+       [0x58] = { .c = 0x28, .l = 10 },
+       [0x59] = { .c = 0x28, .l = 10 },
+       [0x5a] = { .c = 0x28, .l = 10 },
+       [0x5b] = { .c = 0x28, .l = 10 },
+       [0x5c] = { .c = 0x28, .l = 10 },
+       [0x5d] = { .c = 0x28, .l = 10 },
+       [0x5e] = { .c = 0x28, .l = 10 },
+       [0x5f] = { .c = 0x28, .l = 10 },
+       [0x60] = { .c = 0x29, .l = 10 },
+       [0x61] = { .c = 0x29, .l = 10 },
+       [0x62] = { .c = 0x29, .l = 10 },
+       [0x63] = { .c = 0x29, .l = 10 },
+       [0x64] = { .c = 0x29, .l = 10 },
+       [0x65] = { .c = 0x29, .l = 10 },
+       [0x66] = { .c = 0x29, .l = 10 },
+       [0x67] = { .c = 0x29, .l = 10 },
+       [0x68] = { .c = 0x29, .l = 10 },
+       [0x69] = { .c = 0x29, .l = 10 },
+       [0x6a] = { .c = 0x29, .l = 10 },
+       [0x6b] = { .c = 0x29, .l = 10 },
+       [0x6c] = { .c = 0x29, .l = 10 },
+       [0x6d] = { .c = 0x29, .l = 10 },
+       [0x6e] = { .c = 0x29, .l = 10 },
+       [0x6f] = { .c = 0x29, .l = 10 },
+       [0x70] = { .c = 0x29, .l = 10 },
+       [0x71] = { .c = 0x29, .l = 10 },
+       [0x72] = { .c = 0x29, .l = 10 },
+       [0x73] = { .c = 0x29, .l = 10 },
+       [0x74] = { .c = 0x29, .l = 10 },
+       [0x75] = { .c = 0x29, .l = 10 },
+       [0x76] = { .c = 0x29, .l = 10 },
+       [0x77] = { .c = 0x29, .l = 10 },
+       [0x78] = { .c = 0x29, .l = 10 },
+       [0x79] = { .c = 0x29, .l = 10 },
+       [0x7a] = { .c = 0x29, .l = 10 },
+       [0x7b] = { .c = 0x29, .l = 10 },
+       [0x7c] = { .c = 0x29, .l = 10 },
+       [0x7d] = { .c = 0x29, .l = 10 },
+       [0x7e] = { .c = 0x29, .l = 10 },
+       [0x7f] = { .c = 0x29, .l = 10 },
+       [0x80] = { .c = 0x3f, .l = 10 },
+       [0x81] = { .c = 0x3f, .l = 10 },
+       [0x82] = { .c = 0x3f, .l = 10 },
+       [0x83] = { .c = 0x3f, .l = 10 },
+       [0x84] = { .c = 0x3f, .l = 10 },
+       [0x85] = { .c = 0x3f, .l = 10 },
+       [0x86] = { .c = 0x3f, .l = 10 },
+       [0x87] = { .c = 0x3f, .l = 10 },
+       [0x88] = { .c = 0x3f, .l = 10 },
+       [0x89] = { .c = 0x3f, .l = 10 },
+       [0x8a] = { .c = 0x3f, .l = 10 },
+       [0x8b] = { .c = 0x3f, .l = 10 },
+       [0x8c] = { .c = 0x3f, .l = 10 },
+       [0x8d] = { .c = 0x3f, .l = 10 },
+       [0x8e] = { .c = 0x3f, .l = 10 },
+       [0x8f] = { .c = 0x3f, .l = 10 },
+       [0x90] = { .c = 0x3f, .l = 10 },
+       [0x91] = { .c = 0x3f, .l = 10 },
+       [0x92] = { .c = 0x3f, .l = 10 },
+       [0x93] = { .c = 0x3f, .l = 10 },
+       [0x94] = { .c = 0x3f, .l = 10 },
+       [0x95] = { .c = 0x3f, .l = 10 },
+       [0x96] = { .c = 0x3f, .l = 10 },
+       [0x97] = { .c = 0x3f, .l = 10 },
+       [0x98] = { .c = 0x3f, .l = 10 },
+       [0x99] = { .c = 0x3f, .l = 10 },
+       [0x9a] = { .c = 0x3f, .l = 10 },
+       [0x9b] = { .c = 0x3f, .l = 10 },
+       [0x9c] = { .c = 0x3f, .l = 10 },
+       [0x9d] = { .c = 0x3f, .l = 10 },
+       [0x9e] = { .c = 0x3f, .l = 10 },
+       [0x9f] = { .c = 0x3f, .l = 10 },
+       [0xa0] = { .c = 0x27, .l = 11 },
+       [0xa1] = { .c = 0x27, .l = 11 },
+       [0xa2] = { .c = 0x27, .l = 11 },
+       [0xa3] = { .c = 0x27, .l = 11 },
+       [0xa4] = { .c = 0x27, .l = 11 },
+       [0xa5] = { .c = 0x27, .l = 11 },
+       [0xa6] = { .c = 0x27, .l = 11 },
+       [0xa7] = { .c = 0x27, .l = 11 },
+       [0xa8] = { .c = 0x27, .l = 11 },
+       [0xa9] = { .c = 0x27, .l = 11 },
+       [0xaa] = { .c = 0x27, .l = 11 },
+       [0xab] = { .c = 0x27, .l = 11 },
+       [0xac] = { .c = 0x27, .l = 11 },
+       [0xad] = { .c = 0x27, .l = 11 },
+       [0xae] = { .c = 0x27, .l = 11 },
+       [0xaf] = { .c = 0x27, .l = 11 },
+       [0xb0] = { .c = 0x2b, .l = 11 },
+       [0xb1] = { .c = 0x2b, .l = 11 },
+       [0xb2] = { .c = 0x2b, .l = 11 },
+       [0xb3] = { .c = 0x2b, .l = 11 },
+       [0xb4] = { .c = 0x2b, .l = 11 },
+       [0xb5] = { .c = 0x2b, .l = 11 },
+       [0xb6] = { .c = 0x2b, .l = 11 },
+       [0xb7] = { .c = 0x2b, .l = 11 },
+       [0xb8] = { .c = 0x2b, .l = 11 },
+       [0xb9] = { .c = 0x2b, .l = 11 },
+       [0xba] = { .c = 0x2b, .l = 11 },
+       [0xbb] = { .c = 0x2b, .l = 11 },
+       [0xbc] = { .c = 0x2b, .l = 11 },
+       [0xbd] = { .c = 0x2b, .l = 11 },
+       [0xbe] = { .c = 0x2b, .l = 11 },
+       [0xbf] = { .c = 0x2b, .l = 11 },
+       [0xc0] = { .c = 0x7c, .l = 11 },
+       [0xc1] = { .c = 0x7c, .l = 11 },
+       [0xc2] = { .c = 0x7c, .l = 11 },
+       [0xc3] = { .c = 0x7c, .l = 11 },
+       [0xc4] = { .c = 0x7c, .l = 11 },
+       [0xc5] = { .c = 0x7c, .l = 11 },
+       [0xc6] = { .c = 0x7c, .l = 11 },
+       [0xc7] = { .c = 0x7c, .l = 11 },
+       [0xc8] = { .c = 0x7c, .l = 11 },
+       [0xc9] = { .c = 0x7c, .l = 11 },
+       [0xca] = { .c = 0x7c, .l = 11 },
+       [0xcb] = { .c = 0x7c, .l = 11 },
+       [0xcc] = { .c = 0x7c, .l = 11 },
+       [0xcd] = { .c = 0x7c, .l = 11 },
+       [0xce] = { .c = 0x7c, .l = 11 },
+       [0xcf] = { .c = 0x7c, .l = 11 },
+       [0xd0] = { .c = 0x23, .l = 12 },
+       [0xd1] = { .c = 0x23, .l = 12 },
+       [0xd2] = { .c = 0x23, .l = 12 },
+       [0xd3] = { .c = 0x23, .l = 12 },
+       [0xd4] = { .c = 0x23, .l = 12 },
+       [0xd5] = { .c = 0x23, .l = 12 },
+       [0xd6] = { .c = 0x23, .l = 12 },
+       [0xd7] = { .c = 0x23, .l = 12 },
+       [0xd8] = { .c = 0x3e, .l = 12 },
+       [0xd9] = { .c = 0x3e, .l = 12 },
+       [0xda] = { .c = 0x3e, .l = 12 },
+       [0xdb] = { .c = 0x3e, .l = 12 },
+       [0xdc] = { .c = 0x3e, .l = 12 },
+       [0xdd] = { .c = 0x3e, .l = 12 },
+       [0xde] = { .c = 0x3e, .l = 12 },
+       [0xdf] = { .c = 0x3e, .l = 12 },
+       [0xe0] = { .c = 0x00, .l = 13 },
+       [0xe1] = { .c = 0x00, .l = 13 },
+       [0xe2] = { .c = 0x00, .l = 13 },
+       [0xe3] = { .c = 0x00, .l = 13 },
+       [0xe4] = { .c = 0x24, .l = 13 },
+       [0xe5] = { .c = 0x24, .l = 13 },
+       [0xe6] = { .c = 0x24, .l = 13 },
+       [0xe7] = { .c = 0x24, .l = 13 },
+       [0xe8] = { .c = 0x40, .l = 13 },
+       [0xe9] = { .c = 0x40, .l = 13 },
+       [0xea] = { .c = 0x40, .l = 13 },
+       [0xeb] = { .c = 0x40, .l = 13 },
+       [0xec] = { .c = 0x5b, .l = 13 },
+       [0xed] = { .c = 0x5b, .l = 13 },
+       [0xee] = { .c = 0x5b, .l = 13 },
+       [0xef] = { .c = 0x5b, .l = 13 },
+       [0xf0] = { .c = 0x5d, .l = 13 },
+       [0xf1] = { .c = 0x5d, .l = 13 },
+       [0xf2] = { .c = 0x5d, .l = 13 },
+       [0xf3] = { .c = 0x5d, .l = 13 },
+       [0xf4] = { .c = 0x7e, .l = 13 },
+       [0xf5] = { .c = 0x7e, .l = 13 },
+       [0xf6] = { .c = 0x7e, .l = 13 },
+       [0xf7] = { .c = 0x7e, .l = 13 },
+       [0xf8] = { .c = 0x5e, .l = 14 },
+       [0xf9] = { .c = 0x5e, .l = 14 },
+       [0xfa] = { .c = 0x7d, .l = 14 },
+       [0xfb] = { .c = 0x7d, .l = 14 },
+       [0xfc] = { .c = 0x3c, .l = 15 },
+       [0xfd] = { .c = 0x60, .l = 15 },
+       [0xfe] = { .c = 0x7b, .l = 15 },
+};
+
+struct rht rht_bit15_11_fe[32] = {
+       [0x00] = { .c = 0x5c, .l = 19 },
+       [0x01] = { .c = 0x5c, .l = 19 },
+       [0x02] = { .c = 0x5c, .l = 19 },
+       [0x03] = { .c = 0x5c, .l = 19 },
+       [0x04] = { .c = 0xc3, .l = 19 },
+       [0x05] = { .c = 0xc3, .l = 19 },
+       [0x06] = { .c = 0xc3, .l = 19 },
+       [0x07] = { .c = 0xc3, .l = 19 },
+       [0x08] = { .c = 0xd0, .l = 19 },
+       [0x09] = { .c = 0xd0, .l = 19 },
+       [0x0a] = { .c = 0xd0, .l = 19 },
+       [0x0b] = { .c = 0xd0, .l = 19 },
+       [0x0c] = { .c = 0x80, .l = 20 },
+       [0x0d] = { .c = 0x80, .l = 20 },
+       [0x0e] = { .c = 0x82, .l = 20 },
+       [0x0f] = { .c = 0x82, .l = 20 },
+       [0x10] = { .c = 0x83, .l = 20 },
+       [0x11] = { .c = 0x83, .l = 20 },
+       [0x12] = { .c = 0xa2, .l = 20 },
+       [0x13] = { .c = 0xa2, .l = 20 },
+       [0x14] = { .c = 0xb8, .l = 20 },
+       [0x15] = { .c = 0xb8, .l = 20 },
+       [0x16] = { .c = 0xc2, .l = 20 },
+       [0x17] = { .c = 0xc2, .l = 20 },
+       [0x18] = { .c = 0xe0, .l = 20 },
+       [0x19] = { .c = 0xe0, .l = 20 },
+       [0x1a] = { .c = 0xe2, .l = 20 },
+       [0x1b] = { .c = 0xe2, .l = 20 },
+       [0x1c] = { .c = 0x99, .l = 21 },
+       [0x1d] = { .c = 0xa1, .l = 21 },
+       [0x1e] = { .c = 0xa7, .l = 21 },
+       [0x1f] = { .c = 0xac, .l = 21 },
+};
+
+struct rht rht_bit15_8[256] = {
+       [0x00] = { .c = 0xb0, .l = 21 },
+       [0x01] = { .c = 0xb0, .l = 21 },
+       [0x02] = { .c = 0xb0, .l = 21 },
+       [0x03] = { .c = 0xb0, .l = 21 },
+       [0x04] = { .c = 0xb0, .l = 21 },
+       [0x05] = { .c = 0xb0, .l = 21 },
+       [0x06] = { .c = 0xb0, .l = 21 },
+       [0x07] = { .c = 0xb0, .l = 21 },
+       [0x08] = { .c = 0xb1, .l = 21 },
+       [0x09] = { .c = 0xb1, .l = 21 },
+       [0x0a] = { .c = 0xb1, .l = 21 },
+       [0x0b] = { .c = 0xb1, .l = 21 },
+       [0x0c] = { .c = 0xb1, .l = 21 },
+       [0x0d] = { .c = 0xb1, .l = 21 },
+       [0x0e] = { .c = 0xb1, .l = 21 },
+       [0x0f] = { .c = 0xb1, .l = 21 },
+       [0x10] = { .c = 0xb3, .l = 21 },
+       [0x11] = { .c = 0xb3, .l = 21 },
+       [0x12] = { .c = 0xb3, .l = 21 },
+       [0x13] = { .c = 0xb3, .l = 21 },
+       [0x14] = { .c = 0xb3, .l = 21 },
+       [0x15] = { .c = 0xb3, .l = 21 },
+       [0x16] = { .c = 0xb3, .l = 21 },
+       [0x17] = { .c = 0xb3, .l = 21 },
+       [0x18] = { .c = 0xd1, .l = 21 },
+       [0x19] = { .c = 0xd1, .l = 21 },
+       [0x1a] = { .c = 0xd1, .l = 21 },
+       [0x1b] = { .c = 0xd1, .l = 21 },
+       [0x1c] = { .c = 0xd1, .l = 21 },
+       [0x1d] = { .c = 0xd1, .l = 21 },
+       [0x1e] = { .c = 0xd1, .l = 21 },
+       [0x1f] = { .c = 0xd1, .l = 21 },
+       [0x20] = { .c = 0xd8, .l = 21 },
+       [0x21] = { .c = 0xd8, .l = 21 },
+       [0x22] = { .c = 0xd8, .l = 21 },
+       [0x23] = { .c = 0xd8, .l = 21 },
+       [0x24] = { .c = 0xd8, .l = 21 },
+       [0x25] = { .c = 0xd8, .l = 21 },
+       [0x26] = { .c = 0xd8, .l = 21 },
+       [0x27] = { .c = 0xd8, .l = 21 },
+       [0x28] = { .c = 0xd9, .l = 21 },
+       [0x29] = { .c = 0xd9, .l = 21 },
+       [0x2a] = { .c = 0xd9, .l = 21 },
+       [0x2b] = { .c = 0xd9, .l = 21 },
+       [0x2c] = { .c = 0xd9, .l = 21 },
+       [0x2d] = { .c = 0xd9, .l = 21 },
+       [0x2e] = { .c = 0xd9, .l = 21 },
+       [0x2f] = { .c = 0xd9, .l = 21 },
+       [0x30] = { .c = 0xe3, .l = 21 },
+       [0x31] = { .c = 0xe3, .l = 21 },
+       [0x32] = { .c = 0xe3, .l = 21 },
+       [0x33] = { .c = 0xe3, .l = 21 },
+       [0x34] = { .c = 0xe3, .l = 21 },
+       [0x35] = { .c = 0xe3, .l = 21 },
+       [0x36] = { .c = 0xe3, .l = 21 },
+       [0x37] = { .c = 0xe3, .l = 21 },
+       [0x38] = { .c = 0xe5, .l = 21 },
+       [0x39] = { .c = 0xe5, .l = 21 },
+       [0x3a] = { .c = 0xe5, .l = 21 },
+       [0x3b] = { .c = 0xe5, .l = 21 },
+       [0x3c] = { .c = 0xe5, .l = 21 },
+       [0x3d] = { .c = 0xe5, .l = 21 },
+       [0x3e] = { .c = 0xe5, .l = 21 },
+       [0x3f] = { .c = 0xe5, .l = 21 },
+       [0x40] = { .c = 0xe6, .l = 21 },
+       [0x41] = { .c = 0xe6, .l = 21 },
+       [0x42] = { .c = 0xe6, .l = 21 },
+       [0x43] = { .c = 0xe6, .l = 21 },
+       [0x44] = { .c = 0xe6, .l = 21 },
+       [0x45] = { .c = 0xe6, .l = 21 },
+       [0x46] = { .c = 0xe6, .l = 21 },
+       [0x47] = { .c = 0xe6, .l = 21 },
+       [0x48] = { .c = 0x81, .l = 22 },
+       [0x49] = { .c = 0x81, .l = 22 },
+       [0x4a] = { .c = 0x81, .l = 22 },
+       [0x4b] = { .c = 0x81, .l = 22 },
+       [0x4c] = { .c = 0x84, .l = 22 },
+       [0x4d] = { .c = 0x84, .l = 22 },
+       [0x4e] = { .c = 0x84, .l = 22 },
+       [0x4f] = { .c = 0x84, .l = 22 },
+       [0x50] = { .c = 0x85, .l = 22 },
+       [0x51] = { .c = 0x85, .l = 22 },
+       [0x52] = { .c = 0x85, .l = 22 },
+       [0x53] = { .c = 0x85, .l = 22 },
+       [0x54] = { .c = 0x86, .l = 22 },
+       [0x55] = { .c = 0x86, .l = 22 },
+       [0x56] = { .c = 0x86, .l = 22 },
+       [0x57] = { .c = 0x86, .l = 22 },
+       [0x58] = { .c = 0x88, .l = 22 },
+       [0x59] = { .c = 0x88, .l = 22 },
+       [0x5a] = { .c = 0x88, .l = 22 },
+       [0x5b] = { .c = 0x88, .l = 22 },
+       [0x5c] = { .c = 0x92, .l = 22 },
+       [0x5d] = { .c = 0x92, .l = 22 },
+       [0x5e] = { .c = 0x92, .l = 22 },
+       [0x5f] = { .c = 0x92, .l = 22 },
+       [0x60] = { .c = 0x9a, .l = 22 },
+       [0x61] = { .c = 0x9a, .l = 22 },
+       [0x62] = { .c = 0x9a, .l = 22 },
+       [0x63] = { .c = 0x9a, .l = 22 },
+       [0x64] = { .c = 0x9c, .l = 22 },
+       [0x65] = { .c = 0x9c, .l = 22 },
+       [0x66] = { .c = 0x9c, .l = 22 },
+       [0x67] = { .c = 0x9c, .l = 22 },
+       [0x68] = { .c = 0xa0, .l = 22 },
+       [0x69] = { .c = 0xa0, .l = 22 },
+       [0x6a] = { .c = 0xa0, .l = 22 },
+       [0x6b] = { .c = 0xa0, .l = 22 },
+       [0x6c] = { .c = 0xa3, .l = 22 },
+       [0x6d] = { .c = 0xa3, .l = 22 },
+       [0x6e] = { .c = 0xa3, .l = 22 },
+       [0x6f] = { .c = 0xa3, .l = 22 },
+       [0x70] = { .c = 0xa4, .l = 22 },
+       [0x71] = { .c = 0xa4, .l = 22 },
+       [0x72] = { .c = 0xa4, .l = 22 },
+       [0x73] = { .c = 0xa4, .l = 22 },
+       [0x74] = { .c = 0xa9, .l = 22 },
+       [0x75] = { .c = 0xa9, .l = 22 },
+       [0x76] = { .c = 0xa9, .l = 22 },
+       [0x77] = { .c = 0xa9, .l = 22 },
+       [0x78] = { .c = 0xaa, .l = 22 },
+       [0x79] = { .c = 0xaa, .l = 22 },
+       [0x7a] = { .c = 0xaa, .l = 22 },
+       [0x7b] = { .c = 0xaa, .l = 22 },
+       [0x7c] = { .c = 0xad, .l = 22 },
+       [0x7d] = { .c = 0xad, .l = 22 },
+       [0x7e] = { .c = 0xad, .l = 22 },
+       [0x7f] = { .c = 0xad, .l = 22 },
+       [0x80] = { .c = 0xb2, .l = 22 },
+       [0x81] = { .c = 0xb2, .l = 22 },
+       [0x82] = { .c = 0xb2, .l = 22 },
+       [0x83] = { .c = 0xb2, .l = 22 },
+       [0x84] = { .c = 0xb5, .l = 22 },
+       [0x85] = { .c = 0xb5, .l = 22 },
+       [0x86] = { .c = 0xb5, .l = 22 },
+       [0x87] = { .c = 0xb5, .l = 22 },
+       [0x88] = { .c = 0xb9, .l = 22 },
+       [0x89] = { .c = 0xb9, .l = 22 },
+       [0x8a] = { .c = 0xb9, .l = 22 },
+       [0x8b] = { .c = 0xb9, .l = 22 },
+       [0x8c] = { .c = 0xba, .l = 22 },
+       [0x8d] = { .c = 0xba, .l = 22 },
+       [0x8e] = { .c = 0xba, .l = 22 },
+       [0x8f] = { .c = 0xba, .l = 22 },
+       [0x90] = { .c = 0xbb, .l = 22 },
+       [0x91] = { .c = 0xbb, .l = 22 },
+       [0x92] = { .c = 0xbb, .l = 22 },
+       [0x93] = { .c = 0xbb, .l = 22 },
+       [0x94] = { .c = 0xbd, .l = 22 },
+       [0x95] = { .c = 0xbd, .l = 22 },
+       [0x96] = { .c = 0xbd, .l = 22 },
+       [0x97] = { .c = 0xbd, .l = 22 },
+       [0x98] = { .c = 0xbe, .l = 22 },
+       [0x99] = { .c = 0xbe, .l = 22 },
+       [0x9a] = { .c = 0xbe, .l = 22 },
+       [0x9b] = { .c = 0xbe, .l = 22 },
+       [0x9c] = { .c = 0xc4, .l = 22 },
+       [0x9d] = { .c = 0xc4, .l = 22 },
+       [0x9e] = { .c = 0xc4, .l = 22 },
+       [0x9f] = { .c = 0xc4, .l = 22 },
+       [0xa0] = { .c = 0xc6, .l = 22 },
+       [0xa1] = { .c = 0xc6, .l = 22 },
+       [0xa2] = { .c = 0xc6, .l = 22 },
+       [0xa3] = { .c = 0xc6, .l = 22 },
+       [0xa4] = { .c = 0xe4, .l = 22 },
+       [0xa5] = { .c = 0xe4, .l = 22 },
+       [0xa6] = { .c = 0xe4, .l = 22 },
+       [0xa7] = { .c = 0xe4, .l = 22 },
+       [0xa8] = { .c = 0xe8, .l = 22 },
+       [0xa9] = { .c = 0xe8, .l = 22 },
+       [0xaa] = { .c = 0xe8, .l = 22 },
+       [0xab] = { .c = 0xe8, .l = 22 },
+       [0xac] = { .c = 0xe9, .l = 22 },
+       [0xad] = { .c = 0xe9, .l = 22 },
+       [0xae] = { .c = 0xe9, .l = 22 },
+       [0xaf] = { .c = 0xe9, .l = 22 },
+       [0xb0] = { .c = 0x01, .l = 23 },
+       [0xb1] = { .c = 0x01, .l = 23 },
+       [0xb2] = { .c = 0x87, .l = 23 },
+       [0xb3] = { .c = 0x87, .l = 23 },
+       [0xb4] = { .c = 0x89, .l = 23 },
+       [0xb5] = { .c = 0x89, .l = 23 },
+       [0xb6] = { .c = 0x8a, .l = 23 },
+       [0xb7] = { .c = 0x8a, .l = 23 },
+       [0xb8] = { .c = 0x8b, .l = 23 },
+       [0xb9] = { .c = 0x8b, .l = 23 },
+       [0xba] = { .c = 0x8c, .l = 23 },
+       [0xbb] = { .c = 0x8c, .l = 23 },
+       [0xbc] = { .c = 0x8d, .l = 23 },
+       [0xbd] = { .c = 0x8d, .l = 23 },
+       [0xbe] = { .c = 0x8f, .l = 23 },
+       [0xbf] = { .c = 0x8f, .l = 23 },
+       [0xc0] = { .c = 0x93, .l = 23 },
+       [0xc1] = { .c = 0x93, .l = 23 },
+       [0xc2] = { .c = 0x95, .l = 23 },
+       [0xc3] = { .c = 0x95, .l = 23 },
+       [0xc4] = { .c = 0x96, .l = 23 },
+       [0xc5] = { .c = 0x96, .l = 23 },
+       [0xc6] = { .c = 0x97, .l = 23 },
+       [0xc7] = { .c = 0x97, .l = 23 },
+       [0xc8] = { .c = 0x98, .l = 23 },
+       [0xc9] = { .c = 0x98, .l = 23 },
+       [0xca] = { .c = 0x9b, .l = 23 },
+       [0xcb] = { .c = 0x9b, .l = 23 },
+       [0xcc] = { .c = 0x9d, .l = 23 },
+       [0xcd] = { .c = 0x9d, .l = 23 },
+       [0xce] = { .c = 0x9e, .l = 23 },
+       [0xcf] = { .c = 0x9e, .l = 23 },
+       [0xd0] = { .c = 0xa5, .l = 23 },
+       [0xd1] = { .c = 0xa5, .l = 23 },
+       [0xd2] = { .c = 0xa6, .l = 23 },
+       [0xd3] = { .c = 0xa6, .l = 23 },
+       [0xd4] = { .c = 0xa8, .l = 23 },
+       [0xd5] = { .c = 0xa8, .l = 23 },
+       [0xd6] = { .c = 0xae, .l = 23 },
+       [0xd7] = { .c = 0xae, .l = 23 },
+       [0xd8] = { .c = 0xaf, .l = 23 },
+       [0xd9] = { .c = 0xaf, .l = 23 },
+       [0xda] = { .c = 0xb4, .l = 23 },
+       [0xdb] = { .c = 0xb4, .l = 23 },
+       [0xdc] = { .c = 0xb6, .l = 23 },
+       [0xdd] = { .c = 0xb6, .l = 23 },
+       [0xde] = { .c = 0xb7, .l = 23 },
+       [0xdf] = { .c = 0xb7, .l = 23 },
+       [0xe0] = { .c = 0xbc, .l = 23 },
+       [0xe1] = { .c = 0xbc, .l = 23 },
+       [0xe2] = { .c = 0xbf, .l = 23 },
+       [0xe3] = { .c = 0xbf, .l = 23 },
+       [0xe4] = { .c = 0xc5, .l = 23 },
+       [0xe5] = { .c = 0xc5, .l = 23 },
+       [0xe6] = { .c = 0xe7, .l = 23 },
+       [0xe7] = { .c = 0xe7, .l = 23 },
+       [0xe8] = { .c = 0xef, .l = 23 },
+       [0xe9] = { .c = 0xef, .l = 23 },
+       [0xea] = { .c = 0x09, .l = 24 },
+       [0xeb] = { .c = 0x8e, .l = 24 },
+       [0xec] = { .c = 0x90, .l = 24 },
+       [0xed] = { .c = 0x91, .l = 24 },
+       [0xee] = { .c = 0x94, .l = 24 },
+       [0xef] = { .c = 0x9f, .l = 24 },
+       [0xf0] = { .c = 0xab, .l = 24 },
+       [0xf1] = { .c = 0xce, .l = 24 },
+       [0xf2] = { .c = 0xd7, .l = 24 },
+       [0xf3] = { .c = 0xe1, .l = 24 },
+       [0xf4] = { .c = 0xec, .l = 24 },
+       [0xf5] = { .c = 0xed, .l = 24 },
+};
+
+struct rht rht_bit11_4[256] = {
+       [0x60] = { .c = 0xc7, .l = 25 },
+       [0x61] = { .c = 0xc7, .l = 25 },
+       [0x62] = { .c = 0xc7, .l = 25 },
+       [0x63] = { .c = 0xc7, .l = 25 },
+       [0x64] = { .c = 0xc7, .l = 25 },
+       [0x65] = { .c = 0xc7, .l = 25 },
+       [0x66] = { .c = 0xc7, .l = 25 },
+       [0x67] = { .c = 0xc7, .l = 25 },
+       [0x68] = { .c = 0xcf, .l = 25 },
+       [0x69] = { .c = 0xcf, .l = 25 },
+       [0x6a] = { .c = 0xcf, .l = 25 },
+       [0x6b] = { .c = 0xcf, .l = 25 },
+       [0x6c] = { .c = 0xcf, .l = 25 },
+       [0x6d] = { .c = 0xcf, .l = 25 },
+       [0x6e] = { .c = 0xcf, .l = 25 },
+       [0x6f] = { .c = 0xcf, .l = 25 },
+       [0x70] = { .c = 0xea, .l = 25 },
+       [0x71] = { .c = 0xea, .l = 25 },
+       [0x72] = { .c = 0xea, .l = 25 },
+       [0x73] = { .c = 0xea, .l = 25 },
+       [0x74] = { .c = 0xea, .l = 25 },
+       [0x75] = { .c = 0xea, .l = 25 },
+       [0x76] = { .c = 0xea, .l = 25 },
+       [0x77] = { .c = 0xea, .l = 25 },
+       [0x78] = { .c = 0xeb, .l = 25 },
+       [0x79] = { .c = 0xeb, .l = 25 },
+       [0x7a] = { .c = 0xeb, .l = 25 },
+       [0x7b] = { .c = 0xeb, .l = 25 },
+       [0x7c] = { .c = 0xeb, .l = 25 },
+       [0x7d] = { .c = 0xeb, .l = 25 },
+       [0x7e] = { .c = 0xeb, .l = 25 },
+       [0x7f] = { .c = 0xeb, .l = 25 },
+       [0x80] = { .c = 0xc0, .l = 26 },
+       [0x81] = { .c = 0xc0, .l = 26 },
+       [0x82] = { .c = 0xc0, .l = 26 },
+       [0x83] = { .c = 0xc0, .l = 26 },
+       [0x84] = { .c = 0xc1, .l = 26 },
+       [0x85] = { .c = 0xc1, .l = 26 },
+       [0x86] = { .c = 0xc1, .l = 26 },
+       [0x87] = { .c = 0xc1, .l = 26 },
+       [0x88] = { .c = 0xc8, .l = 26 },
+       [0x89] = { .c = 0xc8, .l = 26 },
+       [0x8a] = { .c = 0xc8, .l = 26 },
+       [0x8b] = { .c = 0xc8, .l = 26 },
+       [0x8c] = { .c = 0xc9, .l = 26 },
+       [0x8d] = { .c = 0xc9, .l = 26 },
+       [0x8e] = { .c = 0xc9, .l = 26 },
+       [0x8f] = { .c = 0xc9, .l = 26 },
+       [0x90] = { .c = 0xca, .l = 26 },
+       [0x91] = { .c = 0xca, .l = 26 },
+       [0x92] = { .c = 0xca, .l = 26 },
+       [0x93] = { .c = 0xca, .l = 26 },
+       [0x94] = { .c = 0xcd, .l = 26 },
+       [0x95] = { .c = 0xcd, .l = 26 },
+       [0x96] = { .c = 0xcd, .l = 26 },
+       [0x97] = { .c = 0xcd, .l = 26 },
+       [0x98] = { .c = 0xd2, .l = 26 },
+       [0x99] = { .c = 0xd2, .l = 26 },
+       [0x9a] = { .c = 0xd2, .l = 26 },
+       [0x9b] = { .c = 0xd2, .l = 26 },
+       [0x9c] = { .c = 0xd5, .l = 26 },
+       [0x9d] = { .c = 0xd5, .l = 26 },
+       [0x9e] = { .c = 0xd5, .l = 26 },
+       [0x9f] = { .c = 0xd5, .l = 26 },
+       [0xa0] = { .c = 0xda, .l = 26 },
+       [0xa1] = { .c = 0xda, .l = 26 },
+       [0xa2] = { .c = 0xda, .l = 26 },
+       [0xa3] = { .c = 0xda, .l = 26 },
+       [0xa4] = { .c = 0xdb, .l = 26 },
+       [0xa5] = { .c = 0xdb, .l = 26 },
+       [0xa6] = { .c = 0xdb, .l = 26 },
+       [0xa7] = { .c = 0xdb, .l = 26 },
+       [0xa8] = { .c = 0xee, .l = 26 },
+       [0xa9] = { .c = 0xee, .l = 26 },
+       [0xaa] = { .c = 0xee, .l = 26 },
+       [0xab] = { .c = 0xee, .l = 26 },
+       [0xac] = { .c = 0xf0, .l = 26 },
+       [0xad] = { .c = 0xf0, .l = 26 },
+       [0xae] = { .c = 0xf0, .l = 26 },
+       [0xaf] = { .c = 0xf0, .l = 26 },
+       [0xb0] = { .c = 0xf2, .l = 26 },
+       [0xb1] = { .c = 0xf2, .l = 26 },
+       [0xb2] = { .c = 0xf2, .l = 26 },
+       [0xb3] = { .c = 0xf2, .l = 26 },
+       [0xb4] = { .c = 0xf3, .l = 26 },
+       [0xb5] = { .c = 0xf3, .l = 26 },
+       [0xb6] = { .c = 0xf3, .l = 26 },
+       [0xb7] = { .c = 0xf3, .l = 26 },
+       [0xb8] = { .c = 0xff, .l = 26 },
+       [0xb9] = { .c = 0xff, .l = 26 },
+       [0xba] = { .c = 0xff, .l = 26 },
+       [0xbb] = { .c = 0xff, .l = 26 },
+       [0xbc] = { .c = 0xcb, .l = 27 },
+       [0xbd] = { .c = 0xcb, .l = 27 },
+       [0xbe] = { .c = 0xcc, .l = 27 },
+       [0xbf] = { .c = 0xcc, .l = 27 },
+       [0xc0] = { .c = 0xd3, .l = 27 },
+       [0xc1] = { .c = 0xd3, .l = 27 },
+       [0xc2] = { .c = 0xd4, .l = 27 },
+       [0xc3] = { .c = 0xd4, .l = 27 },
+       [0xc4] = { .c = 0xd6, .l = 27 },
+       [0xc5] = { .c = 0xd6, .l = 27 },
+       [0xc6] = { .c = 0xdd, .l = 27 },
+       [0xc7] = { .c = 0xdd, .l = 27 },
+       [0xc8] = { .c = 0xde, .l = 27 },
+       [0xc9] = { .c = 0xde, .l = 27 },
+       [0xca] = { .c = 0xdf, .l = 27 },
+       [0xcb] = { .c = 0xdf, .l = 27 },
+       [0xcc] = { .c = 0xf1, .l = 27 },
+       [0xcd] = { .c = 0xf1, .l = 27 },
+       [0xce] = { .c = 0xf4, .l = 27 },
+       [0xcf] = { .c = 0xf4, .l = 27 },
+       [0xd0] = { .c = 0xf5, .l = 27 },
+       [0xd1] = { .c = 0xf5, .l = 27 },
+       [0xd2] = { .c = 0xf6, .l = 27 },
+       [0xd3] = { .c = 0xf6, .l = 27 },
+       [0xd4] = { .c = 0xf7, .l = 27 },
+       [0xd5] = { .c = 0xf7, .l = 27 },
+       [0xd6] = { .c = 0xf8, .l = 27 },
+       [0xd7] = { .c = 0xf8, .l = 27 },
+       [0xd8] = { .c = 0xfa, .l = 27 },
+       [0xd9] = { .c = 0xfa, .l = 27 },
+       [0xda] = { .c = 0xfb, .l = 27 },
+       [0xdb] = { .c = 0xfb, .l = 27 },
+       [0xdc] = { .c = 0xfc, .l = 27 },
+       [0xdd] = { .c = 0xfc, .l = 27 },
+       [0xde] = { .c = 0xfd, .l = 27 },
+       [0xdf] = { .c = 0xfd, .l = 27 },
+       [0xe0] = { .c = 0xfe, .l = 27 },
+       [0xe1] = { .c = 0xfe, .l = 27 },
+       [0xe2] = { .c = 0x02, .l = 28 },
+       [0xe3] = { .c = 0x03, .l = 28 },
+       [0xe4] = { .c = 0x04, .l = 28 },
+       [0xe5] = { .c = 0x05, .l = 28 },
+       [0xe6] = { .c = 0x06, .l = 28 },
+       [0xe7] = { .c = 0x07, .l = 28 },
+       [0xe8] = { .c = 0x08, .l = 28 },
+       [0xe9] = { .c = 0x0b, .l = 28 },
+       [0xea] = { .c = 0x0c, .l = 28 },
+       [0xeb] = { .c = 0x0e, .l = 28 },
+       [0xec] = { .c = 0x0f, .l = 28 },
+       [0xed] = { .c = 0x10, .l = 28 },
+       [0xee] = { .c = 0x11, .l = 28 },
+       [0xef] = { .c = 0x12, .l = 28 },
+       [0xf0] = { .c = 0x13, .l = 28 },
+       [0xf1] = { .c = 0x14, .l = 28 },
+       [0xf2] = { .c = 0x15, .l = 28 },
+       [0xf3] = { .c = 0x17, .l = 28 },
+       [0xf4] = { .c = 0x18, .l = 28 },
+       [0xf5] = { .c = 0x19, .l = 28 },
+       [0xf6] = { .c = 0x1a, .l = 28 },
+       [0xf7] = { .c = 0x1b, .l = 28 },
+       [0xf8] = { .c = 0x1c, .l = 28 },
+       [0xf9] = { .c = 0x1d, .l = 28 },
+       [0xfa] = { .c = 0x1e, .l = 28 },
+       [0xfb] = { .c = 0x1f, .l = 28 },
+       [0xfc] = { .c = 0x7f, .l = 28 },
+       [0xfd] = { .c = 0xdc, .l = 28 },
+       [0xfe] = { .c = 0xf9, .l = 28 },
+       [0xff] = { .c = 0x0a, .l = 30 },
+       /* Note, when l==30, bits 2..3 give 00:0x0a, 01:0x0d, 10:0x16, 11:EOS */
+};
+
+/* huffman-encode string <s> into the huff_tmp buffer and returns the amount
+ * of output bytes. The caller must ensure the output is large enough (ie at
+ * least 4 times as long as s).
+ *
+ * FIXME: bits are only counted for now, no code is emitted!
+ */
+int huff_enc(const char *s, char *out)
+{
+       int bits = 0;
+
+       while (*s) {
+               bits += ht[(uint8_t)*s].b;
+               s++;
+       }
+       bits += 7;
+
+       /*  FIXME: huffman code is not emitted yet. */
+       //memset(out, 'H', bits / 8);
+       return bits / 8;
+}
+
+/* pass a huffman string, it will decode it and return the new output size or
+ * -1 in case of error.
+ *
+ * The principle of the decoder is to lookup full bytes in reverse-huffman
+ * tables. Since we may need up to 30 bits and the word positions are not
+ * always multiples of 8, we build the code word by shifting the "current"
+ * 32-bit word and the "next" one of the appropriate amount of bits. Once
+ * the shift goes beyond 32, words are swapped and the "next" one is refilled
+ * with new bytes. Shift operations are cheap when done a single time like this.
+ * On 64-bit platforms it is possible to further improve this by storing both
+ * of them in a single word.
+ */
+int huff_dec(const uint8_t *huff, int hlen, char *out, int olen)
+{
+       char *out_start = out;
+       char *out_end = out + olen;
+       const uint8_t *huff_end = huff + hlen;
+       uint32_t curr = 0;
+       uint32_t next = 0;
+       uint32_t shift;
+       uint32_t code; /* The 30-bit code being looked up, MSB-aligned */
+       uint8_t sym;
+       int bleft; /* bits left */
+       int l;
+
+       code = 0;
+       shift = 64; // start with an empty buffer
+       bleft = hlen << 3;
+       while (bleft > 0 && out != out_end) {
+               while (shift >= 32) {
+                       curr = next;
+
+                       /* read up to 4 bytes into next. FIXME: this should
+                        * later be optimized to perform a single 32-bit big
+                        * endian read when unaligned accesses are possible.
+                        */
+                       next = 0;
+
+                       if (huff + 4 <= huff_end) {
+                               next = (huff[0] << 24) + (huff[1] << 16) + (huff[2] <<  8) + huff[3];
+                               huff += 4;
+                       }
+                       else {
+                               /* note: we append 0 and not 0xff so that we can
+                                * distinguish shifted bits from a really inserted
+                                * EOS.
+                                */
+                               next =  (((huff + 0 < huff_end) ? huff[0] : 0x00) << 24) +
+                                       (((huff + 1 < huff_end) ? huff[1] : 0x00) << 16) +
+                                       (((huff + 2 < huff_end) ? huff[2] : 0x00) <<  8) +
+                                       ((huff + 3 < huff_end) ? huff[3] : 0x00);
+                               huff = huff_end;
+                       }
+
+                       shift -= 32;
+               }
+
+               /* curr:next contain 64 bit of huffman code */
+               code = curr;
+               if (shift)
+                       code = (code << shift) + (next >> (32 - shift));
+
+               /* now we necessarily have 32 bits available */
+               if ((code >> 24) < 0xfe) {
+                       /* single byte */
+                       l = rht_bit31_24[code >> 24].l;
+                       sym = rht_bit31_24[code >> 24].c;
+               }
+               else if (((code >> 17) & 0xff) < 0xff) {
+                       /* two bytes, 0xfe + 2 bits or 0xff + 2..7 bits */
+                       l = rht_bit24_17[(code >> 17) & 0xff].l;
+                       sym = rht_bit24_17[(code >> 17) & 0xff].c;
+               }
+               else if (((code >> 16) & 0xff) < 0xff) { /* 3..5 bits */
+                       /* 0xff + 0xfe + 3..5 bits or
+                        * 0xff + 0xff + 5..8 bits for values till 0xf5
+                        */
+                       l = rht_bit15_11_fe[(code >> 11) & 0x1f].l;
+                       sym = rht_bit15_11_fe[(code >> 11) & 0x1f].c;
+               }
+               else if (((code >> 8) & 0xff) < 0xf6) { /* 5..8 bits */
+                       /* that's 0xff + 0xff */
+                       l = rht_bit15_8[(code >> 8) & 0xff].l;
+                       sym = rht_bit15_8[(code >> 8) & 0xff].c;
+               }
+               else {
+                       /* 0xff 0xff 0xf6..0xff */
+                       l = rht_bit11_4[(code >> 4) & 0xff].l;
+                       if (l < 30)
+                               sym = rht_bit11_4[(code >> 4) & 0xff].c;
+                       else if ((code & 0xff) == 0xf0)
+                               sym = 10;
+                       else if ((code & 0xff) == 0xf4)
+                               sym = 13;
+                       else if ((code & 0xff) == 0xf8)
+                               sym = 22;
+                       else { // 0xfc : EOS
+                               break;
+                       }
+               }
+
+               if (!l || bleft - l < 0)
+                       break;
+
+               bleft -= l;
+               shift += l;
+               *out++ = sym;
+       }
+
+       if (bleft > 0) {
+               /* some bits were not consumed after the last code, they must
+                * match EOS (ie: all ones).
+                */
+               if ((code & -(1 << (32 - bleft))) != (uint32_t)-(1 << (32 - bleft)))
+                       return -1;
+       }
+
+       if (out < out_end)
+               *out = 0; // end of string whenever possible
+       return out - out_start;
+}