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 primitive types
This adds support for boolean, (unsigned) integers, and null types. JSON_PRIMITIVE should be used as the type when parsing and the value should be struct json_iter. Once parsed the actual value can be obtained using one of the primitive getters. If the type does not match they will return false. If using JSON_OPTIONAL with JSON_PRIMITIVE the resulting iterator can be checked with json_iter_is_valid. If false the key/value was not found or the type was not matching.
This commit is contained in:
parent
23a1a66aee
commit
4f1cd8af93
120
src/json.c
120
src/json.c
@ -82,14 +82,14 @@ static int count_tokens_in_container(struct json_iter *iter,
|
||||
return contents - container;
|
||||
}
|
||||
|
||||
static void iter_recurse(struct json_iter *iter, jsmntok_t *object,
|
||||
static void iter_recurse(struct json_iter *iter, jsmntok_t *token,
|
||||
struct json_iter *child)
|
||||
{
|
||||
struct json_contents *c = iter->contents;
|
||||
|
||||
child->contents = c;
|
||||
child->start = object - c->tokens;
|
||||
child->count = count_tokens_in_container(iter, object);
|
||||
child->start = token - c->tokens;
|
||||
child->count = count_tokens_in_container(iter, token);
|
||||
}
|
||||
|
||||
struct json_contents *json_contents_new(const char *json, size_t json_len)
|
||||
@ -150,7 +150,7 @@ static void assign_arg(void *data, void *user_data)
|
||||
struct json_arg *arg = data;
|
||||
struct json_contents *c = iter->contents;
|
||||
char **sval;
|
||||
struct json_iter *oval;
|
||||
struct json_iter *iter_val;
|
||||
|
||||
switch (arg->type) {
|
||||
case JSON_STRING:
|
||||
@ -160,12 +160,13 @@ static void assign_arg(void *data, void *user_data)
|
||||
|
||||
break;
|
||||
case JSON_OBJECT:
|
||||
oval = arg->value;
|
||||
case JSON_PRIMITIVE:
|
||||
iter_val = arg->value;
|
||||
|
||||
if (!arg->v)
|
||||
oval->start = -1;
|
||||
iter_val->start = -1;
|
||||
else
|
||||
iter_recurse(iter, arg->v, oval);
|
||||
iter_recurse(iter, arg->v, iter_val);
|
||||
|
||||
break;
|
||||
default:
|
||||
@ -206,6 +207,7 @@ bool json_iter_parse(struct json_iter *iter, enum json_type type, ...)
|
||||
goto done;
|
||||
case JSON_STRING:
|
||||
case JSON_OBJECT:
|
||||
case JSON_PRIMITIVE:
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
@ -265,3 +267,107 @@ error:
|
||||
l_queue_destroy(args, l_free);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool iter_get_primitive_data(struct json_iter *iter, void **ptr,
|
||||
size_t *len)
|
||||
{
|
||||
struct json_contents *c = iter->contents;
|
||||
jsmntok_t *t = c->tokens + iter->start;
|
||||
|
||||
if (t->type != JSMN_PRIMITIVE)
|
||||
return false;
|
||||
|
||||
*ptr = TOK_PTR(c->json, t);
|
||||
*len = TOK_LEN(t);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool json_iter_get_int(struct json_iter *iter, int *i)
|
||||
{
|
||||
void *ptr;
|
||||
size_t len;
|
||||
long int r;
|
||||
int t;
|
||||
char *endp;
|
||||
|
||||
if (!iter_get_primitive_data(iter, &ptr, &len))
|
||||
return false;
|
||||
|
||||
errno = 0;
|
||||
|
||||
t = r = strtol(ptr, &endp, 10);
|
||||
if (endp != ptr + len)
|
||||
return false;
|
||||
|
||||
if (errno == ERANGE || r != t)
|
||||
return false;
|
||||
|
||||
if (i)
|
||||
*i = r;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool json_iter_get_uint(struct json_iter *iter, unsigned int *i)
|
||||
{
|
||||
void *ptr;
|
||||
size_t len;
|
||||
unsigned long int r;
|
||||
unsigned int t;
|
||||
char *endp;
|
||||
|
||||
if (!iter_get_primitive_data(iter, &ptr, &len))
|
||||
return false;
|
||||
|
||||
errno = 0;
|
||||
|
||||
t = r = strtoul(ptr, &endp, 10);
|
||||
if (endp != ptr + len)
|
||||
return false;
|
||||
|
||||
if (errno == ERANGE || r != t)
|
||||
return false;
|
||||
|
||||
if (i)
|
||||
*i = r;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool json_iter_get_boolean(struct json_iter *iter, bool *b)
|
||||
{
|
||||
void *ptr;
|
||||
size_t len;
|
||||
|
||||
if (!iter_get_primitive_data(iter, &ptr, &len))
|
||||
return false;
|
||||
|
||||
if (len == 4 && !memcmp(ptr, "true", 4)) {
|
||||
if (b)
|
||||
*b = true;
|
||||
|
||||
return true;
|
||||
} else if (len == 5 && !memcmp(ptr, "false", 5)) {
|
||||
if (b)
|
||||
*b = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool json_iter_get_null(struct json_iter *iter)
|
||||
{
|
||||
void *ptr;
|
||||
size_t len;
|
||||
|
||||
if (!iter_get_primitive_data(iter, &ptr, &len))
|
||||
return false;
|
||||
|
||||
if (len == 4 && !memcmp(ptr, "null", 4))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
13
src/json.h
13
src/json.h
@ -73,11 +73,22 @@ void json_iter_init(struct json_iter *iter, struct json_contents *c);
|
||||
*
|
||||
* String values should be of type char ** and must be freed
|
||||
* Object values should be of type struct json_iter *
|
||||
* Primitive types (numbers, booleans, null) should be of type
|
||||
* struct json_iter *. This is to allow the caller to distinguish
|
||||
* between the actual value type after parsing using a getter for
|
||||
* the expected type (get_uint/get_int/get_boolean etc.). In
|
||||
* addition this lets the caller use JSON_OPTIONAL and check post
|
||||
* json_iter_parse if the iterator is valid (json_iter_is_valid).
|
||||
*
|
||||
* No other types are supported at this time, and json_iter_parse will fail if
|
||||
* other types are encountered.
|
||||
*
|
||||
* JSON_OPTIONAL string values will point to NULL if not found
|
||||
* JSON_OPTIONAL objects can be checked with json_object_not_found.
|
||||
* JSON_OPTIONAL objects/primitives can be checked with json_object_is_valid.
|
||||
*/
|
||||
bool json_iter_parse(struct json_iter *iter, enum json_type type, ...);
|
||||
|
||||
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_boolean(struct json_iter *iter, bool *b);
|
||||
bool json_iter_get_null(struct json_iter *iter);
|
||||
|
Loading…
Reference in New Issue
Block a user