Created
March 20, 2011 06:21
-
-
Save Neopallium/878156 to your computer and use it in GitHub Desktop.
mongrel2 json gen speed-up.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if 1 | |
#define B(K, V) if((V) != NULL) { \ | |
vstr = json_escape(V); \ | |
bcatcstr(headers, ",\""); \ | |
bcatcstr(headers, bdata(K)); \ | |
bcatcstr(headers, "\":\""); \ | |
bcatcstr(headers, bdata(vstr)); \ | |
bcatcstr(headers, "\""); \ | |
bdestroy(vstr); \ | |
} | |
#else | |
#define B(K, V) if((V) != NULL) { \ | |
vstr = json_escape(V); \ | |
bformata(headers, ",\"%s\":\"%s\"", bdata(K), bdata(vstr)); \ | |
bdestroy(vstr); \ | |
} | |
#endif | |
static struct tagbstring QUOTE_CHAR = bsStatic("\""); | |
static struct tagbstring QUOTE_REPLACE = bsStatic("\\\""); | |
static struct tagbstring BSLASH_CHAR = bsStatic("\\"); | |
static struct tagbstring BSLASH_REPLACE = bsStatic("\\\\"); | |
static inline bstring json_escape(bstring in) | |
{ | |
if(in == NULL) return NULL; | |
// TODO: this isn't efficient at all, make it better | |
bstring vstr = bstrcpy(in); | |
// MUST GO IN THIS ORDER | |
bfindreplace(vstr, &BSLASH_CHAR, &BSLASH_REPLACE, 0); | |
bfindreplace(vstr, "E_CHAR, "E_REPLACE, 0); | |
return vstr; | |
} | |
struct tagbstring JSON_LISTSEP = bsStatic("\",\""); | |
bstring Request_to_payload(Request *req, bstring uuid, int fd, const char *buf, size_t len) | |
{ | |
bstring headers = bformat("{\"%s\":\"%s\"", bdata(&HTTP_PATH), bdata(req->path)); | |
bstring result = NULL; | |
int id = Register_id_for_fd(fd); | |
bstring vstr = NULL; // used in the B macro | |
bstring key = NULL; | |
hnode_t *i = NULL; | |
hscan_t scan; | |
struct bstrList *val_list = NULL; | |
//ballocmin(headers, 8192); | |
check(id != -1, "Asked to generate a paylod for an fd that doesn't exist: %d", fd); | |
hash_scan_begin(&scan, req->headers); | |
for(i = hash_scan_next(&scan); i != NULL; i = hash_scan_next(&scan)) { | |
val_list = hnode_get(i); | |
key = (bstring)hnode_getkey(i); | |
if(val_list->qty > 1) { | |
// join all the values together as a json array then add that to the key | |
bstring list = bjoin(val_list, &JSON_LISTSEP); | |
#if 0 | |
bformata(headers, ",\"%s\":[\"%s\"]", bdata(key), bdata(list)); | |
#else | |
bcatcstr(headers, ",\""); | |
bcatcstr(headers, bdata(key)); | |
bcatcstr(headers, "\":[\""); | |
bcatcstr(headers, bdata(list)); | |
bcatcstr(headers, "\"]"); | |
#endif | |
bdestroy(list); | |
} else { | |
B(key, val_list->entry[0]); | |
} | |
} | |
// these come after so that if anyone attempts to hijack these somehow, most | |
// hash algorithms languages have will replace the browser ones with ours | |
if(Request_is_json(req)) { | |
B(&HTTP_METHOD, &JSON_METHOD); | |
} else if(Request_is_xml(req)) { | |
B(&HTTP_METHOD, &XML_METHOD); | |
} else { | |
B(&HTTP_METHOD, req->request_method); | |
} | |
B(&HTTP_VERSION, req->version); | |
B(&HTTP_URI, req->uri); | |
B(&HTTP_QUERY, req->query_string); | |
B(&HTTP_FRAGMENT, req->fragment); | |
B(&HTTP_PATTERN, req->pattern); | |
bconchar(headers, '}'); | |
result = bformat("%s %d %s %d:%s,%d:", bdata(uuid), id, | |
bdata(Request_path(req)), | |
blength(headers), bdata(headers), len); | |
bcatblk(result, buf, len); | |
bconchar(result, ','); | |
check(result, "Failed to construct payload result."); | |
bdestroy(headers); | |
return result; | |
error: | |
bdestroy(headers); | |
bdestroy(result); | |
return NULL; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment