Refactoring unicorn_http C/Ragel code
[unicorn.git] / ext / unicorn_http / common_field_optimization.h
blob978f0d77ee08fac67f8880c44d71e36601c013a9
1 #ifndef common_field_optimization
2 #define common_field_optimization
3 #include "ruby.h"
5 struct common_field {
6 const signed long len;
7 const char *name;
8 VALUE value;
9 };
12 * A list of common HTTP headers we expect to receive.
13 * This allows us to avoid repeatedly creating identical string
14 * objects to be used with rb_hash_aset().
16 static struct common_field common_http_fields[] = {
17 # define f(N) { (sizeof(N) - 1), N, Qnil }
18 f("ACCEPT"),
19 f("ACCEPT_CHARSET"),
20 f("ACCEPT_ENCODING"),
21 f("ACCEPT_LANGUAGE"),
22 f("ALLOW"),
23 f("AUTHORIZATION"),
24 f("CACHE_CONTROL"),
25 f("CONNECTION"),
26 f("CONTENT_ENCODING"),
27 f("CONTENT_LENGTH"),
28 f("CONTENT_TYPE"),
29 f("COOKIE"),
30 f("DATE"),
31 f("EXPECT"),
32 f("FROM"),
33 f("HOST"),
34 f("IF_MATCH"),
35 f("IF_MODIFIED_SINCE"),
36 f("IF_NONE_MATCH"),
37 f("IF_RANGE"),
38 f("IF_UNMODIFIED_SINCE"),
39 f("KEEP_ALIVE"), /* Firefox sends this */
40 f("MAX_FORWARDS"),
41 f("PRAGMA"),
42 f("PROXY_AUTHORIZATION"),
43 f("RANGE"),
44 f("REFERER"),
45 f("TE"),
46 f("TRAILER"),
47 f("TRANSFER_ENCODING"),
48 f("UPGRADE"),
49 f("USER_AGENT"),
50 f("VIA"),
51 f("X_FORWARDED_FOR"), /* common for proxies */
52 f("X_FORWARDED_PROTO"), /* common for proxies */
53 f("X_REAL_IP"), /* common for proxies */
54 f("WARNING")
55 # undef f
58 #define HTTP_PREFIX "HTTP_"
59 #define HTTP_PREFIX_LEN (sizeof(HTTP_PREFIX) - 1)
61 /* this function is not performance-critical, called only at load time */
62 static void init_common_fields(void)
64 int i;
65 struct common_field *cf = common_http_fields;
66 char tmp[64];
67 memcpy(tmp, HTTP_PREFIX, HTTP_PREFIX_LEN);
69 for(i = 0; i < ARRAY_SIZE(common_http_fields); cf++, i++) {
70 /* Rack doesn't like certain headers prefixed with "HTTP_" */
71 if (!strcmp("CONTENT_LENGTH", cf->name) ||
72 !strcmp("CONTENT_TYPE", cf->name)) {
73 cf->value = rb_str_new(cf->name, cf->len);
74 } else {
75 memcpy(tmp + HTTP_PREFIX_LEN, cf->name, cf->len + 1);
76 cf->value = rb_str_new(tmp, HTTP_PREFIX_LEN + cf->len);
78 cf->value = rb_obj_freeze(cf->value);
79 rb_global_variable(&cf->value);
83 /* this function is called for every header set */
84 static VALUE find_common_field_value(const char *field, size_t flen)
86 int i;
87 struct common_field *cf = common_http_fields;
89 for(i = 0; i < ARRAY_SIZE(common_http_fields); i++, cf++) {
90 if (cf->len == flen && !memcmp(cf->name, field, flen))
91 return cf->value;
93 return Qnil;
96 #endif /* common_field_optimization_h */