Objectively
Ultra-lightweight object oriented framework for GNU C.
Loading...
Searching...
No Matches
JSONContext.c
Go to the documentation of this file.
1/*
2 * Objectively: Ultra-lightweight object oriented framework for GNU C.
3 * Copyright (C) 2014 Jay Dolan <jay@jaydolan.com>
4 *
5 * This software is provided 'as-is', without any express or implied
6 * warranty. In no event will the authors be held liable for any damages
7 * arising from the use of this software.
8 *
9 * Permission is granted to anyone to use this software for any purpose,
10 * including commercial applications, and to alter it and redistribute it
11 * freely, subject to the following restrictions:
12 *
13 * 1. The origin of this software must not be misrepresented; you must not
14 * claim that you wrote the original software. If you use this software
15 * in a product, an acknowledgment in the product documentation would be
16 * appreciated but is not required.
17 *
18 * 2. Altered source versions must be plainly marked as such, and must not be
19 * misrepresented as being the original software.
20 *
21 * 3. This notice may not be removed or altered from any source distribution.
22 */
23
24#include <assert.h>
25#include <stddef.h>
26#include <stdint.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30
31#include "Boole.h"
32#include "JSONContext.h"
33#include "Array.h"
34#include "Data.h"
35#include "Dictionary.h"
36#include "Null.h"
37#include "Number.h"
38#include "String.h"
39
40#define _Class _JSONContext
41
42#pragma mark - Object
43
47static void dealloc(Object *self) {
48
49 JSONContext *this = (JSONContext *) self;
50
51 release(this->errors);
52
53 super(Object, self, dealloc);
54}
55
56#pragma mark - Writer
57
65static void addError(JSONContext *self, int code, const char *key, const char *description) {
66
67 if (!self) {
68 return;
69 }
70
71 if (!self->errors) {
72 self->errors = $(alloc(Array), init);
73 }
74
75 String *domain = $$(String, stringWithCharacters, "JSONContext");
76 String *message;
77 if (key) {
78 message = $(alloc(String), initWithFormat, "%s: %s", key, description);
79 } else {
81 }
82
83 Error *error = $(alloc(Error), initWithDomain, domain, code, message);
84 $(self->errors, addObject, error);
85
86 release(domain);
87 release(message);
89}
90
94typedef struct {
97 size_t depth;
99
100static void writeElement(JSONWriter *writer, const ident obj);
101
105static void writeNull(JSONWriter *writer, const Null *null) {
106
107 $(writer->data, appendBytes, (uint8_t *) "null", 4);
108}
109
113static void writeBoole(JSONWriter *writer, const Boole *boolean) {
114
115 if (boolean->value) {
116 $(writer->data, appendBytes, (uint8_t *) "true", 4);
117 } else {
118 $(writer->data, appendBytes, (uint8_t *) "false", 5);
119 }
120}
121
125static void writeString(JSONWriter *writer, const String *string) {
126
127 $(writer->data, appendBytes, (uint8_t *) "\"", 1);
128
129 const char *s = string->chars;
130 const char *end = s + string->length;
131 while (s < end) {
132 const unsigned char c = (unsigned char) *s++;
133 switch (c) {
134 case '"': $(writer->data, appendBytes, (uint8_t *) "\\\"", 2); break;
135 case '\\': $(writer->data, appendBytes, (uint8_t *) "\\\\", 2); break;
136 case '\b': $(writer->data, appendBytes, (uint8_t *) "\\b", 2); break;
137 case '\f': $(writer->data, appendBytes, (uint8_t *) "\\f", 2); break;
138 case '\n': $(writer->data, appendBytes, (uint8_t *) "\\n", 2); break;
139 case '\r': $(writer->data, appendBytes, (uint8_t *) "\\r", 2); break;
140 case '\t': $(writer->data, appendBytes, (uint8_t *) "\\t", 2); break;
141 default:
142 if (c < 0x20) {
143 char seq[7];
144 snprintf(seq, sizeof(seq), "\\u%04x", c);
145 $(writer->data, appendBytes, (uint8_t *) seq, 6);
146 } else {
147 $(writer->data, appendBytes, (uint8_t *) &c, 1);
148 }
149 break;
150 }
151 }
152
153 $(writer->data, appendBytes, (uint8_t *) "\"", 1);
154}
155
159static void writeNumber(JSONWriter *writer, const Number *number) {
160
161 // Use enough significant digits to preserve 32-bit epoch seconds and other
162 // large integers exactly when round-tripping through JSON.
163 String *string = $(alloc(String), initWithFormat, "%.17g", number->value);
164 $(writer->data, appendBytes, (uint8_t *) string->chars, string->length);
165 release(string);
166}
167
171static void writeLabel(JSONWriter *writer, const String *label) {
172
173 writeString(writer, label);
174 $(writer->data, appendBytes, (uint8_t *) ": ", 2);
175}
176
180static void writePretty(JSONWriter *writer) {
181
182 if (writer->options & JSON_WRITE_PRETTY) {
183 $(writer->data, appendBytes, (uint8_t *) "\n", 1);
184 for (size_t i = 0; i < writer->depth; i++) {
185 $(writer->data, appendBytes, (uint8_t *) " ", 2);
186 }
187 }
188}
189
193static void writeObject(JSONWriter *writer, const Dictionary *object) {
194
195 $(writer->data, appendBytes, (uint8_t *) "{", 1);
196 writer->depth++;
197
198 Array *keys = $(object, allKeys);
199 if (writer->options & JSON_WRITE_SORTED) {
200 Array *sorted = $(keys, sortedArray, StringCompare);
201 release(keys);
202 keys = sorted;
203 }
204
205 for (size_t i = 0; i < keys->count; i++) {
206
207 writePretty(writer);
208
209 const ident key = $(keys, objectAtIndex, i);
210 writeLabel(writer, (String *) key);
211
212 const ident obj = $(object, objectForKey, key);
213 writeElement(writer, obj);
214
215 if (i < keys->count - 1) {
216 $(writer->data, appendBytes, (uint8_t *) ",", 1);
217 }
218 }
219
220 release(keys);
221
222 writer->depth--;
223 writePretty(writer);
224
225 $(writer->data, appendBytes, (uint8_t *) "}", 1);
226}
227
231static void writeArray(JSONWriter *writer, const Array *array) {
232
233 $(writer->data, appendBytes, (uint8_t *) "[", 1);
234 writer->depth++;
235
236 for (size_t i = 0; i < array->count; i++) {
237
238 writePretty(writer);
239 writeElement(writer, $(array, objectAtIndex, i));
240
241 if (i < array->count - 1) {
242 $(writer->data, appendBytes, (uint8_t *) ",", 1);
243 }
244 }
245
246 writer->depth--;
247 writePretty(writer);
248
249 $(writer->data, appendBytes, (uint8_t *) "]", 1);
250}
251
255static void writeElement(JSONWriter *writer, const ident obj) {
256
257 const Object *object = cast(Object, obj);
258 if (object) {
259 if ($(object, isKindOfClass, _Dictionary())) {
260 writeObject(writer, (const Dictionary *) object);
261 } else if ($(object, isKindOfClass, _Array())) {
262 writeArray(writer, (const Array *) object);
263 } else if ($(object, isKindOfClass, _String())) {
264 writeString(writer, (const String *) object);
265 } else if ($(object, isKindOfClass, _Number())) {
266 writeNumber(writer, (const Number *) object);
267 } else if ($(object, isKindOfClass, _Boole())) {
268 writeBoole(writer, (const Boole *) object);
269 } else if ($(object, isKindOfClass, _Null())) {
270 writeNull(writer, (const Null *) object);
271 }
272 }
273}
274
275#pragma mark - Reader
276
280typedef struct {
281 const Data *data;
283 uint8_t *b;
284 bool error;
285} JSONReader;
286
287static ident readElement(JSONReader *reader);
288
293static int readByte(JSONReader *reader) {
294
295 if (reader->b) {
296 if (reader->b - reader->data->bytes < reader->data->length) {
297 return (int) *(++(reader->b));
298 }
299 } else {
300 if (reader->data->bytes) {
301 return (int) *(reader->b = reader->data->bytes);
302 }
303 }
304
305 return -1;
306}
307
312static int readByteUntil(JSONReader *reader, const char *stop) {
313
314 int b;
315
316 while (true) {
317 b = readByte(reader);
318 if (b == -1 || strchr(stop, b)) {
319 break;
320 }
321 }
322
323 return b;
324}
325
330static bool consumeBytes(JSONReader *reader, const char *bytes) {
331
332 for (size_t i = 1; i < strlen(bytes); i++) {
333 const int b = readByte(reader);
334 if (b != bytes[i]) {
335 reader->error = true;
336 return false;
337 }
338 }
339
340 return true;
341}
342
346static String *readString(JSONReader *reader) {
347
348 Data *buf = $(alloc(Data), init);
349
350 while (true) {
351 int b = readByte(reader);
352 if (b == -1 || b == '"') {
353 break;
354 }
355 if (b == '\\') {
356 b = readByte(reader);
357 switch (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;
366 case 'u': {
367 char hex[5] = {0};
368 for (int i = 0; i < 4; i++) {
369 int h = readByte(reader);
370 if (h == -1) {
371 reader->error = true;
372 release(buf);
373 return NULL;
374 }
375 hex[i] = (char) h;
376 }
377 unsigned long cp = strtoul(hex, NULL, 16);
378 if (cp < 0x80) {
379 uint8_t byte = (uint8_t) cp;
380 $(buf, appendBytes, &byte, 1);
381 } else if (cp < 0x800) {
382 uint8_t bytes[2] = {
383 (uint8_t) (0xC0 | (cp >> 6)),
384 (uint8_t) (0x80 | (cp & 0x3F))
385 };
386 $(buf, appendBytes, bytes, 2);
387 } else {
388 uint8_t bytes[3] = {
389 (uint8_t) (0xE0 | (cp >> 12)),
390 (uint8_t) (0x80 | ((cp >> 6) & 0x3F)),
391 (uint8_t) (0x80 | (cp & 0x3F))
392 };
393 $(buf, appendBytes, bytes, 3);
394 }
395 continue;
396 }
397 default:
398 reader->error = true;
399 release(buf);
400 return NULL;
401 }
402 }
403 uint8_t byte = (uint8_t) b;
404 $(buf, appendBytes, &byte, 1);
405 }
406
407 String *string = $$(String, stringWithBytes, buf->bytes, buf->length, STRING_ENCODING_UTF8);
408 release(buf);
409 return string;
410}
411
415static Number *readNumber(JSONReader *reader) {
416
417 uint8_t *bytes = reader->b;
418
419 uint8_t *end;
420 const double d = strtod((char *) bytes, (char **) &end);
421
422 if (end <= bytes) {
423 reader->error = true;
424 return NULL;
425 }
426
427 reader->b = end - 1;
428 return $$(Number, numberWithValue, d);
429}
430
434static Boole *readBoole(JSONReader *reader) {
435
436 Boole *boolean = NULL;
437
438 switch (*reader->b) {
439 case 't':
440 if (!consumeBytes(reader, "true")) {
441 return NULL;
442 }
443 boolean = $$(Boole, True);
444 break;
445 case 'f':
446 if (!consumeBytes(reader, "false")) {
447 return NULL;
448 }
449 boolean = $$(Boole, False);
450 break;
451 default:
452 reader->error = true;
453 return NULL;
454 }
455
456 return retain(boolean);
457}
458
462static Null *readNull(JSONReader *reader) {
463
464 if (!consumeBytes(reader, "null")) {
465 return NULL;
466 }
467
468 return retain($$(Null, null));
469}
470
474static String *readLabel(JSONReader *reader) {
475
476 const int b = readByteUntil(reader, "\"}");
477 if (b == '"') {
478 return readString(reader);
479 }
480 if (b == '}') {
481 reader->b--;
482 }
483
484 return NULL;
485}
486
491
492 Dictionary *object = $(alloc(Dictionary), init);
493
494 while (true) {
495
496 String *key = readLabel(reader);
497 if (key == NULL) {
498 const int b = readByteUntil(reader, "}");
499 if (b != '}') {
500 reader->error = true;
501 }
502 break;
503 }
504
505 const int b = readByteUntil(reader, ":");
506 if (b != ':') {
507 release(key);
508 reader->error = true;
509 break;
510 }
511
512 ident obj = readElement(reader);
513 if (!obj) {
514 release(key);
515 reader->error = true;
516 break;
517 }
518
519 $(object, setObjectForKey, obj, key);
520
521 release(key);
522 release(obj);
523 }
524
525 return (Dictionary *) object;
526}
527
531static Array *readArray(JSONReader *reader) {
532
533 Array *array = $(alloc(Array), init);
534
535 while (true) {
536
537 Object *obj = readElement(reader);
538 if (obj == NULL) {
539 const int b = readByteUntil(reader, "]");
540 if (b != ']') {
541 reader->error = true;
542 }
543 break;
544 }
545
546 $(array, addObject, obj);
547 release(obj);
548 }
549
550 return (Array *) array;
551}
552
556static ident readElement(JSONReader *reader) {
557
558 const int b = readByteUntil(reader, "{[\"tfn0123456789.-]}");
559 if (b == '{') {
560 return readObject(reader);
561 } else if (b == '[') {
562 return readArray(reader);
563 } else if (b == '"') {
564 return readString(reader);
565 } else if (b == 't' || b == 'f') {
566 return readBoole(reader);
567 } else if (b == 'n') {
568 return readNull(reader);
569 } else if (b == '.' || b == '-' || isdigit(b)) {
570 return readNumber(reader);
571 } else if (b == ']' || b == '}') {
572 reader->b--;
573 }
574
575 return NULL;
576}
577
578#pragma mark - JSONContext
579
584static Data *dataFromObject(JSONContext *self, const ident obj, int options) {
585
586 (void) self;
587
588 if (obj) {
589 JSONWriter writer = {
590 .data = $(alloc(Data), init),
591 .options = options
592 };
593
594 writeElement(&writer, obj);
595
596 return (Data *) writer.data;
597 }
598
599 return NULL;
600}
601
606static Data *dataFromStruct(JSONContext *self, const JSONProperties *properties, const ident instance) {
607
608 Dictionary *dict = $(self, dictionaryFromStruct, properties, instance);
609 Data *data = dataFromObject(self, dict, 0);
610 release(dict);
611 return data;
612}
613
618static Data *dataFromStructs(JSONContext *self, const JSONProperties *properties, const ident instances, size_t count) {
619
620 if (!count) {
621 return NULL;
622 }
623
624 Array *array = $(alloc(Array), init);
625
626 for (size_t i = 0; i < count; i++) {
627 const ident instance = instances + i * properties->size;
628 Dictionary *dict = $(self, dictionaryFromStruct, properties, instance);
629 $(array, addObject, dict);
630 release(dict);
631 }
632
633 Data *data = dataFromObject(self, array, 0);
634 release(array);
635 return data;
636}
637
641static Dictionary *dictionaryFromStruct(JSONContext *self, const JSONProperties *properties, const ident instance) {
642
643 if (!properties || !instance) {
644 return NULL;
645 }
646
647 Dictionary *dict = $(alloc(Dictionary), init);
648
649 for (const JSONProperty *p = properties->properties; p->key; p++) {
650 if (!p->serializer) {
651 continue;
652 }
653
654 const ident field = instance + p->offset;
655 ident val = p->serializer(properties, p, field, p->data, self);
656
657 if (val) {
658 String *key = $$(String, stringWithCharacters, p->key);
659 $(dict, setObjectForKey, val, key);
660 release(key);
661 release(val);
662 }
663 }
664
665 return (Dictionary *) dict;
666}
667
672 return (JSONContext *) super(Object, self, init);
673}
674
679static ident objectFromData(JSONContext *self, const Data *data, int options) {
680
681 if (data && data->length) {
682 JSONReader reader = {
683 .data = data,
684 .options = options
685 };
686
687 ident obj = readElement(&reader);
688
689 if (reader.error) {
690 addError(self, 1, NULL, "JSON parse error");
691 release(obj);
692 return NULL;
693 }
694
695 return obj;
696 }
697
698 return NULL;
699}
700
704static bool structFromDictionary(JSONContext *self, const JSONProperties *properties, const Dictionary *dictionary, ident instance) {
705
706 if (!properties || !dictionary || !instance) {
707 return false;
708 }
709
710 bool ok = true;
711
712 for (const JSONProperty *p = properties->properties; p->key; p++) {
713 if (!p->deserializer) {
714 continue;
715 }
716
717 String *key = $$(String, stringWithCharacters, p->key);
718 const Object *val = $(dictionary, objectForKey, key);
719 release(key);
720
721 if (!val) {
722 continue;
723 }
724
725 if (!p->deserializer(properties, p, val, instance + p->offset, self)) {
726 addError(self, 2, p->key, "type mismatch");
727 ok = false;
728 }
729 }
730
731 return ok;
732}
733
737static size_t structsFromArray(JSONContext *self, const JSONProperties *properties, const Array *array, ident instances, size_t count) {
738
739 if (!properties || !array || !instances || !count) {
740 return 0;
741 }
742
743 const size_t n = min(array->count, count);
744
745 for (size_t i = 0; i < n; i++) {
747 $(self, structFromDictionary, properties, dictionary, instances + i * properties->size);
748 }
749
750 return n;
751}
752
757static bool structFromData(JSONContext *self, const JSONProperties *properties, const Data *data, ident instance) {
758
759 ident obj = $(self, objectFromData, data, 0);
760 if (!obj || !$((Object *) obj, isKindOfClass, _Dictionary())) {
761 release(obj);
762 return false;
763 }
764
765 const bool ok = structFromDictionary(self, properties, (Dictionary *) obj, instance);
766
767 release(obj);
768 return ok;
769}
770
775static size_t structsFromData(JSONContext *self, const JSONProperties *properties, const Data *data, ident instances, size_t count) {
776
777 ident obj = objectFromData(self, data, 0);
778 if (!obj || !$((Object *) obj, isKindOfClass, _Array())) {
779 release(obj);
780 return 0;
781 }
782
783 const size_t n = structsFromArray(self, properties, (Array *) obj, instances, count);
784
785 release(obj);
786 return n;
787}
788
789#pragma mark - Class lifecycle
790
794static void destroy(Class *clazz) {
795 (void) clazz;
796}
797
801static void initialize(Class *clazz) {
802
803 ((ObjectInterface *) clazz->interface)->dealloc = dealloc;
804
805 ((JSONContextInterface *) clazz->interface)->dataFromObject = dataFromObject;
806 ((JSONContextInterface *) clazz->interface)->dataFromStruct = dataFromStruct;
807 ((JSONContextInterface *) clazz->interface)->dataFromStructs = dataFromStructs;
808 ((JSONContextInterface *) clazz->interface)->dictionaryFromStruct = dictionaryFromStruct;
809 ((JSONContextInterface *) clazz->interface)->init = init;
810 ((JSONContextInterface *) clazz->interface)->objectFromData = objectFromData;
811 ((JSONContextInterface *) clazz->interface)->structFromData = structFromData;
812 ((JSONContextInterface *) clazz->interface)->structsFromData = structsFromData;
813 ((JSONContextInterface *) clazz->interface)->structFromDictionary = structFromDictionary;
814 ((JSONContextInterface *) clazz->interface)->structsFromArray = structsFromArray;
815}
816
822 static Class *clazz;
823 static Once once;
824
825 do_once(&once, {
826 clazz = _initialize(&(const ClassDef) {
827 .name = "JSONContext",
828 .superclass = _Object(),
829 .instanceSize = sizeof(JSONContext),
830 .interfaceOffset = offsetof(JSONContext, interface),
831 .interfaceSize = sizeof(JSONContextInterface),
833 .destroy = destroy,
834 });
835 });
836
837 return clazz;
838}
839
840#undef _Class
Class * _Array(void)
Definition Array.c:760
static ident objectAtIndex(const Array *self, size_t index)
Definition Array.c:578
static Array * sortedArray(const Array *self, Comparator comparator)
Definition Array.c:694
static String * description(const Object *self)
Definition Array.c:115
static void addObject(Array *self, const ident obj)
Definition Array.c:181
static Array * array(void)
Definition Array.c:234
Arrays.
static Boole * True(void)
Definition Boole.c:77
Class * _Boole(void)
Definition Boole.c:125
static Boole * False(void)
Definition Boole.c:59
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,...
Definition Class.c:195
Class * _initialize(const ClassDef *def)
Initializes the given Class.
Definition Class.c:86
ident retain(ident obj)
Atomically increment the given Object's reference count.
Definition Class.c:210
#define obj
#define alloc(type)
Allocate and initialize and instance of type.
Definition Class.h:176
#define cast(type, obj)
Safely cast obj to type.
Definition Class.h:182
#define super(type, obj, method,...)
static Data * data(void)
Definition Data.c:286
static void appendBytes(Data *self, const uint8_t *bytes, size_t length)
Definition Data.c:262
Data buffers.
static DateFormatter * initWithFormat(DateFormatter *self, const char *fmt)
static void setObjectForKey(Dictionary *self, const ident obj, const ident key)
Definition Dictionary.c:634
Class * _Dictionary(void)
Definition Dictionary.c:762
static Dictionary * dictionary(void)
Definition Dictionary.c:242
static Array * allKeys(const Dictionary *self)
Definition Dictionary.c:193
static ident objectForKey(const Dictionary *self, const ident key)
Definition Dictionary.c:439
Key-value stores.
static Error * initWithDomain(Error *self, String *domain, int code, String *message)
Definition Error.c:128
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.
Definition JSONContext.c:65
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)
Definition JSONContext.c:47
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.
Definition JSONContext.h:52
@ JSON_WRITE_SORTED
Enables lexicographic sorting of JSON object keys.
Definition JSONContext.h:57
static void error(const Log *self, const char *fmt,...)
Definition Log.c:80
static Null * null(void)
Definition Null.c:48
Class * _Null(void)
Definition Null.c:83
The Null sentinel.
static Number * numberWithValue(double value)
Definition Number.c:159
Class * _Number(void)
Definition Number.c:198
A wrapper for placing numeric primitives into collections, etc.
static bool isKindOfClass(const Object *self, const Class *clazz)
Definition Object.c:101
Class * _Object(void)
Definition Object.c:136
static int options(RESTClient *self, const char *url, Data **data)
Definition RESTClient.c:217
static String * string(void)
Definition String.c:905
static String * stringWithCharacters(const char *chars)
Definition String.c:349
Class * _String(void)
Definition String.c:999
Order StringCompare(const ident a, const ident b)
Definition String.c:1066
static String * stringWithBytes(const uint8_t *bytes, size_t length, StringEncoding encoding)
Definition String.c:340
UTF-8 strings.
@ STRING_ENCODING_UTF8
Definition String.h:53
void * ident
The identity type, similar to Objective-C id.
Definition Types.h:49
#define min(a, b)
Definition Types.h:159
long Once
The Once type.
Definition Once.h:37
#define do_once(once, block)
Executes the given block at most one time.
Definition Once.h:43
Arrays.
Definition Array.h:56
size_t count
The count of elements.
Definition Array.h:72
A wrapper for placing boolean primitives into collections, etc.
Definition Boole.h:41
bool value
The backing bool.
Definition Boole.h:57
ClassDefs are passed to _initialize via an archetype to initialize a Class.
Definition Class.h:41
The runtime representation of a Class.
Definition Class.h:95
ident interface
The interface of the Class.
Definition Class.h:105
Data buffers.
Definition Data.h:50
size_t length
The length of bytes.
Definition Data.h:76
uint8_t * bytes
The bytes.
Definition Data.h:66
Key-value stores.
Definition Dictionary.h:60
Dictionary * init(Dictionary *self)
Initializes this Dictionary.
Definition Dictionary.c:350
Encapsulation for error conditions.
Definition Error.h:41
A context for JSON serialization and deserialization.
Definition JSONContext.h:72
Array * errors
Errors accumulated during the operation.
Definition JSONContext.h:89
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.
uint8_t * b
const Data * data
Internal state for JSON text generation.
Definition JSONContext.c:94
Data * data
Definition JSONContext.c:95
size_t depth
Definition JSONContext.c:97
The Null sentinel.
Definition Null.h:42
A wrapper for placing numeric primitives into collections, etc.
Definition Number.h:41
double value
The backing value.
Definition Number.h:57
Object is the root Class of The Objectively Class hierarchy.
Definition Object.h:46
UTF-8 strings.
Definition String.h:69
char * chars
The backing null-terminated UTF-8 encoded character array.
Definition String.h:85
size_t length
The length of the String in bytes.
Definition String.h:90