From f1e1e37ead10d17dd30ca1992d64335f9c53c838 Mon Sep 17 00:00:00 2001 From: Jim Radford Date: Sat, 10 Aug 2013 10:25:02 -0700 Subject: [PATCH] curl_json plugin: support arrays Allow access to data in JSON arrays. For example { workers: [ { requests: 10 }, { requests: 10 } ] } can all be accessed with workers/*/requests or just one by using the index. workers/1/requests --- src/curl_json.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/src/curl_json.c b/src/curl_json.c index deee460b..5bc3e419 100644 --- a/src/curl_json.c +++ b/src/curl_json.c @@ -82,6 +82,8 @@ struct cj_s /* {{{ */ c_avl_tree_t *tree; cj_key_t *key; }; + _Bool in_array; + int index; char name[DATA_MAX_NAME_LEN]; } state[YAJL_MAX_DEPTH]; }; @@ -167,10 +169,41 @@ static int cj_get_type (cj_key_t *key) return ds->ds[0].type; } +static int cj_cb_map_key (void *ctx, const unsigned char *val, + yajl_len_t len); + +static void cj_cb_inc_array_index (void * ctx, _Bool ignore) +{ + cj_t *db = (cj_t *)ctx; + + if (db->state[db->depth].in_array) { + if (ignore) + db->state[db->depth].index++; + else { + char name[DATA_MAX_NAME_LEN]; + cj_cb_map_key (ctx, (unsigned char *)name, + ssnprintf (name, sizeof (name), + "%d", db->state[db->depth].index++)); + } + } +} + /* yajl callbacks */ #define CJ_CB_ABORT 0 #define CJ_CB_CONTINUE 1 +static int cj_cb_boolean (void * ctx, int boolVal) +{ + cj_cb_inc_array_index (ctx, 1); + return (CJ_CB_CONTINUE); +} + +static int cj_cb_null (void * ctx) +{ + cj_cb_inc_array_index (ctx, 1); + return (CJ_CB_CONTINUE); +} + /* "number" may not be null terminated, so copy it into a buffer before * parsing. */ static int cj_cb_number (void *ctx, @@ -184,8 +217,11 @@ static int cj_cb_number (void *ctx, int type; int status; - if ((key == NULL) || !CJ_IS_KEY (key)) + if ((key == NULL) || !CJ_IS_KEY (key)) { + cj_cb_inc_array_index (ctx, 1); return (CJ_CB_CONTINUE); + } else + cj_cb_inc_array_index (ctx, 0); memcpy (buffer, number, number_len); buffer[sizeof (buffer) - 1] = 0; @@ -236,6 +272,9 @@ static int cj_cb_string (void *ctx, const unsigned char *val, cj_t *db = (cj_t *)ctx; char str[len + 1]; + cj_cb_inc_array_index (ctx, 1); + return (CJ_CB_CONTINUE); + /* Create a null-terminated version of the string. */ memcpy (str, val, len); str[len] = 0; @@ -276,6 +315,7 @@ static int cj_cb_end (void *ctx) static int cj_cb_start_map (void *ctx) { + cj_cb_inc_array_index (ctx, 0); return cj_cb_start (ctx); } @@ -286,17 +326,25 @@ static int cj_cb_end_map (void *ctx) static int cj_cb_start_array (void * ctx) { + cj_t *db = (cj_t *)ctx; + cj_cb_inc_array_index (ctx, 0); + if (db->depth+1 < YAJL_MAX_DEPTH) { + db->state[db->depth+1].in_array = 1; + db->state[db->depth+1].index = 0; + } return cj_cb_start (ctx); } static int cj_cb_end_array (void * ctx) { + cj_t *db = (cj_t *)ctx; + db->state[db->depth].in_array = 0; return cj_cb_end (ctx); } static yajl_callbacks ycallbacks = { - NULL, /* null */ - NULL, /* boolean */ + cj_cb_null, /* null */ + cj_cb_boolean, /* boolean */ NULL, /* integer */ NULL, /* double */ cj_cb_number, -- 2.11.0