about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-08-02 16:16:28 -0700
committerEric Wong <normalperson@yhbt.net>2009-08-09 01:29:40 -0700
commit60b4397f51894d5e679a6eed73a8cde957f03c4a (patch)
tree9da48622b713dd0f3913f83a83a4c0e420f936ff
parent074dc90aaefc17dd5a60c3f67187305924849b05 (diff)
downloadunicorn-60b4397f51894d5e679a6eed73a8cde957f03c4a.tar.gz
The macro version lets us painlessly compare Ruby strings
against constant C strings.  It wraps a C version of the
function which is necessary to avoid double evaluation while
preventing the user from having to type sizeof or strlen.
-rw-r--r--ext/unicorn_http/ext_help.h8
-rw-r--r--ext/unicorn_http/unicorn_http.rl26
2 files changed, 19 insertions, 15 deletions
diff --git a/ext/unicorn_http/ext_help.h b/ext/unicorn_http/ext_help.h
index fec4f41..19f08c9 100644
--- a/ext/unicorn_http/ext_help.h
+++ b/ext/unicorn_http/ext_help.h
@@ -18,4 +18,12 @@ static void rb_18_str_set_len(VALUE str, long len)
 #  define rb_str_set_len(str,len) rb_18_str_set_len(str,len)
 #endif
 
+static inline int str_cstr_eq(VALUE val, const char *ptr, size_t len)
+{
+  return (RSTRING_LEN(val) == len && !memcmp(ptr, RSTRING_PTR(val), len));
+}
+
+#define STR_CSTR_EQ(val, const_str) \
+  str_cstr_eq(val, const_str, sizeof(const_str) - 1)
+
 #endif
diff --git a/ext/unicorn_http/unicorn_http.rl b/ext/unicorn_http/unicorn_http.rl
index 5081605..76831bb 100644
--- a/ext/unicorn_http/unicorn_http.rl
+++ b/ext/unicorn_http/unicorn_http.rl
@@ -71,16 +71,18 @@ static void header_done(VALUE req, const char *at, size_t length);
   }
   action request_uri {
     size_t len = LEN(mark, fpc);
+    VALUE str;
+
     VALIDATE_MAX_LENGTH(len, REQUEST_URI);
-    rb_hash_aset(req, g_request_uri, STR_NEW(mark, fpc));
+    str = rb_hash_aset(req, g_request_uri, STR_NEW(mark, fpc));
     /*
      * "OPTIONS * HTTP/1.1\r\n" is a valid request, but we can't have '*'
      * in REQUEST_PATH or PATH_INFO or else Rack::Lint will complain
      */
-    if (len == 1 && *PTR_TO(mark) == '*') {
-      VALUE val = rb_str_new(NULL, 0);
-      rb_hash_aset(req, g_request_path, val);
-      rb_hash_aset(req, g_path_info, val);
+    if (STR_CSTR_EQ(str, "*")) {
+      str = rb_str_new(NULL, 0);
+      rb_hash_aset(req, g_path_info, str);
+      rb_hash_aset(req, g_request_path, str);
     }
   }
   action fragment {
@@ -100,11 +102,10 @@ static void header_done(VALUE req, const char *at, size_t length);
     size_t len = LEN(mark, fpc);
 
     VALIDATE_MAX_LENGTH(len, REQUEST_PATH);
-    val = STR_NEW(mark, fpc);
+    val = rb_hash_aset(req, g_request_path, STR_NEW(mark, fpc));
 
-    rb_hash_aset(req, g_request_path, val);
     /* rack says PATH_INFO must start with "/" or be empty */
-    if (!(len == 1 && *PTR_TO(mark) == '*'))
+    if (!STR_CSTR_EQ(val, "*"))
       rb_hash_aset(req, g_path_info, val);
   }
   action done {
@@ -177,11 +178,6 @@ static void http_field(VALUE req, const char *field, size_t flen, VALUE val)
   rb_hash_aset(req, f, val);
 }
 
-static int is_https(VALUE str)
-{
-  return RSTRING_LEN(str) == 5 && !memcmp("https", RSTRING_PTR(str), 5);
-}
-
 static void set_server_params(VALUE req)
 {
   VALUE temp = rb_hash_aref(req, g_rack_url_scheme);
@@ -191,12 +187,12 @@ static void set_server_params(VALUE req)
   /* set rack.url_scheme to "https" or "http", no others are allowed by Rack */
   if (temp == Qnil) {
     temp = rb_hash_aref(req, g_http_x_forwarded_proto);
-    if (temp != Qnil && is_https(temp))
+    if (temp != Qnil && STR_CSTR_EQ(temp, "https"))
       server_port = g_port_443;
     else
       temp = g_http;
     rb_hash_aset(req, g_rack_url_scheme, temp);
-  } else if (is_https(temp)) {
+  } else if (STR_CSTR_EQ(temp, "https")) {
     server_port = g_port_443;
   }