2 * Copyright (c) 2012 Rogerz Zhang <rogerz.zhang@gmail.com>
4 * Jansson is free software; you can redistribute it and/or modify
5 * it under the terms of the MIT license. See LICENSE for details.
7 * source here https://github.com/rogerz/jansson/blob/json_path/src/path.c
14 #include "jansson_private.h"
17 json_t
*json_path_get(const json_t
*json
, const char *path
)
19 static const char root_chr
= '$', array_open
= '[';
20 static const char *path_delims
= ".[", *array_close
= "]";
22 char *token
, *buf
, *peek
, *endptr
, delim
= '\0';
25 if (!json
|| !path
|| path
[0] != root_chr
)
28 buf
= jsonp_strdup(path
);
35 while (peek
&& *peek
&& cursor
)
37 char *last_peek
= peek
;
38 peek
= strpbrk(peek
, expect
);
40 if (!token
&& peek
!= last_peek
)
44 } else if (expect
!= path_delims
|| !token
) {
48 if (expect
== path_delims
) {
50 cursor
= json_object_get(cursor
, token
);
52 expect
= (delim
== array_open
? array_close
: path_delims
);
54 } else if (expect
== array_close
) {
55 size_t index
= strtol(token
, &endptr
, 0);
58 cursor
= json_array_get(cursor
, index
);
67 return (json_t
*)cursor
;
73 int json_path_set_new(json_t
*json
, const char *path
, json_t
*value
, size_t flags
, json_error_t
*error
)
75 static const char root_chr
= '$', array_open
= '[', object_delim
= '.';
76 static const char * const path_delims
= ".[", *array_close
= "]";
78 json_t
*cursor
, *parent
= NULL
;
79 char *token
, *buf
= NULL
, *peek
, delim
= '\0';
83 jsonp_error_init(error
, "<path>");
85 if (!json
|| !path
|| flags
|| !value
) {
86 jsonp_error_set(error
, -1, -1, 0, json_error_invalid_argument
, "invalid argument");
89 buf
= jsonp_strdup(path
);
92 if (buf
[0] != root_chr
) {
93 jsonp_error_set(error
, -1, -1, 0, json_error_invalid_format
, "path should start with $");
100 expect
= path_delims
;
102 while (peek
&& *peek
&& cursor
)
104 char *last_peek
= peek
;
105 peek
= strpbrk(last_peek
, expect
);
108 if (!token
&& peek
!= last_peek
) {
109 jsonp_error_set(error
, -1, -1, last_peek
- buf
, json_error_invalid_format
, "unexpected trailing chars");
114 } else { // end of path
115 if (expect
== path_delims
) {
118 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_invalid_format
, "missing ']'?");
123 if (expect
== path_delims
) {
125 if (token
[0] == '\0') {
126 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_invalid_format
, "empty token");
131 cursor
= json_object_get(parent
, token
);
134 if (!json_is_object(parent
)) {
135 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_item_not_found
, "object expected");
138 if (delim
== object_delim
) {
139 cursor
= json_object();
140 json_object_set_new(parent
, token
, cursor
);
142 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_item_not_found
, "new array is not allowed");
147 expect
= (delim
== array_open
? array_close
: path_delims
);
149 } else if (expect
== array_close
) {
154 if (!json_is_array(parent
)) {
155 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_item_not_found
, "array expected");
158 index
= strtol(token
, &endptr
, 0);
160 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_item_not_found
, "invalid array index");
163 cursor
= json_array_get(parent
, index
);
165 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_item_not_found
, "array index out of bound");
170 expect
= path_delims
;
173 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_unknown
, "unexpected error in path move");
179 if (json_is_object(cursor
)) {
180 json_object_set(cursor
, token
, value
);
182 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_item_not_found
, "object expected");
185 cursor
= json_object_get(cursor
, token
);
186 } else if (index_saved
!= -1 && json_is_array(parent
)) {
187 json_array_set(parent
, index_saved
, value
);
188 cursor
= json_array_get(parent
, index_saved
);
190 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_item_not_found
, "invalid path");