/** * @file json_helpers.c * @brief Implements the json helpers subsystem. */ #include #include #include #include #include #include #include #include akerr_ErrorContext *akgl_get_json_object_value(json_t *obj, char *key, json_t **dest) { PREPARE_ERROR(errctx); FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL object pointer"); json_t *value = json_object_get(obj, key); FAIL_ZERO_RETURN(errctx, value, AKERR_KEY, "Key %s not found in object", key); FAIL_ZERO_RETURN(errctx, (json_is_object(value)), AKERR_TYPE, "Key %s in object has incorrect type", key); *dest = value; SUCCEED_RETURN(errctx); } akerr_ErrorContext *akgl_get_json_boolean_value(json_t *obj, char *key, bool *dest) { PREPARE_ERROR(errctx); FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL object pointer"); json_t *value = json_object_get(obj, key); FAIL_ZERO_RETURN(errctx, value, AKERR_KEY, "Key %s not found in object", key); FAIL_ZERO_RETURN(errctx, (json_is_boolean(value)), AKERR_TYPE, "Key %s in object has incorrect type", key); *dest = json_boolean_value(value); SUCCEED_RETURN(errctx); } akerr_ErrorContext *akgl_get_json_integer_value(json_t *obj, char *key, int *dest) { PREPARE_ERROR(errctx); FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL object pointer"); json_t *value = json_object_get(obj, key); FAIL_ZERO_RETURN(errctx, value, AKERR_KEY, "Key %s not found in object", key); FAIL_ZERO_RETURN(errctx, (json_is_integer(value)), AKERR_TYPE, "Key %s in object has incorrect type", key); *dest = json_integer_value(value); SUCCEED_RETURN(errctx); } akerr_ErrorContext *akgl_get_json_number_value(json_t *obj, char *key, float *dest) { PREPARE_ERROR(errctx); FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL pointer reference"); json_t *value = json_object_get(obj, key); FAIL_ZERO_RETURN(errctx, value, AKERR_KEY, "Key %s not found in object", key); FAIL_ZERO_RETURN(errctx, (json_is_number(value)), AKERR_TYPE, "Key %s in object has incorrect type", key); *dest = json_number_value(value); SUCCEED_RETURN(errctx); } akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_double_value(json_t *obj, char *key, double *dest) { PREPARE_ERROR(errctx); FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL pointer reference"); json_t *value = json_object_get(obj, key); FAIL_ZERO_RETURN(errctx, value, AKERR_KEY, "Key %s not found in object", key); FAIL_ZERO_RETURN(errctx, (json_is_number(value)), AKERR_TYPE, "Key %s in object has incorrect type", key); *dest = json_number_value(value); SUCCEED_RETURN(errctx); } akerr_ErrorContext *akgl_get_json_string_value(json_t *obj, char *key, akgl_String **dest) { json_t *value = NULL; PREPARE_ERROR(errctx); FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL pointer reference"); FAIL_ZERO_RETURN(errctx, key, AKERR_NULLPOINTER, "NULL pointer reference"); FAIL_ZERO_RETURN(errctx, dest, AKERR_NULLPOINTER, "NULL pointer reference"); value = json_object_get(obj, key); FAIL_ZERO_RETURN(errctx, value, AKERR_KEY, "Key %s not found in object", key); FAIL_ZERO_RETURN(errctx, (json_is_string(value)), AKERR_TYPE, "Key %s in object has incorrect type", key); ATTEMPT { if ( *dest == NULL ) { CATCH(errctx, akgl_heap_next_string(dest)); CATCH(errctx, akgl_string_initialize(*dest, NULL)); } } CLEANUP { } PROCESS(errctx) { } FINISH(errctx, false); strncpy((char *)&(*dest)->data, json_string_value(value), AKGL_MAX_STRING_LENGTH); SUCCEED_RETURN(errctx); } akerr_ErrorContext *akgl_get_json_array_value(json_t *obj, char *key, json_t **dest) { PREPARE_ERROR(errctx); FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL pointer reference"); json_t *value = json_object_get(obj, key); FAIL_ZERO_RETURN(errctx, value, AKERR_KEY, "Key %s not found in object", key); FAIL_ZERO_RETURN(errctx, (json_is_array(value)), AKERR_TYPE, "Key %s in object has incorrect type", key); *dest = value; SUCCEED_RETURN(errctx); } akerr_ErrorContext *akgl_get_json_array_index_object(json_t *array, int index, json_t **dest) { PREPARE_ERROR(errctx); FAIL_ZERO_RETURN(errctx, array, AKERR_NULLPOINTER, "NULL pointer reference"); json_t *value = json_array_get(array, index); FAIL_ZERO_RETURN(errctx, value, AKERR_OUTOFBOUNDS, "Index %d out of bounds for array", index); FAIL_ZERO_RETURN(errctx, (json_is_object(value)), AKERR_TYPE, "Index %d in object has incorrect type", index); *dest = value; SUCCEED_RETURN(errctx); } akerr_ErrorContext *akgl_get_json_array_index_integer(json_t *array, int index, int *dest) { PREPARE_ERROR(errctx); FAIL_ZERO_RETURN(errctx, array, AKERR_NULLPOINTER, "NULL pointer reference"); json_t *value = json_array_get(array, index); FAIL_ZERO_RETURN(errctx, value, AKERR_OUTOFBOUNDS, "Index %d out of bounds for array", index); FAIL_ZERO_RETURN(errctx, (json_is_integer(value)), AKERR_TYPE, "Index %d in object has incorrect type", index); *dest = json_integer_value(value); SUCCEED_RETURN(errctx); } akerr_ErrorContext *akgl_get_json_array_index_string(json_t *array, int index, akgl_String **dest) { PREPARE_ERROR(errctx); FAIL_ZERO_RETURN(errctx, array, AKERR_NULLPOINTER, "NULL pointer reference"); FAIL_ZERO_RETURN(errctx, dest, AKERR_NULLPOINTER, "NULL destination pointer reference"); json_t *value = json_array_get(array, index); FAIL_ZERO_RETURN(errctx, value, AKERR_OUTOFBOUNDS, "Index %d out of bounds for array", index); FAIL_ZERO_RETURN(errctx, (json_is_string(value)), AKERR_TYPE, "Index %d in object has incorrect type", index); ATTEMPT { if ( *dest == NULL ) { CATCH(errctx, akgl_heap_next_string(dest)); CATCH(errctx, akgl_string_initialize(*dest, NULL)); } } CLEANUP { } PROCESS(errctx) { } FINISH(errctx, false); strncpy((char *)&(*dest)->data, json_string_value(value), AKGL_MAX_STRING_LENGTH); SUCCEED_RETURN(errctx); } akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_with_default(akerr_ErrorContext *err, void *defval, void *dest, uint32_t defsize) { PREPARE_ERROR(e); if ( err == NULL ) { SUCCEED_RETURN(e); } int docopy = 0; FAIL_ZERO_RETURN(e, err, AKERR_NULLPOINTER, "err"); FAIL_ZERO_RETURN(e, defval, AKERR_NULLPOINTER, "defval"); FAIL_ZERO_RETURN(e, dest, AKERR_NULLPOINTER, "dest"); ATTEMPT { } CLEANUP { } PROCESS(err) { } HANDLE_GROUP(err, AKERR_KEY) { } HANDLE_GROUP(err, AKERR_INDEX) { memcpy(dest, defval, defsize); } FINISH(err, true); SUCCEED_RETURN(e); }