blob: e1acdc12c6f4cc0d57a5b2dff2dba08d4fa10dce [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 Tiller2e7687c2015-11-18 14:56:46 -080039
40# configuration: a list of either strings or 2-tuples of strings
41# a single string represents a static grpc_mdstr
42# a 2-tuple represents a static grpc_mdelem (and appropriate grpc_mdstrs will
43# also be created)
44
45CONFIG = [
Craig Tiller47718a62016-11-14 14:48:42 -080046 # metadata strings
Craig Tiller2e7687c2015-11-18 14:56:46 -080047 'grpc-timeout',
Craig Tillerebdef9d2015-11-19 17:09:49 -080048 'grpc-internal-encoding-request',
Makdharma178f4bc2016-08-24 15:16:53 -070049 'grpc-payload-bin',
Craig Tiller2e7687c2015-11-18 14:56:46 -080050 ':path',
51 'grpc-encoding',
52 'grpc-accept-encoding',
53 'user-agent',
54 ':authority',
55 'host',
56 'grpc-message',
57 'grpc-status',
David Garcia Quintas8eec9ec2016-08-01 17:05:04 -070058 'grpc-tracing-bin',
David Garcia Quintas98d5f5c2016-09-14 14:34:22 -070059 'grpc-stats-bin',
Craig Tiller2e7687c2015-11-18 14:56:46 -080060 '',
Craig Tiller47718a62016-11-14 14:48:42 -080061 # channel arg keys
62 'grpc.wait_for_ready',
63 'grpc.timeout',
64 'grpc.max_request_message_bytes',
65 'grpc.max_response_message_bytes',
Craig Tillerd7f15832016-11-16 17:12:55 -080066 # well known method names
67 '/grpc.lb.v1.LoadBalancer/BalanceLoad',
Craig Tiller47718a62016-11-14 14:48:42 -080068 # metadata elements
Craig Tiller2e7687c2015-11-18 14:56:46 -080069 ('grpc-status', '0'),
Craig Tillerebdef9d2015-11-19 17:09:49 -080070 ('grpc-status', '1'),
71 ('grpc-status', '2'),
72 ('grpc-encoding', 'identity'),
73 ('grpc-encoding', 'gzip'),
74 ('grpc-encoding', 'deflate'),
Craig Tiller2e7687c2015-11-18 14:56:46 -080075 ('te', 'trailers'),
Craig Tillerebdef9d2015-11-19 17:09:49 -080076 ('content-type', 'application/grpc'),
Craig Tiller2e7687c2015-11-18 14:56:46 -080077 (':method', 'POST'),
78 (':status', '200'),
79 (':status', '404'),
80 (':scheme', 'http'),
81 (':scheme', 'https'),
82 (':scheme', 'grpc'),
83 (':authority', ''),
84 (':method', 'GET'),
Craig Tillerc6549762016-03-09 17:10:43 -080085 (':method', 'PUT'),
Craig Tiller2e7687c2015-11-18 14:56:46 -080086 (':path', '/'),
87 (':path', '/index.html'),
88 (':status', '204'),
89 (':status', '206'),
90 (':status', '304'),
91 (':status', '400'),
92 (':status', '500'),
93 ('accept-charset', ''),
94 ('accept-encoding', ''),
95 ('accept-encoding', 'gzip, deflate'),
96 ('accept-language', ''),
97 ('accept-ranges', ''),
98 ('accept', ''),
99 ('access-control-allow-origin', ''),
100 ('age', ''),
101 ('allow', ''),
102 ('authorization', ''),
103 ('cache-control', ''),
104 ('content-disposition', ''),
105 ('content-encoding', ''),
106 ('content-language', ''),
107 ('content-length', ''),
108 ('content-location', ''),
109 ('content-range', ''),
110 ('content-type', ''),
111 ('cookie', ''),
112 ('date', ''),
113 ('etag', ''),
114 ('expect', ''),
115 ('expires', ''),
116 ('from', ''),
117 ('host', ''),
118 ('if-match', ''),
119 ('if-modified-since', ''),
120 ('if-none-match', ''),
121 ('if-range', ''),
122 ('if-unmodified-since', ''),
123 ('last-modified', ''),
David Garcia Quintasa3654db2016-10-11 15:52:39 -0700124 ('lb-token', ''),
David Garcia Quintasd8fe3342016-10-15 15:25:51 -0700125 ('lb-cost-bin', ''),
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 Tillerb2b42612015-11-20 12:02:17 -0800145COMPRESSION_ALGORITHMS = [
146 'identity',
147 'deflate',
148 'gzip',
149]
150
Craig Tiller2e7687c2015-11-18 14:56:46 -0800151# utility: mangle the name of a config
152def mangle(elem):
153 xl = {
154 '-': '_',
155 ':': '',
156 '/': 'slash',
157 '.': 'dot',
158 ',': 'comma',
159 ' ': '_',
160 }
161 def m0(x):
162 if not x: return 'empty'
163 r = ''
164 for c in x:
165 put = xl.get(c, c.lower())
166 if not put: continue
167 last_is_underscore = r[-1] == '_' if r else True
168 if last_is_underscore and put == '_': continue
169 elif len(put) > 1:
170 if not last_is_underscore: r += '_'
171 r += put
172 r += '_'
173 else:
174 r += put
175 if r[-1] == '_': r = r[:-1]
176 return r
177 if isinstance(elem, tuple):
178 return 'grpc_mdelem_%s_%s' % (m0(elem[0]), m0(elem[1]))
179 else:
180 return 'grpc_mdstr_%s' % (m0(elem))
181
182# utility: generate some hash value for a string
183def fake_hash(elem):
184 return hashlib.md5(elem).hexdigest()[0:8]
185
186# utility: print a big comment block into a set of files
187def put_banner(files, banner):
188 for f in files:
189 print >>f, '/*'
190 for line in banner:
191 print >>f, ' * %s' % line
192 print >>f, ' */'
193 print >>f
194
195# build a list of all the strings we need
Craig Tillerd7f15832016-11-16 17:12:55 -0800196all_strs = list()
197all_elems = list()
Craig Tillerb2b42612015-11-20 12:02:17 -0800198static_userdata = {}
Craig Tiller2e7687c2015-11-18 14:56:46 -0800199for elem in CONFIG:
200 if isinstance(elem, tuple):
Craig Tillerd7f15832016-11-16 17:12:55 -0800201 if elem[0] not in all_strs:
202 all_strs.append(elem[0])
203 if elem[1] not in all_strs:
204 all_strs.append(elem[1])
205 if elem not in all_elems:
206 all_elems.append(elem)
Craig Tiller2e7687c2015-11-18 14:56:46 -0800207 else:
Craig Tillerd7f15832016-11-16 17:12:55 -0800208 if elem not in all_strs:
209 all_strs.append(elem)
Craig Tillerb2b42612015-11-20 12:02:17 -0800210compression_elems = []
211for mask in range(1, 1<<len(COMPRESSION_ALGORITHMS)):
212 val = ','.join(COMPRESSION_ALGORITHMS[alg]
213 for alg in range(0, len(COMPRESSION_ALGORITHMS))
214 if (1 << alg) & mask)
215 elem = ('grpc-accept-encoding', val)
Craig Tillerd7f15832016-11-16 17:12:55 -0800216 if val not in all_strs:
217 all_strs.append(val)
218 if elem not in all_elems:
219 all_elems.append(elem)
Craig Tillerb2b42612015-11-20 12:02:17 -0800220 compression_elems.append(elem)
David Garcia Quintas07503b62016-03-21 11:59:33 -0700221 static_userdata[elem] = 1 + (mask | 1)
Craig Tiller2e7687c2015-11-18 14:56:46 -0800222all_strs = sorted(list(all_strs), key=mangle)
223all_elems = sorted(list(all_elems), key=mangle)
224
225# output configuration
226args = sys.argv[1:]
227H = None
228C = None
Craig Tiller134a6b62016-04-18 08:14:20 -0700229D = None
Craig Tiller2e7687c2015-11-18 14:56:46 -0800230if args:
231 if 'header' in args:
232 H = sys.stdout
233 else:
234 H = open('/dev/null', 'w')
235 if 'source' in args:
236 C = sys.stdout
237 else:
238 C = open('/dev/null', 'w')
Craig Tiller134a6b62016-04-18 08:14:20 -0700239 if 'dictionary' in args:
240 D = sys.stdout
241 else:
242 D = open('/dev/null', 'w')
Craig Tiller2e7687c2015-11-18 14:56:46 -0800243else:
244 H = open(os.path.join(
Craig Tillerffae43c2016-03-25 19:34:29 -0700245 os.path.dirname(sys.argv[0]), '../../../src/core/lib/transport/static_metadata.h'), 'w')
Craig Tiller2e7687c2015-11-18 14:56:46 -0800246 C = open(os.path.join(
Craig Tillerffae43c2016-03-25 19:34:29 -0700247 os.path.dirname(sys.argv[0]), '../../../src/core/lib/transport/static_metadata.c'), 'w')
Craig Tiller134a6b62016-04-18 08:14:20 -0700248 D = open(os.path.join(
249 os.path.dirname(sys.argv[0]), '../../../test/core/end2end/fuzzers/hpack.dictionary'), 'w')
Craig Tiller2e7687c2015-11-18 14:56:46 -0800250
251# copy-paste copyright notice from this file
252with open(sys.argv[0]) as my_source:
253 copyright = []
254 for line in my_source:
255 if line[0] != '#': break
256 for line in my_source:
257 if line[0] == '#':
258 copyright.append(line)
259 break
260 for line in my_source:
261 if line[0] != '#':
262 break
263 copyright.append(line)
Craig Tiller3bd96952016-03-28 12:43:02 -0700264 put_banner([H,C], [line[2:].rstrip() for line in copyright])
Craig Tiller2e7687c2015-11-18 14:56:46 -0800265
Craig Tiller134a6b62016-04-18 08:14:20 -0700266
267hex_bytes = [ord(c) for c in "abcdefABCDEF0123456789"]
268
269
Craig Tiller69b6d4e2016-04-18 15:08:14 -0700270def esc_dict(line):
Craig Tiller134a6b62016-04-18 08:14:20 -0700271 out = "\""
Craig Tiller134a6b62016-04-18 08:14:20 -0700272 for c in line:
273 if 32 <= c < 127:
Craig Tiller134a6b62016-04-18 08:14:20 -0700274 if c != ord('"'):
275 out += chr(c)
276 else:
277 out += "\\\""
Craig Tiller134a6b62016-04-18 08:14:20 -0700278 else:
Craig Tiller69b6d4e2016-04-18 15:08:14 -0700279 out += "\\x%02X" % c
Craig Tiller134a6b62016-04-18 08:14:20 -0700280 return out + "\""
281
Craig Tiller2e7687c2015-11-18 14:56:46 -0800282put_banner([H,C],
283"""WARNING: Auto-generated code.
284
Craig Tiller3bd96952016-03-28 12:43:02 -0700285To make changes to this file, change
286tools/codegen/core/gen_static_metadata.py, and then re-run it.
Craig Tiller51ae0be2015-11-19 07:51:25 -0800287
Craig Tiller3bd96952016-03-28 12:43:02 -0700288See metadata.h for an explanation of the interface here, and metadata.c for
289an explanation of what's going on.
Craig Tiller2e7687c2015-11-18 14:56:46 -0800290""".splitlines())
291
Craig Tiller3bd96952016-03-28 12:43:02 -0700292print >>H, '#ifndef GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H'
293print >>H, '#define GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H'
Craig Tiller2e7687c2015-11-18 14:56:46 -0800294print >>H
Craig Tillerffae43c2016-03-25 19:34:29 -0700295print >>H, '#include "src/core/lib/transport/metadata.h"'
Craig Tiller2e7687c2015-11-18 14:56:46 -0800296print >>H
297
Craig Tillerffae43c2016-03-25 19:34:29 -0700298print >>C, '#include "src/core/lib/transport/static_metadata.h"'
Craig Tiller2e7687c2015-11-18 14:56:46 -0800299print >>C
Craig Tiller19614362016-11-17 16:05:27 -0800300print >>C, '#include "src/core/lib/slice/slice_internal.h"'
301print >>C
Craig Tiller2e7687c2015-11-18 14:56:46 -0800302
303print >>H, '#define GRPC_STATIC_MDSTR_COUNT %d' % len(all_strs)
Craig Tillere52bbb12016-11-10 15:34:06 -0800304print >>H, 'extern const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT];'
Craig Tiller2e7687c2015-11-18 14:56:46 -0800305for i, elem in enumerate(all_strs):
306 print >>H, '/* "%s" */' % elem
Craig Tiller5ef31ab2016-11-10 16:27:48 -0800307 print >>H, '#define %s (grpc_static_slice_table[%d])' % (mangle(elem).upper(), i)
Craig Tiller2e7687c2015-11-18 14:56:46 -0800308print >>H
Craig Tillere52bbb12016-11-10 15:34:06 -0800309print >>H, 'bool grpc_is_static_metadata_string(grpc_slice slice);'
310print >>H
311print >>C, 'static uint8_t g_raw_bytes[] = {%s};' % (','.join('%d' % ord(c) for c in ''.join(all_strs)))
312print >>C
313print >>C, 'static void static_ref(void *unused) {}'
314print >>C, 'static void static_unref(grpc_exec_ctx *exec_ctx, void *unused) {}'
Craig Tiller19614362016-11-17 16:05:27 -0800315print >>C, 'static const grpc_slice_refcount_vtable static_vtable = {static_ref, static_unref, grpc_static_slice_hash};';
Craig Tiller0451c3d2016-11-17 09:34:14 -0800316print >>C, 'static grpc_slice_refcount g_refcnt = {&static_vtable};'
Craig Tillere52bbb12016-11-10 15:34:06 -0800317print >>C
318print >>C, 'bool grpc_is_static_metadata_string(grpc_slice slice) {'
Craig Tiller0451c3d2016-11-17 09:34:14 -0800319print >>C, ' return slice.refcount != NULL && slice.refcount->vtable == &static_vtable;'
Craig Tillerd7f15832016-11-16 17:12:55 -0800320print >>C, '}'
Craig Tillere52bbb12016-11-10 15:34:06 -0800321print >>C
322print >>C, 'const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT] = {'
323str_ofs = 0
324revmap = {}
325zero_length_idx = None
Craig Tiller7885d1a2016-11-17 14:07:45 -0800326id2strofs = {}
327def slice_def(i):
328 return '{.refcount = &g_refcnt, .data.refcounted = {.bytes = g_raw_bytes+%d, .length=%d}}' % (id2strofs[i], len(all_strs[i]))
Craig Tillere52bbb12016-11-10 15:34:06 -0800329for i, elem in enumerate(all_strs):
Craig Tiller7885d1a2016-11-17 14:07:45 -0800330 id2strofs[i] = str_ofs
331 print >>C, slice_def(i) + ','
Craig Tillere52bbb12016-11-10 15:34:06 -0800332 revmap[str_ofs] = i
333 if len(elem) == 0: zero_length_idx = i
334 str_ofs += len(elem);
335print >>C, '};'
336print >>C
337print >>C, 'static const uint8_t g_revmap[] = {%s};' % ','.join('%d' % (revmap[i] if i in revmap else 255) for i in range(0, str_ofs))
338print >>C
Craig Tiller19614362016-11-17 16:05:27 -0800339print >>H, 'int grpc_static_metadata_index(grpc_slice slice);'
Craig Tillere52bbb12016-11-10 15:34:06 -0800340print >>C, 'int grpc_static_metadata_index(grpc_slice slice) {'
341print >>C, ' if (GRPC_SLICE_LENGTH(slice) == 0) return %d;' % zero_length_idx
Craig Tillerb2348ba2016-11-18 08:10:46 -0800342print >>C, ' if (slice.refcount != &g_refcnt) return -1;'
343print >>C, ' size_t ofs = (size_t)(slice.data.refcounted.bytes - g_raw_bytes);'
Craig Tillere52bbb12016-11-10 15:34:06 -0800344print >>C, ' if (ofs > sizeof(g_revmap)) return -1;'
345print >>C, ' uint8_t id = g_revmap[ofs];'
Craig Tillerb2348ba2016-11-18 08:10:46 -0800346print >>C, ' return id == 255 ? -1 : (grpc_static_slice_table[id].data.refcounted.length == slice.data.refcounted.length? id : -1);'
Craig Tillerd7f15832016-11-16 17:12:55 -0800347print >>C, '}'
Craig Tiller2e7687c2015-11-18 14:56:46 -0800348print >>C
349
Craig Tiller134a6b62016-04-18 08:14:20 -0700350print >>D, '# hpack fuzzing dictionary'
351for i, elem in enumerate(all_strs):
Craig Tiller69b6d4e2016-04-18 15:08:14 -0700352 print >>D, '%s' % (esc_dict([len(elem)] + [ord(c) for c in elem]))
Craig Tiller942568b2016-04-18 22:19:00 -0700353for i, elem in enumerate(all_elems):
354 print >>D, '%s' % (esc_dict([0, len(elem[0])] + [ord(c) for c in elem[0]] +
355 [len(elem[1])] + [ord(c) for c in elem[1]]))
Craig Tiller134a6b62016-04-18 08:14:20 -0700356
Craig Tiller2e7687c2015-11-18 14:56:46 -0800357print >>H, '#define GRPC_STATIC_MDELEM_COUNT %d' % len(all_elems)
Craig Tiller0160de92016-11-18 08:46:46 -0800358print >>H, 'extern grpc_mdelem_data grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];'
Craig Tillerc6549762016-03-09 17:10:43 -0800359print >>H, 'extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT];'
Craig Tiller2e7687c2015-11-18 14:56:46 -0800360for i, elem in enumerate(all_elems):
361 print >>H, '/* "%s": "%s" */' % elem
Craig Tiller0160de92016-11-18 08:46:46 -0800362 print >>H, '#define %s ((grpc_mdelem){&grpc_static_mdelem_table[%d]})' % (mangle(elem).upper(), i)
Craig Tiller2e7687c2015-11-18 14:56:46 -0800363print >>H
Craig Tillerc6549762016-03-09 17:10:43 -0800364print >>C, 'uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] = {'
Craig Tillerb2b42612015-11-20 12:02:17 -0800365print >>C, ' %s' % ','.join('%d' % static_userdata.get(elem, 0) for elem in all_elems)
366print >>C, '};'
Craig Tiller2e7687c2015-11-18 14:56:46 -0800367print >>C
368
369def str_idx(s):
370 for i, s2 in enumerate(all_strs):
371 if s == s2:
372 return i
373
Craig Tillerb2b42612015-11-20 12:02:17 -0800374def md_idx(m):
375 for i, m2 in enumerate(all_elems):
376 if m == m2:
377 return i
378
Craig Tillere52bbb12016-11-10 15:34:06 -0800379def perfect_hash(keys, name):
Craig Tillerd7f15832016-11-16 17:12:55 -0800380 ok = False
381 cmd = '%s/perfect/build.sh' % (os.path.dirname(sys.argv[0]))
Craig Tillere52bbb12016-11-10 15:34:06 -0800382 subprocess.check_call(cmd, shell=True)
Craig Tillerd7f15832016-11-16 17:12:55 -0800383 for offset in reversed(range(0, min(keys))):
384 tmp = open('/tmp/keys.txt', 'w')
385 tmp.write(''.join('%d\n' % (x - offset) for x in keys))
386 tmp.close()
387 cmd = '%s/perfect/run.sh %s -dms' % (os.path.dirname(sys.argv[0]), tmp.name)
388 out = subprocess.check_output(cmd, shell=True)
389 if 'fatal error' not in out:
390 ok = True
391 break
392 assert ok, "Failed to find hash of keys in /tmp/keys.txt"
Craig Tillere52bbb12016-11-10 15:34:06 -0800393
394 code = ''
395
396 results = {}
397 with open('%s/perfect/phash.h' % os.path.dirname(sys.argv[0])) as f:
398 txt = f.read()
399 for var in ('PHASHLEN', 'PHASHNKEYS', 'PHASHRANGE', 'PHASHSALT'):
400 val = re.search(r'#define %s ([0-9a-zA-Z]+)' % var, txt).group(1)
401 code += '#define %s_%s %s\n' % (name.upper(), var, val)
402 results[var] = val
403 code += '\n'
404 pycode = 'def f(val):\n'
Craig Tillerd7f15832016-11-16 17:12:55 -0800405 pycode += ' val -= %d\n' % offset
Craig Tillere52bbb12016-11-10 15:34:06 -0800406 with open('%s/perfect/phash.c' % os.path.dirname(sys.argv[0])) as f:
407 txt = f.read()
408 tabdata = re.search(r'ub1 tab\[\] = \{([^}]+)\}', txt, re.MULTILINE).group(1)
409 code += 'static const uint8_t %s_tab[] = {%s};\n\n' % (name, tabdata)
410 func_body = re.search(r'ub4 phash\(val\)\nub4 val;\n\{([^}]+)\}', txt, re.MULTILINE).group(1).replace('ub4', 'uint32_t')
411 code += 'static uint32_t %s_phash(uint32_t val) {\nval -= %d;\n%s}\n' % (name,
Craig Tillerd7f15832016-11-16 17:12:55 -0800412 offset, func_body.replace('tab', '%s_tab' % name))
Craig Tillere52bbb12016-11-10 15:34:06 -0800413 pycode += ' tab=(%s)' % tabdata.replace('\n', '')
414 pycode += '\n'.join(' %s' % s.strip() for s in func_body.splitlines()[2:])
415 g = {}
416 exec pycode in g
417 pyfunc = g['f']
418
419 results['code'] = code
420 results['pyfunc'] = pyfunc
421 return results
422
423elem_keys = [str_idx(elem[0]) * len(all_strs) + str_idx(elem[1]) for elem in all_elems]
424elem_hash = perfect_hash(elem_keys, "elems")
425print >>C, elem_hash['code']
426
427keys = [0] * int(elem_hash['PHASHRANGE'])
428idxs = [-1] * int(elem_hash['PHASHNKEYS'])
429for i, k in enumerate(elem_keys):
430 h = elem_hash['pyfunc'](k)
431 assert keys[h] == 0
432 keys[h] = k
433 idxs[h] = i
434print >>C, 'static const uint16_t elem_keys[] = {%s};' % ','.join('%d' % k for k in keys)
435print >>C, 'static const uint8_t elem_idxs[] = {%s};' % ','.join('%d' % i for i in idxs)
436print >>C
437
Craig Tiller0160de92016-11-18 08:46:46 -0800438print >>H, 'grpc_mdelem grpc_static_mdelem_for_static_strings(int a, int b);'
439print >>C, 'grpc_mdelem grpc_static_mdelem_for_static_strings(int a, int b) {'
440print >>C, ' if (a == -1 || b == -1) return GRPC_MDNULL;'
Craig Tillere52bbb12016-11-10 15:34:06 -0800441print >>C, ' uint32_t k = (uint32_t)(a * %d + b);' % len(all_strs)
442print >>C, ' uint32_t h = elems_phash(k);'
Craig Tiller0160de92016-11-18 08:46:46 -0800443print >>C, ' return elem_keys[h] == k ? (grpc_mdelem){&grpc_static_mdelem_table[elem_idxs[h]]} : GRPC_MDNULL;'
Craig Tillere52bbb12016-11-10 15:34:06 -0800444print >>C, '}'
445print >>C
446
Craig Tiller0160de92016-11-18 08:46:46 -0800447print >>C, 'grpc_mdelem_data grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT] = {'
Craig Tiller7885d1a2016-11-17 14:07:45 -0800448for a, b in all_elems:
449 print >>C, '{%s,%s},' % (slice_def(str_idx(a)), slice_def(str_idx(b)))
Craig Tiller2e7687c2015-11-18 14:56:46 -0800450print >>C, '};'
Craig Tiller2e7687c2015-11-18 14:56:46 -0800451
Craig Tillerc6549762016-03-09 17:10:43 -0800452print >>H, 'extern const uint8_t grpc_static_accept_encoding_metadata[%d];' % (1 << len(COMPRESSION_ALGORITHMS))
453print >>C, 'const uint8_t grpc_static_accept_encoding_metadata[%d] = {' % (1 << len(COMPRESSION_ALGORITHMS))
Craig Tillerb2b42612015-11-20 12:02:17 -0800454print >>C, '0,%s' % ','.join('%d' % md_idx(elem) for elem in compression_elems)
455print >>C, '};'
456print >>C
457
Craig Tiller0160de92016-11-18 08:46:46 -0800458print >>H, '#define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs) ((grpc_mdelem){&grpc_static_mdelem_table[grpc_static_accept_encoding_metadata[(algs)]]})'
Craig Tillerb2b42612015-11-20 12:02:17 -0800459
Craig Tiller3bd96952016-03-28 12:43:02 -0700460print >>H, '#endif /* GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H */'
Craig Tiller2e7687c2015-11-18 14:56:46 -0800461
462H.close()
463C.close()