add documentation - resolves #431

Sun, 15 Dec 2024 12:19:21 +0100

author
Mike Becker <universe@uap-core.de>
date
Sun, 15 Dec 2024 12:19:21 +0100
changeset 1012
21884374edbb
parent 1011
838b096c1d08
child 1013
add8358fc3c3

add documentation - resolves #431

src/cx/json.h file | annotate | diff | comparison | revisions
src/json.c file | annotate | diff | comparison | revisions
--- a/src/cx/json.h	Sun Dec 15 11:11:16 2024 +0100
+++ b/src/cx/json.h	Sun Dec 15 12:19:21 2024 +0100
@@ -46,92 +46,291 @@
 extern "C" {
 #endif
 
+
+/**
+ * The type of the parsed token.
+ */
 enum cx_json_token_type {
+    /**
+     * No complete token parsed, yet.
+     */
     CX_JSON_NO_TOKEN,
+    /**
+     * The presumed token contains syntactical errors.
+     */
     CX_JSON_TOKEN_ERROR,
+    /**
+     * A "begin of array" '[' token.
+     */
     CX_JSON_TOKEN_BEGIN_ARRAY,
+    /**
+     * A "begin of object" '{' token.
+     */
     CX_JSON_TOKEN_BEGIN_OBJECT,
+    /**
+     * An "end of array" ']' token.
+     */
     CX_JSON_TOKEN_END_ARRAY,
+    /**
+     * An "end of object" '}' token.
+     */
     CX_JSON_TOKEN_END_OBJECT,
+    /**
+     * A colon ':' token separating names and values.
+     */
     CX_JSON_TOKEN_NAME_SEPARATOR,
+    /**
+     * A comma ',' token separating object entries or array elements.
+     */
     CX_JSON_TOKEN_VALUE_SEPARATOR,
+    /**
+     * A string token.
+     */
     CX_JSON_TOKEN_STRING,
+    /**
+     * A number token that can be represented as integer.
+     */
     CX_JSON_TOKEN_INTEGER,
+    /**
+     * A number token that cannot be represented as integer.
+     */
     CX_JSON_TOKEN_NUMBER,
+    /**
+     * A literal token.
+     */
     CX_JSON_TOKEN_LITERAL,
+    /**
+     * A white-space token.
+     */
     CX_JSON_TOKEN_SPACE
 };
 
+/**
+ * The type of some JSON value.
+ */
 enum cx_json_value_type {
+    /**
+     * Reserved.
+     */
     CX_JSON_NOTHING, // this allows us to always return non-NULL values
+    /**
+     * A JSON object.
+     */
     CX_JSON_OBJECT,
+    /**
+     * A JSON array.
+     */
     CX_JSON_ARRAY,
+    /**
+     * A string.
+     */
     CX_JSON_STRING,
+    /**
+     * A number that contains an integer.
+     */
     CX_JSON_INTEGER,
+    /**
+     * A number, not necessarily an integer.
+     */
     CX_JSON_NUMBER,
+    /**
+     * A literal (true, false, null).
+     */
     CX_JSON_LITERAL
 };
 
+/**
+ * JSON literal types.
+ */
 enum cx_json_literal {
+    /**
+     * The \c null literal.
+     */
     CX_JSON_NULL,
+    /**
+     * The \c true literal.
+     */
     CX_JSON_TRUE,
+    /**
+     * The \c false literal.
+     */
     CX_JSON_FALSE
 };
 
+/**
+ * Type alias for the token type enum.
+ */
 typedef enum cx_json_token_type CxJsonTokenType;
+/**
+ * Type alias for the value type enum.
+ */
 typedef enum cx_json_value_type CxJsonValueType;
 
+/**
+ * Type alias for the JSON parser interface.
+ */
 typedef struct cx_json_s CxJson;
+
+/**
+ * Type alias for the token struct.
+ */
 typedef struct cx_json_token_s CxJsonToken;
 
+/**
+ * Type alias for the JSON value struct.
+ */
 typedef struct cx_json_value_s CxJsonValue;
 
+/**
+ * Type alias for the JSON array struct.
+ */
 typedef struct cx_json_array_s CxJsonArray;
+/**
+ * Type alias for the JSON object struct.
+ */
 typedef struct cx_json_object_s CxJsonObject;
+/**
+ * Type alias for a JSON string.
+ */
 typedef struct cx_mutstr_s CxJsonString;
+/**
+ * Type alias for a number that can be represented as 64-bit signed integer.
+ */
 typedef int64_t CxJsonInteger;
+/**
+ * Type alias for number that is not an integer.
+ */
 typedef double CxJsonNumber;
+/**
+ * Type alias for a JSON literal.
+ */
 typedef enum cx_json_literal CxJsonLiteral;
 
+/**
+ * Type alias for a key/value pair in a JSON object.
+ */
 typedef struct cx_json_obj_value_s CxJsonObjValue;
 
-
+/**
+ * JSON array structure.
+ */
 struct cx_json_array_s {
+    /**
+     * The array data.
+     */
     CX_ARRAY_DECLARE(CxJsonValue*, array);
 };
 
+/**
+ * JSON object structure.
+ */
 struct cx_json_object_s {
+    /**
+     * The key/value entries.
+     */
     CX_ARRAY_DECLARE(CxJsonObjValue, values);
 };
 
+/**
+ * Structure for a key/value entry in a JSON object.
+ */
 struct cx_json_obj_value_s {
+    /**
+     * The key a.k.a. name of the value.
+     */
     char *name;
+    /**
+     * The value.
+     */
     CxJsonValue *value;
 };
 
+/**
+ * Structure for a JSON value.
+ */
 struct cx_json_value_s {
+    /**
+     * The allocator with which the value was allocated.
+     *
+     * Required for recursively deallocating memory of objects and arrays.
+     */
     const CxAllocator *allocator;
+    /**
+     * The type of this value.
+     *
+     * Specifies how the \c value union shall be resolved.
+     */
     CxJsonValueType type;
+    /**
+     * The value data.
+     */
     union {
+        /**
+         * The array data if type is #CX_JSON_ARRAY.
+         */
         CxJsonArray array;
+        /**
+         * The object data if type is #CX_JSON_OBJECT.
+         */
         CxJsonObject object;
+        /**
+         * The string data if type is #CX_JSON_STRING.
+         */
         CxJsonString string;
+        /**
+         * The integer if type is #CX_JSON_INTEGER.
+         */
         CxJsonInteger integer;
+        /**
+         * The number if type is #CX_JSON_NUMBER.
+         */
         CxJsonNumber number;
+        /**
+         * The literal type if type is #CX_JSON_LITERAL.
+         */
         CxJsonLiteral literal;
     } value;
 };
 
+/**
+ * Structure for a parsed token.
+ */
 struct cx_json_token_s {
+    /**
+     * The token type.
+     */
     CxJsonTokenType tokentype;
+    /**
+     * True, iff the \c content must be passed to cx_strfree().
+     */
     bool allocated;
+    /**
+     * The token text, if any.
+     *
+     * This is not necessarily set when the token type already
+     * uniquely identifies the content.
+     */
     cxmutstr content;
 };
 
+/**
+ * The JSON parser interface.
+ */
 struct cx_json_s {
+    /**
+     * The allocator used for produced JSON values.
+     */
     const CxAllocator *allocator;
+    /**
+     * The input buffer.
+     */
     CxBuffer buffer;
 
+    /**
+     * Used internally.
+     *
+     * Remembers the prefix of the last uncompleted token.
+     */
     CxJsonToken uncompleted;
 
     /**
@@ -161,7 +360,9 @@
      */
     CxJsonValue* vbuf_internal[8];
 
-    int error; // TODO: currently unused
+    /**
+     * Used internally.
+     */
     bool tokenizer_escape; // TODO: check if it can be replaced with look-behind
 };
 
@@ -215,12 +416,36 @@
  */
 typedef enum cx_json_status CxJsonStatus;
 
+/**
+ * Initializes the json interface.
+ *
+ * @param json the json interface
+ * @param allocator the allocator that shall be used for the produced values
+ * @see cxJsonDestroy()
+ */
 cx_attr_nonnull_arg(1)
 void cxJsonInit(CxJson *json, const CxAllocator *allocator);
 
+/**
+ * Destroys the json interface.
+ *
+ * @param json the json interface
+ * @see cxJsonInit()
+ */
 cx_attr_nonnull
 void cxJsonDestroy(CxJson *json);
 
+/**
+ * Adds more data to the input buffer.
+ *
+ * The data will be copied.
+ *
+ * @param json the json interface
+ * @param buf the source buffer
+ * @param len the length of the source buffer
+ * @return zero on success, non-zero on internal allocation error
+ * @see cxJsonFill()
+ */
 cx_attr_nonnull
 cx_attr_access_r(2, 3)
 int cxJsonFilln(CxJson *json, const char *buf, size_t len);
@@ -228,6 +453,16 @@
 #ifdef __cplusplus
 } // extern "C"
 
+/**
+ * Adds more data to the input buffer.
+ *
+ * The data will be copied.
+ *
+ * @param json the json interface
+ * @param str the string to add to the buffer
+ * @return zero on success, non-zero on internal allocation error
+ * @see cxJsonFilln()
+ */
 cx_attr_nonnull
 static inline int cxJsonFill(
         CxJson *json,
@@ -236,6 +471,16 @@
     return cxJsonFilln(json, str.ptr, str.length);
 }
 
+/**
+ * Adds more data to the input buffer.
+ *
+ * The data will be copied.
+ *
+ * @param json the json interface
+ * @param str the string to add to the buffer
+ * @return zero on success, non-zero on internal allocation error
+ * @see cxJsonFilln()
+ */
 cx_attr_nonnull
 static inline int cxJsonFill(
         CxJson *json,
@@ -244,6 +489,16 @@
     return cxJsonFilln(json, str.ptr, str.length);
 }
 
+/**
+ * Adds more data to the input buffer.
+ *
+ * The data will be copied.
+ *
+ * @param json the json interface
+ * @param str the string to add to the buffer
+ * @return zero on success, non-zero on internal allocation error
+ * @see cxJsonFilln()
+ */
 cx_attr_nonnull
 cx_attr_cstr_arg(2)
 static inline int cxJsonFill(
@@ -255,6 +510,16 @@
 
 extern "C" {
 #else // __cplusplus
+/**
+ * Adds more data to the input buffer.
+ *
+ * The data will be copied.
+ *
+ * @param json the json interface
+ * @param str the string to add to the buffer
+ * @return zero on success, non-zero on internal allocation error
+ * @see cxJsonFilln()
+ */
 #define cxJsonFill(json, str) _Generic((str), \
     cxstring: cx_json_fill_cxstr,             \
     cxmutstr: cx_json_fill_mutstr,            \
@@ -262,6 +527,16 @@
     const char*: cx_json_fill_str)            \
     (json, str)
 
+/**
+ * Adds more data to the input buffer.
+ *
+ * Internal function - please use the #cxJsonFill() macro.
+ *
+ * @param json the json interface
+ * @param str the string to add to the buffer
+ * @return zero on success, non-zero on internal allocation error
+ * @see cxJsonFill()
+ */
 cx_attr_nonnull
 static inline int cx_json_fill_cxstr(
         CxJson *json,
@@ -270,6 +545,16 @@
     return cxJsonFilln(json, str.ptr, str.length);
 }
 
+/**
+ * Adds more data to the input buffer.
+ *
+ * Internal function - please use the #cxJsonFill() macro.
+ *
+ * @param json the json interface
+ * @param str the string to add to the buffer
+ * @return zero on success, non-zero on internal allocation error
+ * @see cxJsonFill()
+ */
 cx_attr_nonnull
 static inline int cx_json_fill_mutstr(
         CxJson *json,
@@ -278,6 +563,16 @@
     return cxJsonFilln(json, str.ptr, str.length);
 }
 
+/**
+ * Adds more data to the input buffer.
+ *
+ * Internal function - please use the #cxJsonFill() macro.
+ *
+ * @param json the json interface
+ * @param str the string to add to the buffer
+ * @return zero on success, non-zero on internal allocation error
+ * @see cxJsonFill()
+ */
 cx_attr_nonnull
 cx_attr_cstr_arg(2)
 static inline int cx_json_fill_str(
@@ -288,77 +583,216 @@
 }
 #endif
 
+/**
+ * Recursively deallocates the memory of a JSON value.
+ *
+ * \remark The type of each deallocated value will be changed
+ * to #CX_JSON_NOTHING and values of such type will be skipped
+ * by the de-allocation. That means, this function protects
+ * you from double-frees when you are accidentally freeing
+ * a nested value and then the parent value (or vice versa).
+ *
+ * @param value the value
+ */
 void cxJsonValueFree(CxJsonValue *value);
 
+/**
+ * Tries to obtain the next JSON value.
+ *
+ *
+ * @param json the json interface
+ * @param value a pointer where the next value shall be stored
+ * @return a status code
+ */
 cx_attr_nonnull
+cx_attr_access_w(2)
 CxJsonStatus cxJsonNext(CxJson *json, CxJsonValue **value);
 
+/**
+ * Checks if the specified value is a JSON object.
+ *
+ * @param value a pointer to the value
+ * @return true if the value is a JSON object, false otherwise
+ */
 cx_attr_nonnull
 static inline bool cxJsonIsObject(const CxJsonValue *value) {
     return value->type == CX_JSON_OBJECT;
 }
 
+/**
+ * Checks if the specified value is a JSON array.
+ *
+ * @param value a pointer to the value
+ * @return true if the value is a JSON array, false otherwise
+ */
 cx_attr_nonnull
 static inline bool cxJsonIsArray(const CxJsonValue *value) {
     return value->type == CX_JSON_ARRAY;
 }
 
+/**
+ * Checks if the specified value is a string.
+ *
+ * @param value a pointer to the value
+ * @return true if the value is a string, false otherwise
+ */
 cx_attr_nonnull
 static inline bool cxJsonIsString(const CxJsonValue *value) {
     return value->type == CX_JSON_STRING;
 }
 
+/**
+ * Checks if the specified value is a JSON number.
+ *
+ * This function will return true for both floating point and
+ * integer numbers.
+ *
+ * @param value a pointer to the value
+ * @return true if the value is a JSON number, false otherwise
+ * @see cxJsonIsInteger()
+ */
 cx_attr_nonnull
 static inline bool cxJsonIsNumber(const CxJsonValue *value) {
     return value->type == CX_JSON_NUMBER || value->type == CX_JSON_INTEGER;
 }
 
+/**
+ * Checks if the specified value is an integer number.
+ *
+ * @param value a pointer to the value
+ * @return true if the value is an integer number, false otherwise
+ * @see cxJsonIsNumber()
+ */
 cx_attr_nonnull
 static inline bool cxJsonIsInteger(const CxJsonValue *value) {
     return value->type == CX_JSON_INTEGER;
 }
 
+/**
+ * Checks if the specified value is a JSON literal.
+ *
+ * JSON literals are \c true, \c false, and \c null.
+ *
+ * @param value a pointer to the value
+ * @return true if the value is a JSON literal, false otherwise
+ * @see cxJsonIsTrue()
+ * @see cxJsonIsFalse()
+ * @see cxJsonIsNull()
+ */
 cx_attr_nonnull
 static inline bool cxJsonIsLiteral(const CxJsonValue *value) {
     return value->type == CX_JSON_LITERAL;
 }
 
+/**
+ * Checks if the specified value is a Boolean literal.
+ *
+ * @param value a pointer to the value
+ * @return true if the value is either \c true or \c false, false otherwise
+ * @see cxJsonIsTrue()
+ * @see cxJsonIsFalse()
+ */
 cx_attr_nonnull
 static inline bool cxJsonIsBool(const CxJsonValue *value) {
     return cxJsonIsLiteral(value) && value->value.literal != CX_JSON_NULL;
 }
 
+/**
+ * Checks if the specified value is \c true.
+ *
+ * \remark Be advised, that this is not the same as
+ * testing \c !cxJsonIsFalse(v).
+ *
+ * @param value a pointer to the value
+ * @return true if the value is \c true, false otherwise
+ * @see cxJsonIsBool()
+ * @see cxJsonIsFalse()
+ */
 cx_attr_nonnull
 static inline bool cxJsonIsTrue(const CxJsonValue *value) {
     return cxJsonIsLiteral(value) && value->value.literal == CX_JSON_TRUE;
 }
 
+/**
+ * Checks if the specified value is \c false.
+ *
+ * \remark Be advised, that this is not the same as
+ * testing \c !cxJsonIsTrue(v).
+ *
+ * @param value a pointer to the value
+ * @return true if the value is \c false, false otherwise
+ * @see cxJsonIsBool()
+ * @see cxJsonIsTrue()
+ */
 cx_attr_nonnull
 static inline bool cxJsonIsFalse(const CxJsonValue *value) {
     return cxJsonIsLiteral(value) && value->value.literal == CX_JSON_FALSE;
 }
 
+/**
+ * Checks if the specified value is \c null.
+ *
+ * @param value a pointer to the value
+ * @return true if the value is \c null, false otherwise
+ * @see cxJsonIsLiteral()
+ */
 cx_attr_nonnull
 static inline bool cxJsonIsNull(const CxJsonValue *value) {
     return cxJsonIsLiteral(value) && value->value.literal == CX_JSON_NULL;
 }
 
+/**
+ * Obtains a C string from the given JSON value.
+ *
+ * If the value is not a string, the behavior is undefined.
+ *
+ * @param value the JSON value
+ * @return the value represented as C string
+ * @see cxJsonIsString()
+ */
 cx_attr_nonnull
 cx_attr_returns_nonnull
 static inline char *cxJsonAsString(const CxJsonValue *value) {
     return value->value.string.ptr;
 }
 
+/**
+ * Obtains a UCX string from the given JSON value.
+ *
+ * If the value is not a string, the behavior is undefined.
+ *
+ * @param value the JSON value
+ * @return the value represented as UCX string
+ * @see cxJsonIsString()
+ */
 cx_attr_nonnull
 static inline cxstring cxJsonAsCxString(const CxJsonValue *value) {
     return cx_strcast(value->value.string);
 }
 
+/**
+ * Obtains a mutable UCX string from the given JSON value.
+ *
+ * If the value is not a string, the behavior is undefined.
+ *
+ * @param value the JSON value
+ * @return the value represented as mutable UCX string
+ * @see cxJsonIsString()
+ */
 cx_attr_nonnull
 static inline cxmutstr cxJsonAsCxMutStr(const CxJsonValue *value) {
     return value->value.string;
 }
 
+/**
+ * Obtains a double-precision floating point value from the given JSON value.
+ *
+ * If the value is not a JSON number, the behavior is undefined.
+ *
+ * @param value the JSON value
+ * @return the value represented as double
+ * @see cxJsonIsNumber()
+ */
 cx_attr_nonnull
 static inline double cxJsonAsDouble(const CxJsonValue *value) {
     if (value->type == CX_JSON_INTEGER) {
@@ -368,6 +802,18 @@
     }
 }
 
+/**
+ * Obtains a 64-bit signed integer from the given JSON value.
+ *
+ * If the value is not a JSON number, the behavior is undefined.
+ * If it is a JSON number, but not an integer, the value will be
+ * converted to an integer, possibly losing precision.
+ *
+ * @param value the JSON value
+ * @return the value represented as double
+ * @see cxJsonIsNumber()
+ * @see cxJsonIsInteger()
+ */
 cx_attr_nonnull
 static inline int64_t cxJsonAsInteger(const CxJsonValue *value) {
     if (value->type == CX_JSON_INTEGER) {
@@ -377,23 +823,67 @@
     }
 }
 
+/**
+ * Obtains a Boolean value from the given JSON value.
+ *
+ * If the value is not a JSON literal, the behavior is undefined.
+ * The \c null literal is interpreted as \c false.
+ *
+ * @param value the JSON value
+ * @return the value represented as double
+ * @see cxJsonIsLiteral()
+ */
 cx_attr_nonnull
 static inline bool cxJsonAsBool(const CxJsonValue *value) {
     return value->value.literal == CX_JSON_TRUE;
 }
 
+/**
+ * Returns the size of a JSON array.
+ *
+ * If the value is not a JSON array, the behavior is undefined.
+ *
+ * @param value the JSON value
+ * @return the size of the array
+ * @see cxJsonIsArray()
+ */
 cx_attr_nonnull
 static inline size_t cxJsonArrSize(const CxJsonValue *value) {
     return value->value.array.array_size;
 }
 
+/**
+ * Returns an element from a JSON array.
+ *
+ * If the value is not a JSON array, the behavior is undefined.
+ *
+ * This function guarantees to return a value. If the index is
+ * out of bounds, the returned value will be of type
+ * #CX_JSON_NOTHING, but never \c NULL.
+ *
+ * @param value the JSON value
+ * @param index the index in the array
+ * @return the value at the specified index
+ * @see cxJsonIsArray()
+ */
 cx_attr_nonnull
 cx_attr_returns_nonnull
 CxJsonValue *cxJsonArrGet(const CxJsonValue *value, size_t index);
 
-// TODO: add cxJsonArrIter()
-
-// TODO: implement cxJsonObjGet as a _Generic with support for cxstring
+/**
+ * Returns a value corresponding to a key in a JSON object.
+ *
+ * If the value is not a JSON object, the behavior is undefined.
+ *
+ * This function guarantees to return a JSON value. If the
+ * object does not contain \p name, the returned JSON value
+ * will be of type #CX_JSON_NOTHING, but never \c NULL.
+ *
+ * @param value the JSON object
+ * @param name the key to look up
+ * @return the value corresponding to the key
+ * @see cxJsonIsObject()
+ */
 cx_attr_nonnull
 cx_attr_returns_nonnull
 cx_attr_cstr_arg(2)
--- a/src/json.c	Sun Dec 15 11:11:16 2024 +0100
+++ b/src/json.c	Sun Dec 15 12:19:21 2024 +0100
@@ -633,8 +633,7 @@
 }
 
 void cxJsonValueFree(CxJsonValue *value) {
-    if (value == NULL || value == &cx_json_value_nothing) return;
-
+    if (value == NULL || value->type == CX_JSON_NOTHING) return;
     switch (value->type) {
         case CX_JSON_OBJECT: {
             CxJsonObject obj = value->value.object;

mercurial