1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3
4# This scripts reads static table entries [1] and generates
5# token_stable and stable.  This table is used in lib/nghttp3_qpack.c.
6#
7# [1] https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#name-static-table-2
8
9import re, sys
10
11def hd_map_hash(name):
12  h = 2166136261
13
14  # FNV hash variant: http://isthe.com/chongo/tech/comp/fnv/
15  for c in name:
16    h ^= ord(c)
17    h *= 16777619
18    h &= 0xffffffff
19
20  return h
21
22class Header:
23  def __init__(self, idx, name, value):
24    self.idx = idx
25    self.name = name
26    self.value = value
27    self.token = -1
28
29entries = []
30for line in sys.stdin:
31    m = re.match(r'(\d+)\s+(\S+)\s+(\S.*)?', line)
32    val = m.group(3).strip() if m.group(3) else ''
33    entries.append(Header(int(m.group(1)), m.group(2), val))
34
35token_entries = sorted(entries, key=lambda ent: ent.name)
36
37token = 0
38seq = 0
39name = token_entries[0].name
40for i, ent in enumerate(token_entries):
41    if name != ent.name:
42        name = ent.name
43        token = seq
44    seq += 1
45    ent.token = token
46
47def to_enum_hd(k):
48    res = 'NGHTTP3_QPACK_TOKEN_'
49    for c in k.upper():
50        if c == ':' or c == '-':
51            res += '_'
52            continue
53        res += c
54    return res
55
56def gen_enum(entries):
57    used = {}
58    print('typedef enum nghttp3_qpack_token {')
59    for ent in entries:
60        if ent.name in used:
61            continue
62        used[ent.name] = True
63        enumname = to_enum_hd(ent.name)
64        print('''\
65  /**
66   * :enum:`{enumname}` is a token for ``{name}``.
67   */'''.format(enumname=enumname, name=ent.name))
68        if ent.token is None:
69            print('  {},'.format(enumname))
70        else:
71            print('  {} = {},'.format(enumname, ent.token))
72    print('} nghttp3_qpack_token;')
73
74gen_enum(entries)
75
76print()
77
78print('static nghttp3_qpack_static_entry token_stable[] = {')
79for i, ent in enumerate(token_entries):
80    print('MAKE_STATIC_ENT({}, {}, {}u),'\
81          .format(ent.idx, to_enum_hd(ent.name), hd_map_hash(ent.name)))
82print('};')
83
84print()
85
86print('static nghttp3_qpack_static_header stable[] = {')
87for ent in entries:
88    print('MAKE_STATIC_HD("{}", "{}", {}),'\
89          .format(ent.name, ent.value, to_enum_hd(ent.name)))
90print('};')
91