cmkl/fall-2025/sen-210/Executables/JobWizard/console_example/json.h

164 lines
5.3 KiB
C

#pragma once
#include <stddef.h>
#ifndef __cplusplus
typedef unsigned int bool;
#define true (1)
#define false (0)
#endif
#define typed(name) name##_t
typedef const char *typed(json_string);
typedef bool typed(json_boolean);
typedef union json_number_value_u typed(json_number_value);
typedef signed long typed(json_number_long);
typedef double typed(json_number_double);
typedef struct json_number_s typed(json_number);
typedef union json_element_value_u typed(json_element_value);
typedef struct json_element_s typed(json_element);
typedef struct json_entry_s typed(json_entry);
typedef struct json_object_s typed(json_object);
typedef struct json_array_s typed(json_array);
#define result(name) name##_result_t
#define result_ok(name) name##_result_ok
#define result_err(name) name##_result_err
#define result_is_ok(name) name##_result_is_ok
#define result_is_err(name) name##_result_is_err
#define result_unwrap(name) name##_result_unwrap
#define result_unwrap_err(name) name##_result_unwrap_err
#define result_map_err(outer_name, inner_name, value) \
result_err(outer_name)(result_unwrap_err(inner_name)(value))
#define result_try(outer_name, inner_name, lvalue, rvalue) \
result(inner_name) lvalue##_result = rvalue; \
if (result_is_err(inner_name)(&lvalue##_result)) \
return result_map_err(outer_name, inner_name, &lvalue##_result); \
const typed(inner_name) lvalue = result_unwrap(inner_name)(&lvalue##_result);
#define declare_result_type(name) \
typedef struct name##_result_s { \
typed(json_boolean) is_ok; \
union { \
typed(name) value; \
typed(json_error) err; \
} inner; \
} result(name); \
result(name) result_ok(name)(typed(name)); \
result(name) result_err(name)(typed(json_error)); \
typed(json_boolean) result_is_ok(name)(result(name) *); \
typed(json_boolean) result_is_err(name)(result(name) *); \
typed(name) result_unwrap(name)(result(name) *); \
typed(json_error) result_unwrap_err(name)(result(name) *);
typedef enum json_element_type_e {
JSON_ELEMENT_TYPE_STRING = 0,
JSON_ELEMENT_TYPE_NUMBER,
JSON_ELEMENT_TYPE_OBJECT,
JSON_ELEMENT_TYPE_ARRAY,
JSON_ELEMENT_TYPE_BOOLEAN,
JSON_ELEMENT_TYPE_NULL
} typed(json_element_type);
typedef enum json_number_type_e {
JSON_NUMBER_TYPE_LONG = 0,
JSON_NUMBER_TYPE_DOUBLE,
} typed(json_number_type);
union json_number_value_u {
typed(json_number_long) as_long;
typed(json_number_double) as_double;
};
struct json_number_s {
typed(json_number_type) type;
typed(json_number_value) value;
};
union json_element_value_u {
typed(json_string) as_string;
typed(json_number) as_number;
typed(json_object) * as_object;
typed(json_array) * as_array;
typed(json_boolean) as_boolean;
};
struct json_element_s {
typed(json_element_type) type;
typed(json_element_value) value;
};
struct json_entry_s {
typed(json_string) key;
typed(json_element) element;
};
struct json_object_s {
typed(size) count;
typed(json_entry) * *entries;
};
struct json_array_s {
typed(size) count;
typed(json_element) * elements;
};
typedef enum json_error_e {
JSON_ERROR_EMPTY = 0,
JSON_ERROR_INVALID_TYPE,
JSON_ERROR_INVALID_KEY,
JSON_ERROR_INVALID_VALUE
} typed(json_error);
declare_result_type(json_element_type)
declare_result_type(json_element_value)
declare_result_type(json_element)
declare_result_type(json_entry)
declare_result_type(json_string)
declare_result_type(size)
/**
* @brief Parses a JSON string into a JSON element {json_element_t}
* with a fallible `result` type
*
* @param json_str The raw JSON string
* @return The parsed {json_element_t} wrapped in a `result` type
*/
result(json_element) json_parse(typed(json_string) json_str);
/**
* @brief Tries to get the element by key. If not found, returns
* a {JSON_ERROR_INVALID_KEY} error
*
* @param object The object to find the key in
* @param key The key of the element to be found
* @return Either a {json_element_t} or {json_error_t}
*/
result(json_element)
json_object_find(typed(json_object) * object, typed(json_string) key);
/**
* @brief Prints a JSON element {json_element_t} with proper
* indentation
*
* @param indent The number of spaces to indent each level by
*/
void json_print(typed(json_element) * element, int indent);
/**
* @brief Frees a JSON element {json_element_t} from memory
*
* @param element The JSON element {json_element_t} to free
*/
void json_free(typed(json_element) * element);
/**
* @brief Returns a string representation of JSON error {json_error_t} type
*
* @param error The JSON error enum {json_error_t} type
* @return The string representation
*/
typed(json_string) json_error_to_string(typed(json_error) error);