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