diff --git a/src/xrt/auxiliary/util/u_json.c b/src/xrt/auxiliary/util/u_json.c index 2cda29e85..3778520b3 100644 --- a/src/xrt/auxiliary/util/u_json.c +++ b/src/xrt/auxiliary/util/u_json.c @@ -9,41 +9,214 @@ */ #include "u_json.h" +#include +// This includes the c file completely. #include "cjson/cJSON.c" + +/*! + * Less typing. + */ +static inline const cJSON * +get(const cJSON *json, const char *f) +{ + return cJSON_GetObjectItemCaseSensitive(json, f); +} + +bool +u_json_get_string_into_array(const cJSON *json, char *out_str, size_t max_size) +{ + assert(out_str != NULL); + + if (!json) { + return false; + } + if (!cJSON_IsString(json)) { + return false; + } + + int ret = snprintf(out_str, max_size, "%s", json->valuestring); + if (ret < 0) { + return false; + } else if ((size_t)ret < max_size) { + return true; + } else { + return false; + } +} + +bool +u_json_get_int(const cJSON *json, int *out_int) +{ + assert(out_int != NULL); + + if (!json) { + return false; + } + if (!cJSON_IsNumber(json)) { + return false; + } + + *out_int = json->valueint; + + return true; +} + +bool +u_json_get_double(const cJSON *json, double *out_double) +{ + assert(out_double != NULL); + + if (!json) { + return false; + } + if (!cJSON_IsNumber(json)) { + return false; + } + *out_double = json->valuedouble; + return true; +} + +bool +u_json_get_float(const cJSON *json, float *out_float) +{ + assert(out_float != NULL); + + double d = 0; + if (!u_json_get_double(json, &d)) { + return false; + } + + *out_float = (float)d; + return true; +} + +bool +u_json_get_vec3(const cJSON *json, struct xrt_vec3 *out_vec3) +{ + assert(out_vec3 != NULL); + + if (!json) { + return false; + } + if (!cJSON_IsObject(json)) { + return false; + } + + struct xrt_vec3 ret; + if (!u_json_get_float(get(json, "x"), &ret.x)) { + return false; + } + if (!u_json_get_float(get(json, "y"), &ret.y)) { + return false; + } + if (!u_json_get_float(get(json, "z"), &ret.z)) { + return false; + } + + *out_vec3 = ret; + + return true; +} + +bool +u_json_get_quat(const cJSON *json, struct xrt_quat *out_quat) +{ + assert(out_quat != NULL); + + if (!json) { + return false; + } + if (!cJSON_IsObject(json)) { + return false; + } + + struct xrt_quat ret; + if (!u_json_get_float(get(json, "w"), &ret.w)) { + return false; + } + if (!u_json_get_float(get(json, "x"), &ret.x)) { + return false; + } + if (!u_json_get_float(get(json, "y"), &ret.y)) { + return false; + } + if (!u_json_get_float(get(json, "z"), &ret.z)) { + return false; + } + + *out_quat = ret; + + return true; +} + +size_t +u_json_get_float_array(const cJSON *json_array, + float *out_array, + size_t max_size) +{ + assert(out_array != NULL); + + if (!json_array) { + return 0; + } + if (!cJSON_IsArray(json_array)) { + return 0; + } + + size_t i = 0; + const cJSON *elt; + cJSON_ArrayForEach(elt, json_array) + { + if (i >= max_size) { + break; + } + + if (!u_json_get_float(elt, &out_array[i])) { + fprintf(stderr, + "warning: u_json_get_float_array got a " + "non-number in a numeric array"); + return i; + } + + i++; + } + + return i; +} + size_t u_json_get_double_array(const cJSON *json_array, double *out_array, size_t max_size) { + assert(out_array != NULL); + if (!json_array) { return 0; } - if (!out_array) { - return 0; - } if (!cJSON_IsArray(json_array)) { return 0; } - if (max_size == 0) { - return 0; - } + size_t i = 0; const cJSON *elt; cJSON_ArrayForEach(elt, json_array) { - if (!cJSON_IsNumber(elt)) { + if (i >= max_size) { + break; + } + + if (!u_json_get_double(elt, &out_array[i])) { fprintf(stderr, "warning: u_json_get_double_array got a " "non-number in a numeric array"); return i; } - out_array[i] = elt->valuedouble; - ++i; - if (i == max_size) { - break; - } + + i++; } + return i; } diff --git a/src/xrt/auxiliary/util/u_json.h b/src/xrt/auxiliary/util/u_json.h index 11ae76be8..c63633be2 100644 --- a/src/xrt/auxiliary/util/u_json.h +++ b/src/xrt/auxiliary/util/u_json.h @@ -11,6 +11,7 @@ #pragma once #include "xrt/xrt_compiler.h" +#include "xrt/xrt_defines.h" #include "cjson/cJSON.h" @@ -19,6 +20,66 @@ extern "C" { #endif // __cplusplus + +/*! + * @brief Parse a string from a JSON object into a char array. + * + * @return true if successful, false if string does not fit in + * array or any other error. + */ +bool +u_json_get_string_into_array(const cJSON *json, char *out, size_t max_size); + +/*! + * @brief Parse an int from a JSON object. + * + * @return true if successful, false if not. + */ +bool +u_json_get_int(const cJSON *json, int *out_int); + +/*! + * @brief Parse a float from a JSON object. + * + * @return true if successful, false if not. + */ +bool +u_json_get_float(const cJSON *json, float *out_float); + +/*! + * @brief Parse a double from a JSON object. + * + * @return true if successful, false if not. + */ +bool +u_json_get_double(const cJSON *json, double *out_double); + +/*! + * @brief Parse a vec3 from a JSON object. + * + * @return true if successful, false if not. + */ +bool +u_json_get_vec3(const cJSON *json, struct xrt_vec3 *out_vec3); + +/*! + * @brief Parse a quaternion from a JSON object. + * + * @return true if successful, false if not. + */ +bool +u_json_get_quat(const cJSON *json, struct xrt_quat *out_quat); + +/*! + * @brief Parse up to max_size floats from a JSON array. + * + * @return the number of elements set. + */ +size_t +u_json_get_float_array(const cJSON *json_array, + float *out_array, + size_t max_size); + /*! * @brief Parse up to max_size doubles from a JSON array. * @@ -28,6 +89,8 @@ size_t u_json_get_double_array(const cJSON *json_array, double *out_array, size_t max_size); + + #ifdef __cplusplus } // extern "C" #endif // __cplusplus