Rakefile: kill raa_update task
[unicorn.git] / ext / unicorn_http / common_field_optimization.h
blob42c5430c36d572029626e91437ddadbbeac15bee
1 #ifndef common_field_optimization
2 #define common_field_optimization
3 #include "ruby.h"
4 #include "c_util.h"
6 struct common_field {
7 const signed long len;
8 const char *name;
9 VALUE value;
13 * A list of common HTTP headers we expect to receive.
14 * This allows us to avoid repeatedly creating identical string
15 * objects to be used with rb_hash_aset().
17 static struct common_field common_http_fields[] = {
18 # define f(N) { (sizeof(N) - 1), N, Qnil }
19 f("ACCEPT"),
20 f("ACCEPT_CHARSET"),
21 f("ACCEPT_ENCODING"),
22 f("ACCEPT_LANGUAGE"),
23 f("ALLOW"),
24 f("AUTHORIZATION"),
25 f("CACHE_CONTROL"),
26 f("CONNECTION"),
27 f("CONTENT_ENCODING"),
28 f("CONTENT_LENGTH"),
29 f("CONTENT_TYPE"),
30 f("COOKIE"),
31 f("DATE"),
32 f("EXPECT"),
33 f("FROM"),
34 f("HOST"),
35 f("IF_MATCH"),
36 f("IF_MODIFIED_SINCE"),
37 f("IF_NONE_MATCH"),
38 f("IF_RANGE"),
39 f("IF_UNMODIFIED_SINCE"),
40 f("KEEP_ALIVE"), /* Firefox sends this */
41 f("MAX_FORWARDS"),
42 f("PRAGMA"),
43 f("PROXY_AUTHORIZATION"),
44 f("RANGE"),
45 f("REFERER"),
46 f("TE"),
47 f("TRAILER"),
48 f("TRANSFER_ENCODING"),
49 f("UPGRADE"),
50 f("USER_AGENT"),
51 f("VIA"),
52 f("X_FORWARDED_FOR"), /* common for proxies */
53 f("X_FORWARDED_PROTO"), /* common for proxies */
54 f("X_REAL_IP"), /* common for proxies */
55 f("WARNING")
56 # undef f
59 #define HTTP_PREFIX "HTTP_"
60 #define HTTP_PREFIX_LEN (sizeof(HTTP_PREFIX) - 1)
62 /* this function is not performance-critical, called only at load time */
63 static void init_common_fields(void)
65 int i;
66 struct common_field *cf = common_http_fields;
67 char tmp[64];
68 memcpy(tmp, HTTP_PREFIX, HTTP_PREFIX_LEN);
70 for(i = ARRAY_SIZE(common_http_fields); --i >= 0; cf++) {
71 /* Rack doesn't like certain headers prefixed with "HTTP_" */
72 if (!strcmp("CONTENT_LENGTH", cf->name) ||
73 !strcmp("CONTENT_TYPE", cf->name)) {
74 cf->value = rb_str_new(cf->name, cf->len);
75 } else {
76 memcpy(tmp + HTTP_PREFIX_LEN, cf->name, cf->len + 1);
77 cf->value = rb_str_new(tmp, HTTP_PREFIX_LEN + cf->len);
79 cf->value = rb_obj_freeze(cf->value);
80 rb_global_variable(&cf->value);
84 /* this function is called for every header set */
85 static VALUE find_common_field(const char *field, size_t flen)
87 int i;
88 struct common_field *cf = common_http_fields;
90 for(i = ARRAY_SIZE(common_http_fields); --i >= 0; cf++) {
91 if (cf->len == (long)flen && !memcmp(cf->name, field, flen))
92 return cf->value;
94 return Qnil;
98 * We got a strange header that we don't have a memoized value for.
99 * Fallback to creating a new string to use as a hash key.
101 static VALUE uncommon_field(const char *field, size_t flen)
103 VALUE f = rb_str_new(NULL, HTTP_PREFIX_LEN + flen);
104 memcpy(RSTRING_PTR(f), HTTP_PREFIX, HTTP_PREFIX_LEN);
105 memcpy(RSTRING_PTR(f) + HTTP_PREFIX_LEN, field, flen);
106 assert(*(RSTRING_PTR(f) + RSTRING_LEN(f)) == '\0' &&
107 "string didn't end with \\0"); /* paranoia */
108 return rb_obj_freeze(f);
111 #endif /* common_field_optimization_h */