diff --git a/TODO.txt b/TODO.txt index 3afe1ce..6ae1e11 100644 --- a/TODO.txt +++ b/TODO.txt @@ -35,7 +35,7 @@ Due: January 1, 2023 [x] HashMap [ ] Http [ ] HttpServer - [ ] Json + [x] Json [x] Log [ ] Matrix [x] Queue diff --git a/man/man3/Json.3 b/man/man3/Json.3 new file mode 100644 index 0000000..0f37c6e --- /dev/null +++ b/man/man3/Json.3 @@ -0,0 +1,228 @@ +.Dd $Mdocdate: November 30 2022 $ +.Dt JSON 3 +.Os Telodendria Project +.Sh NAME +.Nm Json +.Nd A fully-featured JSON API. +.Sh SYNOPSIS +.In Json.h +.Ft JsonType +.Fn JsonValueType "JsonValue *" +.Ft JsonValue * +.Fn JsonValueObject "HashMap *" +.Ft HashMap * +.Fn JsonValueAsObject "JsonValue *" +.Ft JsonValue * +.Fn JsonValueArray "Array *" +.Ft Array * +.Fn JsonValueAsArray " +.Ft JsonValue * +.Fn JsonValueString "char *" +.Ft char * +.Fn JsonValueAsString "JsonValue *" +.Ft JsonValue * +.Fn JsonValueInteger "long" +.Ft long +.Fn JsonValueAsInteger "JsonValue *" +.Ft JsonValue * +.Fn JsonValueFloat "double" +.Ft double +.Fn JsonValueAsFloat "JsonValue *" +.Ft JsonValue * +.Fn JsonValueBoolean "int" +.Ft int +.Fn JsonValueAsBoolean "JsonValue *" +.Ft JsonValue * +.Fn JsonValueNull "void" +.Ft void +.Fn JsonValueFree "JsonValue *" +.Ft void +.Fn JsonFree "HashMap *" +.Ft void +.Fn JsonEncodeString "const char *" "FILE *" +.Ft void +.Fn JsonEncodeValue "JsonValue *" "FILE *" +.Ft int +.Fn JsonEncode "HashMap *" "FILE *" +.Ft HashMap * +.Fn JsonDecode "FILE *" +.Sh DESCRIPTION +.Nm +is a fully-featured JSON API for C using +.Xr Array 3 +and +.Xr HashMap 3 +that can parse JSON, and serialize an in-memory structure +to JSON. +It builds on the foundation set up by those APIs because +that's all JSON really is, just maps and arrays. +.Nm +also provides a structure for encapsulating an arbitrary +value and identifying its type, making it easy for a program +to work with JSON data. +.Nm +is very strict and tries to adhere as closely as possible to +the proper defintion of JSON. It will fail on syntax errors +of any kind, which is fine for a Matrix homeserver because we can +just return M_BAD_JSON if anything here fails, but it may not +be suitable for other purposes. +.Pp +This JSON implementation focuses primarily on serialization and +deserialization to and from streams. It does not provide facilities +for handling JSON strings; it only writes JSON to output streams, and +reads them from input streams. If course, you can use the POSIX +.Xr fmemopen 3 +and +.Xr open_memstream 3 +if you want to deal with JSON strings, but JSON is intended to be an +exchange format. Data should be converted to JSON right before it is +leaving the program, and converted from JSON as soon as it is coming +in. +.Pp +The +.Nm +header defines the following enumeration for identifying types of +values: +.Bd -literal -offset indent +typedef enum JsonType +{ + JSON_NULL, /* Maps to C NULL */ + JSON_OBJECT, /* Maps to a HashMap of JsonValues */ + JSON_ARRAY, /* Maps to an Array of JsonValues */ + JSON_STRING, /* Maps to a NULL-terminated C string */ + JSON_INTEGER, /* Maps to a C long */ + JSON_FLOAT, /* Maps to a C double */ + JSON_BOOLEAN /* Maps to a C boolean, 1 or 0 */ +} JsonType; +.Ed +.Pp +A JsonValue encapsulates all the possible types that can be stored in +JSON. It is an opaque structure that can be managed entirely by the +functions defined in this API. It is important to note that in the case +of objects, arrays, and strings, this structure only stores pointers to +the allocated data, it doesn't store the data itself, but the data IS +freed when using +.Fn JsonFree . +.Pp +Objects are represented as hash maps consisting entirely of JsonValue +structures, and arrays are represented as arrays consisting entirely +of JsonValue structures. When generating a JSON object, any +attempt to stuff a value into a hash map or array without encoding it +as a JsonValue first will result in undefined behavior. +.Pp +.Fn JsonValueType +determines the type of a given JsonValue. +.Pp +The +.Fn JsonValue* +functions wrap their input in a JsonValue that represents the given +value. The +.Fn JsonValueAs* +functions do the opposite; they unwrap a JsonValue and return the +actual usable value itself. They all closely resemble each other and +they all behave the same way, so to save on time and effort, they're +not explicitly documented individually. If something is unclear about +how these functions work, consult the source code, and feel free +to write the documentation yourself for clarification. Otherwise, +reach out to the official Matrix rooms, and someone should be able +to help you. +.Pp +.Fn JsonValueNull +is a special case that represents a JSON null. Because +.Xr Array 3 +and +.Xr HashMap 3 +do not accept NULL values, this function should be used to represent +NULL in JSON. Even though a small amount of memory is allocated just +to point to NULL, this keeps the APIs clean. +.Pp +.Fn JsonValueFree +frees the memory being used by a JSON value. Note that this will +recursively free all Arrays, HashMaps, and other JsonValues that +are reachable from the given value. It also invokes +.Fn Free +(documented in +.Xr Memory ) +on all strings, so make sure passed string pointers point to strings +on the heap, not the stack. This will be the case for all strings +returned by +.Fn JsonDecode , +but if you are manually creating JSON objects and stitching them +together, you should be aware that calling this function on a value +that contains a pointer to a stack string will result in undefined +behavior. +.Pp +.Fn JsonFree +recursively frees a JSON object, iterating over all the values and +freeing them using +.Fn JsonValueFree . +.Pp +.Fn JsonEncodeString +encodes the given string in such a way that it can be embedded in a +JSON stream. This entails: +.Bl -bullet -offset indent +.It +Escaping quotes, backslashes, and other special characters using +their backslash escape. +.It +Encoding bytes that are not UTF-8 using escapes. +.It +Wrapping the entire string in double quotes. +.El +.Pp +This function is provided via the public +.Nm +API so that it is accessible to custom JSON encoders, such as +.Xr CanonicalJson 3 . +This will typically be used for encoding JSON keys; for encoding +values, just use +.Fn JsonEncodeValue . +.Pp +.Fn JsonEncodeValue +serializes a JsonValue as it would appear in JSON output. This is +a recursive function that also encodes all child values reachable +from the given value. This function is exposed via the public +.Nm +API so that it is accessible to custom JSON encoders. Normal users +that are not writing custom encoders should in most cases just use +.Fn JsonEncode +to encode an entire object. +.Pp +.Fn JsonEncode +encodes a JSON object as minimized JSON and writes it to the given +output stream. This function is recursive; it will serialize +everything accessible from the passed object. +.Fn JsonDecode +does the opposite; it reads from a JSON stream and decodes it +into a hash map of JsonValues. +.Sh RETURN VALUES +.Pp +.Fn JsonValueType +returns a JsonType, documented above, that tells what the given +value actually is, or JSON_NULL if the passed value is NULL. +Note that even a fully valid JsonValue may actually be of type +JSON_NULL, so this function should not be used to determine +whether or not a given value is valid. +.Pp +The +.Fn JsonValue* +functions return a JsonValue that holds a pointer to the passed +value, or NULL if there was an error allocating memory. The +.Fn JsonValueAs* +functions return the actual value represented by the given +JsonValue so that it can be manipulated by the program, or +NULL if no value was provided, or the value is not of the +correct type expected by the function. +.Pp +.Fn JsonEncode +returns whether or not the encoding operation was successful. +This function will fail if any passed parameters are NULL, +otherwise it will assume all pointers are valid and return a +success value. +.Pp +.Fn JsonDecode +returns a hash map of JsonValues that can be manipulated by +this API, or NULL if there was an error parsing the JSON. +.Sh SEE ALSO +.Xr HashMap 3 , +.Xr Array 3 diff --git a/site/index.html b/site/index.html index 82ae7a3..820a655 100644 --- a/site/index.html +++ b/site/index.html @@ -229,6 +229,12 @@ cache. Smart memory management API. + +Json(3) + +A feature-complete API for reading and writing JSON. + +

Resources