fix ASAN build
[folly.git] / folly / build / generate_escape_tables.py
1 #!/usr/bin/env python
2 #
3 # Generate Escape tables.
4 # Copyright 2011 Facebook
5 #
6 # @author Tudor Bosman (tudorb@fb.com)
7 #
8 import os
9 from optparse import OptionParser
10
11 OUTPUT_FILE = "EscapeTables.cpp"
12
13 def generate(f):
14     f.write("namespace folly {\n"
15             "namespace detail {\n"
16             "\n")
17
18     f.write("extern const char cEscapeTable[] =\n")
19     escapes = dict((
20         ('"', '\\"'),
21         ('\\', '\\\\'),
22         ('?', '?'),
23         ('\n', 'n'),
24         ('\r', 'r'),
25         ('\t', 't'),
26     ))
27     for i in range(0, 256):
28         if i % 64 == 0:
29             if i != 0:
30                 f.write("\"\n")
31             f.write("  \"")
32         c = chr(i)
33         if c in escapes:
34             c = escapes[c]
35         elif i < 32 or i > 126:
36             c = 'O'  # octal
37         else:
38             c = 'P'  # printable
39         f.write(c)
40     f.write("\";\n\n")
41
42     f.write("extern const char cUnescapeTable[] =\n")
43     for i in range(0, 256):
44         if i % 64 == 0:
45             if i != 0:
46                 f.write("\"\n")
47             f.write("  \"")
48         c = chr(i)
49         if c in '\'?':
50             f.write(c)
51         elif c in '"\\abfnrtv':
52             f.write("\\" + c)
53         elif i >= ord('0') and i <= ord('7'):
54             f.write("O")  # octal
55         elif c == "x":
56             f.write("X")  # hex
57         else:
58             f.write("I")  # invalid
59     f.write("\";\n\n")
60
61     f.write("extern const unsigned char hexTable[] = {")
62     for i in range(0, 256):
63         if i % 16 == 0:
64             f.write("\n  ")
65         if i >= ord('0') and i <= ord('9'):
66             f.write("{0:2d}, ".format(i - ord('0')))
67         elif i >= ord('a') and i <= ord('f'):
68             f.write("{0:2d}, ".format(i - ord('a') + 10))
69         elif i >= ord('A') and i <= ord('F'):
70             f.write("{0:2d}, ".format(i - ord('A') + 10))
71         else:
72             f.write("16, ")
73     f.write("\n};\n\n")
74
75     # 0 = passthrough
76     # 1 = unused
77     # 2 = safe in path (/)
78     # 3 = space (replace with '+' in query)
79     # 4 = always percent-encode
80     f.write("extern const unsigned char uriEscapeTable[] = {")
81     passthrough = (
82         list(map(ord, '0123456789')) +
83         list(map(ord, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')) +
84         list(map(ord, 'abcdefghijklmnopqrstuvwxyz')) +
85         list(map(ord, '-_.~')))
86     for i in range(0, 256):
87         if i % 16 == 0:
88             f.write("\n  ")
89         if i in passthrough:
90             f.write("0, ")
91         elif i == ord('/'):
92             f.write("2, ")
93         elif i == ord(' '):
94             f.write("3, ")
95         else:
96             f.write("4, ")
97     f.write("\n};\n\n")
98
99     f.write("}  // namespace detail\n"
100             "}  // namespace folly\n")
101
102 def main():
103     parser = OptionParser()
104     parser.add_option("--install_dir", dest="install_dir", default=".",
105                       help="write output to DIR", metavar="DIR")
106     parser.add_option("--fbcode_dir")
107     (options, args) = parser.parse_args()
108     f = open(os.path.join(options.install_dir, OUTPUT_FILE), "w")
109     generate(f)
110     f.close()
111
112 if __name__ == "__main__":
113     main()