diff options
author | Yorhel <git@yorhel.nl> | 2012-03-02 16:20:16 +0100 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2012-03-02 16:33:38 +0100 |
commit | d17d94cefafd25471234307c3b4a67c276d0b651 (patch) | |
tree | 28679123487b9baf20920d4f62c6735402abc813 | |
parent | e7e685dae254e918c2a4afe063e2a1201b97e8ef (diff) |
Use lbuf abstraction for JSON-formatting tuples
Makes it easier/more efficient to write tuples directly to the link buffer.
-rw-r--r-- | tanja.c | 191 | ||||
-rw-r--r-- | tanja.h | 2 | ||||
-rw-r--r-- | test.c | 7 |
3 files changed, 97 insertions, 103 deletions
@@ -38,6 +38,58 @@ static void tn_session_reply(tn_session *, tn_tuple *, tn_returnpath *); +// Tiny buffer abstraction for internal use +// Note that these macros aren't very safe with respect to argument naming / +// evaluation. Only pass variables directly. + +typedef struct { + char *dat; + int len; + int size; +} lbuf; + +#define lbuf_init(b) do {\ + b.dat = NULL;\ + b.size = b.len = 0;\ + } while(0) + +#define lbuf_free(b) do {\ + if(b.dat)\ + free(b.dat);\ + lbuf_init(b);\ + } while(0) + +#define lbuf_grow(b, _m) do {\ + if(b.size < 16)\ + b.size = 16;\ + else\ + b.size *= 2;\ + if(b.size < _m)\ + b.size = _m;\ + b.dat = realloc(b.dat, b.size);\ + } while(0) + +#define lbuf_append(b, _buf, _len) do {\ + if(b.size < b.len + _len)\ + lbuf_grow(b, b.len + _len);\ + memcpy(b.dat+b.len, _buf, _len);\ + b.len += _len;\ + } while(0) + +#define lbuf_append_c(b, _c) do {\ + if(b.size < b.len + 1)\ + lbuf_grow(b, b.len + 1);\ + b.dat[b.len++] = _c;\ + } while(0) + +#define lbuf_shift(b, _len) do {\ + memmove(b.dat, b.dat+_len, b.len-_len);\ + b.len -= _len;\ + } while(0) + + + + // Generic tuple management @@ -252,20 +304,14 @@ int tn_tuple_match(tn_tuple *p, tn_tuple *t) { // Tuple-to-json encoder -#define ac(c) do {\ - buf[(*w)++] = c;\ - if(--(*len) <= 0)\ - return -1;\ - } while(0) +#define ac(_c) lbuf_append_c((*buf), _c) -#define as(s) do {\ - char *tmp=s;\ - while(*tmp)\ - ac(*(tmp++));\ +#define as(_s) do {\ + int _len = strlen(_s);\ + lbuf_append((*buf), _s, _len);\ } while(0) - -static int json_fmt_string(char *str, char *buf, int *w, int *len) { +static inline void json_fmt_string(char *str, lbuf *buf) { ac('\"'); while(*str) { switch(*str) { @@ -284,11 +330,10 @@ static int json_fmt_string(char *str, char *buf, int *w, int *len) { str++; } ac('\"'); - return *w; } -static int json_fmt_element(tn_element e, char *buf, int *w, int *len) { +static void json_fmt_element(tn_element e, lbuf *buf) { char b[25]; int i; switch(e.type) { @@ -301,16 +346,14 @@ static int json_fmt_element(tn_element e, char *buf, int *w, int *len) { as(b); break; case TN_VT_STR: - if(json_fmt_string(e.v.s, buf, w, len) < 0) - return -1; + json_fmt_string(e.v.s, buf); break; case TN_VT_AR: ac('['); for(i=0; i<e.count; i++) { if(i) ac(','); - if(json_fmt_element(e.v.a[i], buf, w, len) < 0) - return -1; + json_fmt_element(e.v.a[i], buf); } ac(']'); break; @@ -319,11 +362,9 @@ static int json_fmt_element(tn_element e, char *buf, int *w, int *len) { for(i=0; i<e.count; i++) { if(i) ac(','); - if(json_fmt_string(e.v.m[i].key, buf, w, len) < 0) - return -1; + json_fmt_string(e.v.m[i].key, buf); ac(':'); - if(json_fmt_element(e.v.m[i].val, buf, w, len) < 0) - return -1; + json_fmt_element(e.v.m[i].val, buf); } ac('}'); break; @@ -331,36 +372,35 @@ static int json_fmt_element(tn_element e, char *buf, int *w, int *len) { assert(e.type == TN_VT_WC); as("null"); } - return *w; } -// Write a JSON representation of the tuple into *buf. Returns -1 if it doesn't -// fit in the buffer, the number of written characters (excluding the trailing -// \0) otherwise. -int tn_json_fmt(tn_tuple *tup, char *buf, int l) { - if(!l) - return -1; - int *len = &l; - int wr = 0; - int *w = ≀ +static void tn_json_fmt_buf(tn_tuple *tup, lbuf *buf) { ac('['); int i; for(i=0; i<tup->n; i++) { if(i) ac(','); - if(json_fmt_element(tup->e[i], buf, w, len) < 0) - return -1; + json_fmt_element(tup->e[i], buf); } ac(']'); - buf[wr] = 0; - return wr; } #undef as #undef ac +// Returns a (0-terminated) JSON representation of the tuple. The returned +// buffer must be free()'d after use. +char *tn_json_fmt(tn_tuple *tup) { + lbuf buf; + lbuf_init(buf); + tn_json_fmt_buf(tup, &buf); + lbuf_append_c(buf, 0); + return buf.dat; +} + + @@ -819,48 +859,13 @@ struct tn_link { int errcode; char *errmsg; void *data; - char *rbuf; - int rbuf_len; - int rbuf_size; - char *wbuf; - int wbuf_len; - int wbuf_size; + lbuf rbuf; + lbuf wbuf; unsigned handshaked : 1; unsigned sync : 1; }; -// Tiny buffer abstraction - -#define lbuf_init(b) do {\ - b = NULL;\ - b##_size = b##_len = 0;\ - } while(0) - -#define lbuf_free(b) do {\ - if(b)\ - free(b);\ - lbuf_init(b);\ - } while(0) - -#define lbuf_grow(b, m) do {\ - if(b##_size < 16)\ - b##_size = 16;\ - else\ - b##_size *= 2;\ - if(b##_size < m)\ - b##_size = m;\ - b = realloc(b, b##_size);\ - } while(0) - -#define lbuf_append(b, buf, len) do {\ - if(b##_size < b##_len + len)\ - lbuf_grow(b, b##_len + len);\ - memcpy(b+b##_len, buf, len);\ - b##_len += len;\ - } while(0) - - static inline void tn_link_write(tn_link *l, char *msg, int len) { // No write dispatcher? Then assume we can call ctx->write() directly if(!l->ctx->wdispatch) { @@ -871,7 +876,7 @@ static inline void tn_link_write(tn_link *l, char *msg, int len) { } // Otherwise, append to the buffer and call the write dispatcher mutex_lock(l->lock); - int empty = !l->wbuf_len; + int empty = !l->wbuf.len; lbuf_append(l->wbuf, msg, len); mutex_unlock(l->lock); if(empty) @@ -991,7 +996,7 @@ void tn_link_read(tn_link *l, const char *buf, int len) { // Don't copy things to the read buffer if we have a full message int n=1; - while(!l->rbuf_len && len > 0 && n) { + while(!l->rbuf.len && len > 0 && n) { n = tn_link_handleread(l, buf, len); buf += n; len -= n; @@ -1008,14 +1013,12 @@ void tn_link_read(tn_link *l, const char *buf, int len) { // actually have to be checked. int r=0; n=1; - while(l->rbuf_len-r > 0 && n) { - n = tn_link_handleread(l, l->rbuf+r, l->rbuf_len-r); + while(l->rbuf.len-r > 0 && n) { + n = tn_link_handleread(l, l->rbuf.dat+r, l->rbuf.len-r); r += n; } - if(r > 0) { - memmove(l->rbuf, l->rbuf+r, l->rbuf_len-r); - l->rbuf_len -= r; - } + if(r > 0) + lbuf_shift(l->rbuf, r); } @@ -1034,40 +1037,34 @@ void tn_link_dispatch(tn_link *l) { // temporarily replace it with an empty one so that other threads can keep // writing without blocking or losing the new data. mutex_lock(l->lock); - if(l->wbuf_len) { - char *buf = l->wbuf; - int buf_len = l->wbuf_len; - int buf_size = l->wbuf_size; + if(l->wbuf.len) { + lbuf buf = l->wbuf; lbuf_init(l->wbuf); mutex_unlock(l->lock); - int n = l->ctx->write(l, buf, buf_len, &l->errmsg, l->data); + int n = l->ctx->write(l, buf.dat, buf.len, &l->errmsg, l->data); if(n < 0) { l->errcode = -n; l->ctx->dispatch(l, l->data); - free(buf); + free(buf.dat); return; } mutex_lock(l->lock); - if(n > 0) { - memmove(buf, buf+n, buf_len-n); - buf_len -= n; - } + if(n > 0) + lbuf_shift(buf, n); // If our buffer has been emptied, then just free it and leave the write buffer alone. - if(!buf_len) + if(!buf.len) lbuf_free(buf); else { // Oops, someone else has written to the buffer while we were being // busy. Append this data to our buffer. - if(l->wbuf_len) - lbuf_append(buf, l->wbuf, l->wbuf_len); + if(l->wbuf.len) + lbuf_append(buf, l->wbuf.dat, l->wbuf.len); // Now give back our temporary buffer - if(l->wbuf) - free(l->wbuf); + if(l->wbuf.dat) + free(l->wbuf.dat); l->wbuf = buf; - l->wbuf_len = buf_len; - l->wbuf_size = buf_size; } } mutex_unlock(l->lock); @@ -81,7 +81,7 @@ void tn_map_set(tn_element *, char *, ...); tn_tuple *tn_tuple_new(char *, ...); int tn_tuple_match(tn_tuple *, tn_tuple *); -int tn_json_fmt(tn_tuple *, char *, int); +char *tn_json_fmt(tn_tuple *); void tn_reply(tn_returnpath *, tn_tuple *); void tn_reply_close(tn_returnpath *rp); @@ -29,11 +29,8 @@ int main() { tn_array_new("i", INT64_MIN), tn_map_new("sn", strdup("k\ney"), strdup("va\rlue"), strdup("number\""), 1.5e10) ); - char *buf = malloc(98); - if(tn_json_fmt(t, buf, 98) > 0) - puts(buf); - else - puts("Too long"); + char *buf = tn_json_fmt(t); + puts(buf); free(buf); tn_tuple_unref(t); tn_node *n = tn_node_create(); |