mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-22 06:13:27 -07:00
added path.c to jansson
This commit is contained in:
parent
1900197557
commit
23523ca9b0
1 changed files with 202 additions and 0 deletions
202
client/jansson/path.c
Normal file
202
client/jansson/path.c
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012 Rogerz Zhang <rogerz.zhang@gmail.com>
|
||||||
|
*
|
||||||
|
* Jansson is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
|
*
|
||||||
|
* source here https://github.com/rogerz/jansson/blob/json_path/src/path.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <jansson.h>
|
||||||
|
#include "jansson_private.h"
|
||||||
|
|
||||||
|
|
||||||
|
json_t *json_path_get(const json_t *json, const char *path)
|
||||||
|
{
|
||||||
|
static const char root_chr = '$', array_open = '[';
|
||||||
|
static const char *path_delims = ".[", *array_close = "]";
|
||||||
|
const json_t *cursor;
|
||||||
|
char *token, *buf, *peek, *endptr, delim = '\0';
|
||||||
|
const char *expect;
|
||||||
|
|
||||||
|
if (!json || !path || path[0] != root_chr)
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
buf = jsonp_strdup(path);
|
||||||
|
|
||||||
|
peek = buf + 1;
|
||||||
|
cursor = json;
|
||||||
|
token = NULL;
|
||||||
|
expect = path_delims;
|
||||||
|
|
||||||
|
while (peek && *peek && cursor)
|
||||||
|
{
|
||||||
|
char *last_peek = peek;
|
||||||
|
peek = strpbrk(peek, expect);
|
||||||
|
if (peek) {
|
||||||
|
if (!token && peek != last_peek)
|
||||||
|
goto fail;
|
||||||
|
delim = *peek;
|
||||||
|
*peek++ = '\0';
|
||||||
|
} else if (expect != path_delims || !token) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expect == path_delims) {
|
||||||
|
if (token) {
|
||||||
|
cursor = json_object_get(cursor, token);
|
||||||
|
}
|
||||||
|
expect = (delim == array_open ? array_close : path_delims);
|
||||||
|
token = peek;
|
||||||
|
} else if (expect == array_close) {
|
||||||
|
size_t index = strtol(token, &endptr, 0);
|
||||||
|
if (*endptr)
|
||||||
|
goto fail;
|
||||||
|
cursor = json_array_get(cursor, index);
|
||||||
|
token = NULL;
|
||||||
|
expect = path_delims;
|
||||||
|
} else {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonp_free(buf);
|
||||||
|
return (json_t *)cursor;
|
||||||
|
fail:
|
||||||
|
jsonp_free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int json_path_set_new(json_t *json, const char *path, json_t *value, size_t flags, json_error_t *error)
|
||||||
|
{
|
||||||
|
static const char root_chr = '$', array_open = '[', object_delim = '.';
|
||||||
|
static const char * const path_delims = ".[", *array_close = "]";
|
||||||
|
|
||||||
|
json_t *cursor, *parent = NULL;
|
||||||
|
char *token, *buf = NULL, *peek, delim = '\0';
|
||||||
|
const char *expect;
|
||||||
|
int index_saved = -1;
|
||||||
|
|
||||||
|
jsonp_error_init(error, "<path>");
|
||||||
|
|
||||||
|
if (!json || !path || flags || !value) {
|
||||||
|
jsonp_error_set(error, -1, -1, 0, json_error_invalid_argument, "invalid argument");
|
||||||
|
goto fail;
|
||||||
|
} else {
|
||||||
|
buf = jsonp_strdup(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf[0] != root_chr) {
|
||||||
|
jsonp_error_set(error, -1, -1, 0, json_error_invalid_format, "path should start with $");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
peek = buf + 1;
|
||||||
|
cursor = json;
|
||||||
|
token = NULL;
|
||||||
|
expect = path_delims;
|
||||||
|
|
||||||
|
while (peek && *peek && cursor)
|
||||||
|
{
|
||||||
|
char *last_peek = peek;
|
||||||
|
peek = strpbrk(last_peek, expect);
|
||||||
|
|
||||||
|
if (peek) {
|
||||||
|
if (!token && peek != last_peek) {
|
||||||
|
jsonp_error_set(error, -1, -1, last_peek - buf, json_error_invalid_format, "unexpected trailing chars");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
delim = *peek;
|
||||||
|
*peek++ = '\0';
|
||||||
|
} else { // end of path
|
||||||
|
if (expect == path_delims) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
jsonp_error_set(error, -1, -1, peek - buf, json_error_invalid_format, "missing ']'?");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expect == path_delims) {
|
||||||
|
if (token) {
|
||||||
|
if (token[0] == '\0') {
|
||||||
|
jsonp_error_set(error, -1, -1, peek - buf, json_error_invalid_format, "empty token");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent = cursor;
|
||||||
|
cursor = json_object_get(parent, token);
|
||||||
|
|
||||||
|
if (!cursor) {
|
||||||
|
if (!json_is_object(parent)) {
|
||||||
|
jsonp_error_set(error, -1, -1, peek - buf, json_error_item_not_found, "object expected");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (delim == object_delim) {
|
||||||
|
cursor = json_object();
|
||||||
|
json_object_set_new(parent, token, cursor);
|
||||||
|
} else {
|
||||||
|
jsonp_error_set(error, -1, -1, peek - buf, json_error_item_not_found, "new array is not allowed");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect = (delim == array_open ? array_close : path_delims);
|
||||||
|
token = peek;
|
||||||
|
} else if (expect == array_close) {
|
||||||
|
char *endptr;
|
||||||
|
size_t index;
|
||||||
|
|
||||||
|
parent = cursor;
|
||||||
|
if (!json_is_array(parent)) {
|
||||||
|
jsonp_error_set(error, -1, -1, peek - buf, json_error_item_not_found, "array expected");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
index = strtol(token, &endptr, 0);
|
||||||
|
if (*endptr) {
|
||||||
|
jsonp_error_set(error, -1, -1, peek - buf, json_error_item_not_found, "invalid array index");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
cursor = json_array_get(parent, index);
|
||||||
|
if (!cursor) {
|
||||||
|
jsonp_error_set(error, -1, -1, peek - buf, json_error_item_not_found, "array index out of bound");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
index_saved = index;
|
||||||
|
token = NULL;
|
||||||
|
expect = path_delims;
|
||||||
|
} else {
|
||||||
|
assert(1);
|
||||||
|
jsonp_error_set(error, -1, -1, peek - buf, json_error_unknown, "unexpected error in path move");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token) {
|
||||||
|
if (json_is_object(cursor)) {
|
||||||
|
json_object_set(cursor, token, value);
|
||||||
|
} else {
|
||||||
|
jsonp_error_set(error, -1, -1, peek - buf, json_error_item_not_found, "object expected");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
cursor = json_object_get(cursor, token);
|
||||||
|
} else if (index_saved != -1 && json_is_array(parent)) {
|
||||||
|
json_array_set(parent, index_saved, value);
|
||||||
|
cursor = json_array_get(parent, index_saved);
|
||||||
|
} else {
|
||||||
|
jsonp_error_set(error, -1, -1, peek - buf, json_error_item_not_found, "invalid path");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_decref(value);
|
||||||
|
jsonp_free(buf);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
json_decref(value);
|
||||||
|
jsonp_free(buf);
|
||||||
|
return -1;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue