mirror of
https://github.com/json-c/json-c.git
synced 2026-03-31 19:09:07 +08:00
json_pointer: add json_pointer_getf/setf() function variants
These include support for printf() style args for path. Adds support for calling with 'json_pointer_getf(obj, &res, "/foo/%d/%s", 0, bar)' style args. Makes it easier for doing more dynamic stuff/magic, without needing to use vasprintf() externally. Signed-off-by: Alexandru Ardelean <ardeleanalex@gmail.com>
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@@ -192,6 +193,37 @@ int json_pointer_get(struct json_object *obj, const char *path, struct json_obje
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int json_pointer_getf(struct json_object *obj, struct json_object **res, const char *path_fmt, ...)
|
||||||
|
{
|
||||||
|
char *path_copy = NULL;
|
||||||
|
int rc = 0;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
if (!obj || !path_fmt) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
va_start(args, path_fmt);
|
||||||
|
rc = vasprintf(&path_copy, path_fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if (path_copy[0] == '\0') {
|
||||||
|
if (res)
|
||||||
|
*res = obj;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = json_pointer_get_recursive(obj, path_copy, res);
|
||||||
|
out:
|
||||||
|
free(path_copy);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
int json_pointer_set(struct json_object **obj, const char *path, struct json_object *value)
|
int json_pointer_set(struct json_object **obj, const char *path, struct json_object *value)
|
||||||
{
|
{
|
||||||
const char *endp;
|
const char *endp;
|
||||||
@@ -237,3 +269,56 @@ int json_pointer_set(struct json_object **obj, const char *path, struct json_obj
|
|||||||
return json_pointer_set_single_path(set, endp, value);
|
return json_pointer_set_single_path(set, endp, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int json_pointer_setf(struct json_object **obj, struct json_object *value, const char *path_fmt, ...)
|
||||||
|
{
|
||||||
|
char *endp;
|
||||||
|
char *path_copy = NULL;
|
||||||
|
struct json_object *set = NULL;
|
||||||
|
va_list args;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (!obj || !path_fmt) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pass a working copy to the recursive call */
|
||||||
|
va_start(args, path_fmt);
|
||||||
|
rc = vasprintf(&path_copy, path_fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if (path_copy[0] == '\0') {
|
||||||
|
json_object_put(*obj);
|
||||||
|
*obj = value;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path_copy[0] != '/') {
|
||||||
|
errno = EINVAL;
|
||||||
|
rc = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If there's only 1 level to set, stop here */
|
||||||
|
if ((endp = strrchr(path_copy, '/')) == path_copy) {
|
||||||
|
set = *obj;
|
||||||
|
goto set_single_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
*endp = '\0';
|
||||||
|
rc = json_pointer_get_recursive(*obj, path_copy, &set);
|
||||||
|
|
||||||
|
if (rc)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
set_single_path:
|
||||||
|
endp++;
|
||||||
|
rc = json_pointer_set_single_path(set, endp, value);
|
||||||
|
out:
|
||||||
|
free(path_copy);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,11 @@ extern "C" {
|
|||||||
* Internally, this is equivalent to doing a series of 'json_object_object_get()'
|
* Internally, this is equivalent to doing a series of 'json_object_object_get()'
|
||||||
* and 'json_object_array_get_idx()' along the given 'path'.
|
* and 'json_object_array_get_idx()' along the given 'path'.
|
||||||
*
|
*
|
||||||
|
* Note that the 'path' string supports 'printf()' type arguments, so, whatever
|
||||||
|
* is added after the 'res' param will be treated as an argument for 'path'
|
||||||
|
* Example: json_pointer_get(obj, "/foo/%d/%s", &res, 0, bar)
|
||||||
|
* This means, that you need to escape '%' with '%%' (just like in printf())
|
||||||
|
*
|
||||||
* @param obj the json_object instance/tree from where to retrieve sub-objects
|
* @param obj the json_object instance/tree from where to retrieve sub-objects
|
||||||
* @param path a (RFC6901) string notation for the sub-object to retrieve
|
* @param path a (RFC6901) string notation for the sub-object to retrieve
|
||||||
* @param res a pointer where to store a reference to the json_object
|
* @param res a pointer where to store a reference to the json_object
|
||||||
@@ -36,6 +41,24 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
int json_pointer_get(struct json_object *obj, const char *path, struct json_object **res);
|
int json_pointer_get(struct json_object *obj, const char *path, struct json_object **res);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a variant of 'json_pointer_get()' that supports printf() style arguments.
|
||||||
|
*
|
||||||
|
* Example: json_pointer_getf(obj, res, "/foo/%d/%s", 0, bak)
|
||||||
|
* This also means that you need to escape '%' with '%%' (just like in printf())
|
||||||
|
*
|
||||||
|
* Please take into consideration all recommended 'printf()' format security
|
||||||
|
* aspects when using this function.
|
||||||
|
*
|
||||||
|
* @param obj the json_object instance/tree to which to add a sub-object
|
||||||
|
* @param res a pointer where to store a reference to the json_object
|
||||||
|
* associated with the given path
|
||||||
|
* @param path_fmt a printf() style format for the path
|
||||||
|
*
|
||||||
|
* @return negative if an error (or not found), or 0 if succeeded
|
||||||
|
*/
|
||||||
|
int json_pointer_getf(struct json_object *obj, struct json_object **res, const char *path_fmt, ...);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets JSON object 'value' in the 'obj' tree at the location specified
|
* Sets JSON object 'value' in the 'obj' tree at the location specified
|
||||||
* by the 'path'. 'path' is JSON pointer notation as defined in RFC 6901
|
* by the 'path'. 'path' is JSON pointer notation as defined in RFC 6901
|
||||||
@@ -54,6 +77,11 @@ int json_pointer_get(struct json_object *obj, const char *path, struct json_obje
|
|||||||
* That also implies that 'json_pointer_set()' does not do any refcount incrementing.
|
* That also implies that 'json_pointer_set()' does not do any refcount incrementing.
|
||||||
* (Just that single decrement that was mentioned above).
|
* (Just that single decrement that was mentioned above).
|
||||||
*
|
*
|
||||||
|
* Note that the 'path' string supports 'printf()' type arguments, so, whatever
|
||||||
|
* is added after the 'value' param will be treated as an argument for 'path'
|
||||||
|
* Example: json_pointer_set(obj, "/foo/%d/%s", value, 0, bak)
|
||||||
|
* This means, that you need to escape '%' with '%%' (just like in printf())
|
||||||
|
*
|
||||||
* @param obj the json_object instance/tree to which to add a sub-object
|
* @param obj the json_object instance/tree to which to add a sub-object
|
||||||
* @param path a (RFC6901) string notation for the sub-object to set in the tree
|
* @param path a (RFC6901) string notation for the sub-object to set in the tree
|
||||||
* @param value object to set at path
|
* @param value object to set at path
|
||||||
@@ -62,6 +90,24 @@ int json_pointer_get(struct json_object *obj, const char *path, struct json_obje
|
|||||||
*/
|
*/
|
||||||
int json_pointer_set(struct json_object **obj, const char *path, struct json_object *value);
|
int json_pointer_set(struct json_object **obj, const char *path, struct json_object *value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a variant of 'json_pointer_set()' that supports printf() style arguments.
|
||||||
|
*
|
||||||
|
* Example: json_pointer_setf(obj, value, "/foo/%d/%s", 0, bak)
|
||||||
|
* This also means that you need to escape '%' with '%%' (just like in printf())
|
||||||
|
*
|
||||||
|
* Please take into consideration all recommended 'printf()' format security
|
||||||
|
* aspects when using this function.
|
||||||
|
*
|
||||||
|
* @param obj the json_object instance/tree to which to add a sub-object
|
||||||
|
* @param value object to set at path
|
||||||
|
* @param path_fmt a printf() style format for the path
|
||||||
|
*
|
||||||
|
* @return negative if an error (or not found), or 0 if succeeded
|
||||||
|
*/
|
||||||
|
int json_pointer_setf(struct json_object **obj, struct json_object *value, const char *path_fmt, ...);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user