]> git.zerfleddert.de Git - proxmark3-svn/blob - client/jansson/path.c
08f2da9f67eed82a88203cea42835b46ee2c3ee4
[proxmark3-svn] / client / jansson / path.c
1 /*
2 * Copyright (c) 2012 Rogerz Zhang <rogerz.zhang@gmail.com>
3 *
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.
6 *
7 * source here https://github.com/rogerz/jansson/blob/json_path/src/path.c
8 */
9
10 #include <string.h>
11 #include <assert.h>
12
13 #include <jansson.h>
14 #include "jansson_private.h"
15
16
17 json_t *json_path_get(const json_t *json, const char *path)
18 {
19 static const char root_chr = '$', array_open = '[';
20 static const char *path_delims = ".[", *array_close = "]";
21 const json_t *cursor;
22 char *token, *buf, *peek, *endptr, delim = '\0';
23 const char *expect;
24
25 if (!json || !path || path[0] != root_chr)
26 return NULL;
27 else
28 buf = jsonp_strdup(path);
29
30 peek = buf + 1;
31 cursor = json;
32 token = NULL;
33 expect = path_delims;
34
35 while (peek && *peek && cursor)
36 {
37 char *last_peek = peek;
38 peek = strpbrk(peek, expect);
39 if (peek) {
40 if (!token && peek != last_peek)
41 goto fail;
42 delim = *peek;
43 *peek++ = '\0';
44 } else if (expect != path_delims || !token) {
45 goto fail;
46 }
47
48 if (expect == path_delims) {
49 if (token) {
50 cursor = json_object_get(cursor, token);
51 }
52 expect = (delim == array_open ? array_close : path_delims);
53 token = peek;
54 } else if (expect == array_close) {
55 size_t index = strtol(token, &endptr, 0);
56 if (*endptr)
57 goto fail;
58 cursor = json_array_get(cursor, index);
59 token = NULL;
60 expect = path_delims;
61 } else {
62 goto fail;
63 }
64 }
65
66 jsonp_free(buf);
67 return (json_t *)cursor;
68 fail:
69 jsonp_free(buf);
70 return NULL;
71 }
72
73 int json_path_set_new(json_t *json, const char *path, json_t *value, size_t flags, json_error_t *error)
74 {
75 static const char root_chr = '$', array_open = '[', object_delim = '.';
76 static const char * const path_delims = ".[", *array_close = "]";
77
78 json_t *cursor, *parent = NULL;
79 char *token, *buf = NULL, *peek, delim = '\0';
80 const char *expect;
81 int index_saved = -1;
82
83 jsonp_error_init(error, "<path>");
84
85 if (!json || !path || flags || !value) {
86 jsonp_error_set(error, -1, -1, 0, json_error_invalid_argument, "invalid argument");
87 goto fail;
88 } else {
89 buf = jsonp_strdup(path);
90 }
91
92 if (buf[0] != root_chr) {
93 jsonp_error_set(error, -1, -1, 0, json_error_invalid_format, "path should start with $");
94 goto fail;
95 }
96
97 peek = buf + 1;
98 cursor = json;
99 token = NULL;
100 expect = path_delims;
101
102 while (peek && *peek && cursor)
103 {
104 char *last_peek = peek;
105 peek = strpbrk(last_peek, expect);
106
107 if (peek) {
108 if (!token && peek != last_peek) {
109 jsonp_error_set(error, -1, -1, last_peek - buf, json_error_invalid_format, "unexpected trailing chars");
110 goto fail;
111 }
112 delim = *peek;
113 *peek++ = '\0';
114 } else { // end of path
115 if (expect == path_delims) {
116 break;
117 } else {
118 jsonp_error_set(error, -1, -1, peek - buf, json_error_invalid_format, "missing ']'?");
119 goto fail;
120 }
121 }
122
123 if (expect == path_delims) {
124 if (token) {
125 if (token[0] == '\0') {
126 jsonp_error_set(error, -1, -1, peek - buf, json_error_invalid_format, "empty token");
127 goto fail;
128 }
129
130 parent = cursor;
131 cursor = json_object_get(parent, token);
132
133 if (!cursor) {
134 if (!json_is_object(parent)) {
135 jsonp_error_set(error, -1, -1, peek - buf, json_error_item_not_found, "object expected");
136 goto fail;
137 }
138 if (delim == object_delim) {
139 cursor = json_object();
140 json_object_set_new(parent, token, cursor);
141 } else {
142 jsonp_error_set(error, -1, -1, peek - buf, json_error_item_not_found, "new array is not allowed");
143 goto fail;
144 }
145 }
146 }
147 expect = (delim == array_open ? array_close : path_delims);
148 token = peek;
149 } else if (expect == array_close) {
150 char *endptr;
151 size_t index;
152
153 parent = cursor;
154 if (!json_is_array(parent)) {
155 jsonp_error_set(error, -1, -1, peek - buf, json_error_item_not_found, "array expected");
156 goto fail;
157 }
158 index = strtol(token, &endptr, 0);
159 if (*endptr) {
160 jsonp_error_set(error, -1, -1, peek - buf, json_error_item_not_found, "invalid array index");
161 goto fail;
162 }
163 cursor = json_array_get(parent, index);
164 if (!cursor) {
165 jsonp_error_set(error, -1, -1, peek - buf, json_error_item_not_found, "array index out of bound");
166 goto fail;
167 }
168 index_saved = index;
169 token = NULL;
170 expect = path_delims;
171 } else {
172 assert(1);
173 jsonp_error_set(error, -1, -1, peek - buf, json_error_unknown, "unexpected error in path move");
174 goto fail;
175 }
176 }
177
178 if (token) {
179 if (json_is_object(cursor)) {
180 json_object_set(cursor, token, value);
181 } else {
182 jsonp_error_set(error, -1, -1, peek - buf, json_error_item_not_found, "object expected");
183 goto fail;
184 }
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);
189 } else {
190 jsonp_error_set(error, -1, -1, peek - buf, json_error_item_not_found, "invalid path");
191 goto fail;
192 }
193
194 json_decref(value);
195 jsonp_free(buf);
196 return 0;
197
198 fail:
199 json_decref(value);
200 jsonp_free(buf);
201 return -1;
202 }
Impressum, Datenschutz