#include "config.h"
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
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)
{
const char *endp;
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;
+}
+
* Internally, this is equivalent to doing a series of 'json_object_object_get()'
* 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 path a (RFC6901) string notation for the sub-object to retrieve
* @param res a pointer where to store a reference to the json_object
*/
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
* by the 'path'. 'path' is JSON pointer notation as defined in RFC 6901
* That also implies that 'json_pointer_set()' does not do any refcount incrementing.
* (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 path a (RFC6901) string notation for the sub-object to set in the tree
* @param value object to set at path
*/
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
}
#endif