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;
|
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_iter *child)
|
||||||
{
|
{
|
||||||
struct json_contents *c = iter->contents;
|
struct json_contents *c = iter->contents;
|
||||||
|
|
||||||
child->contents = c;
|
child->contents = c;
|
||||||
child->start = object - c->tokens;
|
child->start = token - c->tokens;
|
||||||
child->count = count_tokens_in_container(iter, object);
|
child->count = count_tokens_in_container(iter, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
@ -150,7 +150,7 @@ static void assign_arg(void *data, void *user_data)
|
|||||||
struct json_arg *arg = data;
|
struct json_arg *arg = data;
|
||||||
struct json_contents *c = iter->contents;
|
struct json_contents *c = iter->contents;
|
||||||
char **sval;
|
char **sval;
|
||||||
struct json_iter *oval;
|
struct json_iter *iter_val;
|
||||||
|
|
||||||
switch (arg->type) {
|
switch (arg->type) {
|
||||||
case JSON_STRING:
|
case JSON_STRING:
|
||||||
@ -160,12 +160,13 @@ static void assign_arg(void *data, void *user_data)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case JSON_OBJECT:
|
case JSON_OBJECT:
|
||||||
oval = arg->value;
|
case JSON_PRIMITIVE:
|
||||||
|
iter_val = arg->value;
|
||||||
|
|
||||||
if (!arg->v)
|
if (!arg->v)
|
||||||
oval->start = -1;
|
iter_val->start = -1;
|
||||||
else
|
else
|
||||||
iter_recurse(iter, arg->v, oval);
|
iter_recurse(iter, arg->v, iter_val);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -206,6 +207,7 @@ bool json_iter_parse(struct json_iter *iter, enum json_type type, ...)
|
|||||||
goto done;
|
goto done;
|
||||||
case JSON_STRING:
|
case JSON_STRING:
|
||||||
case JSON_OBJECT:
|
case JSON_OBJECT:
|
||||||
|
case JSON_PRIMITIVE:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto error;
|
goto error;
|
||||||
@ -265,3 +267,107 @@ error:
|
|||||||
l_queue_destroy(args, l_free);
|
l_queue_destroy(args, l_free);
|
||||||
return false;
|
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
|
* String values should be of type char ** and must be freed
|
||||||
* Object values should be of type struct json_iter *
|
* 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
|
* No other types are supported at this time, and json_iter_parse will fail if
|
||||||
* other types are encountered.
|
* other types are encountered.
|
||||||
*
|
*
|
||||||
* JSON_OPTIONAL string values will point to NULL if not found
|
* 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_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