w.deng | e87b500 | 2025-08-20 10:43:03 +0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2016 Alexadru Ardelean. |
| 3 | * |
| 4 | * This is free software; you can redistribute it and/or modify |
| 5 | * it under the terms of the MIT license. See COPYING for details. |
| 6 | * |
| 7 | */ |
| 8 | |
| 9 | /** |
| 10 | * @file |
| 11 | * @brief JSON Pointer (RFC 6901) implementation for retrieving |
| 12 | * objects from a json-c object tree. |
| 13 | */ |
| 14 | #ifndef _json_pointer_h_ |
| 15 | #define _json_pointer_h_ |
| 16 | |
| 17 | #include "json_object.h" |
| 18 | |
| 19 | #ifdef __cplusplus |
| 20 | extern "C" { |
| 21 | #endif |
| 22 | |
| 23 | /** |
| 24 | * Retrieves a JSON sub-object from inside another JSON object |
| 25 | * using the JSON pointer notation as defined in RFC 6901 |
| 26 | * https://tools.ietf.org/html/rfc6901 |
| 27 | * |
| 28 | * The returned JSON sub-object is equivalent to parsing manually the |
| 29 | * 'obj' JSON tree ; i.e. it's not a new object that is created, but rather |
| 30 | * a pointer inside the JSON tree. |
| 31 | * |
| 32 | * Internally, this is equivalent to doing a series of 'json_object_object_get()' |
| 33 | * and 'json_object_array_get_idx()' along the given 'path'. |
| 34 | * |
| 35 | * Note that the 'path' string supports 'printf()' type arguments, so, whatever |
| 36 | * is added after the 'res' param will be treated as an argument for 'path' |
| 37 | * Example: json_pointer_get(obj, "/foo/%d/%s", &res, 0, bar) |
| 38 | * This means, that you need to escape '%' with '%%' (just like in printf()) |
| 39 | * |
| 40 | * @param obj the json_object instance/tree from where to retrieve sub-objects |
| 41 | * @param path a (RFC6901) string notation for the sub-object to retrieve |
| 42 | * @param res a pointer that stores a reference to the json_object |
| 43 | * associated with the given path |
| 44 | * |
| 45 | * @return negative if an error (or not found), or 0 if succeeded |
| 46 | */ |
| 47 | JSON_EXPORT int json_pointer_get(struct json_object *obj, const char *path, |
| 48 | struct json_object **res); |
| 49 | |
| 50 | /** |
| 51 | * This is a variant of 'json_pointer_get()' that supports printf() style arguments. |
| 52 | * |
| 53 | * Example: json_pointer_getf(obj, res, "/foo/%d/%s", 0, bak) |
| 54 | * This also means that you need to escape '%' with '%%' (just like in printf()) |
| 55 | * |
| 56 | * Please take into consideration all recommended 'printf()' format security |
| 57 | * aspects when using this function. |
| 58 | * |
| 59 | * @param obj the json_object instance/tree to which to add a sub-object |
| 60 | * @param res a pointer that stores a reference to the json_object |
| 61 | * associated with the given path |
| 62 | * @param path_fmt a printf() style format for the path |
| 63 | * |
| 64 | * @return negative if an error (or not found), or 0 if succeeded |
| 65 | */ |
| 66 | JSON_EXPORT int json_pointer_getf(struct json_object *obj, struct json_object **res, |
| 67 | const char *path_fmt, ...); |
| 68 | |
| 69 | /** |
| 70 | * Sets JSON object 'value' in the 'obj' tree at the location specified |
| 71 | * by the 'path'. 'path' is JSON pointer notation as defined in RFC 6901 |
| 72 | * https://tools.ietf.org/html/rfc6901 |
| 73 | * |
| 74 | * Note that 'obj' is a double pointer, mostly for the "" (empty string) |
| 75 | * case, where the entire JSON object would be replaced by 'value'. |
| 76 | * In the case of the "" path, the object at '*obj' will have it's refcount |
| 77 | * decremented with 'json_object_put()' and the 'value' object will be assigned to it. |
| 78 | * |
| 79 | * For other cases (JSON sub-objects) ownership of 'value' will be transferred into |
| 80 | * '*obj' via 'json_object_object_add()' & 'json_object_array_put_idx()', so the |
| 81 | * only time the refcount should be decremented for 'value' is when the return value of |
| 82 | * 'json_pointer_set()' is negative (meaning the 'value' object did not get set into '*obj'). |
| 83 | * |
| 84 | * That also implies that 'json_pointer_set()' does not do any refcount incrementing. |
| 85 | * (Just that single decrement that was mentioned above). |
| 86 | * |
| 87 | * Note that the 'path' string supports 'printf()' type arguments, so, whatever |
| 88 | * is added after the 'value' param will be treated as an argument for 'path' |
| 89 | * Example: json_pointer_set(obj, "/foo/%d/%s", value, 0, bak) |
| 90 | * This means, that you need to escape '%' with '%%' (just like in printf()) |
| 91 | * |
| 92 | * @param obj the json_object instance/tree to which to add a sub-object |
| 93 | * @param path a (RFC6901) string notation for the sub-object to set in the tree |
| 94 | * @param value object to set at path |
| 95 | * |
| 96 | * @return negative if an error (or not found), or 0 if succeeded |
| 97 | */ |
| 98 | JSON_EXPORT int json_pointer_set(struct json_object **obj, const char *path, |
| 99 | struct json_object *value); |
| 100 | |
| 101 | /** |
| 102 | * This is a variant of 'json_pointer_set()' that supports printf() style arguments. |
| 103 | * |
| 104 | * Example: json_pointer_setf(obj, value, "/foo/%d/%s", 0, bak) |
| 105 | * This also means that you need to escape '%' with '%%' (just like in printf()) |
| 106 | * |
| 107 | * Please take into consideration all recommended 'printf()' format security |
| 108 | * aspects when using this function. |
| 109 | * |
| 110 | * @param obj the json_object instance/tree to which to add a sub-object |
| 111 | * @param value object to set at path |
| 112 | * @param path_fmt a printf() style format for the path |
| 113 | * |
| 114 | * @return negative if an error (or not found), or 0 if succeeded |
| 115 | */ |
| 116 | JSON_EXPORT int json_pointer_setf(struct json_object **obj, struct json_object *value, |
| 117 | const char *path_fmt, ...); |
| 118 | |
| 119 | #ifdef __cplusplus |
| 120 | } |
| 121 | #endif |
| 122 | |
| 123 | #endif |