/*******************************************************************************
* This file is part of the Incubed project.
* Sources: https://github.com/blockchainsllc/in3
*
* Copyright (C) 2018-2020 slock.it GmbH, Blockchains LLC
*
*
* COMMERCIAL LICENSE USAGE
*
* Licensees holding a valid commercial license may use this file in accordance
* with the commercial license agreement provided with the Software or, alternatively,
* in accordance with the terms contained in a written agreement between you and
* slock.it GmbH/Blockchains LLC. For licensing terms and conditions or further
* information please contact slock.it at in3@slock.it.
*
* Alternatively, this file may be used under the AGPL license as follows:
*
* AGPL LICENSE USAGE
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Affero General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
* [Permissions of this strong copyleft license are conditioned on making available
* complete source code of licensed works and modifications, which include larger
* works using a licensed work, under the same license. Copyright and license notices
* must be preserved. Contributors provide an express grant of patent rights.]
* You should have received a copy of the GNU Affero General Public License along
* with this program. If not, see .
*******************************************************************************/
// @PUBLIC_HEADER
/** @file
* json-parser.
*
* The parser can read from :
* - json
* - bin
*
* When reading from json all '0x'... values will be stored as bytes_t. If the value is lower than 0xFFFFFFF, it is converted as integer.
*
*
* */
#ifndef __DATA_H__
#define __DATA_H__
#ifdef __cplusplus
extern "C" {
#endif
#ifndef DATA_DEPTH_MAX
/** the max DEPTH of the JSON-data allowed. It will throw an error if reached. */
#define DATA_DEPTH_MAX 11
#endif
#include "bytes.h"
#include "mem.h"
#include
#include
#include
typedef uint16_t d_key_t;
/** type of a token. */
typedef enum {
T_BYTES = 0, /**< content is stored as data ptr. */
T_STRING = 1, /**len & 0xF0000000) >> 28) : T_NULL); } /**< type of the token */
static inline int d_len(const d_token_t* item) { /**< number of elements in the token (only for object or array, other will return 0) */
if (item == NULL) return 0;
return item->len & 0xFFFFFFF;
}
bool d_eq(const d_token_t* a, const d_token_t* b); /**< compares 2 token and if the value is equal */
NONULL d_key_t keyn(const char* c, const size_t len); /**< generates the keyhash for the given stringrange as defined by len */
d_key_t ikey(json_ctx_t* ctx, const char* name); /**< returnes the indexed key for the given name. */
d_token_t* d_get(d_token_t* item, const uint16_t key); /**< returns the token with the given propertyname (only if item is a object) */
d_token_t* d_get_or(d_token_t* item, const uint16_t key1, const uint16_t key2); /**< returns the token with the given propertyname or if not found, tries the other. (only if item is a object) */
d_token_t* d_get_at(d_token_t* item, const uint32_t index); /**< returns the token of an array with the given index */
d_token_t* d_next(d_token_t* item); /**< returns the next sibling of an array or object */
NONULL void d_serialize_binary(bytes_builder_t* bb, d_token_t* t); /**< write the token as binary data into the builder */
NONULL json_ctx_t* parse_binary(const bytes_t* data); /**< parses the data and returns the context with the token, which needs to be freed after usage! */
NONULL json_ctx_t* parse_binary_str(const char* data, int len); /**< parses the data and returns the context with the token, which needs to be freed after usage! */
NONULL char* parse_json_error(const char* js); /**< parses the json, but only return an error if the json is invalid. The returning string must be freed! */
NONULL json_ctx_t* parse_json(const char* js); /**< parses json-data, which needs to be freed after usage! */
NONULL json_ctx_t* parse_json_indexed(const char* js); /**< parses json-data, which needs to be freed after usage! */
NONULL void json_free(json_ctx_t* parser_ctx); /**< frees the parse-context after usage */
NONULL str_range_t d_to_json(const d_token_t* item); /**< returns the string for a object or array. This only works for json as string. For binary it will not work! */
char* d_create_json(json_ctx_t* ctx, d_token_t* item); /**< creates a json-string. It does not work for objects if the parsed data were binary!*/
json_ctx_t* json_create();
NONULL d_token_t* json_create_null(json_ctx_t* jp);
NONULL d_token_t* json_create_bool(json_ctx_t* jp, bool value);
NONULL d_token_t* json_create_int(json_ctx_t* jp, uint64_t value);
NONULL d_token_t* json_create_string(json_ctx_t* jp, char* value, int len);
NONULL d_token_t* json_create_bytes(json_ctx_t* jp, bytes_t value);
NONULL int json_create_object(json_ctx_t* jp);
NONULL int json_create_array(json_ctx_t* jp);
NONULL void json_object_add_prop(json_ctx_t* jp, int ob_index, d_key_t key, d_token_t* value);
NONULL d_token_t* json_create_ref_item(json_ctx_t* jp, d_type_t type, void* data, int len);
NONULL void json_array_add_value(json_ctx_t* jp, int parent_index, d_token_t* value);
NONULL d_token_t* token_from_string(char* val, d_token_t* d, bytes32_t buffer); /**< returns a token ptr using the val without allocating memory in the heap, which can be used to pass values as token */
NONULL d_token_t* token_from_bytes(bytes_t b, d_token_t* d); /**< returns a token ptr using the val without allocating memory in the heap, which can be used to pass values as token */
// Helper function to map string to 2byte keys (only for tests or debugging)
char* d_get_keystr(json_ctx_t* json, d_key_t k); /**< returns the string for a key. This only works for index keys or known keys! */
NONULL static inline d_key_t key(const char* c) {
uint16_t val = 0;
size_t l = strlen(c);
for (; l; l--, c++) val ^= *c | val << 7;
return val;
}
static inline char* d_get_string(d_token_t* r, d_key_t k) { return d_string(d_get(r, k)); } /**< reads token of a property as string. */
static inline char* d_get_string_at(d_token_t* r, uint32_t pos) { return d_string(d_get_at(r, pos)); } /**< reads string at given pos of an array. */
static inline int32_t d_get_int(d_token_t* r, d_key_t k) { return d_int(d_get(r, k)); } /**< reads token of a property as int. */
static inline int32_t d_get_intd(d_token_t* r, d_key_t k, uint32_t d) { return d_intd(d_get(r, k), d); } /**< reads token of a property as int. */
static inline int32_t d_get_int_at(d_token_t* r, uint32_t pos) { return d_int(d_get_at(r, pos)); } /**< reads a int at given pos of an array. */
static inline uint64_t d_get_long(d_token_t* r, d_key_t k) { return d_long(d_get(r, k)); } /**< reads token of a property as long. */
static inline uint64_t d_get_longd(d_token_t* r, d_key_t k, uint64_t d) { return d_longd(d_get(r, k), d); } /**< reads token of a property as long. */
static inline uint64_t d_get_long_at(d_token_t* r, uint32_t pos) { return d_long(d_get_at(r, pos)); } /**< reads long at given pos of an array. */
static inline bytes_t* d_get_bytes(d_token_t* r, d_key_t k) { return d_bytes(d_get(r, k)); } /**< reads token of a property as bytes. */
static inline bytes_t* d_get_bytes_at(d_token_t* r, uint32_t pos) { return d_bytes(d_get_at(r, pos)); } /**< reads bytes at given pos of an array. */
static inline bool d_is_binary_ctx(json_ctx_t* ctx) { return ctx->allocated == 0; } /**< check if the parser context was created from binary data. */
bytes_t* d_get_byteskl(d_token_t* r, d_key_t k, uint32_t minl);
d_token_t* d_getl(d_token_t* item, uint16_t k, uint32_t minl);
/**
* iterator over elements of a array opf object.
*
* usage:
* ```c
* for (d_iterator_t iter = d_iter( parent ); iter.left ; d_iter_next(&iter)) {
* uint32_t val = d_int(iter.token);
* }
* ```
*/
typedef struct d_iterator {
d_token_t* token; /**< current token */
int left; /**< number of result left */
} d_iterator_t;
d_iterator_t d_iter(d_token_t* parent); /**< creates a iterator for a object or array */
static inline bool d_iter_next(d_iterator_t* const iter) {
iter->token = d_next(iter->token);
return iter->left--;
} /**< fetched the next token an returns a boolean indicating whther there is a next or not.*/
#ifdef __ZEPHYR__
#define printX printk
#define fprintX fprintf // (kg): fprintk caused link-problems!
#define snprintX snprintk
#define vprintX vprintk
#else
#define printX printf
#define fprintX fprintf
#define snprintX snprintf
#define vprintX vprintf
#endif
#ifdef __cplusplus
}
#endif
#endif