40#define _Class _JSONContext
115 if (boolean->
value) {
129 const char *s =
string->chars;
130 const char *end = s +
string->length;
132 const unsigned char c = (
unsigned char) *s++;
144 snprintf(seq,
sizeof(seq),
"\\u%04x", c);
184 for (
size_t i = 0; i < writer->
depth; i++) {
205 for (
size_t i = 0; i < keys->
count; i++) {
215 if (i < keys->count - 1) {
241 if (i < array->count - 1) {
297 return (
int) *(++(reader->
b));
301 return (
int) *(reader->
b = reader->
data->
bytes);
318 if (b == -1 || strchr(stop, b)) {
332 for (
size_t i = 1; i < strlen(bytes); i++) {
335 reader->
error =
true;
352 if (b == -1 || b ==
'"') {
358 case '"': b =
'"';
break;
359 case '\\': b =
'\\';
break;
360 case '/': b =
'/';
break;
361 case 'b': b =
'\b';
break;
362 case 'f': b =
'\f';
break;
363 case 'n': b =
'\n';
break;
364 case 'r': b =
'\r';
break;
365 case 't': b =
'\t';
break;
368 for (
int i = 0; i < 4; i++) {
371 reader->
error =
true;
377 unsigned long cp = strtoul(hex, NULL, 16);
379 uint8_t
byte = (uint8_t) cp;
381 }
else if (cp < 0x800) {
383 (uint8_t) (0xC0 | (cp >> 6)),
384 (uint8_t) (0x80 | (cp & 0x3F))
389 (uint8_t) (0xE0 | (cp >> 12)),
390 (uint8_t) (0x80 | ((cp >> 6) & 0x3F)),
391 (uint8_t) (0x80 | (cp & 0x3F))
398 reader->
error =
true;
403 uint8_t
byte = (uint8_t) b;
417 uint8_t *bytes = reader->
b;
420 const double d = strtod((
char *) bytes, (
char **) &end);
423 reader->
error =
true;
436 Boole *
boolean = NULL;
438 switch (*reader->
b) {
452 reader->
error =
true;
500 reader->
error =
true;
508 reader->
error =
true;
515 reader->
error =
true;
541 reader->
error =
true;
558 const int b =
readByteUntil(reader,
"{[\"tfn0123456789.-]}");
561 }
else if (b ==
'[') {
563 }
else if (b ==
'"') {
565 }
else if (b ==
't' || b ==
'f') {
567 }
else if (b ==
'n') {
569 }
else if (b ==
'.' || b ==
'-' || isdigit(b)) {
571 }
else if (b ==
']' || b ==
'}') {
578#pragma mark - JSONContext
626 for (
size_t i = 0; i < count; i++) {
627 const ident instance = instances + i * properties->
size;
643 if (!properties || !instance) {
650 if (!p->serializer) {
654 const ident field = instance + p->offset;
655 ident val = p->serializer(properties, p, field, p->data, self);
690 addError(self, 1, NULL,
"JSON parse error");
706 if (!properties || !
dictionary || !instance) {
713 if (!p->deserializer) {
725 if (!p->deserializer(properties, p, val, instance + p->offset, self)) {
726 addError(self, 2, p->key,
"type mismatch");
739 if (!properties || !
array || !instances || !count) {
745 for (
size_t i = 0; i < n; i++) {
789#pragma mark - Class lifecycle
827 .name =
"JSONContext",
830 .interfaceOffset = offsetof(
JSONContext, interface),
831 .interfaceSize =
sizeof(JSONContextInterface),
static ident objectAtIndex(const Array *self, size_t index)
static Array * sortedArray(const Array *self, Comparator comparator)
static String * description(const Object *self)
static void addObject(Array *self, const ident obj)
static Array * array(void)
static Boole * True(void)
static Boole * False(void)
A wrapper for placing boolean primitives into collections, etc.
ident release(ident obj)
Atomically decrement the given Object's reference count. If the resulting reference count is 0,...
Class * _initialize(const ClassDef *def)
Initializes the given Class.
ident retain(ident obj)
Atomically increment the given Object's reference count.
#define alloc(type)
Allocate and initialize and instance of type.
#define cast(type, obj)
Safely cast obj to type.
#define super(type, obj, method,...)
static void appendBytes(Data *self, const uint8_t *bytes, size_t length)
static void setObjectForKey(Dictionary *self, const ident obj, const ident key)
Class * _Dictionary(void)
static Dictionary * dictionary(void)
static Array * allKeys(const Dictionary *self)
static ident objectForKey(const Dictionary *self, const ident key)
static Error * initWithDomain(Error *self, String *domain, int code, String *message)
static ident readElement(JSONReader *reader)
Reads any JSON element from reader.
static void writeLabel(JSONWriter *writer, const String *label)
Writes a JSON object key label to writer.
static JSONContext * init(JSONContext *self)
static bool consumeBytes(JSONReader *reader, const char *bytes)
Consumes and validates a fixed byte sequence from reader.
static int readByte(JSONReader *reader)
Advances the reader by one byte.
static void destroy(Class *clazz)
static void writeNull(JSONWriter *writer, const Null *null)
Writes null to writer.
static Dictionary * dictionaryFromStruct(JSONContext *self, const JSONProperties *properties, const ident instance)
Serializes a C struct instance to a Dictionary.
static bool structFromData(JSONContext *self, const JSONProperties *properties, const Data *data, ident instance)
static void writeString(JSONWriter *writer, const String *string)
Writes a JSON-escaped string to writer.
static Data * dataFromStructs(JSONContext *self, const JSONProperties *properties, const ident instances, size_t count)
static void writePretty(JSONWriter *writer)
Writes pretty-print indentation to writer, if enabled.
static void writeNumber(JSONWriter *writer, const Number *number)
Writes a JSON number to writer.
static void writeBoole(JSONWriter *writer, const Boole *boolean)
Writes a JSON boolean to writer.
static Data * dataFromStruct(JSONContext *self, const JSONProperties *properties, const ident instance)
static int readByteUntil(JSONReader *reader, const char *stop)
Advances the reader until one of the bytes in stop is found.
static void addError(JSONContext *self, int code, const char *key, const char *description)
Records an error on the context.
static void writeArray(JSONWriter *writer, const Array *array)
Writes a JSON array to writer.
static size_t structsFromArray(JSONContext *self, const JSONProperties *properties, const Array *array, ident instances, size_t count)
Deserializes a JSON Array into an array of C structs.
static Dictionary * readObject(JSONReader *reader)
Reads a JSON object (Dictionary) from reader.
static void writeObject(JSONWriter *writer, const Dictionary *object)
Writes a JSON object (Dictionary) to writer.
static bool structFromDictionary(JSONContext *self, const JSONProperties *properties, const Dictionary *dictionary, ident instance)
Deserializes a Dictionary into a C struct.
static String * readString(JSONReader *reader)
Reads a JSON-escaped string from reader.
static Data * dataFromObject(JSONContext *self, const ident obj, int options)
static Boole * readBoole(JSONReader *reader)
Reads a JSON boolean from reader.
static Array * readArray(JSONReader *reader)
Reads a JSON array from reader.
static void dealloc(Object *self)
Class * _JSONContext(void)
static void initialize(Class *clazz)
static String * readLabel(JSONReader *reader)
Reads a JSON object key label from reader.
static ident objectFromData(JSONContext *self, const Data *data, int options)
static Number * readNumber(JSONReader *reader)
Reads a JSON number from reader.
static Null * readNull(JSONReader *reader)
Reads a JSON null from reader.
static size_t structsFromData(JSONContext *self, const JSONProperties *properties, const Data *data, ident instances, size_t count)
static void writeElement(JSONWriter *writer, const ident obj)
Writes any JSON element to writer.
JSONContext class for JSON serialization and deserialization.
@ JSON_WRITE_PRETTY
Enables pretty (indented) formatting of JSON output.
@ JSON_WRITE_SORTED
Enables lexicographic sorting of JSON object keys.
static void error(const Log *self, const char *fmt,...)
static Number * numberWithValue(double value)
A wrapper for placing numeric primitives into collections, etc.
static bool isKindOfClass(const Object *self, const Class *clazz)
static int options(RESTClient *self, const char *url, Data **data)
static String * string(void)
static String * stringWithCharacters(const char *chars)
Order StringCompare(const ident a, const ident b)
static String * stringWithBytes(const uint8_t *bytes, size_t length, StringEncoding encoding)
void * ident
The identity type, similar to Objective-C id.
#define do_once(once, block)
Executes the given block at most one time.
size_t count
The count of elements.
A wrapper for placing boolean primitives into collections, etc.
bool value
The backing bool.
ClassDefs are passed to _initialize via an archetype to initialize a Class.
The runtime representation of a Class.
ident interface
The interface of the Class.
size_t length
The length of bytes.
uint8_t * bytes
The bytes.
Dictionary * init(Dictionary *self)
Initializes this Dictionary.
Encapsulation for error conditions.
A context for JSON serialization and deserialization.
Array * errors
Errors accumulated during the operation.
ident objectFromData(JSONContext *self, const Data *data, int options)
Parses a JSON Data buffer into an Objectively object graph.
Describes the JSON binding for all fields of a C struct.
const JSONProperty * properties
The NULL-terminated JSONProperty array.
size_t size
The struct size, i.e. sizeof(Struct).
Describes the JSON binding strategy for a single field of a C struct.
Internal state for JSON text parsing.
Internal state for JSON text generation.
A wrapper for placing numeric primitives into collections, etc.
double value
The backing value.
Object is the root Class of The Objectively Class hierarchy.
char * chars
The backing null-terminated UTF-8 encoded character array.
size_t length
The length of the String in bytes.