mirror of
https://git.telodendria.io/Telodendria/Cytoplasm.git
synced 2025-04-25 10:26:03 +00:00
Move headers from src/include
to include/Cytoplasm
.
This makes it easier to build Cytoplasm as a component of another program (for example, Telodendria), or as a standalone system library.
This commit is contained in:
parent
cd7df7bbb4
commit
461357b526
27 changed files with 1 additions and 1 deletions
332
include/Cytoplasm/Json.h
Normal file
332
include/Cytoplasm/Json.h
Normal file
|
@ -0,0 +1,332 @@
|
|||
/*
|
||||
* Copyright (C) 2022-2024 Jordan Bancino <@jordan:bancino.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CYTOPLASM_JSON_H
|
||||
#define CYTOPLASM_JSON_H
|
||||
|
||||
/***
|
||||
* @Nm Json
|
||||
* @Nd A fully-featured JSON API.
|
||||
* @Dd March 12 2023
|
||||
* @Xr HashMap Array Stream
|
||||
*
|
||||
* .Nm
|
||||
* is a fully-featured JSON API for C using the array and hash map
|
||||
* APIs. It can parse JSON, ans serialize an in-memory structure to
|
||||
* JSON. It build on the foundation of Array and HashMap because that's
|
||||
* all JSON really is, just arrays and maps.
|
||||
* .Nm
|
||||
* also provides a structure for encapsulating an arbitrary value and
|
||||
* identifying its type, making it easy for a strictly-typed language
|
||||
* like C to work with loosely-typed JSON data.
|
||||
* .Nm
|
||||
* is very strict and tries to adhere as closely as possible to the
|
||||
* proper definition of JSON. It will fail on syntax errors of any
|
||||
* kind, which is fine for a Matrix homeserver that can just return
|
||||
* M_BAD_JSON if anything in here fails, but this behavior 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. Of course, you can use the
|
||||
* POSIX
|
||||
* .Xr fmemopen 3
|
||||
* and
|
||||
* .Xr open_memstream 3
|
||||
* functions if you want to deal with JSON strings, but JSON is
|
||||
* intended to be an exchange format. Data should be converted to JSON
|
||||
* right when it is leaving the program, and converted from JSON to the
|
||||
* in-memory format as soon as it is coming in.
|
||||
* .Pp
|
||||
* JSON 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 first encoding it as a JsonValue will result in undefined
|
||||
* behavior.
|
||||
*/
|
||||
|
||||
#include "HashMap.h"
|
||||
#include "Array.h"
|
||||
#include "Stream.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define JSON_DEFAULT -1
|
||||
#define JSON_PRETTY 0
|
||||
|
||||
/**
|
||||
* This opaque structure encapsulates all the possible types that can
|
||||
* be stored in JSON. It is managed entirely by the functions defined
|
||||
* in this API. It is important to note that strings, integers, floats,
|
||||
* booleans, and the NULL value are all stored by value, but objects
|
||||
* and arrays are stored by reference. That is, it doesn't store these
|
||||
* itself, just pointers to them, however, the data
|
||||
* .Em is
|
||||
* freed when using
|
||||
* .Fn JsonFree .
|
||||
*/
|
||||
typedef struct JsonValue JsonValue;
|
||||
|
||||
/**
|
||||
* These are the types that can be used to identify a JsonValue
|
||||
* and act on it accordingly.
|
||||
*/
|
||||
typedef enum JsonType
|
||||
{
|
||||
JSON_NULL, /* Maps to a 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 an Int64 */
|
||||
JSON_FLOAT, /* Maps to a C double */
|
||||
JSON_BOOLEAN /* Maps to a C integer of either 0 or 1 */
|
||||
} JsonType;
|
||||
|
||||
/**
|
||||
* Determine the type of the specified JSON value.
|
||||
*/
|
||||
extern JsonType JsonValueType(JsonValue *);
|
||||
|
||||
/**
|
||||
* Encode a JSON object as a JSON value that can be added to another
|
||||
* object, or an array.
|
||||
*/
|
||||
extern JsonValue * JsonValueObject(HashMap *);
|
||||
|
||||
/**
|
||||
* Unwrap a JSON value that represents an object. This function will
|
||||
* return NULL if the value is not actually an object.
|
||||
*/
|
||||
extern HashMap * JsonValueAsObject(JsonValue *);
|
||||
|
||||
/**
|
||||
* Encode a JSON array as a JSON value that can be added to an object
|
||||
* or another array.
|
||||
*/
|
||||
extern JsonValue * JsonValueArray(Array *);
|
||||
|
||||
/**
|
||||
* Unwrap a JSON value that represents an array. This function will
|
||||
* return NULL if the value is not actually an array.
|
||||
*/
|
||||
extern Array * JsonValueAsArray(JsonValue *);
|
||||
|
||||
/**
|
||||
* Encode a C string as a JSON value that can be added to an object or
|
||||
* an array.
|
||||
*/
|
||||
extern JsonValue * JsonValueString(char *);
|
||||
|
||||
/**
|
||||
* Unwrap a JSON value that represents a string. This function will
|
||||
* return NULL if the value is not actually a string.
|
||||
*/
|
||||
extern char * JsonValueAsString(JsonValue *);
|
||||
|
||||
/**
|
||||
* Encode a number as a JSON value that can be added to an object or
|
||||
* an array.
|
||||
*/
|
||||
extern JsonValue * JsonValueInteger(uint64_t);
|
||||
|
||||
/**
|
||||
* Unwrap a JSON value that represents a number. This function will
|
||||
* return 0 if the value is not actually a number, which may be
|
||||
* misleading. Check the type of the value before making assumptions
|
||||
* about its value.
|
||||
*/
|
||||
extern uint64_t JsonValueAsInteger(JsonValue *);
|
||||
|
||||
/**
|
||||
* Encode a floating point number as a JSON value that can be added
|
||||
* to an object or an array.
|
||||
*/
|
||||
extern JsonValue * JsonValueFloat(double);
|
||||
|
||||
/**
|
||||
* Unwrap a JSON value that represents a floating point number. This
|
||||
* function will return 0 if the value is not actually a floating
|
||||
* point number, which may be misleading. Check the type of the value
|
||||
* before making assumptions about its type.
|
||||
*/
|
||||
extern double JsonValueAsFloat(JsonValue *);
|
||||
|
||||
/**
|
||||
* Encode a C integer according to the way C treats integers in boolean
|
||||
* expressions as a JSON value that can be added to an object or an
|
||||
* array.
|
||||
*/
|
||||
extern JsonValue * JsonValueBoolean(bool);
|
||||
|
||||
/**
|
||||
* Unwrap a JSON value that represents a boolean. This function will
|
||||
* return 0 if the value is not actually a boolean, which may be
|
||||
* misleading. Check the type of the value before making assumptions
|
||||
* about its type.
|
||||
*/
|
||||
extern bool JsonValueAsBoolean(JsonValue *);
|
||||
|
||||
/**
|
||||
* This is a special case that represents a JSON null. Because the
|
||||
* Array and HashMap APIs 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 be a placeholder for nothing,
|
||||
* this keeps the APIs clean.
|
||||
*/
|
||||
extern JsonValue * JsonValueNull(void);
|
||||
|
||||
/**
|
||||
* Free 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, including any strings attached to
|
||||
* this value.
|
||||
*/
|
||||
extern void JsonValueFree(JsonValue *);
|
||||
|
||||
/**
|
||||
* Recursively duplicate the given JSON value. This returns a new
|
||||
* JSON value that is completely identical to the specified value, but
|
||||
* in no way connected to it.
|
||||
*/
|
||||
extern JsonValue * JsonValueDuplicate(JsonValue *);
|
||||
|
||||
/**
|
||||
* Recursively duplicate the given JSON object. This returns a new
|
||||
* JSON object that is completely identical to the specified object,
|
||||
* but in no way connect to it.
|
||||
*/
|
||||
extern HashMap * JsonDuplicate(HashMap *);
|
||||
|
||||
/**
|
||||
* Recursively free a JSON object by iterating over all of its values
|
||||
* and freeing them using
|
||||
* .Fn JsonValueFree .
|
||||
*/
|
||||
extern void JsonFree(HashMap *);
|
||||
|
||||
/**
|
||||
* Encode the given string in such a way that it can be safely
|
||||
* 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 only provided via the public
|
||||
* .Nm
|
||||
* API so that it is accessible to custom JSON encoders, such as the
|
||||
* CanonicalJson encoder. This will typically be used for encoding
|
||||
* object keys; to encode values, just use
|
||||
* .Fn JsonEncodeValue .
|
||||
* .Pp
|
||||
* This function returns the number of bytes written to the stream,
|
||||
* or if the stream is NULL, the number of bytes that would have
|
||||
* been written.
|
||||
*/
|
||||
extern size_t JsonEncodeString(const char *, Stream *);
|
||||
|
||||
/**
|
||||
* Serialize a JSON value 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
|
||||
* The third parameter is an integer that represents the indent level
|
||||
* of the value to be printed, or a negative number if pretty-printing
|
||||
* should be disabled and JSON should be printed as minimized as
|
||||
* possible. To pretty-print a JSON object, set this to
|
||||
* .Va JSON_PRETTY .
|
||||
* To get minified output, set it to
|
||||
* .Va JSON_DEFAULT .
|
||||
* .Pp
|
||||
* This function returns the number of bytes written to the stream,
|
||||
* or if the stream is NULL, the number of bytes that would have
|
||||
* been written.
|
||||
*/
|
||||
extern size_t JsonEncodeValue(JsonValue *, Stream *, int);
|
||||
|
||||
/**
|
||||
* Encode a JSON object as it would appear in JSON output, writing it
|
||||
* to the given output stream. This function is recursive; it will
|
||||
* serialize everything accessible from the passed object. The third
|
||||
* parameter has the same behavior as described above.
|
||||
* .Pp
|
||||
* This function returns the number of bytes written to the stream,
|
||||
* or if the stream is NULL, the number of bytes that would have
|
||||
* been written.
|
||||
*/
|
||||
extern size_t JsonEncode(HashMap *, Stream *, int);
|
||||
|
||||
/**
|
||||
* Decode a JSON object from the given input stream and parse it into
|
||||
* a hash map of JSON values.
|
||||
*/
|
||||
extern HashMap * JsonDecode(Stream *);
|
||||
|
||||
/**
|
||||
* A convenience function that allows the caller to retrieve and
|
||||
* arbitrarily deep keys within a JSON object. It takes a root JSON
|
||||
* object, the number of levels deep to go, and then that number of
|
||||
* keys as a varargs list. All keys must have objects as values, with
|
||||
* the exception of the last one, which is the value that will be
|
||||
* returned. Otherwise, NULL indicates the specified path doas not
|
||||
* exist.
|
||||
*/
|
||||
extern JsonValue * JsonGet(HashMap *, size_t,...);
|
||||
|
||||
/**
|
||||
* A convenience function that allows the caller to set arbitrarily
|
||||
* deep keys within a JSON object. It takes a root JSON object, the
|
||||
* number of levels deep to go, and then that number of keys as a
|
||||
* varargs list. All keys must have object as values, with the
|
||||
* exception of the last one, which is the value that will be set.
|
||||
* The value currently at that key, if any, will be returned.
|
||||
* This function will create any intermediate objects as necessary to
|
||||
* set the proper key.
|
||||
*/
|
||||
extern JsonValue * JsonSet(HashMap *, JsonValue *, size_t,...);
|
||||
|
||||
/**
|
||||
* Recursively merge two JSON objects. The second object is merged
|
||||
* on top of the first; any keys present in the first object that are
|
||||
* also present in the second object are replaced with those in the
|
||||
* second object, and any keys present in the second object that are
|
||||
* not present in the first object are copied to the first object.
|
||||
*/
|
||||
extern void JsonMerge(HashMap *, HashMap *);
|
||||
|
||||
#endif /* CYTOPLASM_JSON_H */
|
Loading…
Add table
Add a link
Reference in a new issue