1 //-----------------------------------------------------------------------------
2 // Borrowed initially from
3 // https://github.com/rogerz/jansson/blob/json_path/src/path.c
4 // Copyright (c) 2012 Rogerz Zhang <rogerz.zhang@gmail.com>
5 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation, either version 3 of the License, or
10 // (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // See LICENSE.txt for the text of the license.
18 //-----------------------------------------------------------------------------
24 #include "jansson_path.h"
26 ////// memory.c private functions
28 /* C89 allows these to be macros */
32 /* memory function pointers */
33 static json_malloc_t do_malloc
= malloc
;
34 static json_free_t do_free
= free
;
36 static void *jsonp_malloc(size_t size
) {
40 return (*do_malloc
)(size
);
43 static void jsonp_free(void *ptr
) {
50 static char *jsonp_strndup(const char *str
, size_t len
) {
51 char *new_str
= jsonp_malloc(len
+ 1);
55 memcpy(new_str
, str
, len
);
60 static char *jsonp_strdup(const char *str
) {
61 return jsonp_strndup(str
, strlen(str
));
64 ////// error.c private functions
66 static void jsonp_error_set_source(json_error_t
*error
, const char *source
) {
69 if (!error
|| !source
)
72 length
= strlen(source
);
73 if (length
< JSON_ERROR_SOURCE_LENGTH
) {
74 strncpy(error
->source
, source
, JSON_ERROR_SOURCE_LENGTH
- 1);
76 size_t extra
= length
- JSON_ERROR_SOURCE_LENGTH
+ 4;
77 memcpy(error
->source
, "...", 3);
78 strncpy(error
->source
+ 3, source
+ extra
, length
- extra
+ 1);
82 static void jsonp_error_init(json_error_t
*error
, const char *source
) {
84 error
->text
[0] = '\0';
89 jsonp_error_set_source(error
, source
);
91 error
->source
[0] = '\0';
95 static void jsonp_error_vset(json_error_t
*error
, int line
, int column
,
96 size_t position
, enum json_error_code code
,
97 const char *msg
, va_list ap
) {
101 if (error
->text
[0] != '\0') {
102 /* error already set */
107 error
->column
= column
;
108 error
->position
= (int)position
;
110 vsnprintf(error
->text
, JSON_ERROR_TEXT_LENGTH
- 1, msg
, ap
);
111 error
->text
[JSON_ERROR_TEXT_LENGTH
- 2] = '\0';
112 error
->text
[JSON_ERROR_TEXT_LENGTH
- 1] = code
;
115 static void jsonp_error_set(json_error_t
*error
, int line
, int column
,
116 size_t position
, enum json_error_code code
,
117 const char *msg
, ...) {
120 jsonp_error_vset(error
, line
, column
, position
, code
, msg
, ap
);
125 // original path.c from jansson fork
127 json_t
*json_path_get(const json_t
*json
, const char *path
) {
128 static const char root_chr
= '$', array_open
= '[';
129 static const char *path_delims
= ".[", *array_close
= "]";
130 const json_t
*cursor
;
131 char *token
, *buf
, *peek
, *endptr
, delim
= '\0';
134 if (!json
|| !path
|| path
[0] != root_chr
)
137 buf
= jsonp_strdup(path
);
142 expect
= path_delims
;
144 while (peek
&& *peek
&& cursor
) {
145 char *last_peek
= peek
;
146 peek
= strpbrk(peek
, expect
);
148 if (!token
&& peek
!= last_peek
)
152 } else if (expect
!= path_delims
|| !token
) {
156 if (expect
== path_delims
) {
158 cursor
= json_object_get(cursor
, token
);
160 expect
= (delim
== array_open
? array_close
: path_delims
);
162 } else if (expect
== array_close
) {
163 size_t index
= strtol(token
, &endptr
, 0);
166 cursor
= json_array_get(cursor
, index
);
168 expect
= path_delims
;
175 return (json_t
*)cursor
;
181 int json_path_set_new(json_t
*json
, const char *path
, json_t
*value
, size_t flags
, json_error_t
*error
) {
182 static const char root_chr
= '$', array_open
= '[', object_delim
= '.';
183 static const char *const path_delims
= ".[", *array_close
= "]";
185 json_t
*cursor
, *parent
= NULL
;
186 char *token
, *buf
= NULL
, *peek
, delim
= '\0';
188 int index_saved
= -1;
190 jsonp_error_init(error
, "<path>");
192 if (!json
|| !path
|| flags
|| !value
) {
193 jsonp_error_set(error
, -1, -1, 0, json_error_invalid_argument
, "invalid argument");
196 buf
= jsonp_strdup(path
);
199 if (buf
[0] != root_chr
) {
200 jsonp_error_set(error
, -1, -1, 0, json_error_invalid_format
, "path should start with $");
207 expect
= path_delims
;
209 while (peek
&& *peek
&& cursor
) {
210 char *last_peek
= peek
;
211 peek
= strpbrk(last_peek
, expect
);
214 if (!token
&& peek
!= last_peek
) {
215 jsonp_error_set(error
, -1, -1, last_peek
- buf
, json_error_invalid_format
, "unexpected trailing chars");
220 } else { // end of path
221 if (expect
== path_delims
) {
224 jsonp_error_set(error
, -1, -1, last_peek
- buf
, json_error_invalid_format
, "missing ']'?");
229 if (expect
== path_delims
) {
231 if (token
[0] == '\0') {
232 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_invalid_format
, "empty token");
237 cursor
= json_object_get(parent
, token
);
240 if (!json_is_object(parent
)) {
241 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_item_not_found
, "object expected");
244 if (delim
== object_delim
) {
245 cursor
= json_object();
246 json_object_set_new(parent
, token
, cursor
);
248 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_item_not_found
, "new array is not allowed");
253 expect
= (delim
== array_open
? array_close
: path_delims
);
255 } else if (expect
== array_close
) {
260 if (!json_is_array(parent
)) {
261 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_item_not_found
, "array expected");
264 index
= strtol(token
, &endptr
, 0);
266 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_item_not_found
, "invalid array index");
269 cursor
= json_array_get(parent
, index
);
271 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_item_not_found
, "array index out of bound");
276 expect
= path_delims
;
279 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_unknown
, "unexpected error in path move");
285 if (json_is_object(cursor
)) {
286 json_object_set(cursor
, token
, value
);
288 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_item_not_found
, "object expected");
291 cursor
= json_object_get(cursor
, token
);
292 } else if (index_saved
!= -1 && json_is_array(parent
)) {
293 json_array_set(parent
, index_saved
, value
);
294 cursor
= json_array_get(parent
, index_saved
);
296 jsonp_error_set(error
, -1, -1, 0, json_error_item_not_found
, "invalid path");