blob: 109701f740b57753602c1eb2dc04d37c049e3bc6 [file] [log] [blame]
Craig Tiller2e7687c2015-11-18 14:56:46 -08001#!/usr/bin/env python2.7
2
Craig Tiller6169d5f2016-03-31 07:46:18 -07003# Copyright 2015, Google Inc.
Craig Tiller2e7687c2015-11-18 14:56:46 -08004# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions are
8# met:
9#
10# * Redistributions of source code must retain the above copyright
11# notice, this list of conditions and the following disclaimer.
12# * Redistributions in binary form must reproduce the above
13# copyright notice, this list of conditions and the following disclaimer
14# in the documentation and/or other materials provided with the
15# distribution.
16# * Neither the name of Google Inc. nor the names of its
17# contributors may be used to endorse or promote products derived from
18# this software without specific prior written permission.
19#
20# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32import hashlib
33import itertools
Craig Tillere52bbb12016-11-10 15:34:06 -080034import collections
Craig Tiller2e7687c2015-11-18 14:56:46 -080035import os
36import sys
Craig Tillere52bbb12016-11-10 15:34:06 -080037import subprocess
38import re
Craig Tillerddea41e2016-11-30 17:05:54 -080039import perfection
Craig Tiller2e7687c2015-11-18 14:56:46 -080040
41# configuration: a list of either strings or 2-tuples of strings
42# a single string represents a static grpc_mdstr
43# a 2-tuple represents a static grpc_mdelem (and appropriate grpc_mdstrs will
44# also be created)
45
46CONFIG = [
Craig Tiller47718a62016-11-14 14:48:42 -080047 # metadata strings
Craig Tillera7d37a32016-11-22 14:37:16 -080048 'host',
Craig Tiller2e7687c2015-11-18 14:56:46 -080049 'grpc-timeout',
Craig Tillerebdef9d2015-11-19 17:09:49 -080050 'grpc-internal-encoding-request',
Makdharma178f4bc2016-08-24 15:16:53 -070051 'grpc-payload-bin',
Craig Tiller2e7687c2015-11-18 14:56:46 -080052 ':path',
53 'grpc-encoding',
54 'grpc-accept-encoding',
55 'user-agent',
56 ':authority',
Craig Tiller2e7687c2015-11-18 14:56:46 -080057 'grpc-message',
58 'grpc-status',
David Garcia Quintas8eec9ec2016-08-01 17:05:04 -070059 'grpc-tracing-bin',
David Garcia Quintas98d5f5c2016-09-14 14:34:22 -070060 'grpc-stats-bin',
Craig Tiller2e7687c2015-11-18 14:56:46 -080061 '',
Craig Tiller47718a62016-11-14 14:48:42 -080062 # channel arg keys
63 'grpc.wait_for_ready',
64 'grpc.timeout',
65 'grpc.max_request_message_bytes',
66 'grpc.max_response_message_bytes',
Craig Tillerd7f15832016-11-16 17:12:55 -080067 # well known method names
68 '/grpc.lb.v1.LoadBalancer/BalanceLoad',
Craig Tiller47718a62016-11-14 14:48:42 -080069 # metadata elements
Craig Tiller2e7687c2015-11-18 14:56:46 -080070 ('grpc-status', '0'),
Craig Tillerebdef9d2015-11-19 17:09:49 -080071 ('grpc-status', '1'),
72 ('grpc-status', '2'),
73 ('grpc-encoding', 'identity'),
74 ('grpc-encoding', 'gzip'),
75 ('grpc-encoding', 'deflate'),
Craig Tiller2e7687c2015-11-18 14:56:46 -080076 ('te', 'trailers'),
Craig Tillerebdef9d2015-11-19 17:09:49 -080077 ('content-type', 'application/grpc'),
Craig Tiller2e7687c2015-11-18 14:56:46 -080078 (':method', 'POST'),
79 (':status', '200'),
80 (':status', '404'),
81 (':scheme', 'http'),
82 (':scheme', 'https'),
83 (':scheme', 'grpc'),
84 (':authority', ''),
85 (':method', 'GET'),
Craig Tillerc6549762016-03-09 17:10:43 -080086 (':method', 'PUT'),
Craig Tiller2e7687c2015-11-18 14:56:46 -080087 (':path', '/'),
88 (':path', '/index.html'),
89 (':status', '204'),
90 (':status', '206'),
91 (':status', '304'),
92 (':status', '400'),
93 (':status', '500'),
94 ('accept-charset', ''),
95 ('accept-encoding', ''),
96 ('accept-encoding', 'gzip, deflate'),
97 ('accept-language', ''),
98 ('accept-ranges', ''),
99 ('accept', ''),
100 ('access-control-allow-origin', ''),
101 ('age', ''),
102 ('allow', ''),
103 ('authorization', ''),
104 ('cache-control', ''),
105 ('content-disposition', ''),
106 ('content-encoding', ''),
107 ('content-language', ''),
108 ('content-length', ''),
109 ('content-location', ''),
110 ('content-range', ''),
111 ('content-type', ''),
112 ('cookie', ''),
113 ('date', ''),
114 ('etag', ''),
115 ('expect', ''),
116 ('expires', ''),
117 ('from', ''),
118 ('host', ''),
119 ('if-match', ''),
120 ('if-modified-since', ''),
121 ('if-none-match', ''),
122 ('if-range', ''),
123 ('if-unmodified-since', ''),
124 ('last-modified', ''),
David Garcia Quintasa3654db2016-10-11 15:52:39 -0700125 ('lb-token', ''),
Craig Tiller2e7687c2015-11-18 14:56:46 -0800126 ('link', ''),
127 ('location', ''),
128 ('max-forwards', ''),
129 ('proxy-authenticate', ''),
130 ('proxy-authorization', ''),
131 ('range', ''),
132 ('referer', ''),
133 ('refresh', ''),
134 ('retry-after', ''),
135 ('server', ''),
136 ('set-cookie', ''),
137 ('strict-transport-security', ''),
138 ('transfer-encoding', ''),
139 ('user-agent', ''),
140 ('vary', ''),
141 ('via', ''),
142 ('www-authenticate', ''),
143]
144
Craig Tillera7d37a32016-11-22 14:37:16 -0800145METADATA_BATCH_CALLOUTS = [
146 ':path',
147 ':method',
148 ':status',
149 ':authority',
150 ':scheme',
151 'te',
152 'grpc-message',
153 'grpc-status',
154 'grpc-payload-bin',
155 'grpc-encoding',
156 'grpc-accept-encoding',
157 'content-type',
158 'grpc-internal-encoding-request',
159 'user-agent',
160 'host',
161 'lb-token',
Craig Tillera7d37a32016-11-22 14:37:16 -0800162]
163
Craig Tillerb2b42612015-11-20 12:02:17 -0800164COMPRESSION_ALGORITHMS = [
165 'identity',
166 'deflate',
167 'gzip',
168]
169
Craig Tiller2e7687c2015-11-18 14:56:46 -0800170# utility: mangle the name of a config
Craig Tillera7d37a32016-11-22 14:37:16 -0800171def mangle(elem, name=None):
Craig Tiller2e7687c2015-11-18 14:56:46 -0800172 xl = {
173 '-': '_',
174 ':': '',
175 '/': 'slash',
176 '.': 'dot',
177 ',': 'comma',
178 ' ': '_',
179 }
180 def m0(x):
181 if not x: return 'empty'
182 r = ''
183 for c in x:
184 put = xl.get(c, c.lower())
185 if not put: continue
186 last_is_underscore = r[-1] == '_' if r else True
187 if last_is_underscore and put == '_': continue
188 elif len(put) > 1:
189 if not last_is_underscore: r += '_'
190 r += put
191 r += '_'
192 else:
193 r += put
194 if r[-1] == '_': r = r[:-1]
195 return r
Craig Tillera7d37a32016-11-22 14:37:16 -0800196 def n(default, name=name):
197 if name is None: return 'grpc_%s_' % default
198 if name == '': return ''
199 return 'grpc_%s_' % name
Craig Tiller2e7687c2015-11-18 14:56:46 -0800200 if isinstance(elem, tuple):
Craig Tillera7d37a32016-11-22 14:37:16 -0800201 return '%s%s_%s' % (n('mdelem'), m0(elem[0]), m0(elem[1]))
Craig Tiller2e7687c2015-11-18 14:56:46 -0800202 else:
Craig Tillera7d37a32016-11-22 14:37:16 -0800203 return '%s%s' % (n('mdstr'), m0(elem))
Craig Tiller2e7687c2015-11-18 14:56:46 -0800204
205# utility: generate some hash value for a string
206def fake_hash(elem):
207 return hashlib.md5(elem).hexdigest()[0:8]
208
209# utility: print a big comment block into a set of files
210def put_banner(files, banner):
211 for f in files:
212 print >>f, '/*'
213 for line in banner:
214 print >>f, ' * %s' % line
215 print >>f, ' */'
216 print >>f
217
218# build a list of all the strings we need
Craig Tillerd7f15832016-11-16 17:12:55 -0800219all_strs = list()
220all_elems = list()
Craig Tillerb2b42612015-11-20 12:02:17 -0800221static_userdata = {}
Craig Tiller6ec8aa12016-11-23 09:35:25 -0800222# put metadata batch callouts first, to make the check of if a static metadata
223# string is a callout trivial
Craig Tillera7d37a32016-11-22 14:37:16 -0800224for elem in METADATA_BATCH_CALLOUTS:
225 if elem not in all_strs:
226 all_strs.append(elem)
Craig Tiller2e7687c2015-11-18 14:56:46 -0800227for elem in CONFIG:
228 if isinstance(elem, tuple):
Craig Tillerd7f15832016-11-16 17:12:55 -0800229 if elem[0] not in all_strs:
230 all_strs.append(elem[0])
231 if elem[1] not in all_strs:
232 all_strs.append(elem[1])
233 if elem not in all_elems:
234 all_elems.append(elem)
Craig Tiller2e7687c2015-11-18 14:56:46 -0800235 else:
Craig Tillerd7f15832016-11-16 17:12:55 -0800236 if elem not in all_strs:
237 all_strs.append(elem)
Craig Tillerb2b42612015-11-20 12:02:17 -0800238compression_elems = []
239for mask in range(1, 1<<len(COMPRESSION_ALGORITHMS)):
240 val = ','.join(COMPRESSION_ALGORITHMS[alg]
241 for alg in range(0, len(COMPRESSION_ALGORITHMS))
242 if (1 << alg) & mask)
243 elem = ('grpc-accept-encoding', val)
Craig Tillerd7f15832016-11-16 17:12:55 -0800244 if val not in all_strs:
245 all_strs.append(val)
246 if elem not in all_elems:
247 all_elems.append(elem)
Craig Tillerb2b42612015-11-20 12:02:17 -0800248 compression_elems.append(elem)
David Garcia Quintas07503b62016-03-21 11:59:33 -0700249 static_userdata[elem] = 1 + (mask | 1)
Craig Tiller2e7687c2015-11-18 14:56:46 -0800250
251# output configuration
252args = sys.argv[1:]
253H = None
254C = None
Craig Tiller134a6b62016-04-18 08:14:20 -0700255D = None
Craig Tiller2e7687c2015-11-18 14:56:46 -0800256if args:
257 if 'header' in args:
258 H = sys.stdout
259 else:
260 H = open('/dev/null', 'w')
261 if 'source' in args:
262 C = sys.stdout
263 else:
264 C = open('/dev/null', 'w')
Craig Tiller134a6b62016-04-18 08:14:20 -0700265 if 'dictionary' in args:
266 D = sys.stdout
267 else:
268 D = open('/dev/null', 'w')
Craig Tiller2e7687c2015-11-18 14:56:46 -0800269else:
270 H = open(os.path.join(
Craig Tillerffae43c2016-03-25 19:34:29 -0700271 os.path.dirname(sys.argv[0]), '../../../src/core/lib/transport/static_metadata.h'), 'w')
Craig Tiller2e7687c2015-11-18 14:56:46 -0800272 C = open(os.path.join(
Craig Tillerffae43c2016-03-25 19:34:29 -0700273 os.path.dirname(sys.argv[0]), '../../../src/core/lib/transport/static_metadata.c'), 'w')
Craig Tiller134a6b62016-04-18 08:14:20 -0700274 D = open(os.path.join(
275 os.path.dirname(sys.argv[0]), '../../../test/core/end2end/fuzzers/hpack.dictionary'), 'w')
Craig Tiller2e7687c2015-11-18 14:56:46 -0800276
277# copy-paste copyright notice from this file
278with open(sys.argv[0]) as my_source:
279 copyright = []
280 for line in my_source:
281 if line[0] != '#': break
282 for line in my_source:
283 if line[0] == '#':
284 copyright.append(line)
285 break
286 for line in my_source:
287 if line[0] != '#':
288 break
289 copyright.append(line)
Craig Tiller3bd96952016-03-28 12:43:02 -0700290 put_banner([H,C], [line[2:].rstrip() for line in copyright])
Craig Tiller2e7687c2015-11-18 14:56:46 -0800291
Craig Tiller134a6b62016-04-18 08:14:20 -0700292
293hex_bytes = [ord(c) for c in "abcdefABCDEF0123456789"]
294
295
Craig Tiller69b6d4e2016-04-18 15:08:14 -0700296def esc_dict(line):
Craig Tiller134a6b62016-04-18 08:14:20 -0700297 out = "\""
Craig Tiller134a6b62016-04-18 08:14:20 -0700298 for c in line:
299 if 32 <= c < 127:
Craig Tiller134a6b62016-04-18 08:14:20 -0700300 if c != ord('"'):
301 out += chr(c)
302 else:
303 out += "\\\""
Craig Tiller134a6b62016-04-18 08:14:20 -0700304 else:
Craig Tiller69b6d4e2016-04-18 15:08:14 -0700305 out += "\\x%02X" % c
Craig Tiller134a6b62016-04-18 08:14:20 -0700306 return out + "\""
307
Craig Tiller2e7687c2015-11-18 14:56:46 -0800308put_banner([H,C],
309"""WARNING: Auto-generated code.
310
Craig Tiller3bd96952016-03-28 12:43:02 -0700311To make changes to this file, change
312tools/codegen/core/gen_static_metadata.py, and then re-run it.
Craig Tiller51ae0be2015-11-19 07:51:25 -0800313
Craig Tiller3bd96952016-03-28 12:43:02 -0700314See metadata.h for an explanation of the interface here, and metadata.c for
315an explanation of what's going on.
Craig Tiller2e7687c2015-11-18 14:56:46 -0800316""".splitlines())
317
Craig Tiller3bd96952016-03-28 12:43:02 -0700318print >>H, '#ifndef GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H'
319print >>H, '#define GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H'
Craig Tiller2e7687c2015-11-18 14:56:46 -0800320print >>H
Craig Tillerffae43c2016-03-25 19:34:29 -0700321print >>H, '#include "src/core/lib/transport/metadata.h"'
Craig Tiller2e7687c2015-11-18 14:56:46 -0800322print >>H
323
Craig Tillerffae43c2016-03-25 19:34:29 -0700324print >>C, '#include "src/core/lib/transport/static_metadata.h"'
Craig Tiller2e7687c2015-11-18 14:56:46 -0800325print >>C
Craig Tiller19614362016-11-17 16:05:27 -0800326print >>C, '#include "src/core/lib/slice/slice_internal.h"'
327print >>C
Craig Tiller2e7687c2015-11-18 14:56:46 -0800328
Craig Tillerdcbe70c2016-11-21 14:07:52 -0800329str_ofs = 0
330id2strofs = {}
331for i, elem in enumerate(all_strs):
332 id2strofs[i] = str_ofs
333 str_ofs += len(elem);
334def slice_def(i):
Craig Tiller43a51692016-11-23 08:03:02 -0800335 return '{.refcount = &grpc_static_metadata_refcounts[%d], .data.refcounted = {g_bytes+%d, %d}}' % (i, id2strofs[i], len(all_strs[i]))
Craig Tillerdcbe70c2016-11-21 14:07:52 -0800336
Craig Tillera7d37a32016-11-22 14:37:16 -0800337# validate configuration
338for elem in METADATA_BATCH_CALLOUTS:
339 assert elem in all_strs
340
Craig Tiller2e7687c2015-11-18 14:56:46 -0800341print >>H, '#define GRPC_STATIC_MDSTR_COUNT %d' % len(all_strs)
Craig Tillere52bbb12016-11-10 15:34:06 -0800342print >>H, 'extern const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT];'
Craig Tiller2e7687c2015-11-18 14:56:46 -0800343for i, elem in enumerate(all_strs):
344 print >>H, '/* "%s" */' % elem
Craig Tiller5ef31ab2016-11-10 16:27:48 -0800345 print >>H, '#define %s (grpc_static_slice_table[%d])' % (mangle(elem).upper(), i)
Craig Tiller2e7687c2015-11-18 14:56:46 -0800346print >>H
Craig Tillerdcbe70c2016-11-21 14:07:52 -0800347print >>C, 'static uint8_t g_bytes[] = {%s};' % (','.join('%d' % ord(c) for c in ''.join(all_strs)))
Craig Tillere52bbb12016-11-10 15:34:06 -0800348print >>C
349print >>C, 'static void static_ref(void *unused) {}'
350print >>C, 'static void static_unref(grpc_exec_ctx *exec_ctx, void *unused) {}'
Craig Tiller43a51692016-11-23 08:03:02 -0800351print >>C, 'static const grpc_slice_refcount_vtable static_sub_vtable = {static_ref, static_unref, grpc_slice_default_eq_impl, grpc_slice_default_hash_impl};';
352print >>H, 'extern const grpc_slice_refcount_vtable grpc_static_metadata_vtable;';
353print >>C, 'const grpc_slice_refcount_vtable grpc_static_metadata_vtable = {static_ref, static_unref, grpc_static_slice_eq, grpc_static_slice_hash};';
354print >>C, 'static grpc_slice_refcount static_sub_refcnt = {&static_sub_vtable, &static_sub_refcnt};';
355print >>H, 'extern grpc_slice_refcount grpc_static_metadata_refcounts[GRPC_STATIC_MDSTR_COUNT];'
356print >>C, 'grpc_slice_refcount grpc_static_metadata_refcounts[GRPC_STATIC_MDSTR_COUNT] = {'
Craig Tillerdcbe70c2016-11-21 14:07:52 -0800357for i, elem in enumerate(all_strs):
Craig Tiller43a51692016-11-23 08:03:02 -0800358 print >>C, ' {&grpc_static_metadata_vtable, &static_sub_refcnt},'
Craig Tillerdcbe70c2016-11-21 14:07:52 -0800359print >>C, '};'
Craig Tillere52bbb12016-11-10 15:34:06 -0800360print >>C
Craig Tillera82d2a32016-11-23 08:13:46 -0800361print >>H, '#define GRPC_IS_STATIC_METADATA_STRING(slice) \\'
362print >>H, ' ((slice).refcount != NULL && (slice).refcount->vtable == &grpc_static_metadata_vtable)'
Craig Tiller43a51692016-11-23 08:03:02 -0800363print >>H
Craig Tillere52bbb12016-11-10 15:34:06 -0800364print >>C, 'const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT] = {'
Craig Tillere52bbb12016-11-10 15:34:06 -0800365for i, elem in enumerate(all_strs):
Craig Tiller7885d1a2016-11-17 14:07:45 -0800366 print >>C, slice_def(i) + ','
Craig Tillere52bbb12016-11-10 15:34:06 -0800367print >>C, '};'
368print >>C
Craig Tillera82d2a32016-11-23 08:13:46 -0800369print >>H, '#define GRPC_STATIC_METADATA_INDEX(static_slice) \\'
370print >>H, ' ((int)((static_slice).refcount - grpc_static_metadata_refcounts))'
Craig Tiller43a51692016-11-23 08:03:02 -0800371print >>H
Craig Tiller2e7687c2015-11-18 14:56:46 -0800372
Craig Tiller134a6b62016-04-18 08:14:20 -0700373print >>D, '# hpack fuzzing dictionary'
374for i, elem in enumerate(all_strs):
Craig Tiller69b6d4e2016-04-18 15:08:14 -0700375 print >>D, '%s' % (esc_dict([len(elem)] + [ord(c) for c in elem]))
Craig Tiller942568b2016-04-18 22:19:00 -0700376for i, elem in enumerate(all_elems):
377 print >>D, '%s' % (esc_dict([0, len(elem[0])] + [ord(c) for c in elem[0]] +
378 [len(elem[1])] + [ord(c) for c in elem[1]]))
Craig Tiller134a6b62016-04-18 08:14:20 -0700379
Craig Tiller2e7687c2015-11-18 14:56:46 -0800380print >>H, '#define GRPC_STATIC_MDELEM_COUNT %d' % len(all_elems)
Craig Tiller0160de92016-11-18 08:46:46 -0800381print >>H, 'extern grpc_mdelem_data grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];'
Craig Tillerc6549762016-03-09 17:10:43 -0800382print >>H, 'extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT];'
Craig Tiller2e7687c2015-11-18 14:56:46 -0800383for i, elem in enumerate(all_elems):
384 print >>H, '/* "%s": "%s" */' % elem
Craig Tiller9ecadce2016-11-18 14:52:25 -0800385 print >>H, '#define %s (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[%d], GRPC_MDELEM_STORAGE_STATIC))' % (mangle(elem).upper(), i)
Craig Tiller2e7687c2015-11-18 14:56:46 -0800386print >>H
Craig Tillerc6549762016-03-09 17:10:43 -0800387print >>C, 'uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] = {'
Craig Tillerb2b42612015-11-20 12:02:17 -0800388print >>C, ' %s' % ','.join('%d' % static_userdata.get(elem, 0) for elem in all_elems)
389print >>C, '};'
Craig Tiller2e7687c2015-11-18 14:56:46 -0800390print >>C
391
392def str_idx(s):
393 for i, s2 in enumerate(all_strs):
394 if s == s2:
395 return i
396
Craig Tillerb2b42612015-11-20 12:02:17 -0800397def md_idx(m):
398 for i, m2 in enumerate(all_elems):
399 if m == m2:
400 return i
401
Craig Tillera7d37a32016-11-22 14:37:16 -0800402def offset_trials(mink):
403 yield 0
404 for i in range(1, 100):
405 for mul in [-1, 1]:
406 yield mul * i
407
Craig Tillere52bbb12016-11-10 15:34:06 -0800408def perfect_hash(keys, name):
Craig Tillerddea41e2016-11-30 17:05:54 -0800409 p = perfection.hash_parameters(keys)
410 def f(i, p=p):
411 i += p.offset
412 x = i % p.t
413 y = i / p.t
414 return x + p.r[y]
415 return {
416 'PHASHRANGE': p.t - 1 + max(p.r),
417 'PHASHNKEYS': len(p.slots),
418 'pyfunc': f,
419 'code': """
420static const int8_t %(name)s_r[] = {%(r)s};
421static uint32_t %(name)s_phash(uint32_t i) {
422 i %(offset_sign)s= %(offset)d;
423 uint32_t x = i %% %(t)d;
424 uint32_t y = i / %(t)d;
Craig Tiller5efdf3c2016-12-07 17:30:21 -0800425 uint32_t h = x;
426 if (y < GPR_ARRAY_SIZE(%(name)s_r)) {
427 uint32_t delta = (uint32_t)%(name)s_r[y];
428 h += delta;
429 }
430 return h;
Craig Tillerddea41e2016-11-30 17:05:54 -0800431}
432 """ % {
433 'name': name,
434 'r': ','.join('%d' % (r if r is not None else 0) for r in p.r),
435 't': p.t,
436 'offset': abs(p.offset),
437 'offset_sign': '+' if p.offset > 0 else '-'
438 }
439 }
Craig Tillere52bbb12016-11-10 15:34:06 -0800440
Craig Tillere52bbb12016-11-10 15:34:06 -0800441
442elem_keys = [str_idx(elem[0]) * len(all_strs) + str_idx(elem[1]) for elem in all_elems]
443elem_hash = perfect_hash(elem_keys, "elems")
444print >>C, elem_hash['code']
445
446keys = [0] * int(elem_hash['PHASHRANGE'])
Craig Tillerddea41e2016-11-30 17:05:54 -0800447idxs = [255] * int(elem_hash['PHASHNKEYS'])
Craig Tillere52bbb12016-11-10 15:34:06 -0800448for i, k in enumerate(elem_keys):
449 h = elem_hash['pyfunc'](k)
450 assert keys[h] == 0
451 keys[h] = k
452 idxs[h] = i
453print >>C, 'static const uint16_t elem_keys[] = {%s};' % ','.join('%d' % k for k in keys)
454print >>C, 'static const uint8_t elem_idxs[] = {%s};' % ','.join('%d' % i for i in idxs)
455print >>C
456
Craig Tiller0160de92016-11-18 08:46:46 -0800457print >>H, 'grpc_mdelem grpc_static_mdelem_for_static_strings(int a, int b);'
458print >>C, 'grpc_mdelem grpc_static_mdelem_for_static_strings(int a, int b) {'
459print >>C, ' if (a == -1 || b == -1) return GRPC_MDNULL;'
Craig Tillere52bbb12016-11-10 15:34:06 -0800460print >>C, ' uint32_t k = (uint32_t)(a * %d + b);' % len(all_strs)
461print >>C, ' uint32_t h = elems_phash(k);'
Craig Tiller0c3fdad2017-01-21 15:16:26 -0800462print >>C, ' return h < GPR_ARRAY_SIZE(elem_keys) && elem_keys[h] == k ? GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[elem_idxs[h]], GRPC_MDELEM_STORAGE_STATIC) : GRPC_MDNULL;'
Craig Tillere52bbb12016-11-10 15:34:06 -0800463print >>C, '}'
464print >>C
465
Craig Tiller0160de92016-11-18 08:46:46 -0800466print >>C, 'grpc_mdelem_data grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT] = {'
Craig Tiller7885d1a2016-11-17 14:07:45 -0800467for a, b in all_elems:
468 print >>C, '{%s,%s},' % (slice_def(str_idx(a)), slice_def(str_idx(b)))
Craig Tiller2e7687c2015-11-18 14:56:46 -0800469print >>C, '};'
Craig Tiller2e7687c2015-11-18 14:56:46 -0800470
Craig Tillera7d37a32016-11-22 14:37:16 -0800471print >>H, 'typedef enum {'
Craig Tiller6ec8aa12016-11-23 09:35:25 -0800472for elem in METADATA_BATCH_CALLOUTS:
Craig Tillera7d37a32016-11-22 14:37:16 -0800473 print >>H, ' %s,' % mangle(elem, 'batch').upper()
474print >>H, ' GRPC_BATCH_CALLOUTS_COUNT'
475print >>H, '} grpc_metadata_batch_callouts_index;'
476print >>H
477print >>H, 'typedef union {'
478print >>H, ' struct grpc_linked_mdelem *array[GRPC_BATCH_CALLOUTS_COUNT];'
479print >>H, ' struct {'
Craig Tiller6ec8aa12016-11-23 09:35:25 -0800480for elem in METADATA_BATCH_CALLOUTS:
Craig Tillera7d37a32016-11-22 14:37:16 -0800481 print >>H, ' struct grpc_linked_mdelem *%s;' % mangle(elem, '').lower()
482print >>H, ' } named;'
483print >>H, '} grpc_metadata_batch_callouts;'
484print >>H
Craig Tiller6ec8aa12016-11-23 09:35:25 -0800485print >>H, '#define GRPC_BATCH_INDEX_OF(slice) \\'
Craig Tiller28d776e2016-11-23 10:16:53 -0800486print >>H, ' (GRPC_IS_STATIC_METADATA_STRING((slice)) ? (grpc_metadata_batch_callouts_index)GPR_CLAMP(GRPC_STATIC_METADATA_INDEX((slice)), 0, GRPC_BATCH_CALLOUTS_COUNT) : GRPC_BATCH_CALLOUTS_COUNT)'
Craig Tillera7d37a32016-11-22 14:37:16 -0800487print >>H
Craig Tillera7d37a32016-11-22 14:37:16 -0800488
Craig Tillerc6549762016-03-09 17:10:43 -0800489print >>H, 'extern const uint8_t grpc_static_accept_encoding_metadata[%d];' % (1 << len(COMPRESSION_ALGORITHMS))
490print >>C, 'const uint8_t grpc_static_accept_encoding_metadata[%d] = {' % (1 << len(COMPRESSION_ALGORITHMS))
Craig Tillerb2b42612015-11-20 12:02:17 -0800491print >>C, '0,%s' % ','.join('%d' % md_idx(elem) for elem in compression_elems)
492print >>C, '};'
493print >>C
494
Craig Tiller9ecadce2016-11-18 14:52:25 -0800495print >>H, '#define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs) (GRPC_MAKE_MDELEM(&grpc_static_mdelem_table[grpc_static_accept_encoding_metadata[(algs)]], GRPC_MDELEM_STORAGE_STATIC))'
Craig Tillerb2b42612015-11-20 12:02:17 -0800496
Craig Tiller3bd96952016-03-28 12:43:02 -0700497print >>H, '#endif /* GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H */'
Craig Tiller2e7687c2015-11-18 14:56:46 -0800498
499H.close()
500C.close()