зеркало из https://github.com/mozilla/gecko-dev.git
203 строки
5.7 KiB
Python
203 строки
5.7 KiB
Python
# This script exists to auto-generate Http2HuffmanIncoming.h from the table
|
|
# contained in the HPACK spec. It's pretty simple to run:
|
|
# python make_incoming_tables.py < http2_huffman_table.txt > Http2HuffmanIncoming.h
|
|
# where huff_incoming.txt is copy/pasted text from the latest version of the
|
|
# HPACK spec, with all non-relevant lines removed (the most recent version
|
|
# of huff_incoming.txt also lives in this directory as an example).
|
|
import sys
|
|
|
|
|
|
def char_cmp(x, y):
|
|
rv = cmp(x["nbits"], y["nbits"])
|
|
if not rv:
|
|
rv = cmp(x["bpat"], y["bpat"])
|
|
if not rv:
|
|
rv = cmp(x["ascii"], y["ascii"])
|
|
return rv
|
|
|
|
|
|
characters = []
|
|
|
|
for line in sys.stdin:
|
|
line = line.rstrip()
|
|
obracket = line.rfind("[")
|
|
nbits = int(line[obracket + 1 : -1])
|
|
|
|
oparen = line.find(" (")
|
|
ascii = int(line[oparen + 2 : oparen + 5].strip())
|
|
|
|
bar = line.find("|", oparen)
|
|
space = line.find(" ", bar)
|
|
bpat = line[bar + 1 : space].strip().rstrip("|")
|
|
|
|
characters.append({"ascii": ascii, "nbits": nbits, "bpat": bpat})
|
|
|
|
characters.sort(cmp=char_cmp)
|
|
raw_entries = []
|
|
for c in characters:
|
|
raw_entries.append((c["ascii"], c["bpat"]))
|
|
|
|
|
|
class DefaultList(list):
|
|
def __init__(self, default=None):
|
|
self.__default = default
|
|
|
|
def __ensure_size(self, sz):
|
|
while sz > len(self):
|
|
self.append(self.__default)
|
|
|
|
def __getitem__(self, idx):
|
|
self.__ensure_size(idx + 1)
|
|
rv = super(DefaultList, self).__getitem__(idx)
|
|
return rv
|
|
|
|
def __setitem__(self, idx, val):
|
|
self.__ensure_size(idx + 1)
|
|
super(DefaultList, self).__setitem__(idx, val)
|
|
|
|
|
|
def expand_to_8bit(bstr):
|
|
while len(bstr) < 8:
|
|
bstr += "0"
|
|
return int(bstr, 2)
|
|
|
|
|
|
table = DefaultList()
|
|
for r in raw_entries:
|
|
ascii, bpat = r
|
|
ascii = int(ascii)
|
|
bstrs = bpat.split("|")
|
|
curr_table = table
|
|
while len(bstrs) > 1:
|
|
idx = expand_to_8bit(bstrs[0])
|
|
if curr_table[idx] is None:
|
|
curr_table[idx] = DefaultList()
|
|
curr_table = curr_table[idx]
|
|
bstrs.pop(0)
|
|
|
|
idx = expand_to_8bit(bstrs[0])
|
|
curr_table[idx] = {
|
|
"prefix_len": len(bstrs[0]),
|
|
"mask": int(bstrs[0], 2),
|
|
"value": ascii,
|
|
}
|
|
|
|
|
|
def output_table(table, name_suffix=""):
|
|
max_prefix_len = 0
|
|
for i, t in enumerate(table):
|
|
if isinstance(t, dict):
|
|
if t["prefix_len"] > max_prefix_len:
|
|
max_prefix_len = t["prefix_len"]
|
|
elif t is not None:
|
|
output_table(t, "%s_%s" % (name_suffix, i))
|
|
|
|
tablename = "HuffmanIncoming%s" % (name_suffix if name_suffix else "Root",)
|
|
entriestable = tablename.replace("HuffmanIncoming", "HuffmanIncomingEntries")
|
|
nexttable = tablename.replace("HuffmanIncoming", "HuffmanIncomingNextTables")
|
|
sys.stdout.write("static const HuffmanIncomingEntry %s[] = {\n" % (entriestable,))
|
|
prefix_len = 0
|
|
value = 0
|
|
i = 0
|
|
while i < 256:
|
|
t = table[i]
|
|
if isinstance(t, dict):
|
|
value = t["value"]
|
|
prefix_len = t["prefix_len"]
|
|
elif t is not None:
|
|
break
|
|
|
|
sys.stdout.write(" { %s, %s }" % (value, prefix_len))
|
|
sys.stdout.write(",\n")
|
|
i += 1
|
|
|
|
indexOfFirstNextTable = i
|
|
if i < 256:
|
|
sys.stdout.write("};\n")
|
|
sys.stdout.write("\n")
|
|
sys.stdout.write("static const HuffmanIncomingTable* %s[] = {\n" % (nexttable,))
|
|
while i < 256:
|
|
subtable = "%s_%s" % (name_suffix, i)
|
|
ptr = "&HuffmanIncoming%s" % (subtable,)
|
|
sys.stdout.write(" %s" % (ptr))
|
|
sys.stdout.write(",\n")
|
|
i += 1
|
|
else:
|
|
nexttable = "nullptr"
|
|
|
|
sys.stdout.write("};\n")
|
|
sys.stdout.write("\n")
|
|
sys.stdout.write("static const HuffmanIncomingTable %s = {\n" % (tablename,))
|
|
sys.stdout.write(" %s,\n" % (entriestable,))
|
|
sys.stdout.write(" %s,\n" % (nexttable,))
|
|
sys.stdout.write(" %s,\n" % (indexOfFirstNextTable,))
|
|
sys.stdout.write(" %s\n" % (max_prefix_len,))
|
|
sys.stdout.write("};\n")
|
|
sys.stdout.write("\n")
|
|
|
|
|
|
sys.stdout.write(
|
|
"""/*
|
|
* THIS FILE IS AUTO-GENERATED. DO NOT EDIT!
|
|
*/
|
|
#ifndef mozilla__net__Http2HuffmanIncoming_h
|
|
#define mozilla__net__Http2HuffmanIncoming_h
|
|
|
|
namespace mozilla {
|
|
namespace net {
|
|
|
|
struct HuffmanIncomingTable;
|
|
|
|
struct HuffmanIncomingEntry {
|
|
uint16_t mValue:9; // 9 bits so it can hold 0..256
|
|
uint16_t mPrefixLen:7; // only holds 1..8
|
|
};
|
|
|
|
// The data members are public only so they can be statically constructed. All
|
|
// accesses should be done through the functions.
|
|
struct HuffmanIncomingTable {
|
|
// The normal entries, for indices in the range 0..(mNumEntries-1).
|
|
const HuffmanIncomingEntry* const mEntries;
|
|
|
|
// The next tables, for indices in the range mNumEntries..255. Must be
|
|
// |nullptr| if mIndexOfFirstNextTable is 256.
|
|
const HuffmanIncomingTable** const mNextTables;
|
|
|
|
// The index of the first next table (equal to the number of entries in
|
|
// mEntries). This cannot be a uint8_t because it can have the value 256,
|
|
// in which case there are no next tables and mNextTables must be |nullptr|.
|
|
const uint16_t mIndexOfFirstNextTable;
|
|
|
|
const uint8_t mPrefixLen;
|
|
|
|
bool IndexHasANextTable(uint8_t aIndex) const
|
|
{
|
|
return aIndex >= mIndexOfFirstNextTable;
|
|
}
|
|
|
|
const HuffmanIncomingEntry* Entry(uint8_t aIndex) const
|
|
{
|
|
MOZ_ASSERT(aIndex < mIndexOfFirstNextTable);
|
|
return &mEntries[aIndex];
|
|
}
|
|
|
|
const HuffmanIncomingTable* NextTable(uint8_t aIndex) const
|
|
{
|
|
MOZ_ASSERT(aIndex >= mIndexOfFirstNextTable);
|
|
return mNextTables[aIndex - mIndexOfFirstNextTable];
|
|
}
|
|
};
|
|
|
|
"""
|
|
)
|
|
|
|
output_table(table)
|
|
|
|
sys.stdout.write(
|
|
"""} // namespace net
|
|
} // namespace mozilla
|
|
|
|
#endif // mozilla__net__Http2HuffmanIncoming_h
|
|
"""
|
|
)
|