mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-25 17:59:25 +01:00
json: add support for array iteration
Arrays can now be parsed using the JSON_ARRAY type (stored in a struct json_iter) then iterated using json_iter_next. When iterating the type can be checked with json_iter_get_type. For each iteration the value can be obtained using any of the type getters (int/uint/boolean/null).
This commit is contained in:
parent
ebed84ab55
commit
7991c861e1
56
src/json.c
56
src/json.c
@ -89,7 +89,17 @@ static void iter_recurse(struct json_iter *iter, jsmntok_t *token,
|
|||||||
|
|
||||||
child->contents = c;
|
child->contents = c;
|
||||||
child->start = token - c->tokens;
|
child->start = token - c->tokens;
|
||||||
|
child->current = child->start;
|
||||||
child->count = count_tokens_in_container(iter, token);
|
child->count = count_tokens_in_container(iter, token);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add one to include the object/array token itself. This is required
|
||||||
|
* since 'current' points to the container initially. Only after a call
|
||||||
|
* to json_iter_next() will 'current' point to the first token in the
|
||||||
|
* container.
|
||||||
|
*/
|
||||||
|
if (token->type == JSMN_OBJECT || token->type == JSMN_ARRAY)
|
||||||
|
child->count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct json_contents *json_contents_new(const char *json, size_t json_len)
|
struct json_contents *json_contents_new(const char *json, size_t json_len)
|
||||||
@ -161,6 +171,7 @@ static void assign_arg(void *data, void *user_data)
|
|||||||
break;
|
break;
|
||||||
case JSON_OBJECT:
|
case JSON_OBJECT:
|
||||||
case JSON_PRIMITIVE:
|
case JSON_PRIMITIVE:
|
||||||
|
case JSON_ARRAY:
|
||||||
iter_val = arg->value;
|
iter_val = arg->value;
|
||||||
|
|
||||||
if (!arg->v)
|
if (!arg->v)
|
||||||
@ -208,6 +219,7 @@ bool json_iter_parse(struct json_iter *iter, enum json_type type, ...)
|
|||||||
case JSON_STRING:
|
case JSON_STRING:
|
||||||
case JSON_OBJECT:
|
case JSON_OBJECT:
|
||||||
case JSON_PRIMITIVE:
|
case JSON_PRIMITIVE:
|
||||||
|
case JSON_ARRAY:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto error;
|
goto error;
|
||||||
@ -272,7 +284,7 @@ static bool iter_get_primitive_data(struct json_iter *iter, void **ptr,
|
|||||||
size_t *len)
|
size_t *len)
|
||||||
{
|
{
|
||||||
struct json_contents *c = iter->contents;
|
struct json_contents *c = iter->contents;
|
||||||
jsmntok_t *t = c->tokens + iter->start;
|
jsmntok_t *t = c->tokens + iter->current;
|
||||||
|
|
||||||
if (t->type != JSMN_PRIMITIVE)
|
if (t->type != JSMN_PRIMITIVE)
|
||||||
return false;
|
return false;
|
||||||
@ -371,3 +383,45 @@ bool json_iter_get_null(struct json_iter *iter)
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum json_type json_iter_get_type(struct json_iter *iter)
|
||||||
|
{
|
||||||
|
struct json_contents *c = iter->contents;
|
||||||
|
jsmntok_t *t = c->tokens + iter->current;
|
||||||
|
|
||||||
|
return (enum json_type) t->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool json_iter_next(struct json_iter *iter)
|
||||||
|
{
|
||||||
|
struct json_contents *c = iter->contents;
|
||||||
|
jsmntok_t *t = c->tokens + iter->current;
|
||||||
|
int inc = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this is the initial iteration skip this and just increment
|
||||||
|
* current by 1 since this iterator points to a container which needs to
|
||||||
|
* be advanced to the first token..
|
||||||
|
*
|
||||||
|
* In addition primitive types and empty containers will have a size
|
||||||
|
* of 1, so no special handling is needed there.
|
||||||
|
*
|
||||||
|
* For non-empty containers 'current' needs to be advanced by all the
|
||||||
|
* containers child tokens, plus the container itself.
|
||||||
|
*
|
||||||
|
* This check ensures:
|
||||||
|
* 1. It is not the initial iteration
|
||||||
|
* 2. This is a container
|
||||||
|
* 3. The container is not empty
|
||||||
|
*/
|
||||||
|
if (iter->current != iter->start && ((t->type == JSMN_OBJECT ||
|
||||||
|
t->type == JSMN_ARRAY) && t->size))
|
||||||
|
inc = count_tokens_in_container(iter, t) + 1;
|
||||||
|
|
||||||
|
if (c->tokens + iter->current + inc >= ITER_END(iter))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
iter->current += inc;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -42,6 +42,7 @@ struct json_iter {
|
|||||||
struct json_contents *contents;
|
struct json_contents *contents;
|
||||||
int start;
|
int start;
|
||||||
int count;
|
int count;
|
||||||
|
int current;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define JSON_MANDATORY(key, type, out) \
|
#define JSON_MANDATORY(key, type, out) \
|
||||||
@ -92,3 +93,6 @@ bool json_iter_get_int(struct json_iter *iter, int *i);
|
|||||||
bool json_iter_get_uint(struct json_iter *iter, unsigned int *i);
|
bool json_iter_get_uint(struct json_iter *iter, unsigned int *i);
|
||||||
bool json_iter_get_boolean(struct json_iter *iter, bool *b);
|
bool json_iter_get_boolean(struct json_iter *iter, bool *b);
|
||||||
bool json_iter_get_null(struct json_iter *iter);
|
bool json_iter_get_null(struct json_iter *iter);
|
||||||
|
|
||||||
|
enum json_type json_iter_get_type(struct json_iter *iter);
|
||||||
|
bool json_iter_next(struct json_iter *iter);
|
||||||
|
Loading…
Reference in New Issue
Block a user