597 lines
19 KiB
C
597 lines
19 KiB
C
// SPDX-FileCopyrightText: 2025 deroad <deroad@kumo.xn--q9jyb4c>
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
#include <rz_util.h>
|
|
|
|
/**
|
|
* \file structured_data.c
|
|
*
|
|
* Generates a structured data which can be converted
|
|
* in a human readable output (like json or yaml).
|
|
*
|
|
*/
|
|
|
|
#include "structured_data_json.c"
|
|
#include "structured_data_yaml.c"
|
|
|
|
typedef enum {
|
|
STRUCTURED_DATA_TYPE_MAP = 0,
|
|
STRUCTURED_DATA_TYPE_ARRAY,
|
|
STRUCTURED_DATA_TYPE_UNSIGNED,
|
|
STRUCTURED_DATA_TYPE_HEXADECIMAL,
|
|
STRUCTURED_DATA_TYPE_SIGNED,
|
|
STRUCTURED_DATA_TYPE_DOUBLE,
|
|
STRUCTURED_DATA_TYPE_BOOL,
|
|
STRUCTURED_DATA_TYPE_STRING,
|
|
} StructuredDataType;
|
|
|
|
struct rz_structured_data_t {
|
|
StructuredDataType type;
|
|
union {
|
|
ut64 v_unsigned;
|
|
st64 v_signed;
|
|
double v_double;
|
|
bool v_bool;
|
|
char *v_string;
|
|
HtSP /*<RzStructuredData *>*/ *v_map;
|
|
};
|
|
RzPVector /*<void *>*/ *v_array; // used also to keep the map keys in order
|
|
};
|
|
|
|
typedef struct structured_data_iter_over_t {
|
|
const RzStructuredDataIterator *fit;
|
|
void *user;
|
|
} StructuredDataIterOver;
|
|
|
|
/**
|
|
* \brief Free a RzStructuredData pointer
|
|
*
|
|
* \param sd The RzStructuredData to free.
|
|
*/
|
|
RZ_API void rz_structured_data_free(RZ_NULLABLE RzStructuredData *sd) {
|
|
if (!sd) {
|
|
return;
|
|
}
|
|
|
|
if (sd->type == STRUCTURED_DATA_TYPE_MAP) {
|
|
ht_sp_free(sd->v_map);
|
|
rz_pvector_free(sd->v_array);
|
|
} else if (sd->type == STRUCTURED_DATA_TYPE_ARRAY) {
|
|
rz_pvector_free(sd->v_array);
|
|
} else if (sd->type == STRUCTURED_DATA_TYPE_STRING) {
|
|
free(sd->v_string);
|
|
}
|
|
free(sd);
|
|
}
|
|
|
|
static RzStructuredData *structured_data_new_map() {
|
|
RzStructuredData *sd = RZ_NEW0(RzStructuredData);
|
|
if (!sd) {
|
|
return NULL;
|
|
}
|
|
sd->type = STRUCTURED_DATA_TYPE_MAP;
|
|
sd->v_map = ht_sp_new(HT_STR_DUP, NULL, (HtSPFreeValue)rz_structured_data_free);
|
|
sd->v_array = rz_pvector_new((RzPVectorFree)free);
|
|
if (!sd->v_map || !sd->v_array) {
|
|
rz_structured_data_free(sd);
|
|
return NULL;
|
|
}
|
|
return sd;
|
|
}
|
|
|
|
static RzStructuredData *structured_data_new_array() {
|
|
RzStructuredData *sd = RZ_NEW0(RzStructuredData);
|
|
if (!sd) {
|
|
return NULL;
|
|
}
|
|
sd->type = STRUCTURED_DATA_TYPE_ARRAY;
|
|
sd->v_array = rz_pvector_new((RzPVectorFree)rz_structured_data_free);
|
|
if (!sd->v_array) {
|
|
free(sd);
|
|
return NULL;
|
|
}
|
|
return sd;
|
|
}
|
|
|
|
static RzStructuredData *structured_data_new_unsigned(ut64 v_unsigned, bool hex) {
|
|
RzStructuredData *sd = RZ_NEW0(RzStructuredData);
|
|
if (!sd) {
|
|
return NULL;
|
|
}
|
|
sd->type = hex ? STRUCTURED_DATA_TYPE_HEXADECIMAL : STRUCTURED_DATA_TYPE_UNSIGNED;
|
|
sd->v_unsigned = v_unsigned;
|
|
return sd;
|
|
}
|
|
|
|
static RzStructuredData *structured_data_new_signed(st64 v_signed) {
|
|
RzStructuredData *sd = RZ_NEW0(RzStructuredData);
|
|
if (!sd) {
|
|
return NULL;
|
|
}
|
|
sd->type = STRUCTURED_DATA_TYPE_SIGNED;
|
|
sd->v_signed = v_signed;
|
|
return sd;
|
|
}
|
|
|
|
static RzStructuredData *structured_data_new_double(double v_double) {
|
|
RzStructuredData *sd = RZ_NEW0(RzStructuredData);
|
|
if (!sd) {
|
|
return NULL;
|
|
}
|
|
sd->type = STRUCTURED_DATA_TYPE_DOUBLE;
|
|
sd->v_double = v_double;
|
|
return sd;
|
|
}
|
|
|
|
static RzStructuredData *structured_data_new_bool(bool v_bool) {
|
|
RzStructuredData *sd = RZ_NEW0(RzStructuredData);
|
|
if (!sd) {
|
|
return NULL;
|
|
}
|
|
sd->type = STRUCTURED_DATA_TYPE_BOOL;
|
|
sd->v_bool = v_bool;
|
|
return sd;
|
|
}
|
|
|
|
static RzStructuredData *structured_data_new_string(char *v_string) {
|
|
RzStructuredData *sd = RZ_NEW0(RzStructuredData);
|
|
if (!sd) {
|
|
return NULL;
|
|
}
|
|
sd->type = STRUCTURED_DATA_TYPE_STRING;
|
|
sd->v_string = v_string;
|
|
return sd;
|
|
}
|
|
|
|
static bool structured_data_map_add(RZ_NONNULL RzStructuredData *parent, const char *key, RZ_NONNULL RZ_OWN RzStructuredData *child) {
|
|
RzPVector *pvec = parent->v_array;
|
|
HtSP *map = parent->v_map;
|
|
if (!map || !pvec || !child || RZ_STR_ISEMPTY(key)) {
|
|
rz_structured_data_free(child);
|
|
RZ_LOG_ERROR("struct_factory: invalid key: '%s'\n", key);
|
|
return false;
|
|
}
|
|
|
|
bool found = false;
|
|
ht_sp_find(map, key, &found);
|
|
if (found) {
|
|
rz_structured_data_free(child);
|
|
RZ_LOG_ERROR("struct_factory: found duplicated key: '%s'\n", key);
|
|
return false;
|
|
}
|
|
|
|
char *key_copy = rz_str_dup(key);
|
|
if (!key_copy || !ht_sp_insert(map, key_copy, child)) {
|
|
rz_structured_data_free(child);
|
|
free(key_copy);
|
|
RZ_LOG_ERROR("struct_factory: cannot add value with key: '%s'\n", key);
|
|
return false;
|
|
}
|
|
|
|
return rz_pvector_push(pvec, key_copy);
|
|
}
|
|
|
|
static bool structured_data_array_add(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL RZ_OWN RzStructuredData *child) {
|
|
RzPVector *pvec = parent->v_array;
|
|
if (!pvec || !child) {
|
|
RZ_LOG_ERROR("struct_factory: invalid array value\n");
|
|
rz_structured_data_free(child);
|
|
return false;
|
|
}
|
|
rz_pvector_push(pvec, child);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* \brief Creates a new RzStructuredData initialized as a map
|
|
*
|
|
* \return On success returns a valid opaque pointer to a RzStructuredData
|
|
*/
|
|
RZ_API RZ_OWN RzStructuredData *rz_structured_data_new_map() {
|
|
return structured_data_new_map();
|
|
}
|
|
|
|
/**
|
|
* \brief Creates a new RzStructuredData initialized as an array
|
|
*
|
|
* \return On success returns a valid opaque pointer to a RzStructuredData
|
|
*/
|
|
RZ_API RZ_OWN RzStructuredData *rz_structured_data_new_array() {
|
|
return structured_data_new_array();
|
|
}
|
|
|
|
/**
|
|
* \brief Returns a child, map type, RzStructuredData that has been added to the given parent
|
|
*
|
|
* \param parent Where to add the child RzStructuredData
|
|
* \param[in] key The key to assign the child RzStructuredData
|
|
*
|
|
* \return On success returns a valid pointer to the child RzStructuredData, otherwise NULL
|
|
*/
|
|
RZ_API RZ_BORROW RzStructuredData *rz_structured_data_map_add_map(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const char *key) {
|
|
rz_return_val_if_fail(parent && parent->type == STRUCTURED_DATA_TYPE_MAP && key, false);
|
|
|
|
RzStructuredData *child = structured_data_new_map();
|
|
if (!structured_data_map_add(parent, key, child)) {
|
|
return NULL;
|
|
}
|
|
|
|
return child;
|
|
}
|
|
|
|
/**
|
|
* \brief Returns a child, array type, RzStructuredData that has been added to the given parent
|
|
*
|
|
* \param parent Where to add the child RzStructuredData
|
|
* \param[in] key The key to assign the child RzStructuredData
|
|
*
|
|
* \return On success returns a valid pointer to the child RzStructuredData, otherwise NULL
|
|
*/
|
|
RZ_API RZ_BORROW RzStructuredData *rz_structured_data_map_add_array(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const char *key) {
|
|
rz_return_val_if_fail(parent && parent->type == STRUCTURED_DATA_TYPE_MAP && key, false);
|
|
|
|
RzStructuredData *child = structured_data_new_array();
|
|
if (!structured_data_map_add(parent, key, child)) {
|
|
return NULL;
|
|
}
|
|
|
|
return child;
|
|
}
|
|
|
|
/**
|
|
* \brief Adds an owned RzStructuredData child to a parent and assigns it a map key
|
|
*
|
|
* \param parent Where to add the child RzStructuredData
|
|
* \param[in] key The key to assign the child RzStructuredData
|
|
* \param child The child RzStructuredData
|
|
*
|
|
* \return On success returns true, otherwise the child gets deallocated by the function and return false.
|
|
*/
|
|
RZ_API bool rz_structured_data_map_add(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const char *key, RZ_NONNULL RZ_OWN RzStructuredData *child) {
|
|
rz_return_val_if_fail(parent && parent->type == STRUCTURED_DATA_TYPE_MAP && key && child, false);
|
|
|
|
return structured_data_map_add(parent, key, child);
|
|
}
|
|
|
|
/**
|
|
* \brief Adds unsigned type child to a parent and assigns it a map key
|
|
*
|
|
* \param parent Where to add the child RzStructuredData
|
|
* \param[in] key The key to assign the child RzStructuredData
|
|
* \param n The value to assign to the child
|
|
* \param hex When true the type is going to be set as base16 number instead of base10 unsigned number.
|
|
*
|
|
* \return On success returns true, otherwise false.
|
|
*/
|
|
RZ_API bool rz_structured_data_map_add_unsigned(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const char *key, ut64 n, bool hex) {
|
|
rz_return_val_if_fail(parent && parent->type == STRUCTURED_DATA_TYPE_MAP && key, false);
|
|
|
|
RzStructuredData *child = structured_data_new_unsigned(n, hex);
|
|
return structured_data_map_add(parent, key, child);
|
|
}
|
|
|
|
/**
|
|
* \brief Adds signed type child to a parent and assigns it a map key
|
|
*
|
|
* \param parent Where to add the child RzStructuredData
|
|
* \param[in] key The key to assign the child RzStructuredData
|
|
* \param n The value to assign to the child
|
|
*
|
|
* \return On success returns true, otherwise false.
|
|
*/
|
|
RZ_API bool rz_structured_data_map_add_signed(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const char *key, st64 n) {
|
|
rz_return_val_if_fail(parent && parent->type == STRUCTURED_DATA_TYPE_MAP && key, false);
|
|
|
|
RzStructuredData *child = structured_data_new_signed(n);
|
|
return structured_data_map_add(parent, key, child);
|
|
}
|
|
|
|
/**
|
|
* \brief Adds double type child to a parent and assigns it a map key
|
|
*
|
|
* \param parent Where to add the child RzStructuredData
|
|
* \param[in] key The key to assign the child RzStructuredData
|
|
* \param d The value to assign to the child
|
|
*
|
|
* \return On success returns true, otherwise false.
|
|
*/
|
|
RZ_API bool rz_structured_data_map_add_double(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const char *key, double d) {
|
|
rz_return_val_if_fail(parent && parent->type == STRUCTURED_DATA_TYPE_MAP && key, false);
|
|
|
|
RzStructuredData *child = structured_data_new_double(d);
|
|
return structured_data_map_add(parent, key, child);
|
|
}
|
|
|
|
/**
|
|
* \brief Adds boolean type child to a parent and assigns it a map key
|
|
*
|
|
* \param parent Where to add the child RzStructuredData
|
|
* \param[in] key The key to assign the child RzStructuredData
|
|
* \param b The value to assign to the child
|
|
*
|
|
* \return On success returns true, otherwise false.
|
|
*/
|
|
RZ_API bool rz_structured_data_map_add_boolean(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const char *key, bool b) {
|
|
rz_return_val_if_fail(parent && parent->type == STRUCTURED_DATA_TYPE_MAP && key, false);
|
|
|
|
RzStructuredData *child = structured_data_new_bool(b);
|
|
return structured_data_map_add(parent, key, child);
|
|
}
|
|
|
|
/**
|
|
* \brief Adds a null terminated string type child to a parent and assigns it a map key
|
|
*
|
|
* \param parent Where to add the child RzStructuredData
|
|
* \param[in] key The key to assign the child RzStructuredData
|
|
* \param s The value to assign to the child
|
|
*
|
|
* \return On success returns true, otherwise false.
|
|
*/
|
|
RZ_API bool rz_structured_data_map_add_string(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const char *key, RZ_NONNULL const char *s) {
|
|
rz_return_val_if_fail(parent && parent->type == STRUCTURED_DATA_TYPE_MAP && key && s, false);
|
|
|
|
char *copy = rz_str_dup(s);
|
|
if (!copy) {
|
|
return false;
|
|
}
|
|
|
|
RzStructuredData *child = structured_data_new_string(copy);
|
|
return structured_data_map_add(parent, key, child);
|
|
}
|
|
|
|
/**
|
|
* \brief Returns a child, map type, RzStructuredData that has been added to the given parent
|
|
*
|
|
* \param parent Where to add the child RzStructuredData
|
|
*
|
|
* \return On success returns a valid pointer to the child RzStructuredData, otherwise NULL
|
|
*/
|
|
RZ_API RZ_BORROW RzStructuredData *rz_structured_data_array_add_map(RZ_NONNULL RzStructuredData *parent) {
|
|
rz_return_val_if_fail(parent && parent->type == STRUCTURED_DATA_TYPE_ARRAY, false);
|
|
|
|
RzStructuredData *child = structured_data_new_map();
|
|
if (!structured_data_array_add(parent, child)) {
|
|
return NULL;
|
|
}
|
|
|
|
return child;
|
|
}
|
|
|
|
/**
|
|
* \brief Returns a child, array type, RzStructuredData that has been added to the given parent
|
|
*
|
|
* \param parent Where to add the child RzStructuredData
|
|
*
|
|
* \return On success returns a valid pointer to the child RzStructuredData, otherwise NULL
|
|
*/
|
|
RZ_API RZ_BORROW RzStructuredData *rz_structured_data_array_add_array(RZ_NONNULL RzStructuredData *parent) {
|
|
rz_return_val_if_fail(parent && parent->type == STRUCTURED_DATA_TYPE_ARRAY, false);
|
|
|
|
RzStructuredData *child = structured_data_new_array();
|
|
if (!structured_data_array_add(parent, child)) {
|
|
return NULL;
|
|
}
|
|
|
|
return child;
|
|
}
|
|
|
|
/**
|
|
* \brief Adds an owned RzStructuredData child to an array type parent
|
|
*
|
|
* \param parent Where to add the child RzStructuredData
|
|
* \param child The child RzStructuredData
|
|
*
|
|
* \return On success returns true, otherwise the child gets deallocated by the function and return false.
|
|
*/
|
|
RZ_API bool rz_structured_data_array_add(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL RZ_OWN RzStructuredData *child) {
|
|
rz_return_val_if_fail(parent && parent->type == STRUCTURED_DATA_TYPE_ARRAY && child, false);
|
|
|
|
return structured_data_array_add(parent, child);
|
|
}
|
|
|
|
/**
|
|
* \brief Adds unsigned type child to an array type parent
|
|
*
|
|
* \param parent Where to add the child RzStructuredData
|
|
* \param n The value to assign to the child
|
|
* \param hex When true the type is going to be set as base16 number instead of base10 unsigned number.
|
|
*
|
|
* \return On success returns true, otherwise false.
|
|
*/
|
|
RZ_API bool rz_structured_data_array_add_unsigned(RZ_NONNULL RzStructuredData *parent, ut64 n, bool hex) {
|
|
rz_return_val_if_fail(parent && parent->type == STRUCTURED_DATA_TYPE_ARRAY, false);
|
|
|
|
RzStructuredData *child = structured_data_new_unsigned(n, hex);
|
|
return structured_data_array_add(parent, child);
|
|
}
|
|
|
|
/**
|
|
* \brief Adds signed type child to an array type parent
|
|
*
|
|
* \param parent Where to add the child RzStructuredData
|
|
* \param n The value to assign to the child
|
|
*
|
|
* \return On success returns true, otherwise false.
|
|
*/
|
|
RZ_API bool rz_structured_data_array_add_signed(RZ_NONNULL RzStructuredData *parent, st64 n) {
|
|
rz_return_val_if_fail(parent && parent->type == STRUCTURED_DATA_TYPE_ARRAY, false);
|
|
|
|
RzStructuredData *child = structured_data_new_signed(n);
|
|
return structured_data_array_add(parent, child);
|
|
}
|
|
|
|
/**
|
|
* \brief Adds double type child to an array type parent
|
|
*
|
|
* \param parent Where to add the child RzStructuredData
|
|
* \param n The value to assign to the child
|
|
*
|
|
* \return On success returns true, otherwise false.
|
|
*/
|
|
RZ_API bool rz_structured_data_array_add_double(RZ_NONNULL RzStructuredData *parent, double d) {
|
|
rz_return_val_if_fail(parent && parent->type == STRUCTURED_DATA_TYPE_ARRAY, false);
|
|
|
|
RzStructuredData *child = structured_data_new_double(d);
|
|
return structured_data_array_add(parent, child);
|
|
}
|
|
|
|
/**
|
|
* \brief Adds signed type child to an array type parent
|
|
*
|
|
* \param parent Where to add the child RzStructuredData
|
|
* \param n The value to assign to the child
|
|
*
|
|
* \return On success returns true, otherwise false.
|
|
*/
|
|
RZ_API bool rz_structured_data_array_add_boolean(RZ_NONNULL RzStructuredData *parent, bool b) {
|
|
rz_return_val_if_fail(parent && parent->type == STRUCTURED_DATA_TYPE_ARRAY, false);
|
|
|
|
RzStructuredData *child = structured_data_new_bool(b);
|
|
return structured_data_array_add(parent, child);
|
|
}
|
|
|
|
/**
|
|
* \brief Adds a null terminated string type child to an array type parent
|
|
*
|
|
* \param parent Where to add the child RzStructuredData
|
|
* \param n The value to assign to the child
|
|
*
|
|
* \return On success returns true, otherwise false.
|
|
*/
|
|
RZ_API bool rz_structured_data_array_add_string(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const char *s) {
|
|
rz_return_val_if_fail(parent && parent->type == STRUCTURED_DATA_TYPE_ARRAY && s, false);
|
|
|
|
char *copy = rz_str_dup(s);
|
|
if (!copy) {
|
|
return false;
|
|
}
|
|
|
|
RzStructuredData *child = structured_data_new_string(copy);
|
|
return structured_data_array_add(parent, child);
|
|
}
|
|
|
|
static void structured_data_iterate_over(StructuredDataIterOver *sdio, const RzStructuredData *sd);
|
|
|
|
static void structured_data_iterate_over_map(StructuredDataIterOver *sdio, const RzStructuredData *sd) {
|
|
void **pit = NULL;
|
|
size_t n_keys = rz_pvector_len(sd->v_array);
|
|
sdio->fit->new_struct(sdio->user, RZ_STRUCTURED_DATA_BLOCK_MAP, n_keys);
|
|
rz_pvector_foreach (sd->v_array, pit) {
|
|
const char *key = *pit;
|
|
const RzStructuredData *elem = (const RzStructuredData *)ht_sp_find(sd->v_map, key, NULL);
|
|
sdio->fit->key(sdio->user, key);
|
|
structured_data_iterate_over(sdio, elem);
|
|
}
|
|
sdio->fit->end_struct(sdio->user);
|
|
}
|
|
|
|
static void structured_data_iterate_over_array(StructuredDataIterOver *sdio, const RzStructuredData *sd) {
|
|
void **pit = NULL;
|
|
size_t array_len = rz_pvector_len(sd->v_array);
|
|
sdio->fit->new_struct(sdio->user, RZ_STRUCTURED_DATA_BLOCK_ARRAY, array_len);
|
|
rz_pvector_foreach (sd->v_array, pit) {
|
|
const RzStructuredData *elem = (const RzStructuredData *)*pit;
|
|
structured_data_iterate_over(sdio, elem);
|
|
}
|
|
sdio->fit->end_struct(sdio->user);
|
|
}
|
|
|
|
static void structured_data_iterate_over(StructuredDataIterOver *sdio, const RzStructuredData *sd) {
|
|
if (!sd) {
|
|
return;
|
|
}
|
|
|
|
switch (sd->type) {
|
|
case STRUCTURED_DATA_TYPE_MAP:
|
|
structured_data_iterate_over_map(sdio, sd);
|
|
return;
|
|
case STRUCTURED_DATA_TYPE_ARRAY:
|
|
structured_data_iterate_over_array(sdio, sd);
|
|
return;
|
|
case STRUCTURED_DATA_TYPE_HEXADECIMAL:
|
|
sdio->fit->val_unsigned(sdio->user, sd->v_unsigned, true);
|
|
return;
|
|
case STRUCTURED_DATA_TYPE_UNSIGNED:
|
|
sdio->fit->val_unsigned(sdio->user, sd->v_unsigned, false);
|
|
return;
|
|
case STRUCTURED_DATA_TYPE_SIGNED:
|
|
sdio->fit->val_signed(sdio->user, sd->v_signed);
|
|
return;
|
|
case STRUCTURED_DATA_TYPE_DOUBLE:
|
|
sdio->fit->val_double(sdio->user, sd->v_double);
|
|
return;
|
|
case STRUCTURED_DATA_TYPE_BOOL:
|
|
sdio->fit->val_bool(sdio->user, sd->v_bool);
|
|
return;
|
|
case STRUCTURED_DATA_TYPE_STRING:
|
|
sdio->fit->val_string(sdio->user, sd->v_string);
|
|
return;
|
|
default:
|
|
rz_warn_if_reached();
|
|
return;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* \brief Iterates over a given RzStructuredData using the provided iterator
|
|
*
|
|
* \param[in] sd The RzStructuredData to iterate over
|
|
* \param[in] iterator The iterator to use
|
|
* \param user The user ponter (can be null)
|
|
*/
|
|
RZ_API void rz_structured_data_iterate(RZ_NONNULL const RzStructuredData *sd, RZ_NONNULL const RzStructuredDataIterator *iterator, RZ_NULLABLE void *user) {
|
|
rz_return_if_fail(sd && iterator && iterator);
|
|
|
|
StructuredDataIterOver sdio = {
|
|
.fit = iterator,
|
|
.user = user,
|
|
};
|
|
|
|
structured_data_iterate_over(&sdio, sd);
|
|
}
|
|
|
|
/**
|
|
* \brief Iterates over a given RzStructuredData and generates a json string
|
|
*
|
|
* \param[in] sd The RzStructuredData to iterate over
|
|
* \param[in] pj The PJ to write into
|
|
*/
|
|
RZ_API void rz_structured_data_to_pj(RZ_NONNULL const RzStructuredData *sd, RZ_NONNULL PJ *pj) {
|
|
rz_return_if_fail(sd && pj);
|
|
|
|
rz_structured_data_iterate(sd, &builder_json_iterator, pj);
|
|
}
|
|
|
|
/**
|
|
* \brief Iterates over a given RzStructuredData and generates a json string
|
|
*
|
|
* \param[in] sd The RzStructuredData to iterate over
|
|
*/
|
|
RZ_API RZ_OWN char *rz_structured_data_to_json(RZ_NONNULL const RzStructuredData *sd) {
|
|
rz_return_val_if_fail(sd, NULL);
|
|
|
|
PJ *pj = pj_new();
|
|
if (!pj) {
|
|
return NULL;
|
|
}
|
|
|
|
rz_structured_data_iterate(sd, &builder_json_iterator, pj);
|
|
|
|
return pj_drain(pj);
|
|
}
|
|
|
|
/**
|
|
* \brief Iterates over a given RzStructuredData and generates a yaml string
|
|
*
|
|
* \param[in] sd The RzStructuredData to iterate over
|
|
*/
|
|
RZ_API RZ_OWN char *rz_structured_data_to_yaml(RZ_NONNULL const RzStructuredData *sd) {
|
|
rz_return_val_if_fail(sd, NULL);
|
|
StructYamlPrinter yaml = { 0 };
|
|
|
|
builder_yaml_init_printer(&yaml);
|
|
|
|
rz_structured_data_iterate(sd, &builder_yaml_iterator, &yaml);
|
|
|
|
return builder_yaml_fini_printer(&yaml);
|
|
}
|