1488570ebSJim Harris /* SPDX-License-Identifier: BSD-3-Clause
2a6dbe372Spaul luse * Copyright (C) 2016 Intel Corporation.
3f9193f4cSDaniel Verkamp * All rights reserved.
4f9193f4cSDaniel Verkamp */
5f9193f4cSDaniel Verkamp
67d716668SDaniel Verkamp #include "spdk/json.h"
77d716668SDaniel Verkamp
80a97bd14SSeth Howell #include "spdk_internal/utf.h"
94e8e97c8STomasz Zawadzki #include "spdk/log.h"
10439641f7SPawel Wodkowski
112172c432STomasz Zawadzki #define SPDK_JSON_DEBUG(...) SPDK_DEBUGLOG(json_util, __VA_ARGS__)
12f9193f4cSDaniel Verkamp
13f9193f4cSDaniel Verkamp size_t
spdk_json_val_len(const struct spdk_json_val * val)14f9193f4cSDaniel Verkamp spdk_json_val_len(const struct spdk_json_val *val)
15f9193f4cSDaniel Verkamp {
16f9193f4cSDaniel Verkamp if (val == NULL) {
17f9193f4cSDaniel Verkamp return 0;
18f9193f4cSDaniel Verkamp }
19f9193f4cSDaniel Verkamp
20f9193f4cSDaniel Verkamp if (val->type == SPDK_JSON_VAL_ARRAY_BEGIN || val->type == SPDK_JSON_VAL_OBJECT_BEGIN) {
21f9193f4cSDaniel Verkamp return val->len + 2;
22f9193f4cSDaniel Verkamp }
23f9193f4cSDaniel Verkamp
24f9193f4cSDaniel Verkamp return 1;
25f9193f4cSDaniel Verkamp }
26f9193f4cSDaniel Verkamp
27f9193f4cSDaniel Verkamp bool
spdk_json_strequal(const struct spdk_json_val * val,const char * str)28f9193f4cSDaniel Verkamp spdk_json_strequal(const struct spdk_json_val *val, const char *str)
29f9193f4cSDaniel Verkamp {
30f9193f4cSDaniel Verkamp size_t len;
31f9193f4cSDaniel Verkamp
32f9193f4cSDaniel Verkamp if (val->type != SPDK_JSON_VAL_STRING && val->type != SPDK_JSON_VAL_NAME) {
33f9193f4cSDaniel Verkamp return false;
34f9193f4cSDaniel Verkamp }
35f9193f4cSDaniel Verkamp
36f9193f4cSDaniel Verkamp len = strlen(str);
37f9193f4cSDaniel Verkamp if (val->len != len) {
38f9193f4cSDaniel Verkamp return false;
39f9193f4cSDaniel Verkamp }
40f9193f4cSDaniel Verkamp
41f9193f4cSDaniel Verkamp return memcmp(val->start, str, len) == 0;
42f9193f4cSDaniel Verkamp }
43f9193f4cSDaniel Verkamp
44f9193f4cSDaniel Verkamp char *
spdk_json_strdup(const struct spdk_json_val * val)45f9193f4cSDaniel Verkamp spdk_json_strdup(const struct spdk_json_val *val)
46f9193f4cSDaniel Verkamp {
47f9193f4cSDaniel Verkamp size_t len;
48f9193f4cSDaniel Verkamp char *s;
49f9193f4cSDaniel Verkamp
50f9193f4cSDaniel Verkamp if (val->type != SPDK_JSON_VAL_STRING && val->type != SPDK_JSON_VAL_NAME) {
51f9193f4cSDaniel Verkamp return NULL;
52f9193f4cSDaniel Verkamp }
53f9193f4cSDaniel Verkamp
54f9193f4cSDaniel Verkamp len = val->len;
55f9193f4cSDaniel Verkamp
56f9193f4cSDaniel Verkamp if (memchr(val->start, '\0', len)) {
57f9193f4cSDaniel Verkamp /* String contains embedded NUL, so it is not a valid C string. */
58f9193f4cSDaniel Verkamp return NULL;
59f9193f4cSDaniel Verkamp }
60f9193f4cSDaniel Verkamp
61f9193f4cSDaniel Verkamp s = malloc(len + 1);
62f9193f4cSDaniel Verkamp if (s == NULL) {
63f9193f4cSDaniel Verkamp return s;
64f9193f4cSDaniel Verkamp }
65f9193f4cSDaniel Verkamp
66f9193f4cSDaniel Verkamp memcpy(s, val->start, len);
67f9193f4cSDaniel Verkamp s[len] = '\0';
68f9193f4cSDaniel Verkamp
69f9193f4cSDaniel Verkamp return s;
70f9193f4cSDaniel Verkamp }
71f9193f4cSDaniel Verkamp
727089d582SDaniel Verkamp struct spdk_json_num {
737089d582SDaniel Verkamp bool negative;
747089d582SDaniel Verkamp uint64_t significand;
757089d582SDaniel Verkamp int64_t exponent;
767089d582SDaniel Verkamp };
777089d582SDaniel Verkamp
787089d582SDaniel Verkamp static int
json_number_split(const struct spdk_json_val * val,struct spdk_json_num * num)790be5557cSSeth Howell json_number_split(const struct spdk_json_val *val, struct spdk_json_num *num)
807089d582SDaniel Verkamp {
817089d582SDaniel Verkamp const char *iter;
827089d582SDaniel Verkamp size_t remaining;
837089d582SDaniel Verkamp uint64_t *pval;
847089d582SDaniel Verkamp uint64_t frac_digits = 0;
857089d582SDaniel Verkamp uint64_t exponent_u64 = 0;
867089d582SDaniel Verkamp bool exponent_negative = false;
877089d582SDaniel Verkamp enum {
887089d582SDaniel Verkamp NUM_STATE_INT,
897089d582SDaniel Verkamp NUM_STATE_FRAC,
907089d582SDaniel Verkamp NUM_STATE_EXP,
917089d582SDaniel Verkamp } state;
927089d582SDaniel Verkamp
937089d582SDaniel Verkamp memset(num, 0, sizeof(*num));
947089d582SDaniel Verkamp
957089d582SDaniel Verkamp if (val->type != SPDK_JSON_VAL_NUMBER) {
967089d582SDaniel Verkamp return -EINVAL;
977089d582SDaniel Verkamp }
987089d582SDaniel Verkamp
997089d582SDaniel Verkamp remaining = val->len;
1007089d582SDaniel Verkamp if (remaining == 0) {
1017089d582SDaniel Verkamp return -EINVAL;
1027089d582SDaniel Verkamp }
1037089d582SDaniel Verkamp
1047089d582SDaniel Verkamp iter = val->start;
1057089d582SDaniel Verkamp if (*iter == '-') {
1067089d582SDaniel Verkamp num->negative = true;
1077089d582SDaniel Verkamp iter++;
1087089d582SDaniel Verkamp remaining--;
1097089d582SDaniel Verkamp }
1107089d582SDaniel Verkamp
1117089d582SDaniel Verkamp state = NUM_STATE_INT;
1127089d582SDaniel Verkamp pval = &num->significand;
1137089d582SDaniel Verkamp while (remaining--) {
1147089d582SDaniel Verkamp char c = *iter++;
1157089d582SDaniel Verkamp
1167089d582SDaniel Verkamp if (c == '.') {
1177089d582SDaniel Verkamp state = NUM_STATE_FRAC;
1187089d582SDaniel Verkamp } else if (c == 'e' || c == 'E') {
1197089d582SDaniel Verkamp state = NUM_STATE_EXP;
1207089d582SDaniel Verkamp pval = &exponent_u64;
1217089d582SDaniel Verkamp } else if (c == '-') {
1227089d582SDaniel Verkamp assert(state == NUM_STATE_EXP);
1237089d582SDaniel Verkamp exponent_negative = true;
1247089d582SDaniel Verkamp } else if (c == '+') {
1257089d582SDaniel Verkamp assert(state == NUM_STATE_EXP);
1267089d582SDaniel Verkamp /* exp_negative = false; */ /* already false by default */
1277089d582SDaniel Verkamp } else {
1287089d582SDaniel Verkamp uint64_t new_val;
1297089d582SDaniel Verkamp
1307089d582SDaniel Verkamp assert(c >= '0' && c <= '9');
1317089d582SDaniel Verkamp new_val = *pval * 10 + c - '0';
1327089d582SDaniel Verkamp if (new_val < *pval) {
1337089d582SDaniel Verkamp return -ERANGE;
1347089d582SDaniel Verkamp }
1357089d582SDaniel Verkamp
1367089d582SDaniel Verkamp if (state == NUM_STATE_FRAC) {
1377089d582SDaniel Verkamp frac_digits++;
1387089d582SDaniel Verkamp }
1397089d582SDaniel Verkamp
1407089d582SDaniel Verkamp *pval = new_val;
1417089d582SDaniel Verkamp }
1427089d582SDaniel Verkamp }
1437089d582SDaniel Verkamp
1447089d582SDaniel Verkamp if (exponent_negative) {
1457089d582SDaniel Verkamp if (exponent_u64 > 9223372036854775808ULL) { /* abs(INT64_MIN) */
1467089d582SDaniel Verkamp return -ERANGE;
1477089d582SDaniel Verkamp }
1487089d582SDaniel Verkamp num->exponent = (int64_t) - exponent_u64;
1497089d582SDaniel Verkamp } else {
1507089d582SDaniel Verkamp if (exponent_u64 > INT64_MAX) {
1517089d582SDaniel Verkamp return -ERANGE;
1527089d582SDaniel Verkamp }
1537089d582SDaniel Verkamp num->exponent = exponent_u64;
1547089d582SDaniel Verkamp }
1557089d582SDaniel Verkamp num->exponent -= frac_digits;
1567089d582SDaniel Verkamp
1577089d582SDaniel Verkamp /* Apply as much of the exponent as possible without overflow or truncation */
1587089d582SDaniel Verkamp if (num->exponent < 0) {
1597089d582SDaniel Verkamp while (num->exponent && num->significand >= 10 && num->significand % 10 == 0) {
1607089d582SDaniel Verkamp num->significand /= 10;
1617089d582SDaniel Verkamp num->exponent++;
1627089d582SDaniel Verkamp }
1637089d582SDaniel Verkamp } else { /* positive exponent */
1647089d582SDaniel Verkamp while (num->exponent) {
1657089d582SDaniel Verkamp uint64_t new_val = num->significand * 10;
1667089d582SDaniel Verkamp
1677089d582SDaniel Verkamp if (new_val < num->significand) {
1687089d582SDaniel Verkamp break;
1697089d582SDaniel Verkamp }
1707089d582SDaniel Verkamp
1717089d582SDaniel Verkamp num->significand = new_val;
1727089d582SDaniel Verkamp num->exponent--;
1737089d582SDaniel Verkamp }
1747089d582SDaniel Verkamp }
1757089d582SDaniel Verkamp
1767089d582SDaniel Verkamp return 0;
1777089d582SDaniel Verkamp }
1787089d582SDaniel Verkamp
179f9193f4cSDaniel Verkamp int
spdk_json_number_to_uint8(const struct spdk_json_val * val,uint8_t * num)180a827fd7eSJacek Kalwas spdk_json_number_to_uint8(const struct spdk_json_val *val, uint8_t *num)
181a827fd7eSJacek Kalwas {
182a827fd7eSJacek Kalwas struct spdk_json_num split_num;
183a827fd7eSJacek Kalwas int rc;
184a827fd7eSJacek Kalwas
185a827fd7eSJacek Kalwas rc = json_number_split(val, &split_num);
186a827fd7eSJacek Kalwas if (rc) {
187a827fd7eSJacek Kalwas return rc;
188a827fd7eSJacek Kalwas }
189a827fd7eSJacek Kalwas
190a827fd7eSJacek Kalwas if (split_num.exponent || split_num.negative) {
191a827fd7eSJacek Kalwas return -ERANGE;
192a827fd7eSJacek Kalwas }
193a827fd7eSJacek Kalwas
194a827fd7eSJacek Kalwas if (split_num.significand > UINT8_MAX) {
195a827fd7eSJacek Kalwas return -ERANGE;
196a827fd7eSJacek Kalwas }
197a827fd7eSJacek Kalwas *num = (uint8_t)split_num.significand;
198a827fd7eSJacek Kalwas return 0;
199a827fd7eSJacek Kalwas }
200a827fd7eSJacek Kalwas
201a827fd7eSJacek Kalwas int
spdk_json_number_to_uint16(const struct spdk_json_val * val,uint16_t * num)2026f872f5aSShuhei Matsumoto spdk_json_number_to_uint16(const struct spdk_json_val *val, uint16_t *num)
2036f872f5aSShuhei Matsumoto {
2046f872f5aSShuhei Matsumoto struct spdk_json_num split_num;
2056f872f5aSShuhei Matsumoto int rc;
2066f872f5aSShuhei Matsumoto
2070be5557cSSeth Howell rc = json_number_split(val, &split_num);
2086f872f5aSShuhei Matsumoto if (rc) {
2096f872f5aSShuhei Matsumoto return rc;
2106f872f5aSShuhei Matsumoto }
2116f872f5aSShuhei Matsumoto
2126f872f5aSShuhei Matsumoto if (split_num.exponent || split_num.negative) {
2136f872f5aSShuhei Matsumoto return -ERANGE;
2146f872f5aSShuhei Matsumoto }
2156f872f5aSShuhei Matsumoto
2166f872f5aSShuhei Matsumoto if (split_num.significand > UINT16_MAX) {
2176f872f5aSShuhei Matsumoto return -ERANGE;
2186f872f5aSShuhei Matsumoto }
2196f872f5aSShuhei Matsumoto *num = (uint16_t)split_num.significand;
2206f872f5aSShuhei Matsumoto return 0;
2216f872f5aSShuhei Matsumoto }
2226f872f5aSShuhei Matsumoto
2236f872f5aSShuhei Matsumoto int
spdk_json_number_to_int32(const struct spdk_json_val * val,int32_t * num)224f9193f4cSDaniel Verkamp spdk_json_number_to_int32(const struct spdk_json_val *val, int32_t *num)
225f9193f4cSDaniel Verkamp {
2267089d582SDaniel Verkamp struct spdk_json_num split_num;
2277089d582SDaniel Verkamp int rc;
228f9193f4cSDaniel Verkamp
2290be5557cSSeth Howell rc = json_number_split(val, &split_num);
2307089d582SDaniel Verkamp if (rc) {
2317089d582SDaniel Verkamp return rc;
232f9193f4cSDaniel Verkamp }
233f9193f4cSDaniel Verkamp
2347089d582SDaniel Verkamp if (split_num.exponent) {
2357089d582SDaniel Verkamp return -ERANGE;
236f9193f4cSDaniel Verkamp }
237f9193f4cSDaniel Verkamp
2387089d582SDaniel Verkamp if (split_num.negative) {
2397089d582SDaniel Verkamp if (split_num.significand > 2147483648) { /* abs(INT32_MIN) */
2407089d582SDaniel Verkamp return -ERANGE;
2417089d582SDaniel Verkamp }
2427089d582SDaniel Verkamp *num = (int32_t) - (int64_t)split_num.significand;
2437089d582SDaniel Verkamp return 0;
2447089d582SDaniel Verkamp }
2457089d582SDaniel Verkamp
2467089d582SDaniel Verkamp /* positive */
2477089d582SDaniel Verkamp if (split_num.significand > INT32_MAX) {
2487089d582SDaniel Verkamp return -ERANGE;
2497089d582SDaniel Verkamp }
2507089d582SDaniel Verkamp *num = (int32_t)split_num.significand;
251f9193f4cSDaniel Verkamp return 0;
252f9193f4cSDaniel Verkamp }
253f9193f4cSDaniel Verkamp
254f9193f4cSDaniel Verkamp int
spdk_json_number_to_uint32(const struct spdk_json_val * val,uint32_t * num)255f9193f4cSDaniel Verkamp spdk_json_number_to_uint32(const struct spdk_json_val *val, uint32_t *num)
256f9193f4cSDaniel Verkamp {
2577089d582SDaniel Verkamp struct spdk_json_num split_num;
2587089d582SDaniel Verkamp int rc;
259f9193f4cSDaniel Verkamp
2600be5557cSSeth Howell rc = json_number_split(val, &split_num);
2617089d582SDaniel Verkamp if (rc) {
2627089d582SDaniel Verkamp return rc;
263f9193f4cSDaniel Verkamp }
264f9193f4cSDaniel Verkamp
2657089d582SDaniel Verkamp if (split_num.exponent || split_num.negative) {
2667089d582SDaniel Verkamp return -ERANGE;
267f9193f4cSDaniel Verkamp }
268f9193f4cSDaniel Verkamp
2697089d582SDaniel Verkamp if (split_num.significand > UINT32_MAX) {
2707089d582SDaniel Verkamp return -ERANGE;
271f9193f4cSDaniel Verkamp }
2727089d582SDaniel Verkamp *num = (uint32_t)split_num.significand;
273f9193f4cSDaniel Verkamp return 0;
274f9193f4cSDaniel Verkamp }
275f9193f4cSDaniel Verkamp
276f9193f4cSDaniel Verkamp int
spdk_json_number_to_uint64(const struct spdk_json_val * val,uint64_t * num)27761119d78SMaciej Szwed spdk_json_number_to_uint64(const struct spdk_json_val *val, uint64_t *num)
27861119d78SMaciej Szwed {
27961119d78SMaciej Szwed struct spdk_json_num split_num;
28061119d78SMaciej Szwed int rc;
28161119d78SMaciej Szwed
2820be5557cSSeth Howell rc = json_number_split(val, &split_num);
28361119d78SMaciej Szwed if (rc) {
28461119d78SMaciej Szwed return rc;
28561119d78SMaciej Szwed }
28661119d78SMaciej Szwed
28761119d78SMaciej Szwed if (split_num.exponent || split_num.negative) {
28861119d78SMaciej Szwed return -ERANGE;
28961119d78SMaciej Szwed }
29061119d78SMaciej Szwed
29161119d78SMaciej Szwed *num = split_num.significand;
29261119d78SMaciej Szwed return 0;
29361119d78SMaciej Szwed }
29461119d78SMaciej Szwed
29590472b86SJacek Kalwas static int
_json_decode_object(const struct spdk_json_val * values,const struct spdk_json_object_decoder * decoders,size_t num_decoders,void * out,bool relaxed)29690472b86SJacek Kalwas _json_decode_object(const struct spdk_json_val *values,
29790472b86SJacek Kalwas const struct spdk_json_object_decoder *decoders, size_t num_decoders, void *out, bool relaxed)
298f9193f4cSDaniel Verkamp {
299f9193f4cSDaniel Verkamp uint32_t i;
300f9193f4cSDaniel Verkamp bool invalid = false;
301f9193f4cSDaniel Verkamp size_t decidx;
302f9193f4cSDaniel Verkamp bool *seen;
303f9193f4cSDaniel Verkamp
304f9193f4cSDaniel Verkamp if (values == NULL || values->type != SPDK_JSON_VAL_OBJECT_BEGIN) {
305f9193f4cSDaniel Verkamp return -1;
306f9193f4cSDaniel Verkamp }
307f9193f4cSDaniel Verkamp
308f9193f4cSDaniel Verkamp seen = calloc(sizeof(bool), num_decoders);
309f9193f4cSDaniel Verkamp if (seen == NULL) {
310f9193f4cSDaniel Verkamp return -1;
311f9193f4cSDaniel Verkamp }
312f9193f4cSDaniel Verkamp
313f9193f4cSDaniel Verkamp for (i = 0; i < values->len;) {
314f9193f4cSDaniel Verkamp const struct spdk_json_val *name = &values[i + 1];
315f9193f4cSDaniel Verkamp const struct spdk_json_val *v = &values[i + 2];
316f9193f4cSDaniel Verkamp bool found = false;
317f9193f4cSDaniel Verkamp
318f9193f4cSDaniel Verkamp for (decidx = 0; decidx < num_decoders; decidx++) {
319f9193f4cSDaniel Verkamp const struct spdk_json_object_decoder *dec = &decoders[decidx];
320f9193f4cSDaniel Verkamp if (spdk_json_strequal(name, dec->name)) {
321f9193f4cSDaniel Verkamp void *field = (void *)((uintptr_t)out + dec->offset);
322f9193f4cSDaniel Verkamp
323f9193f4cSDaniel Verkamp found = true;
324f9193f4cSDaniel Verkamp
325f9193f4cSDaniel Verkamp if (seen[decidx]) {
326f9193f4cSDaniel Verkamp /* duplicate field name */
327f9193f4cSDaniel Verkamp invalid = true;
32840f70de0SPawel Wodkowski SPDK_JSON_DEBUG("Duplicate key '%s'\n", dec->name);
329f9193f4cSDaniel Verkamp } else {
330f9193f4cSDaniel Verkamp seen[decidx] = true;
331f9193f4cSDaniel Verkamp if (dec->decode_func(v, field)) {
332f9193f4cSDaniel Verkamp invalid = true;
33340f70de0SPawel Wodkowski SPDK_JSON_DEBUG("Decoder failed to decode key '%s'\n", dec->name);
334f9193f4cSDaniel Verkamp /* keep going to fill out any other valid keys */
335f9193f4cSDaniel Verkamp }
336f9193f4cSDaniel Verkamp }
337f9193f4cSDaniel Verkamp break;
338f9193f4cSDaniel Verkamp }
339f9193f4cSDaniel Verkamp }
340f9193f4cSDaniel Verkamp
34190472b86SJacek Kalwas if (!relaxed && !found) {
342f9193f4cSDaniel Verkamp invalid = true;
34340f70de0SPawel Wodkowski SPDK_JSON_DEBUG("Decoder not found for key '%.*s'\n", name->len, (char *)name->start);
344f9193f4cSDaniel Verkamp }
345f9193f4cSDaniel Verkamp
346f9193f4cSDaniel Verkamp i += 1 + spdk_json_val_len(v);
347f9193f4cSDaniel Verkamp }
348f9193f4cSDaniel Verkamp
349f9193f4cSDaniel Verkamp for (decidx = 0; decidx < num_decoders; decidx++) {
350f9193f4cSDaniel Verkamp if (!decoders[decidx].optional && !seen[decidx]) {
351f9193f4cSDaniel Verkamp /* required field is missing */
352f9193f4cSDaniel Verkamp invalid = true;
353f9193f4cSDaniel Verkamp break;
354f9193f4cSDaniel Verkamp }
355f9193f4cSDaniel Verkamp }
356f9193f4cSDaniel Verkamp
357f9193f4cSDaniel Verkamp free(seen);
358f9193f4cSDaniel Verkamp return invalid ? -1 : 0;
359f9193f4cSDaniel Verkamp }
360f9193f4cSDaniel Verkamp
361c77c6559SDarek Stojaczyk void
spdk_json_free_object(const struct spdk_json_object_decoder * decoders,size_t num_decoders,void * obj)362c77c6559SDarek Stojaczyk spdk_json_free_object(const struct spdk_json_object_decoder *decoders, size_t num_decoders,
363c77c6559SDarek Stojaczyk void *obj)
364c77c6559SDarek Stojaczyk {
365c77c6559SDarek Stojaczyk struct spdk_json_val invalid_val = {
366c77c6559SDarek Stojaczyk .start = "",
367c77c6559SDarek Stojaczyk .len = 0,
368c77c6559SDarek Stojaczyk .type = SPDK_JSON_VAL_INVALID
369c77c6559SDarek Stojaczyk };
370c77c6559SDarek Stojaczyk size_t decidx;
371c77c6559SDarek Stojaczyk
372c77c6559SDarek Stojaczyk for (decidx = 0; decidx < num_decoders; decidx++) {
373c77c6559SDarek Stojaczyk const struct spdk_json_object_decoder *dec = &decoders[decidx];
374c77c6559SDarek Stojaczyk void *field = (void *)((uintptr_t)obj + dec->offset);
375c77c6559SDarek Stojaczyk
376c77c6559SDarek Stojaczyk /* decoding an invalid value will free the
377c77c6559SDarek Stojaczyk * previous memory without allocating it again.
378c77c6559SDarek Stojaczyk */
379c77c6559SDarek Stojaczyk dec->decode_func(&invalid_val, field);
380c77c6559SDarek Stojaczyk }
381c77c6559SDarek Stojaczyk }
382c77c6559SDarek Stojaczyk
383c77c6559SDarek Stojaczyk
384f9193f4cSDaniel Verkamp int
spdk_json_decode_object(const struct spdk_json_val * values,const struct spdk_json_object_decoder * decoders,size_t num_decoders,void * out)38590472b86SJacek Kalwas spdk_json_decode_object(const struct spdk_json_val *values,
38690472b86SJacek Kalwas const struct spdk_json_object_decoder *decoders, size_t num_decoders, void *out)
38790472b86SJacek Kalwas {
38890472b86SJacek Kalwas return _json_decode_object(values, decoders, num_decoders, out, false);
38990472b86SJacek Kalwas }
39090472b86SJacek Kalwas
39190472b86SJacek Kalwas int
spdk_json_decode_object_relaxed(const struct spdk_json_val * values,const struct spdk_json_object_decoder * decoders,size_t num_decoders,void * out)39290472b86SJacek Kalwas spdk_json_decode_object_relaxed(const struct spdk_json_val *values,
39390472b86SJacek Kalwas const struct spdk_json_object_decoder *decoders, size_t num_decoders, void *out)
39490472b86SJacek Kalwas {
39590472b86SJacek Kalwas return _json_decode_object(values, decoders, num_decoders, out, true);
39690472b86SJacek Kalwas }
39790472b86SJacek Kalwas
39890472b86SJacek Kalwas int
spdk_json_decode_array(const struct spdk_json_val * values,spdk_json_decode_fn decode_func,void * out,size_t max_size,size_t * out_size,size_t stride)399f9193f4cSDaniel Verkamp spdk_json_decode_array(const struct spdk_json_val *values, spdk_json_decode_fn decode_func,
400f9193f4cSDaniel Verkamp void *out, size_t max_size, size_t *out_size, size_t stride)
401f9193f4cSDaniel Verkamp {
402f9193f4cSDaniel Verkamp uint32_t i;
403f9193f4cSDaniel Verkamp char *field;
404f9193f4cSDaniel Verkamp
405f9193f4cSDaniel Verkamp if (values == NULL || values->type != SPDK_JSON_VAL_ARRAY_BEGIN) {
406f9193f4cSDaniel Verkamp return -1;
407f9193f4cSDaniel Verkamp }
408f9193f4cSDaniel Verkamp
409f9193f4cSDaniel Verkamp *out_size = 0;
410f9193f4cSDaniel Verkamp field = out;
411f9193f4cSDaniel Verkamp for (i = 0; i < values->len;) {
412f9193f4cSDaniel Verkamp const struct spdk_json_val *v = &values[i + 1];
413f9193f4cSDaniel Verkamp
414*c6480ea7SKonrad Sztyber if (*out_size == max_size) {
415b33e0cafSDaniel Verkamp return -1;
416b33e0cafSDaniel Verkamp }
417b33e0cafSDaniel Verkamp
418f9193f4cSDaniel Verkamp if (decode_func(v, field)) {
419f9193f4cSDaniel Verkamp return -1;
420f9193f4cSDaniel Verkamp }
421f9193f4cSDaniel Verkamp
422f9193f4cSDaniel Verkamp i += spdk_json_val_len(v);
423f9193f4cSDaniel Verkamp field += stride;
424f9193f4cSDaniel Verkamp (*out_size)++;
425f9193f4cSDaniel Verkamp }
426f9193f4cSDaniel Verkamp
427f9193f4cSDaniel Verkamp return 0;
428f9193f4cSDaniel Verkamp }
429f9193f4cSDaniel Verkamp
430f9193f4cSDaniel Verkamp int
spdk_json_decode_bool(const struct spdk_json_val * val,void * out)4311bc2c5abSPawel Wodkowski spdk_json_decode_bool(const struct spdk_json_val *val, void *out)
4321bc2c5abSPawel Wodkowski {
4331bc2c5abSPawel Wodkowski bool *f = out;
4341bc2c5abSPawel Wodkowski
4351bc2c5abSPawel Wodkowski if (val->type != SPDK_JSON_VAL_TRUE && val->type != SPDK_JSON_VAL_FALSE) {
4361bc2c5abSPawel Wodkowski return -1;
4371bc2c5abSPawel Wodkowski }
4381bc2c5abSPawel Wodkowski
4391bc2c5abSPawel Wodkowski *f = val->type == SPDK_JSON_VAL_TRUE;
4401bc2c5abSPawel Wodkowski return 0;
4411bc2c5abSPawel Wodkowski }
4421bc2c5abSPawel Wodkowski
4431bc2c5abSPawel Wodkowski int
spdk_json_decode_uint8(const struct spdk_json_val * val,void * out)444a827fd7eSJacek Kalwas spdk_json_decode_uint8(const struct spdk_json_val *val, void *out)
445a827fd7eSJacek Kalwas {
446a827fd7eSJacek Kalwas uint8_t *i = out;
447a827fd7eSJacek Kalwas
448a827fd7eSJacek Kalwas return spdk_json_number_to_uint8(val, i);
449a827fd7eSJacek Kalwas }
450a827fd7eSJacek Kalwas
451a827fd7eSJacek Kalwas int
spdk_json_decode_uint16(const struct spdk_json_val * val,void * out)4526f872f5aSShuhei Matsumoto spdk_json_decode_uint16(const struct spdk_json_val *val, void *out)
4536f872f5aSShuhei Matsumoto {
4546f872f5aSShuhei Matsumoto uint16_t *i = out;
4556f872f5aSShuhei Matsumoto
4566f872f5aSShuhei Matsumoto return spdk_json_number_to_uint16(val, i);
4576f872f5aSShuhei Matsumoto }
4586f872f5aSShuhei Matsumoto
4596f872f5aSShuhei Matsumoto int
spdk_json_decode_int32(const struct spdk_json_val * val,void * out)460f9193f4cSDaniel Verkamp spdk_json_decode_int32(const struct spdk_json_val *val, void *out)
461f9193f4cSDaniel Verkamp {
462f9193f4cSDaniel Verkamp int32_t *i = out;
463f9193f4cSDaniel Verkamp
464f9193f4cSDaniel Verkamp return spdk_json_number_to_int32(val, i);
465f9193f4cSDaniel Verkamp }
466f9193f4cSDaniel Verkamp
467f9193f4cSDaniel Verkamp int
spdk_json_decode_uint32(const struct spdk_json_val * val,void * out)468f9193f4cSDaniel Verkamp spdk_json_decode_uint32(const struct spdk_json_val *val, void *out)
469f9193f4cSDaniel Verkamp {
470f9193f4cSDaniel Verkamp uint32_t *i = out;
471f9193f4cSDaniel Verkamp
472f9193f4cSDaniel Verkamp return spdk_json_number_to_uint32(val, i);
473f9193f4cSDaniel Verkamp }
474f9193f4cSDaniel Verkamp
475f9193f4cSDaniel Verkamp int
spdk_json_decode_uint64(const struct spdk_json_val * val,void * out)47661119d78SMaciej Szwed spdk_json_decode_uint64(const struct spdk_json_val *val, void *out)
47761119d78SMaciej Szwed {
47861119d78SMaciej Szwed uint64_t *i = out;
47961119d78SMaciej Szwed
48061119d78SMaciej Szwed return spdk_json_number_to_uint64(val, i);
48161119d78SMaciej Szwed }
48261119d78SMaciej Szwed
48361119d78SMaciej Szwed int
spdk_json_decode_string(const struct spdk_json_val * val,void * out)484f9193f4cSDaniel Verkamp spdk_json_decode_string(const struct spdk_json_val *val, void *out)
485f9193f4cSDaniel Verkamp {
486f9193f4cSDaniel Verkamp char **s = out;
487f9193f4cSDaniel Verkamp
488f9193f4cSDaniel Verkamp free(*s);
489f9193f4cSDaniel Verkamp
490f9193f4cSDaniel Verkamp *s = spdk_json_strdup(val);
491f9193f4cSDaniel Verkamp
492f9193f4cSDaniel Verkamp if (*s) {
493f9193f4cSDaniel Verkamp return 0;
494f9193f4cSDaniel Verkamp } else {
495f9193f4cSDaniel Verkamp return -1;
496f9193f4cSDaniel Verkamp }
497f9193f4cSDaniel Verkamp }
498439641f7SPawel Wodkowski
4993e449a54SKonrad Sztyber int
spdk_json_decode_uuid(const struct spdk_json_val * val,void * out)5003e449a54SKonrad Sztyber spdk_json_decode_uuid(const struct spdk_json_val *val, void *out)
5013e449a54SKonrad Sztyber {
5023e449a54SKonrad Sztyber struct spdk_uuid *uuid = out;
5033e449a54SKonrad Sztyber char *str = NULL;
5043e449a54SKonrad Sztyber int rc;
5053e449a54SKonrad Sztyber
5063e449a54SKonrad Sztyber rc = spdk_json_decode_string(val, &str);
5073e449a54SKonrad Sztyber if (rc != 0) {
5083e449a54SKonrad Sztyber return rc;
5093e449a54SKonrad Sztyber }
5103e449a54SKonrad Sztyber
5113e449a54SKonrad Sztyber rc = spdk_uuid_parse(uuid, str);
5123e449a54SKonrad Sztyber free(str);
5133e449a54SKonrad Sztyber
51475b68561SKonrad Sztyber return rc == 0 ? 0 : -1;
5153e449a54SKonrad Sztyber }
5163e449a54SKonrad Sztyber
517439641f7SPawel Wodkowski static struct spdk_json_val *
json_first(struct spdk_json_val * object,enum spdk_json_val_type type)5180be5557cSSeth Howell json_first(struct spdk_json_val *object, enum spdk_json_val_type type)
519439641f7SPawel Wodkowski {
520439641f7SPawel Wodkowski /* 'object' must be JSON object or array. 'type' might be combination of these two. */
521439641f7SPawel Wodkowski assert((type & (SPDK_JSON_VAL_ARRAY_BEGIN | SPDK_JSON_VAL_OBJECT_BEGIN)) != 0);
522439641f7SPawel Wodkowski
523439641f7SPawel Wodkowski assert(object != NULL);
524439641f7SPawel Wodkowski
525439641f7SPawel Wodkowski if ((object->type & type) == 0) {
526439641f7SPawel Wodkowski return NULL;
527439641f7SPawel Wodkowski }
528439641f7SPawel Wodkowski
529439641f7SPawel Wodkowski object++;
530439641f7SPawel Wodkowski if (object->len == 0) {
531439641f7SPawel Wodkowski return NULL;
532439641f7SPawel Wodkowski }
533439641f7SPawel Wodkowski
534439641f7SPawel Wodkowski return object;
535439641f7SPawel Wodkowski }
536439641f7SPawel Wodkowski
537439641f7SPawel Wodkowski static struct spdk_json_val *
json_value(struct spdk_json_val * key)5380be5557cSSeth Howell json_value(struct spdk_json_val *key)
539439641f7SPawel Wodkowski {
540439641f7SPawel Wodkowski return key->type == SPDK_JSON_VAL_NAME ? key + 1 : NULL;
541439641f7SPawel Wodkowski }
542439641f7SPawel Wodkowski
543439641f7SPawel Wodkowski int
spdk_json_find(struct spdk_json_val * object,const char * key_name,struct spdk_json_val ** key,struct spdk_json_val ** val,enum spdk_json_val_type type)544439641f7SPawel Wodkowski spdk_json_find(struct spdk_json_val *object, const char *key_name, struct spdk_json_val **key,
545439641f7SPawel Wodkowski struct spdk_json_val **val, enum spdk_json_val_type type)
546439641f7SPawel Wodkowski {
547439641f7SPawel Wodkowski struct spdk_json_val *_key = NULL;
548439641f7SPawel Wodkowski struct spdk_json_val *_val = NULL;
549bb432b4eStongkunkun struct spdk_json_val *it_first, *it;
550439641f7SPawel Wodkowski
551439641f7SPawel Wodkowski assert(object != NULL);
552439641f7SPawel Wodkowski
553bb432b4eStongkunkun it_first = json_first(object, SPDK_JSON_VAL_OBJECT_BEGIN);
554bb432b4eStongkunkun if (!it_first) {
555bb432b4eStongkunkun SPDK_JSON_DEBUG("Not enclosed in {}\n");
556bb432b4eStongkunkun return -EPROTOTYPE;
557bb432b4eStongkunkun }
558bb432b4eStongkunkun
559bb432b4eStongkunkun for (it = it_first;
560439641f7SPawel Wodkowski it != NULL;
561439641f7SPawel Wodkowski it = spdk_json_next(it)) {
562439641f7SPawel Wodkowski if (it->type != SPDK_JSON_VAL_NAME) {
563439641f7SPawel Wodkowski continue;
564439641f7SPawel Wodkowski }
565439641f7SPawel Wodkowski
566439641f7SPawel Wodkowski if (spdk_json_strequal(it, key_name) != true) {
567439641f7SPawel Wodkowski continue;
568439641f7SPawel Wodkowski }
569439641f7SPawel Wodkowski
570439641f7SPawel Wodkowski if (_key) {
571439641f7SPawel Wodkowski SPDK_JSON_DEBUG("Duplicate key '%s'", key_name);
572439641f7SPawel Wodkowski return -EINVAL;
573439641f7SPawel Wodkowski }
574439641f7SPawel Wodkowski
575439641f7SPawel Wodkowski _key = it;
5760be5557cSSeth Howell _val = json_value(_key);
577439641f7SPawel Wodkowski
578bb432b4eStongkunkun if (type != SPDK_JSON_VAL_ANY && (_val->type & type) == 0) {
579439641f7SPawel Wodkowski SPDK_JSON_DEBUG("key '%s' type is %#x but expected one of %#x\n", key_name, _val->type, type);
580439641f7SPawel Wodkowski return -EDOM;
581439641f7SPawel Wodkowski }
582439641f7SPawel Wodkowski }
583439641f7SPawel Wodkowski
584439641f7SPawel Wodkowski if (key) {
585439641f7SPawel Wodkowski *key = _key;
586439641f7SPawel Wodkowski }
587439641f7SPawel Wodkowski
588439641f7SPawel Wodkowski if (val) {
589439641f7SPawel Wodkowski *val = _val;
590439641f7SPawel Wodkowski }
591439641f7SPawel Wodkowski
592439641f7SPawel Wodkowski return _val ? 0 : -ENOENT;
593439641f7SPawel Wodkowski }
594439641f7SPawel Wodkowski
595439641f7SPawel Wodkowski int
spdk_json_find_string(struct spdk_json_val * object,const char * key_name,struct spdk_json_val ** key,struct spdk_json_val ** val)596439641f7SPawel Wodkowski spdk_json_find_string(struct spdk_json_val *object, const char *key_name,
597439641f7SPawel Wodkowski struct spdk_json_val **key, struct spdk_json_val **val)
598439641f7SPawel Wodkowski {
599439641f7SPawel Wodkowski return spdk_json_find(object, key_name, key, val, SPDK_JSON_VAL_STRING);
600439641f7SPawel Wodkowski }
601439641f7SPawel Wodkowski
602439641f7SPawel Wodkowski int
spdk_json_find_array(struct spdk_json_val * object,const char * key_name,struct spdk_json_val ** key,struct spdk_json_val ** val)603439641f7SPawel Wodkowski spdk_json_find_array(struct spdk_json_val *object, const char *key_name,
604439641f7SPawel Wodkowski struct spdk_json_val **key, struct spdk_json_val **val)
605439641f7SPawel Wodkowski {
606439641f7SPawel Wodkowski return spdk_json_find(object, key_name, key, val, SPDK_JSON_VAL_ARRAY_BEGIN);
607439641f7SPawel Wodkowski }
608439641f7SPawel Wodkowski
609439641f7SPawel Wodkowski struct spdk_json_val *
spdk_json_object_first(struct spdk_json_val * object)610439641f7SPawel Wodkowski spdk_json_object_first(struct spdk_json_val *object)
611439641f7SPawel Wodkowski {
6120be5557cSSeth Howell struct spdk_json_val *first = json_first(object, SPDK_JSON_VAL_OBJECT_BEGIN);
613439641f7SPawel Wodkowski
614439641f7SPawel Wodkowski /* Empty object? */
615439641f7SPawel Wodkowski return first && first->type != SPDK_JSON_VAL_OBJECT_END ? first : NULL;
616439641f7SPawel Wodkowski }
617439641f7SPawel Wodkowski
618439641f7SPawel Wodkowski struct spdk_json_val *
spdk_json_array_first(struct spdk_json_val * array_begin)619439641f7SPawel Wodkowski spdk_json_array_first(struct spdk_json_val *array_begin)
620439641f7SPawel Wodkowski {
6210be5557cSSeth Howell struct spdk_json_val *first = json_first(array_begin, SPDK_JSON_VAL_ARRAY_BEGIN);
622439641f7SPawel Wodkowski
623439641f7SPawel Wodkowski /* Empty array? */
624439641f7SPawel Wodkowski return first && first->type != SPDK_JSON_VAL_ARRAY_END ? first : NULL;
625439641f7SPawel Wodkowski }
626439641f7SPawel Wodkowski
627439641f7SPawel Wodkowski static struct spdk_json_val *
json_skip_object_or_array(struct spdk_json_val * val)6280be5557cSSeth Howell json_skip_object_or_array(struct spdk_json_val *val)
629439641f7SPawel Wodkowski {
630439641f7SPawel Wodkowski unsigned lvl;
631439641f7SPawel Wodkowski enum spdk_json_val_type end_type;
632439641f7SPawel Wodkowski struct spdk_json_val *it;
633439641f7SPawel Wodkowski
634439641f7SPawel Wodkowski if (val->type == SPDK_JSON_VAL_OBJECT_BEGIN) {
635439641f7SPawel Wodkowski end_type = SPDK_JSON_VAL_OBJECT_END;
636439641f7SPawel Wodkowski } else if (val->type == SPDK_JSON_VAL_ARRAY_BEGIN) {
637439641f7SPawel Wodkowski end_type = SPDK_JSON_VAL_ARRAY_END;
638439641f7SPawel Wodkowski } else {
639439641f7SPawel Wodkowski SPDK_JSON_DEBUG("Expected JSON object (%#x) or array (%#x) but got %#x\n",
640c680a792SSeth Howell SPDK_JSON_VAL_OBJECT_BEGIN, SPDK_JSON_VAL_ARRAY_BEGIN, val->type);
641439641f7SPawel Wodkowski return NULL;
642439641f7SPawel Wodkowski }
643439641f7SPawel Wodkowski
644439641f7SPawel Wodkowski lvl = 1;
645439641f7SPawel Wodkowski for (it = val + 1; it->type != SPDK_JSON_VAL_INVALID && lvl != 0; it++) {
646439641f7SPawel Wodkowski if (it->type == val->type) {
647439641f7SPawel Wodkowski lvl++;
648439641f7SPawel Wodkowski } else if (it->type == end_type) {
649439641f7SPawel Wodkowski lvl--;
650439641f7SPawel Wodkowski }
651439641f7SPawel Wodkowski }
652439641f7SPawel Wodkowski
653439641f7SPawel Wodkowski /* if lvl != 0 we have invalid JSON object */
654439641f7SPawel Wodkowski if (lvl != 0) {
655439641f7SPawel Wodkowski SPDK_JSON_DEBUG("Can't find end of object (type: %#x): lvl (%u) != 0)\n", val->type, lvl);
656439641f7SPawel Wodkowski it = NULL;
657439641f7SPawel Wodkowski }
658439641f7SPawel Wodkowski
659439641f7SPawel Wodkowski return it;
660439641f7SPawel Wodkowski }
661439641f7SPawel Wodkowski
662439641f7SPawel Wodkowski struct spdk_json_val *
spdk_json_next(struct spdk_json_val * it)663439641f7SPawel Wodkowski spdk_json_next(struct spdk_json_val *it)
664439641f7SPawel Wodkowski {
665439641f7SPawel Wodkowski struct spdk_json_val *val, *next;
666439641f7SPawel Wodkowski
667439641f7SPawel Wodkowski switch (it->type) {
668439641f7SPawel Wodkowski case SPDK_JSON_VAL_NAME:
6690be5557cSSeth Howell val = json_value(it);
670439641f7SPawel Wodkowski next = spdk_json_next(val);
671439641f7SPawel Wodkowski break;
672439641f7SPawel Wodkowski
673439641f7SPawel Wodkowski /* We are in the middle of an array - get to next entry */
674439641f7SPawel Wodkowski case SPDK_JSON_VAL_NULL:
675439641f7SPawel Wodkowski case SPDK_JSON_VAL_TRUE:
676439641f7SPawel Wodkowski case SPDK_JSON_VAL_FALSE:
677439641f7SPawel Wodkowski case SPDK_JSON_VAL_NUMBER:
678439641f7SPawel Wodkowski case SPDK_JSON_VAL_STRING:
679439641f7SPawel Wodkowski val = it + 1;
680439641f7SPawel Wodkowski return val;
681439641f7SPawel Wodkowski
682439641f7SPawel Wodkowski case SPDK_JSON_VAL_ARRAY_BEGIN:
683439641f7SPawel Wodkowski case SPDK_JSON_VAL_OBJECT_BEGIN:
6840be5557cSSeth Howell next = json_skip_object_or_array(it);
685439641f7SPawel Wodkowski break;
686439641f7SPawel Wodkowski
687439641f7SPawel Wodkowski /* Can't go to the next object if started from the end of array or object */
688439641f7SPawel Wodkowski case SPDK_JSON_VAL_ARRAY_END:
689439641f7SPawel Wodkowski case SPDK_JSON_VAL_OBJECT_END:
690439641f7SPawel Wodkowski case SPDK_JSON_VAL_INVALID:
691439641f7SPawel Wodkowski return NULL;
692439641f7SPawel Wodkowski default:
693439641f7SPawel Wodkowski assert(false);
694439641f7SPawel Wodkowski return NULL;
695439641f7SPawel Wodkowski
696439641f7SPawel Wodkowski }
697439641f7SPawel Wodkowski
698439641f7SPawel Wodkowski /* EOF ? */
699439641f7SPawel Wodkowski if (next == NULL) {
700439641f7SPawel Wodkowski return NULL;
701439641f7SPawel Wodkowski }
702439641f7SPawel Wodkowski
703439641f7SPawel Wodkowski switch (next->type) {
704439641f7SPawel Wodkowski case SPDK_JSON_VAL_ARRAY_END:
705439641f7SPawel Wodkowski case SPDK_JSON_VAL_OBJECT_END:
706439641f7SPawel Wodkowski case SPDK_JSON_VAL_INVALID:
707439641f7SPawel Wodkowski return NULL;
708439641f7SPawel Wodkowski default:
709439641f7SPawel Wodkowski /* Next value */
710439641f7SPawel Wodkowski return next;
711439641f7SPawel Wodkowski }
712439641f7SPawel Wodkowski }
713439641f7SPawel Wodkowski
7142172c432STomasz Zawadzki SPDK_LOG_REGISTER_COMPONENT(json_util)
715