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"
16 json_t
*json_path_get(const json_t
*json
, const char *path
)
18 static const char root_chr
= '$', array_open
= '[';
19 static const char *path_delims
= ".[", *array_close
= "]";
21 char *token
, *buf
, *peek
, *endptr
, delim
= '\0';
24 if (!json
|| !path
|| path
[0] != root_chr
)
27 buf
= jsonp_strdup(path
);
34 while (peek
&& *peek
&& cursor
)
36 char *last_peek
= peek
;
37 peek
= strpbrk(peek
, expect
);
39 if (!token
&& peek
!= last_peek
)
43 } else if (expect
!= path_delims
|| !token
) {
47 if (expect
== path_delims
) {
49 cursor
= json_object_get(cursor
, token
);
51 expect
= (delim
== array_open
? array_close
: path_delims
);
53 } else if (expect
== array_close
) {
54 size_t index
= strtol(token
, &endptr
, 0);
57 cursor
= json_array_get(cursor
, index
);
66 return (json_t
*)cursor
;
72 int json_path_set_new(json_t
*json
, const char *path
, json_t
*value
, size_t flags
, json_error_t
*error
)
74 static const char root_chr
= '$', array_open
= '[', object_delim
= '.';
75 static const char * const path_delims
= ".[", *array_close
= "]";
77 json_t
*cursor
, *parent
= NULL
;
78 char *token
, *buf
= NULL
, *peek
, delim
= '\0';
82 jsonp_error_init(error
, "<path>");
84 if (!json
|| !path
|| flags
|| !value
) {
85 jsonp_error_set(error
, -1, -1, 0, json_error_invalid_argument
, "invalid argument");
88 buf
= jsonp_strdup(path
);
91 if (buf
[0] != root_chr
) {
92 jsonp_error_set(error
, -1, -1, 0, json_error_invalid_format
, "path should start with $");
101 while (peek
&& *peek
&& cursor
)
103 char *last_peek
= peek
;
104 peek
= strpbrk(last_peek
, expect
);
107 if (!token
&& peek
!= last_peek
) {
108 jsonp_error_set(error
, -1, -1, last_peek
- buf
, json_error_invalid_format
, "unexpected trailing chars");
113 } else { // end of path
114 if (expect
== path_delims
) {
117 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_invalid_format
, "missing ']'?");
122 if (expect
== path_delims
) {
124 if (token
[0] == '\0') {
125 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_invalid_format
, "empty token");
130 cursor
= json_object_get(parent
, token
);
133 if (!json_is_object(parent
)) {
134 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_item_not_found
, "object expected");
137 if (delim
== object_delim
) {
138 cursor
= json_object();
139 json_object_set_new(parent
, token
, cursor
);
141 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_item_not_found
, "new array is not allowed");
146 expect
= (delim
== array_open
? array_close
: path_delims
);
148 } else if (expect
== array_close
) {
153 if (!json_is_array(parent
)) {
154 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_item_not_found
, "array expected");
157 index
= strtol(token
, &endptr
, 0);
159 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_item_not_found
, "invalid array index");
162 cursor
= json_array_get(parent
, index
);
164 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_item_not_found
, "array index out of bound");
169 expect
= path_delims
;
172 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_unknown
, "unexpected error in path move");
178 if (json_is_object(cursor
)) {
179 json_object_set(cursor
, token
, value
);
181 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_item_not_found
, "object expected");
184 cursor
= json_object_get(cursor
, token
);
185 } else if (index_saved
!= -1 && json_is_array(parent
)) {
186 json_array_set(parent
, index_saved
, value
);
187 cursor
= json_array_get(parent
, index_saved
);
189 jsonp_error_set(error
, -1, -1, peek
- buf
, json_error_item_not_found
, "invalid path");