FreeWRL / FreeX3D 4.3.0
cson_amalgamation_core.c
1/* auto-generated! Do not edit! */
2#include "cson_amalgamation_core.h"
3/* begin file parser/JSON_parser.h */
4/* See JSON_parser.c for copyright information and licensing. */
5
6#ifndef JSON_PARSER_H
7#define JSON_PARSER_H
8
9/* JSON_parser.h */
10
11
12#include <stddef.h>
13
14/* Windows DLL stuff */
15#ifdef JSON_PARSER_DLL
16# ifdef _MSC_VER
17# ifdef JSON_PARSER_DLL_EXPORTS
18# define JSON_PARSER_DLL_API __declspec(dllexport)
19# else
20# define JSON_PARSER_DLL_API __declspec(dllimport)
21# endif
22# else
23# define JSON_PARSER_DLL_API
24# endif
25#else
26# define JSON_PARSER_DLL_API
27#endif
28
29/* Determine the integer type use to parse non-floating point numbers */
30#ifdef _WIN32
31typedef __int64 JSON_int_t;
32#define JSON_PARSER_INTEGER_SSCANF_TOKEN "%I64d"
33#define JSON_PARSER_INTEGER_SPRINTF_TOKEN "%I64d"
34#elif (__STDC_VERSION__ >= 199901L) || (HAVE_LONG_LONG == 1)
35typedef long long JSON_int_t;
36#define JSON_PARSER_INTEGER_SSCANF_TOKEN "%lld"
37#define JSON_PARSER_INTEGER_SPRINTF_TOKEN "%lld"
38#else
39typedef long JSON_int_t;
40#define JSON_PARSER_INTEGER_SSCANF_TOKEN "%ld"
41#define JSON_PARSER_INTEGER_SPRINTF_TOKEN "%ld"
42#endif
43
44
45#ifdef __cplusplus
46extern "C" {
47#endif
48
49typedef enum
50{
51 JSON_E_NONE = 0,
52 JSON_E_INVALID_CHAR,
53 JSON_E_INVALID_KEYWORD,
54 JSON_E_INVALID_ESCAPE_SEQUENCE,
55 JSON_E_INVALID_UNICODE_SEQUENCE,
56 JSON_E_INVALID_NUMBER,
57 JSON_E_NESTING_DEPTH_REACHED,
58 JSON_E_UNBALANCED_COLLECTION,
59 JSON_E_EXPECTED_KEY,
60 JSON_E_EXPECTED_COLON,
61 JSON_E_OUT_OF_MEMORY
62} JSON_error;
63
64typedef enum
65{
66 JSON_T_NONE = 0,
67 JSON_T_ARRAY_BEGIN,
68 JSON_T_ARRAY_END,
69 JSON_T_OBJECT_BEGIN,
70 JSON_T_OBJECT_END,
71 JSON_T_INTEGER,
72 JSON_T_FLOAT,
73 JSON_T_NULL,
74 JSON_T_TRUE,
75 JSON_T_FALSE,
76 JSON_T_STRING,
77 JSON_T_KEY,
78 JSON_T_MAX
79} JSON_type;
80
81typedef struct JSON_value_struct {
82 union {
83 JSON_int_t integer_value;
84
85 double float_value;
86
87 struct {
88 const char* value;
89 size_t length;
90 } str;
91 } vu;
93
94typedef struct JSON_parser_struct* JSON_parser;
95
107typedef int (*JSON_parser_callback)(void* ctx, int type, const JSON_value* value);
108
109
113typedef void* (*JSON_malloc_t)(size_t n);
117typedef void (*JSON_free_t)(void* mem);
118
121typedef struct {
126 JSON_parser_callback callback;
136 int depth;
155 JSON_malloc_t malloc;
165 JSON_free_t free;
167
178JSON_PARSER_DLL_API void init_JSON_config(JSON_config * config);
179
190JSON_PARSER_DLL_API JSON_parser new_JSON_parser(JSON_config const* config);
191
193JSON_PARSER_DLL_API void delete_JSON_parser(JSON_parser jc);
194
199JSON_PARSER_DLL_API int JSON_parser_char(JSON_parser jc, int next_char);
200
207JSON_PARSER_DLL_API int JSON_parser_done(JSON_parser jc);
208
213JSON_PARSER_DLL_API int JSON_parser_is_legal_white_space_string(const char* s);
214
219JSON_PARSER_DLL_API int JSON_parser_get_last_error(JSON_parser jc);
220
225JSON_PARSER_DLL_API int JSON_parser_reset(JSON_parser jc);
226
227
228#ifdef __cplusplus
229}
230#endif
231
232
233#endif /* JSON_PARSER_H */
234/* end file parser/JSON_parser.h */
235/* begin file parser/JSON_parser.c */
236/*
237Copyright (c) 2007-2013 Jean Gressmann (jean@0x42.de)
238
239Permission is hereby granted, free of charge, to any person obtaining a copy
240of this software and associated documentation files (the "Software"), to deal
241in the Software without restriction, including without limitation the rights
242to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
243copies of the Software, and to permit persons to whom the Software is
244furnished to do so, subject to the following conditions:
245
246The above copyright notice and this permission notice shall be included in all
247copies or substantial portions of the Software.
248
249THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
250IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
251FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
252AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
253LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
254OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
255SOFTWARE.
256*/
257
258/*
259 Changelog:
260 2013-09-08
261 Updated license to to be compatible with Debian license requirements.
262
263 2012-06-06
264 Fix for invalid UTF16 characters and some comment fixex (thomas.h.moog@intel.com).
265
266 2010-11-25
267 Support for custom memory allocation (sgbeal@googlemail.com).
268
269 2010-05-07
270 Added error handling for memory allocation failure (sgbeal@googlemail.com).
271 Added diagnosis errors for invalid JSON.
272
273 2010-03-25
274 Fixed buffer overrun in grow_parse_buffer & cleaned up code.
275
276 2009-10-19
277 Replaced long double in JSON_value_struct with double after reports
278 of strtold being broken on some platforms (charles@transmissionbt.com).
279
280 2009-05-17
281 Incorporated benrudiak@googlemail.com fix for UTF16 decoding.
282
283 2009-05-14
284 Fixed float parsing bug related to a locale being set that didn't
285 use '.' as decimal point character (charles@transmissionbt.com).
286
287 2008-10-14
288 Renamed states.IN to states.IT to avoid name clash which IN macro
289 defined in windef.h (alexey.pelykh@gmail.com)
290
291 2008-07-19
292 Removed some duplicate code & debugging variable (charles@transmissionbt.com)
293
294 2008-05-28
295 Made JSON_value structure ansi C compliant. This bug was report by
296 trisk@acm.jhu.edu
297
298 2008-05-20
299 Fixed bug reported by charles@transmissionbt.com where the switching
300 from static to dynamic parse buffer did not copy the static parse
301 buffer's content.
302*/
303
304
305
306#include <assert.h>
307#include <ctype.h>
308#include <float.h>
309#include <stddef.h>
310#include <stdio.h>
311#include <stdlib.h>
312#include <string.h>
313#include <locale.h>
314
315
316#ifdef _MSC_VER
317# if _MSC_VER >= 1400 /* Visual Studio 2005 and up */
318# pragma warning(disable:4996) /* unsecure sscanf */
319# pragma warning(disable:4127) /* conditional expression is constant */
320# endif
321#endif
322
323
324#define true 1
325#define false 0
326#define __ -1 /* the universal error code */
327
328/* values chosen so that the object size is approx equal to one page (4K) */
329#ifndef JSON_PARSER_STACK_SIZE
330# define JSON_PARSER_STACK_SIZE 128
331#endif
332
333#ifndef JSON_PARSER_PARSE_BUFFER_SIZE
334# define JSON_PARSER_PARSE_BUFFER_SIZE 3500
335#endif
336
337typedef void* (*JSON_debug_malloc_t)(size_t bytes, const char* reason);
338
339#ifdef JSON_PARSER_DEBUG_MALLOC
340# define JSON_parser_malloc(func, bytes, reason) ((JSON_debug_malloc_t)func)(bytes, reason)
341#else
342# define JSON_parser_malloc(func, bytes, reason) func(bytes)
343#endif
344
345typedef unsigned short UTF16;
346
348 JSON_parser_callback callback;
349 void* ctx;
350 signed char state, before_comment_state, type, escaped, comment, allow_comments, handle_floats_manually, error;
351 char decimal_point;
352 UTF16 utf16_high_surrogate;
353 int current_char;
354 int depth;
355 int top;
356 int stack_capacity;
357 signed char* stack;
358 char* parse_buffer;
359 size_t parse_buffer_capacity;
360 size_t parse_buffer_count;
361 signed char static_stack[JSON_PARSER_STACK_SIZE];
362 char static_parse_buffer[JSON_PARSER_PARSE_BUFFER_SIZE];
363 JSON_malloc_t malloc;
364 JSON_free_t free;
365};
366
367#define COUNTOF(x) (sizeof(x)/sizeof(x[0]))
368
369/*
370 Characters are mapped into these character classes. This allows for
371 a significant reduction in the size of the state transition table.
372*/
373
374
375
376enum classes {
377 C_SPACE, /* space */
378 C_WHITE, /* other whitespace */
379 C_LCURB, /* { */
380 C_RCURB, /* } */
381 C_LSQRB, /* [ */
382 C_RSQRB, /* ] */
383 C_COLON, /* : */
384 C_COMMA, /* , */
385 C_QUOTE, /* " */
386 C_BACKS, /* \ */
387 C_SLASH, /* / */
388 C_PLUS, /* + */
389 C_MINUS, /* - */
390 C_POINT, /* . */
391 C_ZERO , /* 0 */
392 C_DIGIT, /* 123456789 */
393 C_LOW_A, /* a */
394 C_LOW_B, /* b */
395 C_LOW_C, /* c */
396 C_LOW_D, /* d */
397 C_LOW_E, /* e */
398 C_LOW_F, /* f */
399 C_LOW_L, /* l */
400 C_LOW_N, /* n */
401 C_LOW_R, /* r */
402 C_LOW_S, /* s */
403 C_LOW_T, /* t */
404 C_LOW_U, /* u */
405 C_ABCDF, /* ABCDF */
406 C_E, /* E */
407 C_ETC, /* everything else */
408 C_STAR, /* * */
409 NR_CLASSES
410};
411
412static const signed char ascii_class[128] = {
413/*
414 This array maps the 128 ASCII characters into character classes.
415 The remaining Unicode characters should be mapped to C_ETC.
416 Non-whitespace control characters are errors.
417*/
418 __, __, __, __, __, __, __, __,
419 __, C_WHITE, C_WHITE, __, __, C_WHITE, __, __,
420 __, __, __, __, __, __, __, __,
421 __, __, __, __, __, __, __, __,
422
423 C_SPACE, C_ETC, C_QUOTE, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC,
424 C_ETC, C_ETC, C_STAR, C_PLUS, C_COMMA, C_MINUS, C_POINT, C_SLASH,
425 C_ZERO, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT,
426 C_DIGIT, C_DIGIT, C_COLON, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC,
427
428 C_ETC, C_ABCDF, C_ABCDF, C_ABCDF, C_ABCDF, C_E, C_ABCDF, C_ETC,
429 C_ETC, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC,
430 C_ETC, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC, C_ETC,
431 C_ETC, C_ETC, C_ETC, C_LSQRB, C_BACKS, C_RSQRB, C_ETC, C_ETC,
432
433 C_ETC, C_LOW_A, C_LOW_B, C_LOW_C, C_LOW_D, C_LOW_E, C_LOW_F, C_ETC,
434 C_ETC, C_ETC, C_ETC, C_ETC, C_LOW_L, C_ETC, C_LOW_N, C_ETC,
435 C_ETC, C_ETC, C_LOW_R, C_LOW_S, C_LOW_T, C_LOW_U, C_ETC, C_ETC,
436 C_ETC, C_ETC, C_ETC, C_LCURB, C_ETC, C_RCURB, C_ETC, C_ETC
437};
438
439
440/*
441 The state codes.
442*/
443enum states {
444 GO, /* start */
445 OK, /* ok */
446 OB, /* object */
447 KE, /* key */
448 CO, /* colon */
449 VA, /* value */
450 AR, /* array */
451 ST, /* string */
452 ES, /* escape */
453 U1, /* u1 */
454 U2, /* u2 */
455 U3, /* u3 */
456 U4, /* u4 */
457 MI, /* minus */
458 ZE, /* zero */
459 IT, /* integer */
460 FR, /* fraction */
461 E1, /* e */
462 E2, /* ex */
463 E3, /* exp */
464 T1, /* tr */
465 T2, /* tru */
466 T3, /* true */
467 F1, /* fa */
468 F2, /* fal */
469 F3, /* fals */
470 F4, /* false */
471 N1, /* nu */
472 N2, /* nul */
473 N3, /* null */
474 C1, /* / */
475 C2, /* / * */
476 C3, /* * */
477 FX, /* *.* *eE* */
478 D1, /* second UTF-16 character decoding started by \ */
479 D2, /* second UTF-16 character proceeded by u */
480 NR_STATES
481};
482
483enum actions
484{
485 CB = -10, /* comment begin */
486 CE = -11, /* comment end */
487 FA = -12, /* false */
488 TR = -13, /* false */
489 NU = -14, /* null */
490 DE = -15, /* double detected by exponent e E */
491 DF = -16, /* double detected by fraction . */
492 SB = -17, /* string begin */
493 MX = -18, /* integer detected by minus */
494 ZX = -19, /* integer detected by zero */
495 IX = -20, /* integer detected by 1-9 */
496 EX = -21, /* next char is escaped */
497 UC = -22 /* Unicode character read */
498};
499
500
501static const signed char state_transition_table[NR_STATES][NR_CLASSES] = {
502/*
503 The state transition table takes the current state and the current symbol,
504 and returns either a new state or an action. An action is represented as a
505 negative number. A JSON text is accepted if at the end of the text the
506 state is OK and if the mode is MODE_DONE.
507
508 white 1-9 ABCDF etc
509 space | { } [ ] : , " \ / + - . 0 | a b c d e f l n r s t u | E | * */
510/*start GO*/ {GO,GO,-6,__,-5,__,__,__,__,__,CB,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
511/*ok OK*/ {OK,OK,__,-8,__,-7,__,-3,__,__,CB,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
512/*object OB*/ {OB,OB,__,-9,__,__,__,__,SB,__,CB,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
513/*key KE*/ {KE,KE,__,__,__,__,__,__,SB,__,CB,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
514/*colon CO*/ {CO,CO,__,__,__,__,-2,__,__,__,CB,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
515/*value VA*/ {VA,VA,-6,__,-5,__,__,__,SB,__,CB,__,MX,__,ZX,IX,__,__,__,__,__,FA,__,NU,__,__,TR,__,__,__,__,__},
516/*array AR*/ {AR,AR,-6,__,-5,-7,__,__,SB,__,CB,__,MX,__,ZX,IX,__,__,__,__,__,FA,__,NU,__,__,TR,__,__,__,__,__},
517/*string ST*/ {ST,__,ST,ST,ST,ST,ST,ST,-4,EX,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST,ST},
518/*escape ES*/ {__,__,__,__,__,__,__,__,ST,ST,ST,__,__,__,__,__,__,ST,__,__,__,ST,__,ST,ST,__,ST,U1,__,__,__,__},
519/*u1 U1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,U2,U2,U2,U2,U2,U2,U2,U2,__,__,__,__,__,__,U2,U2,__,__},
520/*u2 U2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,U3,U3,U3,U3,U3,U3,U3,U3,__,__,__,__,__,__,U3,U3,__,__},
521/*u3 U3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,U4,U4,U4,U4,U4,U4,U4,U4,__,__,__,__,__,__,U4,U4,__,__},
522/*u4 U4*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,UC,UC,UC,UC,UC,UC,UC,UC,__,__,__,__,__,__,UC,UC,__,__},
523/*minus MI*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,ZE,IT,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
524/*zero ZE*/ {OK,OK,__,-8,__,-7,__,-3,__,__,CB,__,__,DF,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
525/*int IT*/ {OK,OK,__,-8,__,-7,__,-3,__,__,CB,__,__,DF,IT,IT,__,__,__,__,DE,__,__,__,__,__,__,__,__,DE,__,__},
526/*frac FR*/ {OK,OK,__,-8,__,-7,__,-3,__,__,CB,__,__,__,FR,FR,__,__,__,__,E1,__,__,__,__,__,__,__,__,E1,__,__},
527/*e E1*/ {__,__,__,__,__,__,__,__,__,__,__,E2,E2,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
528/*ex E2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
529/*exp E3*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,__,E3,E3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
530/*tr T1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,T2,__,__,__,__,__,__,__},
531/*tru T2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,T3,__,__,__,__},
532/*true T3*/ {__,__,__,__,__,__,__,__,__,__,CB,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__,__,__},
533/*fa F1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F2,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
534/*fal F2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F3,__,__,__,__,__,__,__,__,__},
535/*fals F3*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,F4,__,__,__,__,__,__},
536/*false F4*/ {__,__,__,__,__,__,__,__,__,__,CB,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__,__,__},
537/*nu N1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,N2,__,__,__,__},
538/*nul N2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,N3,__,__,__,__,__,__,__,__,__},
539/*null N3*/ {__,__,__,__,__,__,__,__,__,__,CB,__,__,__,__,__,__,__,__,__,__,__,OK,__,__,__,__,__,__,__,__,__},
540/*/ C1*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,C2},
541/*/star C2*/ {C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C3},
542 {C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,CE,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C2,C3},
543/*_. FX*/ {OK,OK,__,-8,__,-7,__,-3,__,__,__,__,__,__,FR,FR,__,__,__,__,E1,__,__,__,__,__,__,__,__,E1,__,__},
544/*\ D1*/ {__,__,__,__,__,__,__,__,__,D2,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__},
545/*\ D2*/ {__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,U1,__,__,__,__},
546};
547
548
549/*
550 These modes can be pushed on the stack.
551*/
552enum modes {
553 MODE_ARRAY = 1,
554 MODE_DONE = 2,
555 MODE_KEY = 3,
556 MODE_OBJECT = 4
557};
558
559static void set_error(JSON_parser jc)
560{
561 switch (jc->state) {
562 case GO:
563 switch (jc->current_char) {
564 case '{': case '}': case '[': case ']':
565 jc->error = JSON_E_UNBALANCED_COLLECTION;
566 break;
567 default:
568 jc->error = JSON_E_INVALID_CHAR;
569 break;
570 }
571 break;
572 case OB:
573 jc->error = JSON_E_EXPECTED_KEY;
574 break;
575 case AR:
576 jc->error = JSON_E_UNBALANCED_COLLECTION;
577 break;
578 case CO:
579 jc->error = JSON_E_EXPECTED_COLON;
580 break;
581 case KE:
582 jc->error = JSON_E_EXPECTED_KEY;
583 break;
584 /* \uXXXX\uYYYY */
585 case U1: case U2: case U3: case U4: case D1: case D2:
586 jc->error = JSON_E_INVALID_UNICODE_SEQUENCE;
587 break;
588 /* true, false, null */
589 case T1: case T2: case T3: case F1: case F2: case F3: case F4: case N1: case N2: case N3:
590 jc->error = JSON_E_INVALID_KEYWORD;
591 break;
592 /* minus, integer, fraction, exponent */
593 case MI: case ZE: case IT: case FR: case E1: case E2: case E3:
594 jc->error = JSON_E_INVALID_NUMBER;
595 break;
596 default:
597 jc->error = JSON_E_INVALID_CHAR;
598 break;
599 }
600}
601
602static int
603push(JSON_parser jc, int mode)
604{
605/*
606 Push a mode onto the stack. Return false if there is overflow.
607*/
608 assert(jc->top <= jc->stack_capacity);
609
610 if (jc->depth < 0) {
611 if (jc->top == jc->stack_capacity) {
612 const size_t bytes_to_copy = jc->stack_capacity * sizeof(jc->stack[0]);
613 const size_t new_capacity = jc->stack_capacity * 2;
614 const size_t bytes_to_allocate = new_capacity * sizeof(jc->stack[0]);
615 void* mem = JSON_parser_malloc(jc->malloc, bytes_to_allocate, "stack");
616 if (!mem) {
617 jc->error = JSON_E_OUT_OF_MEMORY;
618 return false;
619 }
620 jc->stack_capacity = (int)new_capacity;
621 memcpy(mem, jc->stack, bytes_to_copy);
622 if (jc->stack != &jc->static_stack[0]) {
623 jc->free(jc->stack);
624 }
625 jc->stack = (signed char*)mem;
626 }
627 } else {
628 if (jc->top == jc->depth) {
629 jc->error = JSON_E_NESTING_DEPTH_REACHED;
630 return false;
631 }
632 }
633 jc->stack[++jc->top] = (signed char)mode;
634 return true;
635}
636
637
638static int
639pop(JSON_parser jc, int mode)
640{
641/*
642 Pop the stack, assuring that the current mode matches the expectation.
643 Return false if there is underflow or if the modes mismatch.
644*/
645 if (jc->top < 0 || jc->stack[jc->top] != mode) {
646 return false;
647 }
648 jc->top -= 1;
649 return true;
650}
651
652
653#define parse_buffer_clear(jc) \
654 do {\
655 jc->parse_buffer_count = 0;\
656 jc->parse_buffer[0] = 0;\
657 } while (0)
658
659#define parse_buffer_pop_back_char(jc)\
660 do {\
661 assert(jc->parse_buffer_count >= 1);\
662 --jc->parse_buffer_count;\
663 jc->parse_buffer[jc->parse_buffer_count] = 0;\
664 } while (0)
665
666
667
668void delete_JSON_parser(JSON_parser jc)
669{
670 if (jc) {
671 if (jc->stack != &jc->static_stack[0]) {
672 jc->free((void*)jc->stack);
673 }
674 if (jc->parse_buffer != &jc->static_parse_buffer[0]) {
675 jc->free((void*)jc->parse_buffer);
676 }
677 jc->free((void*)jc);
678 }
679}
680
681int JSON_parser_reset(JSON_parser jc)
682{
683 if (NULL == jc) {
684 return false;
685 }
686
687 jc->state = GO;
688 jc->top = -1;
689
690 /* parser has been used previously? */
691 if (NULL == jc->parse_buffer) {
692
693 /* Do we want non-bound stack? */
694 if (jc->depth > 0) {
695 jc->stack_capacity = jc->depth;
696 if (jc->depth <= (int)COUNTOF(jc->static_stack)) {
697 jc->stack = &jc->static_stack[0];
698 } else {
699 const size_t bytes_to_alloc = jc->stack_capacity * sizeof(jc->stack[0]);
700 jc->stack = (signed char*)JSON_parser_malloc(jc->malloc, bytes_to_alloc, "stack");
701 if (jc->stack == NULL) {
702 return false;
703 }
704 }
705 } else {
706 jc->stack_capacity = (int)COUNTOF(jc->static_stack);
707 jc->depth = -1;
708 jc->stack = &jc->static_stack[0];
709 }
710
711 /* set up the parse buffer */
712 jc->parse_buffer = &jc->static_parse_buffer[0];
713 jc->parse_buffer_capacity = COUNTOF(jc->static_parse_buffer);
714 }
715
716 /* set parser to start */
717 push(jc, MODE_DONE);
718 parse_buffer_clear(jc);
719
720 return true;
721}
722
724new_JSON_parser(JSON_config const * config)
725{
726/*
727 new_JSON_parser starts the checking process by constructing a JSON_parser
728 object. It takes a depth parameter that restricts the level of maximum
729 nesting.
730
731 To continue the process, call JSON_parser_char for each character in the
732 JSON text, and then call JSON_parser_done to obtain the final result.
733 These functions are fully reentrant.
734*/
735
736 int use_std_malloc = false;
737 JSON_config default_config;
738 JSON_parser jc;
739 JSON_malloc_t alloc;
740
741 /* set to default configuration if none was provided */
742 if (NULL == config) {
743 /* initialize configuration */
744 init_JSON_config(&default_config);
745 config = &default_config;
746 }
747
748 /* use std malloc if either the allocator or deallocator function isn't set */
749 use_std_malloc = NULL == config->malloc || NULL == config->free;
750
751 alloc = use_std_malloc ? malloc : config->malloc;
752
753 jc = (JSON_parser)JSON_parser_malloc(alloc, sizeof(*jc), "parser");
754
755 if (NULL == jc) {
756 return NULL;
757 }
758
759 /* configure the parser */
760 memset(jc, 0, sizeof(*jc));
761 jc->malloc = alloc;
762 jc->free = use_std_malloc ? free : config->free;
763 jc->callback = config->callback;
764 jc->ctx = config->callback_ctx;
765 jc->allow_comments = (signed char)(config->allow_comments != 0);
766 jc->handle_floats_manually = (signed char)(config->handle_floats_manually != 0);
767 jc->decimal_point = *localeconv()->decimal_point;
768 /* We need to be able to push at least one object */
769 jc->depth = config->depth == 0 ? 1 : config->depth;
770
771 /* reset the parser */
772 if (!JSON_parser_reset(jc)) {
773 jc->free(jc);
774 return NULL;
775 }
776
777 return jc;
778}
779
780static int parse_buffer_grow(JSON_parser jc)
781{
782 const size_t bytes_to_copy = jc->parse_buffer_count * sizeof(jc->parse_buffer[0]);
783 const size_t new_capacity = jc->parse_buffer_capacity * 2;
784 const size_t bytes_to_allocate = new_capacity * sizeof(jc->parse_buffer[0]);
785 void* mem = JSON_parser_malloc(jc->malloc, bytes_to_allocate, "parse buffer");
786
787 if (mem == NULL) {
788 jc->error = JSON_E_OUT_OF_MEMORY;
789 return false;
790 }
791
792 assert(new_capacity > 0);
793 memcpy(mem, jc->parse_buffer, bytes_to_copy);
794
795 if (jc->parse_buffer != &jc->static_parse_buffer[0]) {
796 jc->free(jc->parse_buffer);
797 }
798
799 jc->parse_buffer = (char*)mem;
800 jc->parse_buffer_capacity = new_capacity;
801
802 return true;
803}
804
805static int parse_buffer_reserve_for(JSON_parser jc, unsigned chars)
806{
807 while (jc->parse_buffer_count + chars + 1 > jc->parse_buffer_capacity) {
808 if (!parse_buffer_grow(jc)) {
809 assert(jc->error == JSON_E_OUT_OF_MEMORY);
810 return false;
811 }
812 }
813
814 return true;
815}
816
817#define parse_buffer_has_space_for(jc, count) \
818 (jc->parse_buffer_count + (count) + 1 <= jc->parse_buffer_capacity)
819
820#define parse_buffer_push_back_char(jc, c)\
821 do {\
822 assert(parse_buffer_has_space_for(jc, 1)); \
823 jc->parse_buffer[jc->parse_buffer_count++] = c;\
824 jc->parse_buffer[jc->parse_buffer_count] = 0;\
825 } while (0)
826
827#define assert_is_non_container_type(jc) \
828 assert( \
829 jc->type == JSON_T_NULL || \
830 jc->type == JSON_T_FALSE || \
831 jc->type == JSON_T_TRUE || \
832 jc->type == JSON_T_FLOAT || \
833 jc->type == JSON_T_INTEGER || \
834 jc->type == JSON_T_STRING)
835
836
837static int parse_parse_buffer(JSON_parser jc)
838{
839 if (jc->callback) {
840 JSON_value value, *arg = NULL;
841
842 if (jc->type != JSON_T_NONE) {
843 assert_is_non_container_type(jc);
844
845 switch(jc->type) {
846 case JSON_T_FLOAT:
847 arg = &value;
848 if (jc->handle_floats_manually) {
849 value.vu.str.value = jc->parse_buffer;
850 value.vu.str.length = jc->parse_buffer_count;
851 } else {
852 /* not checking with end pointer b/c there may be trailing ws */
853 value.vu.float_value = strtod(jc->parse_buffer, NULL);
854 }
855 break;
856 case JSON_T_INTEGER:
857 arg = &value;
858 sscanf(jc->parse_buffer, JSON_PARSER_INTEGER_SSCANF_TOKEN, &value.vu.integer_value);
859 break;
860 case JSON_T_STRING:
861 arg = &value;
862 value.vu.str.value = jc->parse_buffer;
863 value.vu.str.length = jc->parse_buffer_count;
864 break;
865 }
866
867 if (!(*jc->callback)(jc->ctx, jc->type, arg)) {
868 return false;
869 }
870 }
871 }
872
873 parse_buffer_clear(jc);
874
875 return true;
876}
877
878#define IS_HIGH_SURROGATE(uc) (((uc) & 0xFC00) == 0xD800)
879#define IS_LOW_SURROGATE(uc) (((uc) & 0xFC00) == 0xDC00)
880#define DECODE_SURROGATE_PAIR(hi,lo) ((((hi) & 0x3FF) << 10) + ((lo) & 0x3FF) + 0x10000)
881static const unsigned char utf8_lead_bits[4] = { 0x00, 0xC0, 0xE0, 0xF0 };
882
883static int decode_unicode_char(JSON_parser jc)
884{
885 int i;
886 unsigned uc = 0;
887 char* p;
888 int trail_bytes;
889
890 assert(jc->parse_buffer_count >= 6);
891
892 p = &jc->parse_buffer[jc->parse_buffer_count - 4];
893
894 for (i = 12; i >= 0; i -= 4, ++p) {
895 unsigned x = *p;
896
897 if (x >= 'a') {
898 x -= ('a' - 10);
899 } else if (x >= 'A') {
900 x -= ('A' - 10);
901 } else {
902 x &= ~0x30u;
903 }
904
905 assert(x < 16);
906
907 uc |= x << i;
908 }
909
910 /* clear UTF-16 char from buffer */
911 jc->parse_buffer_count -= 6;
912 jc->parse_buffer[jc->parse_buffer_count] = 0;
913
914 if (uc == 0xffff || uc == 0xfffe) {
915 return false;
916 }
917
918 /* attempt decoding ... */
919 if (jc->utf16_high_surrogate) {
920 if (IS_LOW_SURROGATE(uc)) {
921 uc = DECODE_SURROGATE_PAIR(jc->utf16_high_surrogate, uc);
922 trail_bytes = 3;
923 jc->utf16_high_surrogate = 0;
924 } else {
925 /* high surrogate without a following low surrogate */
926 return false;
927 }
928 } else {
929 if (uc < 0x80) {
930 trail_bytes = 0;
931 } else if (uc < 0x800) {
932 trail_bytes = 1;
933 } else if (IS_HIGH_SURROGATE(uc)) {
934 /* save the high surrogate and wait for the low surrogate */
935 jc->utf16_high_surrogate = (UTF16)uc;
936 return true;
937 } else if (IS_LOW_SURROGATE(uc)) {
938 /* low surrogate without a preceding high surrogate */
939 return false;
940 } else {
941 trail_bytes = 2;
942 }
943 }
944
945 jc->parse_buffer[jc->parse_buffer_count++] = (char) ((uc >> (trail_bytes * 6)) | utf8_lead_bits[trail_bytes]);
946
947 for (i = trail_bytes * 6 - 6; i >= 0; i -= 6) {
948 jc->parse_buffer[jc->parse_buffer_count++] = (char) (((uc >> i) & 0x3F) | 0x80);
949 }
950
951 jc->parse_buffer[jc->parse_buffer_count] = 0;
952
953 return true;
954}
955
956static int add_escaped_char_to_parse_buffer(JSON_parser jc, int next_char)
957{
958 assert(parse_buffer_has_space_for(jc, 1));
959
960 jc->escaped = 0;
961 /* remove the backslash */
962 parse_buffer_pop_back_char(jc);
963 switch(next_char) {
964 case 'b':
965 parse_buffer_push_back_char(jc, '\b');
966 break;
967 case 'f':
968 parse_buffer_push_back_char(jc, '\f');
969 break;
970 case 'n':
971 parse_buffer_push_back_char(jc, '\n');
972 break;
973 case 'r':
974 parse_buffer_push_back_char(jc, '\r');
975 break;
976 case 't':
977 parse_buffer_push_back_char(jc, '\t');
978 break;
979 case '"':
980 parse_buffer_push_back_char(jc, '"');
981 break;
982 case '\\':
983 parse_buffer_push_back_char(jc, '\\');
984 break;
985 case '/':
986 parse_buffer_push_back_char(jc, '/');
987 break;
988 case 'u':
989 parse_buffer_push_back_char(jc, '\\');
990 parse_buffer_push_back_char(jc, 'u');
991 break;
992 default:
993 return false;
994 }
995
996 return true;
997}
998
999static int add_char_to_parse_buffer(JSON_parser jc, int next_char, int next_class)
1000{
1001 if (!parse_buffer_reserve_for(jc, 1)) {
1002 assert(JSON_E_OUT_OF_MEMORY == jc->error);
1003 return false;
1004 }
1005
1006 if (jc->escaped) {
1007 if (!add_escaped_char_to_parse_buffer(jc, next_char)) {
1008 jc->error = JSON_E_INVALID_ESCAPE_SEQUENCE;
1009 return false;
1010 }
1011 } else if (!jc->comment) {
1012 if ((jc->type != JSON_T_NONE) | !((next_class == C_SPACE) | (next_class == C_WHITE)) /* non-white-space */) {
1013 parse_buffer_push_back_char(jc, (char)next_char);
1014 }
1015 }
1016
1017 return true;
1018}
1019
1020#define assert_type_isnt_string_null_or_bool(jc) \
1021 assert(jc->type != JSON_T_FALSE); \
1022 assert(jc->type != JSON_T_TRUE); \
1023 assert(jc->type != JSON_T_NULL); \
1024 assert(jc->type != JSON_T_STRING)
1025
1026
1027int
1028JSON_parser_char(JSON_parser jc, int next_char)
1029{
1030/*
1031 After calling new_JSON_parser, call this function for each character (or
1032 partial character) in your JSON text. It can accept UTF-8, UTF-16, or
1033 UTF-32. It returns true if things are looking ok so far. If it rejects the
1034 text, it returns false.
1035*/
1036 int next_class, next_state;
1037
1038/*
1039 Store the current char for error handling
1040*/
1041 jc->current_char = next_char;
1042
1043/*
1044 Determine the character's class.
1045*/
1046 if (next_char < 0) {
1047 jc->error = JSON_E_INVALID_CHAR;
1048 return false;
1049 }
1050 if (next_char >= 128) {
1051 next_class = C_ETC;
1052 } else {
1053 next_class = ascii_class[next_char];
1054 if (next_class <= __) {
1055 set_error(jc);
1056 return false;
1057 }
1058 }
1059
1060 if (!add_char_to_parse_buffer(jc, next_char, next_class)) {
1061 return false;
1062 }
1063
1064/*
1065 Get the next state from the state transition table.
1066*/
1067 next_state = state_transition_table[jc->state][next_class];
1068 if (next_state >= 0) {
1069/*
1070 Change the state.
1071*/
1072 jc->state = (signed char)next_state;
1073 } else {
1074/*
1075 Or perform one of the actions.
1076*/
1077 switch (next_state) {
1078/* Unicode character */
1079 case UC:
1080 if(!decode_unicode_char(jc)) {
1081 jc->error = JSON_E_INVALID_UNICODE_SEQUENCE;
1082 return false;
1083 }
1084 /* check if we need to read a second UTF-16 char */
1085 if (jc->utf16_high_surrogate) {
1086 jc->state = D1;
1087 } else {
1088 jc->state = ST;
1089 }
1090 break;
1091/* escaped char */
1092 case EX:
1093 jc->escaped = 1;
1094 jc->state = ES;
1095 break;
1096/* integer detected by minus */
1097 case MX:
1098 jc->type = JSON_T_INTEGER;
1099 jc->state = MI;
1100 break;
1101/* integer detected by zero */
1102 case ZX:
1103 jc->type = JSON_T_INTEGER;
1104 jc->state = ZE;
1105 break;
1106/* integer detected by 1-9 */
1107 case IX:
1108 jc->type = JSON_T_INTEGER;
1109 jc->state = IT;
1110 break;
1111
1112/* floating point number detected by exponent*/
1113 case DE:
1114 assert_type_isnt_string_null_or_bool(jc);
1115 jc->type = JSON_T_FLOAT;
1116 jc->state = E1;
1117 break;
1118
1119/* floating point number detected by fraction */
1120 case DF:
1121 assert_type_isnt_string_null_or_bool(jc);
1122 if (!jc->handle_floats_manually) {
1123/*
1124 Some versions of strtod (which underlies sscanf) don't support converting
1125 C-locale formated floating point values.
1126*/
1127 assert(jc->parse_buffer[jc->parse_buffer_count-1] == '.');
1128 jc->parse_buffer[jc->parse_buffer_count-1] = jc->decimal_point;
1129 }
1130 jc->type = JSON_T_FLOAT;
1131 jc->state = FX;
1132 break;
1133/* string begin " */
1134 case SB:
1135 parse_buffer_clear(jc);
1136 assert(jc->type == JSON_T_NONE);
1137 jc->type = JSON_T_STRING;
1138 jc->state = ST;
1139 break;
1140
1141/* n */
1142 case NU:
1143 assert(jc->type == JSON_T_NONE);
1144 jc->type = JSON_T_NULL;
1145 jc->state = N1;
1146 break;
1147/* f */
1148 case FA:
1149 assert(jc->type == JSON_T_NONE);
1150 jc->type = JSON_T_FALSE;
1151 jc->state = F1;
1152 break;
1153/* t */
1154 case TR:
1155 assert(jc->type == JSON_T_NONE);
1156 jc->type = JSON_T_TRUE;
1157 jc->state = T1;
1158 break;
1159
1160/* closing comment */
1161 case CE:
1162 jc->comment = 0;
1163 assert(jc->parse_buffer_count == 0);
1164 assert(jc->type == JSON_T_NONE);
1165 jc->state = jc->before_comment_state;
1166 break;
1167
1168/* opening comment */
1169 case CB:
1170 if (!jc->allow_comments) {
1171 return false;
1172 }
1173 parse_buffer_pop_back_char(jc);
1174 if (!parse_parse_buffer(jc)) {
1175 return false;
1176 }
1177 assert(jc->parse_buffer_count == 0);
1178 assert(jc->type != JSON_T_STRING);
1179 switch (jc->stack[jc->top]) {
1180 case MODE_ARRAY:
1181 case MODE_OBJECT:
1182 switch(jc->state) {
1183 case VA:
1184 case AR:
1185 jc->before_comment_state = jc->state;
1186 break;
1187 default:
1188 jc->before_comment_state = OK;
1189 break;
1190 }
1191 break;
1192 default:
1193 jc->before_comment_state = jc->state;
1194 break;
1195 }
1196 jc->type = JSON_T_NONE;
1197 jc->state = C1;
1198 jc->comment = 1;
1199 break;
1200/* empty } */
1201 case -9:
1202 parse_buffer_clear(jc);
1203 if (jc->callback && !(*jc->callback)(jc->ctx, JSON_T_OBJECT_END, NULL)) {
1204 return false;
1205 }
1206 if (!pop(jc, MODE_KEY)) {
1207 return false;
1208 }
1209 jc->state = OK;
1210 break;
1211
1212/* } */ case -8:
1213 parse_buffer_pop_back_char(jc);
1214 if (!parse_parse_buffer(jc)) {
1215 return false;
1216 }
1217 if (jc->callback && !(*jc->callback)(jc->ctx, JSON_T_OBJECT_END, NULL)) {
1218 return false;
1219 }
1220 if (!pop(jc, MODE_OBJECT)) {
1221 jc->error = JSON_E_UNBALANCED_COLLECTION;
1222 return false;
1223 }
1224 jc->type = JSON_T_NONE;
1225 jc->state = OK;
1226 break;
1227
1228/* ] */ case -7:
1229 parse_buffer_pop_back_char(jc);
1230 if (!parse_parse_buffer(jc)) {
1231 return false;
1232 }
1233 if (jc->callback && !(*jc->callback)(jc->ctx, JSON_T_ARRAY_END, NULL)) {
1234 return false;
1235 }
1236 if (!pop(jc, MODE_ARRAY)) {
1237 jc->error = JSON_E_UNBALANCED_COLLECTION;
1238 return false;
1239 }
1240
1241 jc->type = JSON_T_NONE;
1242 jc->state = OK;
1243 break;
1244
1245/* { */ case -6:
1246 parse_buffer_pop_back_char(jc);
1247 if (jc->callback && !(*jc->callback)(jc->ctx, JSON_T_OBJECT_BEGIN, NULL)) {
1248 return false;
1249 }
1250 if (!push(jc, MODE_KEY)) {
1251 return false;
1252 }
1253 assert(jc->type == JSON_T_NONE);
1254 jc->state = OB;
1255 break;
1256
1257/* [ */ case -5:
1258 parse_buffer_pop_back_char(jc);
1259 if (jc->callback && !(*jc->callback)(jc->ctx, JSON_T_ARRAY_BEGIN, NULL)) {
1260 return false;
1261 }
1262 if (!push(jc, MODE_ARRAY)) {
1263 return false;
1264 }
1265 assert(jc->type == JSON_T_NONE);
1266 jc->state = AR;
1267 break;
1268
1269/* string end " */ case -4:
1270 parse_buffer_pop_back_char(jc);
1271 switch (jc->stack[jc->top]) {
1272 case MODE_KEY:
1273 assert(jc->type == JSON_T_STRING);
1274 jc->type = JSON_T_NONE;
1275 jc->state = CO;
1276
1277 if (jc->callback) {
1278 JSON_value value;
1279 value.vu.str.value = jc->parse_buffer;
1280 value.vu.str.length = jc->parse_buffer_count;
1281 if (!(*jc->callback)(jc->ctx, JSON_T_KEY, &value)) {
1282 return false;
1283 }
1284 }
1285 parse_buffer_clear(jc);
1286 break;
1287 case MODE_ARRAY:
1288 case MODE_OBJECT:
1289 assert(jc->type == JSON_T_STRING);
1290 if (!parse_parse_buffer(jc)) {
1291 return false;
1292 }
1293 jc->type = JSON_T_NONE;
1294 jc->state = OK;
1295 break;
1296 default:
1297 return false;
1298 }
1299 break;
1300
1301/* , */ case -3:
1302 parse_buffer_pop_back_char(jc);
1303 if (!parse_parse_buffer(jc)) {
1304 return false;
1305 }
1306 switch (jc->stack[jc->top]) {
1307 case MODE_OBJECT:
1308/*
1309 A comma causes a flip from object mode to key mode.
1310*/
1311 if (!pop(jc, MODE_OBJECT) || !push(jc, MODE_KEY)) {
1312 return false;
1313 }
1314 assert(jc->type != JSON_T_STRING);
1315 jc->type = JSON_T_NONE;
1316 jc->state = KE;
1317 break;
1318 case MODE_ARRAY:
1319 assert(jc->type != JSON_T_STRING);
1320 jc->type = JSON_T_NONE;
1321 jc->state = VA;
1322 break;
1323 default:
1324 return false;
1325 }
1326 break;
1327
1328/* : */ case -2:
1329/*
1330 A colon causes a flip from key mode to object mode.
1331*/
1332 parse_buffer_pop_back_char(jc);
1333 if (!pop(jc, MODE_KEY) || !push(jc, MODE_OBJECT)) {
1334 return false;
1335 }
1336 assert(jc->type == JSON_T_NONE);
1337 jc->state = VA;
1338 break;
1339/*
1340 Bad action.
1341*/
1342 default:
1343 set_error(jc);
1344 return false;
1345 }
1346 }
1347 return true;
1348}
1349
1350int
1351JSON_parser_done(JSON_parser jc)
1352{
1353 if ((jc->state == OK || jc->state == GO) && pop(jc, MODE_DONE))
1354 {
1355 return true;
1356 }
1357
1358 jc->error = JSON_E_UNBALANCED_COLLECTION;
1359 return false;
1360}
1361
1362
1363int JSON_parser_is_legal_white_space_string(const char* s)
1364{
1365 int c, char_class;
1366
1367 if (s == NULL) {
1368 return false;
1369 }
1370
1371 for (; *s; ++s) {
1372 c = *s;
1373
1374 if (c < 0 || c >= 128) {
1375 return false;
1376 }
1377
1378 char_class = ascii_class[c];
1379
1380 if (char_class != C_SPACE && char_class != C_WHITE) {
1381 return false;
1382 }
1383 }
1384
1385 return true;
1386}
1387
1388int JSON_parser_get_last_error(JSON_parser jc)
1389{
1390 return jc->error;
1391}
1392
1393
1394void init_JSON_config(JSON_config* config)
1395{
1396 if (config) {
1397 memset(config, 0, sizeof(*config));
1398
1399 config->depth = JSON_PARSER_STACK_SIZE - 1;
1400 config->malloc = malloc;
1401 config->free = free;
1402 }
1403}
1404
1405/* end file parser/JSON_parser.c */
1406/* begin file ./cson.c */
1407#include <assert.h>
1408#include <stdlib.h> /* malloc()/free() */
1409#include <string.h>
1410#include <errno.h>
1411
1412#ifdef _MSC_VER
1413# if _MSC_VER >= 1400 /* Visual Studio 2005 and up */
1414# pragma warning( push )
1415# pragma warning(disable:4996) /* unsecure sscanf (but snscanf() isn't in c89) */
1416# pragma warning(disable:4244) /* complaining about data loss due
1417 to integer precision in the
1418 sqlite3 utf decoding routines */
1419# endif
1420#endif
1421
1422#if 1
1423#include <stdio.h>
1424#define MARKER if(1) printf("MARKER: %s:%d:%s():\t",__FILE__,__LINE__,__func__); if(1) printf
1425#else
1426static void noop_printf(char const * fmt, ...) {}
1427#define MARKER if(0) printf
1428#endif
1429
1430#if defined(__cplusplus)
1431extern "C" {
1432#endif
1433
1434
1435
1444{
1449 const cson_type_id typeID;
1455 void (*cleanup)( cson_value * self );
1468};
1469
1470typedef struct cson_value_api cson_value_api;
1471
1475#define cson_value_api_empty_m { \
1476 CSON_TYPE_UNDEF/*typeID*/, \
1477 NULL/*cleanup*/\
1478 }
1482static const cson_value_api cson_value_api_empty = cson_value_api_empty_m;
1483
1484
1485typedef unsigned int cson_counter_t;
1487{
1494
1504 void * value;
1505
1526 cson_counter_t refcount;
1527};
1528
1529
1533#define cson_value_empty_m { &cson_value_api_empty/*api*/, NULL/*value*/, 0/*refcount*/ }
1537static const cson_value cson_value_empty = cson_value_empty_m;
1538const cson_parse_opt cson_parse_opt_empty = cson_parse_opt_empty_m;
1539const cson_output_opt cson_output_opt_empty = cson_output_opt_empty_m;
1540const cson_object_iterator cson_object_iterator_empty = cson_object_iterator_empty_m;
1541const cson_buffer cson_buffer_empty = cson_buffer_empty_m;
1542const cson_parse_info cson_parse_info_empty = cson_parse_info_empty_m;
1543
1544static void cson_value_destroy_zero_it( cson_value * self );
1545static void cson_value_destroy_object( cson_value * self );
1550static void cson_value_destroy_array( cson_value * self );
1551
1552static const cson_value_api cson_value_api_null = { CSON_TYPE_NULL, cson_value_destroy_zero_it };
1553static const cson_value_api cson_value_api_undef = { CSON_TYPE_UNDEF, cson_value_destroy_zero_it };
1554static const cson_value_api cson_value_api_bool = { CSON_TYPE_BOOL, cson_value_destroy_zero_it };
1555static const cson_value_api cson_value_api_integer = { CSON_TYPE_INTEGER, cson_value_destroy_zero_it };
1556static const cson_value_api cson_value_api_double = { CSON_TYPE_DOUBLE, cson_value_destroy_zero_it };
1557static const cson_value_api cson_value_api_string = { CSON_TYPE_STRING, cson_value_destroy_zero_it };
1558static const cson_value_api cson_value_api_array = { CSON_TYPE_ARRAY, cson_value_destroy_array };
1559static const cson_value_api cson_value_api_object = { CSON_TYPE_OBJECT, cson_value_destroy_object };
1560
1561static const cson_value cson_value_undef = { &cson_value_api_undef, NULL, 0 };
1562static const cson_value cson_value_null_empty = { &cson_value_api_null, NULL, 0 };
1563static const cson_value cson_value_bool_empty = { &cson_value_api_bool, NULL, 0 };
1564static const cson_value cson_value_integer_empty = { &cson_value_api_integer, NULL, 0 };
1565static const cson_value cson_value_double_empty = { &cson_value_api_double, NULL, 0 };
1566static const cson_value cson_value_string_empty = { &cson_value_api_string, NULL, 0 };
1567static const cson_value cson_value_array_empty = { &cson_value_api_array, NULL, 0 };
1568static const cson_value cson_value_object_empty = { &cson_value_api_object, NULL, 0 };
1569
1579{
1580 unsigned int length;
1581};
1582#define cson_string_empty_m {0/*length*/}
1583static const cson_string cson_string_empty = cson_string_empty_m;
1584
1585
1590#define CSON_CAST(T,V) ((T*)((V)->value))
1597#define CSON_VCAST(V) ((cson_value *)(((unsigned char *)(V))-sizeof(cson_value)))
1598
1605#if CSON_VOID_PTR_IS_BIG
1606# define CSON_INT(V) ((cson_int_t*)(&((V)->value)))
1607#else
1608# define CSON_INT(V) ((cson_int_t*)(V)->value)
1609#endif
1610
1611#define CSON_DBL(V) CSON_CAST(cson_double_t,(V))
1612#define CSON_STR(V) CSON_CAST(cson_string,(V))
1613#define CSON_OBJ(V) CSON_CAST(cson_object,(V))
1614#define CSON_ARRAY(V) CSON_CAST(cson_array,(V))
1615
1620static struct CSON_EMPTY_HOLDER_
1621{
1622 char trueValue;
1623 cson_string stringValue;
1624} CSON_EMPTY_HOLDER = {
1625 1/*trueValue*/,
1626 cson_string_empty_m
1627};
1628
1636enum CSON_INTERNAL_VALUES {
1637
1638 CSON_VAL_UNDEF = 0,
1639 CSON_VAL_NULL = 1,
1640 CSON_VAL_TRUE = 2,
1641 CSON_VAL_FALSE = 3,
1642 CSON_VAL_INT_0 = 4,
1643 CSON_VAL_DBL_0 = 5,
1644 CSON_VAL_STR_EMPTY = 6,
1645 CSON_INTERNAL_VALUES_LENGTH
1646};
1647
1660static cson_value CSON_SPECIAL_VALUES[] = {
1661{ &cson_value_api_undef, NULL, 0 }, /* UNDEF */
1662{ &cson_value_api_null, NULL, 0 }, /* NULL */
1663{ &cson_value_api_bool, &CSON_EMPTY_HOLDER.trueValue, 0 }, /* TRUE */
1664{ &cson_value_api_bool, NULL, 0 }, /* FALSE */
1665{ &cson_value_api_integer, NULL, 0 }, /* INT_0 */
1666{ &cson_value_api_double, NULL, 0 }, /* DBL_0 */
1667{ &cson_value_api_string, &CSON_EMPTY_HOLDER.stringValue, 0 }, /* STR_EMPTY */
1668{ NULL, NULL, 0 }
1669};
1670
1671
1679static char cson_value_is_builtin( void const * m )
1680{
1681 if((m >= (void const *)&CSON_EMPTY_HOLDER)
1682 && ( m < (void const *)(&CSON_EMPTY_HOLDER+1)))
1683 return 1;
1684 else return
1685 ((m >= (void const *)&CSON_SPECIAL_VALUES[0])
1686 && ( m < (void const *)&CSON_SPECIAL_VALUES[CSON_INTERNAL_VALUES_LENGTH]) )
1687 ? 1
1688 : 0;
1689}
1690
1691char const * cson_rc_string(int rc)
1692{
1693 if(0 == rc) return "OK";
1694#define CHECK(N) else if(cson_rc.N == rc ) return #N
1695 CHECK(OK);
1696 CHECK(ArgError);
1697 CHECK(RangeError);
1698 CHECK(TypeError);
1699 CHECK(IOError);
1700 CHECK(AllocError);
1701 CHECK(NYIError);
1702 CHECK(InternalError);
1703 CHECK(UnsupportedError);
1704 CHECK(NotFoundError);
1705 CHECK(UnknownError);
1706 CHECK(Parse_INVALID_CHAR);
1707 CHECK(Parse_INVALID_KEYWORD);
1708 CHECK(Parse_INVALID_ESCAPE_SEQUENCE);
1709 CHECK(Parse_INVALID_UNICODE_SEQUENCE);
1710 CHECK(Parse_INVALID_NUMBER);
1711 CHECK(Parse_NESTING_DEPTH_REACHED);
1712 CHECK(Parse_UNBALANCED_COLLECTION);
1713 CHECK(Parse_EXPECTED_KEY);
1714 CHECK(Parse_EXPECTED_COLON);
1715 else return "UnknownError";
1716#undef CHECK
1717}
1718
1723#define CSON_LOG_ALLOC 0
1724
1725
1734#if defined(CSON_FOSSIL_MODE)
1735extern void *fossil_malloc(size_t n);
1736extern void fossil_free(void *p);
1737extern void *fossil_realloc(void *p, size_t n);
1738# define CSON_MALLOC_IMPL fossil_malloc
1739# define CSON_FREE_IMPL fossil_free
1740# define CSON_REALLOC_IMPL fossil_realloc
1741#endif
1742
1743#if !defined CSON_MALLOC_IMPL
1744# define CSON_MALLOC_IMPL malloc
1745#endif
1746#if !defined CSON_FREE_IMPL
1747# define CSON_FREE_IMPL free
1748#endif
1749#if !defined CSON_REALLOC_IMPL
1750# define CSON_REALLOC_IMPL realloc
1751#endif
1752
1757#define CSON_SIMULATE_OOM 0
1758#if CSON_SIMULATE_OOM
1759static unsigned int cson_totalAlloced = 0;
1760#endif
1761
1763static void * cson_malloc( size_t n, char const * descr )
1764{
1765#if CSON_LOG_ALLOC
1766 fprintf(stderr, "Allocating %u bytes [%s].\n", (unsigned int)n, descr);
1767#endif
1768#if CSON_SIMULATE_OOM
1769 cson_totalAlloced += n;
1770 if( cson_totalAlloced > CSON_SIMULATE_OOM )
1771 {
1772 return NULL;
1773 }
1774#endif
1775 return CSON_MALLOC_IMPL(n);
1776}
1777
1779static void cson_free( void * p, char const * descr )
1780{
1781#if CSON_LOG_ALLOC
1782 fprintf(stderr, "Freeing @%p [%s].\n", p, descr);
1783#endif
1784 if( !cson_value_is_builtin(p) )
1785 {
1786 CSON_FREE_IMPL( p );
1787 }
1788}
1790static void * cson_realloc( void * hint, size_t n, char const * descr )
1791{
1792#if CSON_LOG_ALLOC
1793 fprintf(stderr, "%sllocating %u bytes [%s].\n",
1794 hint ? "Rea" : "A",
1795 (unsigned int)n, descr);
1796#endif
1797#if CSON_SIMULATE_OOM
1798 cson_totalAlloced += n;
1799 if( cson_totalAlloced > CSON_SIMULATE_OOM )
1800 {
1801 return NULL;
1802 }
1803#endif
1804 if( 0==n )
1805 {
1806 cson_free(hint, descr);
1807 return NULL;
1808 }
1809 else
1810 {
1811 return CSON_REALLOC_IMPL( hint, n );
1812 }
1813}
1814
1815
1816#undef CSON_LOG_ALLOC
1817#undef CSON_SIMULATE_OOM
1818
1819
1820
1836static void cson_value_clean( cson_value * val );
1837
1843static void cson_refcount_incr( cson_value * cv )
1844{
1845 assert( NULL != cv );
1846 if( cson_value_is_builtin( cv ) )
1847 { /* do nothing: we do not want to modify the shared
1848 instances.
1849 */
1850 return;
1851 }
1852 else
1853 {
1854 ++cv->refcount;
1855 }
1856}
1857
1858#if 0
1859int cson_value_refcount_set( cson_value * cv, unsigned short rc )
1860{
1861 if( NULL == cv ) return cson_rc.ArgError;
1862 else
1863 {
1864 cv->refcount = rc;
1865 return 0;
1866 }
1867}
1868#endif
1869
1870int cson_value_add_reference( cson_value * cv )
1871{
1872 if( NULL == cv ) return cson_rc.ArgError;
1873 else if( (cv->refcount+1) < cv->refcount )
1874 {
1875 return cson_rc.RangeError;
1876 }
1877 else
1878 {
1879 cson_refcount_incr( cv );
1880 return 0;
1881 }
1882}
1883
1891static cson_counter_t cson_refcount_decr( cson_value * cv )
1892{
1893 if( (NULL == cv) || cson_value_is_builtin(cv) ) return 0;
1894 else if( (0 == cv->refcount) || (0 == --cv->refcount) )
1895 {
1896 cson_value_clean(cv);
1897 cson_free(cv,"cson_value::refcount=0");
1898 return 0;
1899 }
1900 else return cv->refcount;
1901}
1902
1903unsigned int cson_string_length_bytes( cson_string const * str )
1904{
1905 return str ? str->length : 0;
1906}
1907
1908
1918static char * cson_string_str(cson_string *v)
1919{
1920 /*
1921 See http://groups.google.com/group/comp.lang.c.moderated/browse_thread/thread/2e0c0df5e8a0cd6a
1922 */
1923#if 1
1924 if( !v || (&CSON_EMPTY_HOLDER.stringValue == v) ) return NULL;
1925 else return (char *)((unsigned char *)( v+1 ));
1926#else
1927 static char empty[2] = {0,0};
1928 return ( NULL == v )
1929 ? NULL
1930 : (v->length
1931 ? (char *) (((unsigned char *)v) + sizeof(cson_string))
1932 : empty)
1933 ;
1934#endif
1935}
1936
1940char const * cson_string_cstr(cson_string const *v)
1941{
1942 /*
1943 See http://groups.google.com/group/comp.lang.c.moderated/browse_thread/thread/2e0c0df5e8a0cd6a
1944 */
1945#if 1
1946 if( ! v ) return NULL;
1947 else if( v == &CSON_EMPTY_HOLDER.stringValue ) return "";
1948 else {
1949 assert((0 < v->length) && "How do we have a non-singleton empty string?");
1950 return (char const *)((unsigned char const *)(v+1));
1951 }
1952#else
1953 return (NULL == v)
1954 ? NULL
1955 : (v->length
1956 ? (char const *) ((unsigned char const *)(v+1))
1957 : "");
1958#endif
1959}
1960
1961
1962#if 0
1967static char * cson_strdup( char const * src, size_t n )
1968{
1969 char * rc = (char *)cson_malloc(n+1, "cson_strdup");
1970 if( ! rc ) return NULL;
1971 memset( rc, 0, n+1 );
1972 rc[n] = 0;
1973 return strncpy( rc, src, n );
1974}
1975#endif
1976
1977int cson_string_cmp_cstr_n( cson_string const * str, char const * other, unsigned int otherLen )
1978{
1979 if( ! other && !str ) return 0;
1980 else if( other && !str ) return 1;
1981 else if( str && !other ) return -1;
1982 else if( !otherLen ) return str->length ? 1 : 0;
1983 else if( !str->length ) return otherLen ? -1 : 0;
1984 else
1985 {
1986 unsigned const int max = (otherLen > str->length) ? otherLen : str->length;
1987 int const rc = strncmp( cson_string_cstr(str), other, max );
1988 return ( (0 == rc) && (otherLen != str->length) )
1989 ? (str->length < otherLen) ? -1 : 1
1990 : rc;
1991 }
1992}
1993
1994int cson_string_cmp_cstr( cson_string const * lhs, char const * rhs )
1995{
1996 return cson_string_cmp_cstr_n( lhs, rhs, (rhs&&*rhs) ? (unsigned int)strlen(rhs) : 0 );
1997}
1998int cson_string_cmp( cson_string const * lhs, cson_string const * rhs )
1999{
2000 return cson_string_cmp_cstr_n( lhs, cson_string_cstr(rhs), rhs ? rhs->length : 0 );
2001}
2002
2003
2008void cson_value_destroy_zero_it( cson_value * self )
2009{
2010 if( self )
2011 {
2012 *self = cson_value_undef;
2013 }
2014}
2015
2023{
2024 cson_value * key;
2025 cson_value * value;
2026};
2027#define cson_kvp_empty_m {NULL,NULL}
2028static const cson_kvp cson_kvp_empty = cson_kvp_empty_m;
2029
2048#define CSON_OBJECT_PROPS_SORT 0
2049
2062#define CSON_OBJECT_PROPS_SORT_USE_LENGTH 0
2063
2064#if CSON_OBJECT_PROPS_SORT
2065
2071static int cson_kvp_cmp( void const * lhs, void const * rhs )
2072{
2073 cson_kvp const * lk = *((cson_kvp const * const*)lhs);
2074 cson_kvp const * rk = *((cson_kvp const * const*)rhs);
2075 cson_string const * l = cson_string_value(lk->key);
2076 cson_string const * r = cson_string_value(rk->key);
2077#if CSON_OBJECT_PROPS_SORT_USE_LENGTH
2078 if( l->length < r->length ) return -1;
2079 else if( l->length > r->length ) return 1;
2080 else return strcmp( cson_string_cstr( l ), cson_string_cstr( r ) );
2081#else
2082 return strcmp( cson_string_cstr( l ),
2083 cson_string_cstr( r ) );
2084#endif /*CSON_OBJECT_PROPS_SORT_USE_LENGTH*/
2085}
2086#endif /*CSON_OBJECT_PROPS_SORT*/
2087
2088
2089#if CSON_OBJECT_PROPS_SORT
2090#error "Need to rework this for cson_string-to-cson_value refactoring"
2096static int cson_kvp_cmp_vs_cstr( void const * lhs, void const * rhs )
2097{
2098 char const * lk = (char const *)lhs;
2099 cson_kvp const * rk =
2100 *((cson_kvp const * const*)rhs)
2101 ;
2102#if CSON_OBJECT_PROPS_SORT_USE_LENGTH
2103 unsigned int llen = strlen(lk);
2104 if( llen < rk->key->length ) return -1;
2105 else if( llen > rk->key->length ) return 1;
2106 else return strcmp( lk, cson_string_cstr( rk->key ) );
2107#else
2108 return strcmp( lk, cson_string_cstr( rk->key ) );
2109#endif /*CSON_OBJECT_PROPS_SORT_USE_LENGTH*/
2110}
2111#endif /*CSON_OBJECT_PROPS_SORT*/
2112
2113
2115{
2116 cson_kvp ** list;
2117 unsigned int count;
2118 unsigned int alloced;
2119};
2120typedef struct cson_kvp_list cson_kvp_list;
2121#define cson_kvp_list_empty_m {NULL/*list*/,0/*count*/,0/*alloced*/}
2122static const cson_kvp_list cson_kvp_list_empty = cson_kvp_list_empty_m;
2123
2125{
2126 cson_kvp_list kvp;
2127};
2128/*typedef struct cson_object cson_object;*/
2129#define cson_object_empty_m { cson_kvp_list_empty_m/*kvp*/ }
2130static const cson_object cson_object_empty = cson_object_empty_m;
2131
2133{
2134 cson_value ** list;
2135 unsigned int count;
2136 unsigned int alloced;
2137};
2138typedef struct cson_value_list cson_value_list;
2139#define cson_value_list_empty_m {NULL/*list*/,0/*count*/,0/*alloced*/}
2140static const cson_value_list cson_value_list_empty = cson_value_list_empty_m;
2141
2143{
2144 cson_value_list list;
2145};
2146/*typedef struct cson_array cson_array;*/
2147#define cson_array_empty_m { cson_value_list_empty_m/*list*/ }
2148static const cson_array cson_array_empty = cson_array_empty_m;
2149
2150
2152{
2153 JSON_parser p;
2154 cson_value * root;
2155 cson_value * node;
2156 cson_array stack;
2157 cson_string * ckey;
2158 int errNo;
2159 unsigned int totalKeyCount;
2160 unsigned int totalValueCount;
2161};
2162typedef struct cson_parser cson_parser;
2163static const cson_parser cson_parser_empty = {
2164NULL/*p*/,
2165NULL/*root*/,
2166NULL/*node*/,
2167cson_array_empty_m/*stack*/,
2168NULL/*ckey*/,
21690/*errNo*/,
21700/*totalKeyCount*/,
21710/*totalValueCount*/
2172};
2173
2174#if 1
2175/* The following funcs are declared in generated code (cson_lists.h),
2176 but we need early access to their decls for the Amalgamation build.
2177*/
2178static unsigned int cson_value_list_reserve( cson_value_list * self, unsigned int n );
2179static unsigned int cson_kvp_list_reserve( cson_kvp_list * self, unsigned int n );
2180static int cson_kvp_list_append( cson_kvp_list * self, cson_kvp * cp );
2181static void cson_kvp_list_clean( cson_kvp_list * self,
2182 void (*cleaner)(cson_kvp * obj) );
2183#if 0
2184static int cson_value_list_append( cson_value_list * self, cson_value * cp );
2185static void cson_value_list_clean( cson_value_list * self, void (*cleaner)(cson_value * obj));
2186static int cson_kvp_list_visit( cson_kvp_list * self,
2187 int (*visitor)(cson_kvp * obj, void * visitorState ),
2188 void * visitorState );
2189static int cson_value_list_visit( cson_value_list * self,
2190 int (*visitor)(cson_value * obj, void * visitorState ),
2191 void * visitorState );
2192#endif
2193#endif
2194
2195#if 0
2196# define LIST_T cson_value_list
2197# define VALUE_T cson_value *
2198# define VALUE_T_IS_PTR 1
2199# define LIST_T cson_kvp_list
2200# define VALUE_T cson_kvp *
2201# define VALUE_T_IS_PTR 1
2202#else
2203#endif
2204
2229static cson_value * cson_value_new(cson_type_id t, size_t extra)
2230{
2231 static const size_t vsz = sizeof(cson_value);
2232 const size_t sz = vsz + extra;
2233 size_t tx = 0;
2234 cson_value def = cson_value_undef;
2235 cson_value * v = NULL;
2236 char const * reason = "cson_value_new";
2237 switch(t)
2238 {
2239 case CSON_TYPE_ARRAY:
2240 assert( 0 == extra );
2241 def = cson_value_array_empty;
2242 tx = sizeof(cson_array);
2243 reason = "cson_value:array";
2244 break;
2245 case CSON_TYPE_DOUBLE:
2246 assert( 0 == extra );
2247 def = cson_value_double_empty;
2248 tx = sizeof(cson_double_t);
2249 reason = "cson_value:double";
2250 break;
2251 case CSON_TYPE_INTEGER:
2252 assert( 0 == extra );
2253 def = cson_value_integer_empty;
2254#if !CSON_VOID_PTR_IS_BIG
2255 tx = sizeof(cson_int_t);
2256#endif
2257 reason = "cson_value:int";
2258 break;
2259 case CSON_TYPE_STRING:
2260 assert( 0 != extra );
2261 def = cson_value_string_empty;
2262 tx = sizeof(cson_string);
2263 reason = "cson_value:string";
2264 break;
2265 case CSON_TYPE_OBJECT:
2266 assert( 0 == extra );
2267 def = cson_value_object_empty;
2268 tx = sizeof(cson_object);
2269 reason = "cson_value:object";
2270 break;
2271 default:
2272 assert(0 && "Unhandled type in cson_value_new()!");
2273 return NULL;
2274 }
2275 assert( def.api->typeID != CSON_TYPE_UNDEF );
2276 v = (cson_value *)cson_malloc(sz+tx, reason);
2277 if( v ) {
2278 *v = def;
2279 if(tx || extra){
2280 memset(v+1, 0, tx + extra);
2281 v->value = (void *)(v+1);
2282 }
2283 }
2284 return v;
2285}
2286
2287void cson_value_free(cson_value *v)
2288{
2289 cson_refcount_decr( v );
2290}
2291
2292#if 0 /* we might actually want this later on. */
2294static char cson_value_is_a( cson_value const * v, cson_type_id is )
2295{
2296 return (v && v->api && (v->api->typeID == is)) ? 1 : 0;
2297}
2298#endif
2299
2300cson_type_id cson_value_type_id( cson_value const * v )
2301{
2302 return (v && v->api) ? v->api->typeID : CSON_TYPE_UNDEF;
2303}
2304
2305char cson_value_is_undef( cson_value const * v )
2306{
2307 return ( !v || !v->api || (v->api==&cson_value_api_undef))
2308 ? 1 : 0;
2309}
2310#define ISA(T,TID) char cson_value_is_##T( cson_value const * v ) { \
2311 /*return (v && v->api) ? cson_value_is_a(v,CSON_TYPE_##TID) : 0;*/ \
2312 return (v && (v->api == &cson_value_api_##T)) ? 1 : 0; \
2313 } static const char bogusPlaceHolderForEmacsIndention##TID = CSON_TYPE_##TID
2314ISA(null,NULL);
2315ISA(bool,BOOL);
2316ISA(integer,INTEGER);
2317ISA(double,DOUBLE);
2318ISA(string,STRING);
2319ISA(array,ARRAY);
2320ISA(object,OBJECT);
2321#undef ISA
2322char cson_value_is_number( cson_value const * v )
2323{
2324 return cson_value_is_integer(v) || cson_value_is_double(v);
2325}
2326
2327
2328void cson_value_clean( cson_value * val )
2329{
2330 if( val && val->api && val->api->cleanup )
2331 {
2332 if( ! cson_value_is_builtin( val ) )
2333 {
2334 cson_counter_t const rc = val->refcount;
2335 val->api->cleanup(val);
2336 *val = cson_value_undef;
2337 val->refcount = rc;
2338 }
2339 }
2340}
2341
2342static cson_value * cson_value_array_alloc()
2343{
2344 cson_value * v = cson_value_new(CSON_TYPE_ARRAY,0);
2345 if( NULL != v )
2346 {
2347 cson_array * ar = CSON_ARRAY(v);
2348 assert(NULL != ar);
2349 *ar = cson_array_empty;
2350 }
2351 return v;
2352}
2353
2354static cson_value * cson_value_object_alloc()
2355{
2356 cson_value * v = cson_value_new(CSON_TYPE_OBJECT,0);
2357 if( NULL != v )
2358 {
2359 cson_object * obj = CSON_OBJ(v);
2360 assert(NULL != obj);
2361 *obj = cson_object_empty;
2362 }
2363 return v;
2364}
2365
2366cson_value * cson_value_new_object()
2367{
2368 return cson_value_object_alloc();
2369}
2370
2371cson_object * cson_new_object()
2372{
2373
2374 return cson_value_get_object( cson_value_new_object() );
2375}
2376
2377cson_value * cson_value_new_array()
2378{
2379 return cson_value_array_alloc();
2380}
2381
2382
2383cson_array * cson_new_array()
2384{
2385 return cson_value_get_array( cson_value_new_array() );
2386}
2387
2392static void cson_kvp_clean( cson_kvp * kvp )
2393{
2394 if( kvp )
2395 {
2396 if(kvp->key)
2397 {
2398 cson_value_free(kvp->key);
2399 kvp->key = NULL;
2400 }
2401 if(kvp->value)
2402 {
2403 cson_value_free( kvp->value );
2404 kvp->value = NULL;
2405 }
2406 }
2407}
2408
2409cson_string * cson_kvp_key( cson_kvp const * kvp )
2410{
2411 return kvp ? cson_value_get_string(kvp->key) : NULL;
2412}
2413cson_value * cson_kvp_value( cson_kvp const * kvp )
2414{
2415 return kvp ? kvp->value : NULL;
2416}
2417
2418
2422static void cson_kvp_free( cson_kvp * kvp )
2423{
2424 if( kvp )
2425 {
2426 cson_kvp_clean(kvp);
2427 cson_free(kvp,"cson_kvp");
2428 }
2429}
2430
2431
2438static void cson_value_destroy_object( cson_value * self )
2439{
2440 if(self && self->value) {
2441 cson_object * obj = (cson_object *)self->value;
2442 assert( self->value == obj );
2443 cson_kvp_list_clean( &obj->kvp, cson_kvp_free );
2444 *self = cson_value_undef;
2445 }
2446}
2447
2458static void cson_array_clean( cson_array * ar, char properlyCleanValues )
2459{
2460 if( ar )
2461 {
2462 unsigned int i = 0;
2463 cson_value * val = NULL;
2464 for( ; i < ar->list.count; ++i )
2465 {
2466 val = ar->list.list[i];
2467 if(val)
2468 {
2469 ar->list.list[i] = NULL;
2470 if( properlyCleanValues )
2471 {
2472 cson_value_free( val );
2473 }
2474 }
2475 }
2476 cson_value_list_reserve(&ar->list,0);
2477 ar->list = cson_value_list_empty
2478 /* Pedantic note: reserve(0) already clears the list-specific
2479 fields, but we do this just in case we ever add new fields
2480 to cson_value_list which are not used in the reserve() impl.
2481 */
2482 ;
2483 }
2484}
2485
2492static void cson_value_destroy_array( cson_value * self )
2493{
2494 cson_array * ar = cson_value_get_array(self);
2495 if(ar) {
2496 assert( self->value == ar );
2497 cson_array_clean( ar, 1 );
2498 *self = cson_value_undef;
2499 }
2500}
2501
2502int cson_buffer_fill_from( cson_buffer * dest, cson_data_source_f src, void * state )
2503{
2504 int rc;
2505 enum { BufSize = 1024 * 4 };
2506 char rbuf[BufSize];
2507 size_t total = 0;
2508 unsigned int rlen = 0;
2509 if( ! dest || ! src ) return cson_rc.ArgError;
2510 dest->used = 0;
2511 while(1)
2512 {
2513 rlen = BufSize;
2514 rc = src( state, rbuf, &rlen );
2515 if( rc ) break;
2516 total += rlen;
2517 if( dest->capacity < (total+1) )
2518 {
2519 rc = cson_buffer_reserve( dest, (cson_size_t)(total + 1));
2520 if( 0 != rc ) break;
2521 }
2522 memcpy( dest->mem + dest->used, rbuf, rlen );
2523 dest->used += rlen;
2524 if( rlen < BufSize ) break;
2525 }
2526 if( !rc && dest->used )
2527 {
2528 assert( dest->used < dest->capacity );
2529 dest->mem[dest->used] = 0;
2530 }
2531 return rc;
2532}
2533
2534int cson_data_source_FILE( void * state, void * dest, unsigned int * n )
2535{
2536 FILE * f = (FILE*) state;
2537 if( ! state || ! n || !dest ) return cson_rc.ArgError;
2538 else if( !*n ) return cson_rc.RangeError;
2539 *n = (unsigned int)fread( dest, 1, *n, f );
2540 if( !*n )
2541 {
2542 return feof(f) ? 0 : cson_rc.IOError;
2543 }
2544 return 0;
2545}
2546
2547int cson_parse_FILE( cson_value ** tgt, FILE * src,
2548 cson_parse_opt const * opt, cson_parse_info * err )
2549{
2550 return cson_parse( tgt, cson_data_source_FILE, src, opt, err );
2551}
2552
2553
2554int cson_value_fetch_bool( cson_value const * val, char * v )
2555{
2560 if( ! val || !val->api ) return cson_rc.ArgError;
2561 else
2562 {
2563 int rc = 0;
2564 char b = 0;
2565 switch( val->api->typeID )
2566 {
2567 case CSON_TYPE_ARRAY:
2568 case CSON_TYPE_OBJECT:
2569 b = 1;
2570 break;
2571 case CSON_TYPE_STRING: {
2572 char const * str = cson_string_cstr(cson_value_get_string(val));
2573 b = (str && *str) ? 1 : 0;
2574 break;
2575 }
2576 case CSON_TYPE_UNDEF:
2577 case CSON_TYPE_NULL:
2578 break;
2579 case CSON_TYPE_BOOL:
2580 b = (NULL==val->value) ? 0 : 1;
2581 break;
2582 case CSON_TYPE_INTEGER: {
2583 cson_int_t i = 0;
2584 cson_value_fetch_integer( val, &i );
2585 b = i ? 1 : 0;
2586 break;
2587 }
2588 case CSON_TYPE_DOUBLE: {
2589 cson_double_t d = 0.0;
2590 cson_value_fetch_double( val, &d );
2591 b = (0.0==d) ? 0 : 1;
2592 break;
2593 }
2594 default:
2595 rc = cson_rc.TypeError;
2596 break;
2597 }
2598 if( v ) *v = b;
2599 return rc;
2600 }
2601}
2602
2603char cson_value_get_bool( cson_value const * val )
2604{
2605 char i = 0;
2606 cson_value_fetch_bool( val, &i );
2607 return i;
2608}
2609
2610int cson_value_fetch_integer( cson_value const * val, cson_int_t * v )
2611{
2612 if( ! val || !val->api ) return cson_rc.ArgError;
2613 else
2614 {
2615 cson_int_t i = 0;
2616 int rc = 0;
2617 switch(val->api->typeID)
2618 {
2619 case CSON_TYPE_UNDEF:
2620 case CSON_TYPE_NULL:
2621 i = 0;
2622 break;
2623 case CSON_TYPE_BOOL: {
2624 char b = 0;
2625 cson_value_fetch_bool( val, &b );
2626 i = b;
2627 break;
2628 }
2629 case CSON_TYPE_INTEGER: {
2630 cson_int_t const * x = CSON_INT(val);
2631 if(!x)
2632 {
2633 assert( val == &CSON_SPECIAL_VALUES[CSON_VAL_INT_0] );
2634 }
2635 i = x ? *x : 0;
2636 break;
2637 }
2638 case CSON_TYPE_DOUBLE: {
2639 cson_double_t d = 0.0;
2640 cson_value_fetch_double( val, &d );
2641 i = (cson_int_t)d;
2642 break;
2643 }
2644 case CSON_TYPE_STRING:
2645 case CSON_TYPE_ARRAY:
2646 case CSON_TYPE_OBJECT:
2647 default:
2648 rc = cson_rc.TypeError;
2649 break;
2650 }
2651 if(!rc && v) *v = i;
2652 return rc;
2653 }
2654}
2655
2656cson_int_t cson_value_get_integer( cson_value const * val )
2657{
2658 cson_int_t i = 0;
2659 cson_value_fetch_integer( val, &i );
2660 return i;
2661}
2662
2663int cson_value_fetch_double( cson_value const * val, cson_double_t * v )
2664{
2665 if( ! val || !val->api ) return cson_rc.ArgError;
2666 else
2667 {
2668 cson_double_t d = 0.0;
2669 int rc = 0;
2670 switch(val->api->typeID)
2671 {
2672 case CSON_TYPE_UNDEF:
2673 case CSON_TYPE_NULL:
2674 d = 0;
2675 break;
2676 case CSON_TYPE_BOOL: {
2677 char b = 0;
2678 cson_value_fetch_bool( val, &b );
2679 d = b ? 1.0 : 0.0;
2680 break;
2681 }
2682 case CSON_TYPE_INTEGER: {
2683 cson_int_t i = 0;
2684 cson_value_fetch_integer( val, &i );
2685 d = i;
2686 break;
2687 }
2688 case CSON_TYPE_DOUBLE: {
2689 cson_double_t const* dv = CSON_DBL(val);
2690 d = dv ? *dv : 0.0;
2691 break;
2692 }
2693 default:
2694 rc = cson_rc.TypeError;
2695 break;
2696 }
2697 if(v) *v = d;
2698 return rc;
2699 }
2700}
2701
2702cson_double_t cson_value_get_double( cson_value const * val )
2703{
2704 cson_double_t i = 0.0;
2705 cson_value_fetch_double( val, &i );
2706 return i;
2707}
2708
2709int cson_value_fetch_string( cson_value const * val, cson_string ** dest )
2710{
2711 if( ! val || ! dest ) return cson_rc.ArgError;
2712 else if( ! cson_value_is_string(val) ) return cson_rc.TypeError;
2713 else
2714 {
2715 if( dest ) *dest = CSON_STR(val);
2716 return 0;
2717 }
2718}
2719
2720cson_string * cson_value_get_string( cson_value const * val )
2721{
2722 cson_string * rc = NULL;
2723 cson_value_fetch_string( val, &rc );
2724 return rc;
2725}
2726
2727char const * cson_value_get_cstr( cson_value const * val )
2728{
2729 return cson_string_cstr( cson_value_get_string(val) );
2730}
2731
2732int cson_value_fetch_object( cson_value const * val, cson_object ** obj )
2733{
2734 if( ! val ) return cson_rc.ArgError;
2735 else if( ! cson_value_is_object(val) ) return cson_rc.TypeError;
2736 else
2737 {
2738 if(obj) *obj = CSON_OBJ(val);
2739 return 0;
2740 }
2741}
2742cson_object * cson_value_get_object( cson_value const * v )
2743{
2744 cson_object * obj = NULL;
2745 cson_value_fetch_object( v, &obj );
2746 return obj;
2747}
2748
2749int cson_value_fetch_array( cson_value const * val, cson_array ** ar)
2750{
2751 if( ! val ) return cson_rc.ArgError;
2752 else if( !cson_value_is_array(val) ) return cson_rc.TypeError;
2753 else
2754 {
2755 if(ar) *ar = CSON_ARRAY(val);
2756 return 0;
2757 }
2758}
2759
2760cson_array * cson_value_get_array( cson_value const * v )
2761{
2762 cson_array * ar = NULL;
2763 cson_value_fetch_array( v, &ar );
2764 return ar;
2765}
2766
2767cson_kvp * cson_kvp_alloc()
2768{
2769 cson_kvp * kvp = (cson_kvp*)cson_malloc(sizeof(cson_kvp),"cson_kvp");
2770 if( kvp )
2771 {
2772 *kvp = cson_kvp_empty;
2773 }
2774 return kvp;
2775}
2776
2777
2778
2779int cson_array_append( cson_array * ar, cson_value * v )
2780{
2781 if( !ar || !v ) return cson_rc.ArgError;
2782 else if( (ar->list.count+1) < ar->list.count ) return cson_rc.RangeError;
2783 else
2784 {
2785 if( !ar->list.alloced || (ar->list.count == ar->list.alloced-1))
2786 {
2787 unsigned int const n = ar->list.count ? (ar->list.count*2) : 7;
2788 if( n > cson_value_list_reserve( &ar->list, n ) )
2789 {
2790 return cson_rc.AllocError;
2791 }
2792 }
2793 return cson_array_set( ar, ar->list.count, v );
2794 }
2795}
2796
2797#if 0
2814static cson_value * cson_array_pop_back( cson_array * ar,
2815 char removeRef )
2816{
2817 if( !ar ) return NULL;
2818 else if( ! ar->list.count ) return NULL;
2819 else
2820 {
2821 unsigned int const ndx = --ar->list.count;
2822 cson_value * v = ar->list.list[ndx];
2823 ar->list.list[ndx] = NULL;
2824 if( removeRef )
2825 {
2826 cson_value_free( v );
2827 v = NULL;
2828 }
2829 return v;
2830 }
2831}
2832#endif
2833
2834cson_value * cson_value_new_bool( char v )
2835{
2836 return v ? &CSON_SPECIAL_VALUES[CSON_VAL_TRUE] : &CSON_SPECIAL_VALUES[CSON_VAL_FALSE];
2837}
2838
2839cson_value * cson_value_true()
2840{
2841 return &CSON_SPECIAL_VALUES[CSON_VAL_TRUE];
2842}
2843cson_value * cson_value_false()
2844{
2845 return &CSON_SPECIAL_VALUES[CSON_VAL_FALSE];
2846}
2847
2848cson_value * cson_value_null()
2849{
2850 return &CSON_SPECIAL_VALUES[CSON_VAL_NULL];
2851}
2852
2853cson_value * cson_new_int( cson_int_t v )
2854{
2855 return cson_value_new_integer(v);
2856}
2857
2858cson_value * cson_value_new_integer( cson_int_t v )
2859{
2860 if( 0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_INT_0];
2861 else
2862 {
2863 cson_value * c = cson_value_new(CSON_TYPE_INTEGER,0);
2864#if !defined(NDEBUG) && CSON_VOID_PTR_IS_BIG
2865 assert( sizeof(cson_int_t) <= sizeof(void *) );
2866#endif
2867 if( c )
2868 {
2869 *CSON_INT(c) = v;
2870 }
2871 return c;
2872 }
2873}
2874
2875cson_value * cson_new_double( cson_double_t v )
2876{
2877 return cson_value_new_double(v);
2878}
2879
2880cson_value * cson_value_new_double( cson_double_t v )
2881{
2882 if( 0.0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_DBL_0];
2883 else
2884 {
2885 cson_value * c = cson_value_new(CSON_TYPE_DOUBLE,0);
2886 if( c )
2887 {
2888 *CSON_DBL(c) = v;
2889 }
2890 return c;
2891 }
2892}
2893
2894cson_string * cson_new_string(char const * str, unsigned int len)
2895{
2896 if( !str || !*str || !len ) return &CSON_EMPTY_HOLDER.stringValue;
2897 else
2898 {
2899 cson_value * c = cson_value_new(CSON_TYPE_STRING, len + 1/*NUL byte*/);
2900 cson_string * s = NULL;
2901 if( c )
2902 {
2903 char * dest = NULL;
2904 s = CSON_STR(c);
2905 *s = cson_string_empty;
2906 assert( NULL != s );
2907 s->length = len;
2908 dest = cson_string_str(s);
2909 assert( NULL != dest );
2910 memcpy( dest, str, len );
2911 dest[len] = 0;
2912 }
2913 return s;
2914 }
2915}
2916
2917cson_value * cson_value_new_string( char const * str, unsigned int len )
2918{
2919 return cson_string_value( cson_new_string(str, len) );
2920}
2921
2922int cson_array_value_fetch( cson_array const * ar, unsigned int pos, cson_value ** v )
2923{
2924 if( !ar) return cson_rc.ArgError;
2925 if( pos >= ar->list.count ) return cson_rc.RangeError;
2926 else
2927 {
2928 if(v) *v = ar->list.list[pos];
2929 return 0;
2930 }
2931}
2932
2933cson_value * cson_array_get( cson_array const * ar, unsigned int pos )
2934{
2935 cson_value *v = NULL;
2936 cson_array_value_fetch(ar, pos, &v);
2937 return v;
2938}
2939
2940int cson_array_length_fetch( cson_array const * ar, unsigned int * v )
2941{
2942 if( ! ar || !v ) return cson_rc.ArgError;
2943 else
2944 {
2945 if(v) *v = ar->list.count;
2946 return 0;
2947 }
2948}
2949
2950unsigned int cson_array_length_get( cson_array const * ar )
2951{
2952 unsigned int i = 0;
2953 cson_array_length_fetch(ar, &i);
2954 return i;
2955}
2956
2957int cson_array_reserve( cson_array * ar, unsigned int size )
2958{
2959 if( ! ar ) return cson_rc.ArgError;
2960 else if( size <= ar->list.alloced )
2961 {
2962 /* We don't want to introduce a can of worms by trying to
2963 handle the cleanup from here.
2964 */
2965 return 0;
2966 }
2967 else
2968 {
2969 return (ar->list.alloced > cson_value_list_reserve( &ar->list, size ))
2970 ? cson_rc.AllocError
2971 : 0
2972 ;
2973 }
2974}
2975
2976int cson_array_set( cson_array * ar, unsigned int ndx, cson_value * v )
2977{
2978 if( !ar || !v ) return cson_rc.ArgError;
2979 else if( (ndx+1) < ndx) /* overflow */return cson_rc.RangeError;
2980 else
2981 {
2982 unsigned const int len = cson_value_list_reserve( &ar->list, ndx+1 );
2983 if( len <= ndx ) return cson_rc.AllocError;
2984 else
2985 {
2986 cson_value * old = ar->list.list[ndx];
2987 if( old )
2988 {
2989 if(old == v) return 0;
2990 else cson_value_free(old);
2991 }
2992 cson_refcount_incr( v );
2993 ar->list.list[ndx] = v;
2994 if( ndx >= ar->list.count )
2995 {
2996 ar->list.count = ndx+1;
2997 }
2998 return 0;
2999 }
3000 }
3001}
3002
3011static cson_kvp * cson_object_search_impl( cson_object const * obj, char const * key, unsigned int * ndx )
3012{
3013 if( obj && key && *key && obj->kvp.count)
3014 {
3015#if CSON_OBJECT_PROPS_SORT
3016 cson_kvp ** s = (cson_kvp**)
3017 bsearch( key, obj->kvp.list,
3018 obj->kvp.count, sizeof(cson_kvp*),
3019 cson_kvp_cmp_vs_cstr );
3020 if( ndx && s )
3021 { /* index of found record is required by
3022 cson_object_unset(). Calculate the offset based on s...*/
3023#if 0
3024 *ndx = (((unsigned char const *)s - ((unsigned char const *)obj->kvp.list))
3025 / sizeof(cson_kvp*));
3026#else
3027 *ndx = s - obj->kvp.list;
3028#endif
3029 }
3030 return s ? *s : NULL;
3031#else
3032 cson_kvp_list const * li = &obj->kvp;
3033 unsigned int i = 0;
3034 cson_kvp * kvp;
3035 const unsigned int klen = (unsigned int)strlen(key);
3036 for( ; i < li->count; ++i )
3037 {
3038 cson_string const * sKey;
3039 kvp = li->list[i];
3040 assert( kvp && kvp->key );
3041 sKey = cson_value_get_string(kvp->key);
3042 assert(sKey);
3043 if( sKey->length != klen ) continue;
3044 else if(0==strcmp(key,cson_string_cstr(sKey)))
3045 {
3046 if(ndx) *ndx = i;
3047 return kvp;
3048 }
3049 }
3050#endif
3051 }
3052 return NULL;
3053}
3054
3055cson_value * cson_object_get( cson_object const * obj, char const * key )
3056{
3057 cson_kvp * kvp = cson_object_search_impl( obj, key, NULL );
3058 return kvp ? kvp->value : NULL;
3059}
3060
3061cson_value * cson_object_get_s( cson_object const * obj, cson_string const *key )
3062{
3063 cson_kvp * kvp = cson_object_search_impl( obj, cson_string_cstr(key), NULL );
3064 return kvp ? kvp->value : NULL;
3065}
3066
3067
3068#if CSON_OBJECT_PROPS_SORT
3069static void cson_object_sort_props( cson_object * obj )
3070{
3071 assert( NULL != obj );
3072 if( obj->kvp.count )
3073 {
3074 qsort( obj->kvp.list, obj->kvp.count, sizeof(cson_kvp*),
3075 cson_kvp_cmp );
3076 }
3077
3078}
3079#endif
3080
3081int cson_object_unset( cson_object * obj, char const * key )
3082{
3083 if( ! obj || !key || !*key ) return cson_rc.ArgError;
3084 else
3085 {
3086 unsigned int ndx = 0;
3087 cson_kvp * kvp = cson_object_search_impl( obj, key, &ndx );
3088 if( ! kvp )
3089 {
3090 return cson_rc.NotFoundError;
3091 }
3092 assert( obj->kvp.count > 0 );
3093 assert( obj->kvp.list[ndx] == kvp );
3094 cson_kvp_free( kvp );
3095 obj->kvp.list[ndx] = NULL;
3096 { /* if my brain were bigger i'd use memmove(). */
3097 unsigned int i = ndx;
3098 for( ; i < obj->kvp.count; ++i )
3099 {
3100 obj->kvp.list[i] =
3101 (i < (obj->kvp.alloced-1))
3102 ? obj->kvp.list[i+1]
3103 : NULL;
3104 }
3105 }
3106 obj->kvp.list[--obj->kvp.count] = NULL;
3107#if CSON_OBJECT_PROPS_SORT
3108 cson_object_sort_props( obj );
3109#endif
3110 return 0;
3111 }
3112}
3113
3114int cson_object_set_s( cson_object * obj, cson_string * key, cson_value * v )
3115{
3116 if( !obj || !key ) return cson_rc.ArgError;
3117 else if( NULL == v ) return cson_object_unset( obj, cson_string_cstr(key) );
3118 else
3119 {
3120 char const * cKey;
3121 cson_value * vKey;
3122 cson_kvp * kvp;
3123 vKey = cson_string_value(key);
3124 assert(vKey && (key==CSON_STR(vKey)));
3125 if( vKey == CSON_VCAST(obj) ){
3126 return cson_rc.ArgError;
3127 }
3128 cKey = cson_string_cstr(key);
3129 kvp = cson_object_search_impl( obj, cKey, NULL );
3130 if( kvp )
3131 { /* "I told 'em we've already got one!" */
3132 if( kvp->key != vKey ){
3133 cson_value_free( kvp->key );
3134 cson_refcount_incr(vKey);
3135 kvp->key = vKey;
3136 }
3137 if(kvp->value != v){
3138 cson_value_free( kvp->value );
3139 cson_refcount_incr( v );
3140 kvp->value = v;
3141 }
3142 return 0;
3143 }
3144 if( !obj->kvp.alloced || (obj->kvp.count == obj->kvp.alloced-1))
3145 { /* reserve space */
3146 unsigned int const n = obj->kvp.count ? (obj->kvp.count*2) : 6;
3147 if( n > cson_kvp_list_reserve( &obj->kvp, n ) )
3148 {
3149 return cson_rc.AllocError;
3150 }
3151 }
3152 { /* insert new item... */
3153 int rc = 0;
3154 kvp = cson_kvp_alloc();
3155 if( ! kvp )
3156 {
3157 return cson_rc.AllocError;
3158 }
3159 rc = cson_kvp_list_append( &obj->kvp, kvp );
3160 if( 0 != rc )
3161 {
3162 cson_kvp_free(kvp);
3163 }
3164 else
3165 {
3166 cson_refcount_incr(vKey);
3167 cson_refcount_incr(v);
3168 kvp->key = vKey;
3169 kvp->value = v;
3170#if CSON_OBJECT_PROPS_SORT
3171 cson_object_sort_props( obj );
3172#endif
3173 }
3174 return rc;
3175 }
3176 }
3177
3178}
3179int cson_object_set( cson_object * obj, char const * key, cson_value * v )
3180{
3181 if( ! obj || !key || !*key ) return cson_rc.ArgError;
3182 else if( NULL == v )
3183 {
3184 return cson_object_unset( obj, key );
3185 }
3186 else
3187 {
3188 cson_string * cs = cson_new_string(key,(unsigned int)strlen(key));
3189 if(!cs) return cson_rc.AllocError;
3190 else
3191 {
3192 int const rc = cson_object_set_s(obj, cs, v);
3193 if(rc) cson_value_free(cson_string_value(cs));
3194 return rc;
3195 }
3196 }
3197}
3198
3199cson_value * cson_object_take( cson_object * obj, char const * key )
3200{
3201 if( ! obj || !key || !*key ) return NULL;
3202 else
3203 {
3204 /* FIXME: this is 90% identical to cson_object_unset(),
3205 only with different refcount handling.
3206 Consolidate them.
3207 */
3208 unsigned int ndx = 0;
3209 cson_kvp * kvp = cson_object_search_impl( obj, key, &ndx );
3210 cson_value * rc = NULL;
3211 if( ! kvp )
3212 {
3213 return NULL;
3214 }
3215 assert( obj->kvp.count > 0 );
3216 assert( obj->kvp.list[ndx] == kvp );
3217 rc = kvp->value;
3218 assert( rc );
3219 kvp->value = NULL;
3220 cson_kvp_free( kvp );
3221 assert( rc->refcount > 0 );
3222 --rc->refcount;
3223 obj->kvp.list[ndx] = NULL;
3224 { /* if my brain were bigger i'd use memmove(). */
3225 unsigned int i = ndx;
3226 for( ; i < obj->kvp.count; ++i )
3227 {
3228 obj->kvp.list[i] =
3229 (i < (obj->kvp.alloced-1))
3230 ? obj->kvp.list[i+1]
3231 : NULL;
3232 }
3233 }
3234 obj->kvp.list[--obj->kvp.count] = NULL;
3235#if CSON_OBJECT_PROPS_SORT
3236 cson_object_sort_props( obj );
3237#endif
3238 return rc;
3239 }
3240}
3254static int cson_parser_set_key( cson_parser * p, cson_value * val )
3255{
3256 assert( p && val );
3257
3258 if( p->ckey && cson_value_is_object(p->node) )
3259 {
3260 int rc;
3261 cson_object * obj = cson_value_get_object(p->node);
3262 cson_kvp * kvp = NULL;
3263 assert( obj && (p->node->value == obj) );
3269 if( !obj->kvp.alloced || (obj->kvp.count == obj->kvp.alloced-1))
3270 {
3271 if( obj->kvp.alloced > cson_kvp_list_reserve( &obj->kvp, obj->kvp.count ? (obj->kvp.count*2) : 5 ) )
3272 {
3273 cson_value_free(val);
3274 return cson_rc.AllocError;
3275 }
3276 }
3277 kvp = cson_kvp_alloc();
3278 if( ! kvp )
3279 {
3280 cson_value_free(val);
3281 return cson_rc.AllocError;
3282 }
3283 kvp->key = cson_string_value(p->ckey)/*transfer ownership*/;
3284 assert(0 == kvp->key->refcount);
3285 cson_refcount_incr(kvp->key);
3286 p->ckey = NULL;
3287 kvp->value = val;
3288 cson_refcount_incr( val );
3289 rc = cson_kvp_list_append( &obj->kvp, kvp );
3290 if( 0 != rc )
3291 {
3292 cson_kvp_free( kvp );
3293 }
3294 else
3295 {
3296 ++p->totalValueCount;
3297 }
3298 return rc;
3299 }
3300 else
3301 {
3302 if(val) cson_value_free(val);
3303 return p->errNo = cson_rc.InternalError;
3304 }
3305
3306}
3307
3318static int cson_parser_push_value( cson_parser * p, cson_value * val )
3319{
3320 if( p->ckey )
3321 { /* we're in Object mode */
3322 assert( cson_value_is_object( p->node ) );
3323 return cson_parser_set_key( p, val );
3324 }
3325 else if( cson_value_is_array( p->node ) )
3326 { /* we're in Array mode */
3327 cson_array * ar = cson_value_get_array( p->node );
3328 int rc;
3329 assert( ar && (ar == p->node->value) );
3330 rc = cson_array_append( ar, val );
3331 if( 0 != rc )
3332 {
3333 cson_value_free(val);
3334 }
3335 else
3336 {
3337 ++p->totalValueCount;
3338 }
3339 return rc;
3340 }
3341 else
3342 { /* WTF? */
3343 assert( 0 && "Internal error in cson_parser code" );
3344 return p->errNo = cson_rc.InternalError;
3345 }
3346}
3347
3352static int cson_parse_callback( void * cx, int type, JSON_value const * value )
3353{
3354 cson_parser * p = (cson_parser *)cx;
3355 int rc = 0;
3356#define ALLOC_V(T,V) cson_value * v = cson_value_new_##T(V); if( ! v ) { rc = cson_rc.AllocError; break; }
3357 switch(type) {
3358 case JSON_T_ARRAY_BEGIN:
3359 case JSON_T_OBJECT_BEGIN: {
3360 cson_value * obja = (JSON_T_ARRAY_BEGIN == type)
3361 ? cson_value_new_array()
3362 : cson_value_new_object();
3363 if( ! obja )
3364 {
3365 p->errNo = cson_rc.AllocError;
3366 break;
3367 }
3368 if( 0 != rc ) break;
3369 if( ! p->root )
3370 {
3371 p->root = p->node = obja;
3372 rc = cson_array_append( &p->stack, obja );
3373 if( 0 != rc )
3374 { /* work around a (potential) corner case in the cleanup code. */
3375 cson_value_free( p->root );
3376 p->root = NULL;
3377 }
3378 else
3379 {
3380 cson_refcount_incr( p->root )
3381 /* simplifies cleanup later on. */
3382 ;
3383 ++p->totalValueCount;
3384 }
3385 }
3386 else
3387 {
3388 rc = cson_array_append( &p->stack, obja );
3389 if(rc) cson_value_free( obja );
3390 else
3391 {
3392 rc = cson_parser_push_value( p, obja );
3393 if( 0 == rc ) p->node = obja;
3394 }
3395 }
3396 break;
3397 }
3398 case JSON_T_ARRAY_END:
3399 case JSON_T_OBJECT_END: {
3400 if( 0 == p->stack.list.count )
3401 {
3402 rc = cson_rc.RangeError;
3403 break;
3404 }
3405#if CSON_OBJECT_PROPS_SORT
3406 if( cson_value_is_object(p->node) )
3407 {/* kludge: the parser uses custom cson_object property
3408 insertion as a malloc/strcpy-reduction optimization.
3409 Because of that, we have to sort the property list
3410 ourselves...
3411 */
3412 cson_object * obj = cson_value_get_object(p->node);
3413 assert( NULL != obj );
3414 cson_object_sort_props( obj );
3415 }
3416#endif
3417
3418#if 1
3419 /* Reminder: do not use cson_array_pop_back( &p->stack )
3420 because that will clean up the object, and we don't want
3421 that. We just want to forget this reference
3422 to it. The object is either the root or was pushed into
3423 an object/array in the parse tree (and is owned by that
3424 object/array).
3425 */
3426 --p->stack.list.count;
3427 assert( p->node == p->stack.list.list[p->stack.list.count] );
3428 cson_refcount_decr( p->node )
3429 /* p->node might be owned by an outer object but we
3430 need to remove the list's reference. For the
3431 root node we manually add a reference to
3432 avoid a special case here. Thus when we close
3433 the root node, its refcount is still 1.
3434 */;
3435 p->stack.list.list[p->stack.list.count] = NULL;
3436 if( p->stack.list.count )
3437 {
3438 p->node = p->stack.list.list[p->stack.list.count-1];
3439 }
3440 else
3441 {
3442 p->node = p->root;
3443 }
3444#else
3445 /*
3446 Causing a leak?
3447 */
3448 cson_array_pop_back( &p->stack, 1 );
3449 if( p->stack.list.count )
3450 {
3451 p->node = p->stack.list.list[p->stack.list.count-1];
3452 }
3453 else
3454 {
3455 p->node = p->root;
3456 }
3457 assert( p->node && (1==p->node->refcount) );
3458#endif
3459 break;
3460 }
3461 case JSON_T_INTEGER: {
3462 ALLOC_V(integer, value->vu.integer_value );
3463 rc = cson_parser_push_value( p, v );
3464 break;
3465 }
3466 case JSON_T_FLOAT: {
3467 ALLOC_V(double, value->vu.float_value );
3468 rc = cson_parser_push_value( p, v );
3469 break;
3470 }
3471 case JSON_T_NULL: {
3472 rc = cson_parser_push_value( p, cson_value_null() );
3473 break;
3474 }
3475 case JSON_T_TRUE: {
3476 rc = cson_parser_push_value( p, cson_value_true() );
3477 break;
3478 }
3479 case JSON_T_FALSE: {
3480 rc = cson_parser_push_value( p, cson_value_false() );
3481 break;
3482 }
3483 case JSON_T_KEY: {
3484 assert(!p->ckey);
3485 p->ckey = cson_new_string( value->vu.str.value, (unsigned int)value->vu.str.length );
3486 if( ! p->ckey )
3487 {
3488 rc = cson_rc.AllocError;
3489 break;
3490 }
3491 ++p->totalKeyCount;
3492 break;
3493 }
3494 case JSON_T_STRING: {
3495 cson_value * v = cson_value_new_string( value->vu.str.value, (unsigned int)value->vu.str.length );
3496 rc = ( NULL == v )
3497 ? cson_rc.AllocError
3498 : cson_parser_push_value( p, v );
3499 break;
3500 }
3501 default:
3502 assert(0);
3503 rc = cson_rc.InternalError;
3504 break;
3505 }
3506#undef ALLOC_V
3507 return ((p->errNo = rc)) ? 0 : 1;
3508}
3509
3510
3514static int cson_json_err_to_rc( JSON_error jrc )
3515{
3516 switch(jrc)
3517 {
3518 case JSON_E_NONE: return 0;
3519 case JSON_E_INVALID_CHAR: return cson_rc.Parse_INVALID_CHAR;
3520 case JSON_E_INVALID_KEYWORD: return cson_rc.Parse_INVALID_KEYWORD;
3521 case JSON_E_INVALID_ESCAPE_SEQUENCE: return cson_rc.Parse_INVALID_ESCAPE_SEQUENCE;
3522 case JSON_E_INVALID_UNICODE_SEQUENCE: return cson_rc.Parse_INVALID_UNICODE_SEQUENCE;
3523 case JSON_E_INVALID_NUMBER: return cson_rc.Parse_INVALID_NUMBER;
3524 case JSON_E_NESTING_DEPTH_REACHED: return cson_rc.Parse_NESTING_DEPTH_REACHED;
3525 case JSON_E_UNBALANCED_COLLECTION: return cson_rc.Parse_UNBALANCED_COLLECTION;
3526 case JSON_E_EXPECTED_KEY: return cson_rc.Parse_EXPECTED_KEY;
3527 case JSON_E_EXPECTED_COLON: return cson_rc.Parse_EXPECTED_COLON;
3528 case JSON_E_OUT_OF_MEMORY: return cson_rc.AllocError;
3529 default:
3530 return cson_rc.InternalError;
3531 }
3532}
3533
3548static int cson_parser_clean( cson_parser * p )
3549{
3550 if( ! p ) return cson_rc.ArgError;
3551 else
3552 {
3553 if( p->p )
3554 {
3555 delete_JSON_parser(p->p);
3556 p->p = NULL;
3557 }
3558 if( p->ckey ){
3559 cson_value_free(cson_string_value(p->ckey));
3560 }
3561 cson_array_clean( &p->stack, 1 );
3562 if( p->root )
3563 {
3564 cson_value_free( p->root );
3565 }
3566 *p = cson_parser_empty;
3567 return 0;
3568 }
3569}
3570
3571
3572int cson_parse( cson_value ** tgt, cson_data_source_f src, void * state,
3573 cson_parse_opt const * opt_, cson_parse_info * info_ )
3574{
3575 unsigned char ch[2] = {0,0};
3576 cson_parse_opt const opt = opt_ ? *opt_ : cson_parse_opt_empty;
3577 int rc = 0;
3578 unsigned int len = 1;
3579 cson_parse_info info = info_ ? *info_ : cson_parse_info_empty;
3580 cson_parser p = cson_parser_empty;
3581 if( ! tgt || ! src ) return cson_rc.ArgError;
3582
3583 {
3584 JSON_config jopt = {0};
3585 init_JSON_config( &jopt );
3586 jopt.allow_comments = opt.allowComments;
3587 jopt.depth = opt.maxDepth;
3588 jopt.callback_ctx = &p;
3589 jopt.handle_floats_manually = 0;
3590 jopt.callback = cson_parse_callback;
3591 p.p = new_JSON_parser(&jopt);
3592 if( ! p.p )
3593 {
3594 return cson_rc.AllocError;
3595 }
3596 }
3597 do
3598 { /* FIXME: buffer the input in multi-kb chunks. */
3599 len = 1;
3600 ch[0] = 0;
3601 rc = src( state, ch, &len );
3602 if( 0 != rc ) break;
3603 else if( !len /* EOF */ ) break;
3604 ++info.length;
3605 if('\n' == ch[0])
3606 {
3607 ++info.line;
3608 info.col = 0;
3609 }
3610 if( ! JSON_parser_char(p.p, ch[0]) )
3611 {
3612 rc = cson_json_err_to_rc( JSON_parser_get_last_error(p.p) );
3613 if(0==rc) rc = p.errNo;
3614 if(0==rc) rc = cson_rc.InternalError;
3615 info.errorCode = rc;
3616 break;
3617 }
3618 if( '\n' != ch[0]) ++info.col;
3619 } while(1);
3620 if( info_ )
3621 {
3622 info.totalKeyCount = p.totalKeyCount;
3623 info.totalValueCount = p.totalValueCount;
3624 *info_ = info;
3625 }
3626 if( 0 != rc )
3627 {
3628 cson_parser_clean(&p);
3629 return rc;
3630 }
3631 if( ! JSON_parser_done(p.p) )
3632 {
3633 rc = cson_json_err_to_rc( JSON_parser_get_last_error(p.p) );
3634 cson_parser_clean(&p);
3635 if(0==rc) rc = p.errNo;
3636 if(0==rc) rc = cson_rc.InternalError;
3637 }
3638 else
3639 {
3640 cson_value * root = p.root;
3641 p.root = NULL;
3642 cson_parser_clean(&p);
3643 if( root )
3644 {
3645 assert( (1 == root->refcount) && "Detected memory mismanagement in the parser." );
3646 root->refcount = 0
3647 /* HUGE KLUDGE! Avoids having one too many references
3648 in some client code, leading to a leak. Here we're
3649 accommodating a memory management workaround in the
3650 parser code which manually adds a reference to the
3651 root node to keep it from being cleaned up
3652 prematurely.
3653 */;
3654 *tgt = root;
3655 }
3656 else
3657 { /* then can happen on empty input. */
3658 rc = cson_rc.UnknownError;
3659 }
3660 }
3661 return rc;
3662}
3663
3673/*
3674** This lookup table is used to help decode the first byte of
3675** a multi-byte UTF8 character.
3676*/
3677static const unsigned char cson_utfTrans1[] = {
3678 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
3679 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
3680 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
3681 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
3682 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
3683 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
3684 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
3685 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00
3686};
3687
3688
3689/*
3690** Translate a single UTF-8 character. Return the unicode value.
3691**
3692** During translation, assume that the byte that zTerm points
3693** is a 0x00.
3694**
3695** Write a pointer to the next unread byte back into *pzNext.
3696**
3697** Notes On Invalid UTF-8:
3698**
3699** * This routine never allows a 7-bit character (0x00 through 0x7f) to
3700** be encoded as a multi-byte character. Any multi-byte character that
3701** attempts to encode a value between 0x00 and 0x7f is rendered as 0xfffd.
3702**
3703** * This routine never allows a UTF16 surrogate value to be encoded.
3704** If a multi-byte character attempts to encode a value between
3705** 0xd800 and 0xe000 then it is rendered as 0xfffd.
3706**
3707** * Bytes in the range of 0x80 through 0xbf which occur as the first
3708** byte of a character are interpreted as single-byte characters
3709** and rendered as themselves even though they are technically
3710** invalid characters.
3711**
3712** * This routine accepts an infinite number of different UTF8 encodings
3713** for unicode values 0x80 and greater. It do not change over-length
3714** encodings to 0xfffd as some systems recommend.
3715*/
3716#define READ_UTF8(zIn, zTerm, c) \
3717 c = *(zIn++); \
3718 if( c>=0xc0 ){ \
3719 c = cson_utfTrans1[c-0xc0]; \
3720 while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \
3721 c = (c<<6) + (0x3f & *(zIn++)); \
3722 } \
3723 if( c<0x80 \
3724 || (c&0xFFFFF800)==0xD800 \
3725 || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
3726 }
3727static int cson_utf8Read(
3728 const unsigned char *z, /* First byte of UTF-8 character */
3729 const unsigned char *zTerm, /* Pretend this byte is 0x00 */
3730 const unsigned char **pzNext /* Write first byte past UTF-8 char here */
3731){
3732 int c;
3733 READ_UTF8(z, zTerm, c);
3734 *pzNext = z;
3735 return c;
3736}
3737#undef READ_UTF8
3738
3739#ifdef _MSC_VER
3740# if _MSC_VER >= 1400 /* Visual Studio 2005 and up */
3741# pragma warning( pop )
3742# endif
3743#endif
3744
3745unsigned int cson_string_length_utf8( cson_string const * str )
3746{
3747 if( ! str ) return 0;
3748 else
3749 {
3750 char unsigned const * pos = (char unsigned const *)cson_string_cstr(str);
3751 char unsigned const * end = pos + str->length;
3752 unsigned int rc = 0;
3753 for( ; (pos < end) && cson_utf8Read(pos, end, &pos);
3754 ++rc )
3755 {
3756 };
3757 return rc;
3758 }
3759}
3760
3773static int cson_str_to_json( char const * str, unsigned int len,
3774 char escapeFwdSlash,
3775 cson_data_dest_f f, void * state )
3776{
3777 if( NULL == f ) return cson_rc.ArgError;
3778 else if( !str || !*str || (0 == len) )
3779 { /* special case for 0-length strings. */
3780 return f( state, "\"\"", 2 );
3781 }
3782 else
3783 {
3784 unsigned char const * pos = (unsigned char const *)str;
3785 unsigned char const * end = (unsigned char const *)(str ? (str + len) : NULL);
3786 unsigned char const * next = NULL;
3787 int ch;
3788 unsigned char clen = 0;
3789 char escChar[3] = {'\\',0,0};
3790 enum { UBLen = 8 };
3791 char ubuf[UBLen];
3792 int rc = 0;
3793 rc = f(state, "\"", 1 );
3794 for( ; (pos < end) && (0 == rc); pos += clen )
3795 {
3796 ch = cson_utf8Read(pos, end, &next);
3797 if( 0 == ch ) break;
3798 assert( next > pos );
3799 clen = (char)(int)(next - pos);
3800 assert( clen );
3801 if( 1 == clen )
3802 { /* ASCII */
3803#if defined(CSON_FOSSIL_MODE)
3804 /* Workaround for fossil repo artifact
3805 f460839cff85d4e4f1360b366bb2858cef1411ea,
3806 which has what appears to be latin1-encoded
3807 text. file(1) thinks it's a FORTRAN program.
3808 */
3809 if(0xfffd==ch){
3810 assert(*pos != ch);
3811 /* MARKER("ch=%04x, *pos=%04x\n", ch, *pos); */
3812 ch = *pos
3813 /* We should arguably translate to '?', and
3814 will if this problem ever comes up with a
3815 non-latin1 encoding. For latin1 this
3816 workaround incidentally corrects the output
3817 to proper UTF8-escaped characters, and only
3818 for that reason is it being kept around.
3819 */;
3820 goto assume_latin1;
3821 }
3822#endif
3823 assert( (*pos == ch) && "Invalid UTF8" );
3824 escChar[1] = 0;
3825 switch(ch)
3826 {
3827 case '\t': escChar[1] = 't'; break;
3828 case '\r': escChar[1] = 'r'; break;
3829 case '\n': escChar[1] = 'n'; break;
3830 case '\f': escChar[1] = 'f'; break;
3831 case '\b': escChar[1] = 'b'; break;
3832 case '/':
3833 /*
3834 Regarding escaping of forward-slashes. See the main exchange below...
3835
3836 --------------
3837 From: Douglas Crockford <douglas@crockford.com>
3838 To: Stephan Beal <sgbeal@googlemail.com>
3839 Subject: Re: Is escaping of forward slashes required?
3840
3841 It is allowed, not required. It is allowed so that JSON can be safely
3842 embedded in HTML, which can freak out when seeing strings containing
3843 "</". JSON tolerates "<\/" for this reason.
3844
3845 On 4/8/2011 2:09 PM, Stephan Beal wrote:
3846 > Hello, Jsonites,
3847 >
3848 > i'm a bit confused on a small grammatic detail of JSON:
3849 >
3850 > if i'm reading the grammar chart on http://www.json.org/ correctly,
3851 > forward slashes (/) are supposed to be escaped in JSON. However, the
3852 > JSON class provided with my browsers (Chrome and FF, both of which i
3853 > assume are fairly standards/RFC-compliant) do not escape such characters.
3854 >
3855 > Is backslash-escaping forward slashes required? If so, what is the
3856 > justification for it? (i ask because i find it unnecessary and hard to
3857 > look at.)
3858 --------------
3859 */
3860 if( escapeFwdSlash ) escChar[1] = '/';
3861 break;
3862 case '\\': escChar[1] = '\\'; break;
3863 case '"': escChar[1] = '"'; break;
3864 default: break;
3865 }
3866 if( escChar[1])
3867 {
3868 rc = f(state, escChar, 2);
3869 }
3870 else
3871 {
3872 rc = f(state, (char const *)pos, clen);
3873 }
3874 continue;
3875 }
3876 else
3877 { /* UTF: transform it to \uXXXX */
3878#if defined(CSON_FOSSIL_MODE)
3879 assume_latin1:
3880#endif
3881 memset(ubuf,0,UBLen);
3882 rc = sprintf(ubuf, "\\u%04x",ch);
3883 if( rc != 6 )
3884 {
3885 rc = cson_rc.RangeError;
3886 break;
3887 }
3888 rc = f( state, ubuf, 6 );
3889 continue;
3890 }
3891 }
3892 if( 0 == rc )
3893 {
3894 rc = f(state, "\"", 1 );
3895 }
3896 return rc;
3897 }
3898}
3899
3900int cson_object_iter_init( cson_object const * obj, cson_object_iterator * iter )
3901{
3902 if( ! obj || !iter ) return cson_rc.ArgError;
3903 else
3904 {
3905 iter->obj = obj;
3906 iter->pos = 0;
3907 return 0;
3908 }
3909}
3910
3911cson_kvp * cson_object_iter_next( cson_object_iterator * iter )
3912{
3913 if( ! iter || !iter->obj ) return NULL;
3914 else if( iter->pos >= iter->obj->kvp.count ) return NULL;
3915 else
3916 {
3917 cson_kvp * rc = iter->obj->kvp.list[iter->pos++];
3918 while( (NULL==rc) && (iter->pos < iter->obj->kvp.count))
3919 {
3920 rc = iter->obj->kvp.list[iter->pos++];
3921 }
3922 return rc;
3923 }
3924}
3925
3926static int cson_output_null( cson_data_dest_f f, void * state )
3927{
3928 if( !f ) return cson_rc.ArgError;
3929 else
3930 {
3931 return f(state, "null", 4);
3932 }
3933}
3934
3935static int cson_output_bool( cson_value const * src, cson_data_dest_f f, void * state )
3936{
3937 if( !f ) return cson_rc.ArgError;
3938 else
3939 {
3940 char const v = cson_value_get_bool(src);
3941 return f(state, v ? "true" : "false", v ? 4 : 5);
3942 }
3943}
3944
3945static int cson_output_integer( cson_value const * src, cson_data_dest_f f, void * state )
3946{
3947 if( !f ) return cson_rc.ArgError;
3948 else if( !cson_value_is_integer(src) ) return cson_rc.TypeError;
3949 else
3950 {
3951 enum { BufLen = 100 };
3952 char b[BufLen];
3953 int rc;
3954 memset( b, 0, BufLen );
3955 rc = sprintf( b, "%"CSON_INT_T_PFMT, cson_value_get_integer(src) )
3956 /* Reminder: snprintf() is C99 */
3957 ;
3958 return ( rc<=0 )
3959 ? cson_rc.RangeError
3960 : f( state, b, (unsigned int)rc )
3961 ;
3962 }
3963}
3964
3965static int cson_output_double( cson_value const * src, cson_data_dest_f f, void * state )
3966{
3967 if( !f ) return cson_rc.ArgError;
3968 else if( !cson_value_is_double(src) ) return cson_rc.TypeError;
3969 else
3970 {
3971 enum { BufLen = 128 /* this must be relatively large or huge
3972 doubles can cause us to overrun here,
3973 resulting in stack-smashing errors.
3974 */};
3975 char b[BufLen];
3976 int rc;
3977 memset( b, 0, BufLen );
3978 rc = sprintf( b, "%"CSON_DOUBLE_T_PFMT, cson_value_get_double(src) )
3979 /* Reminder: snprintf() is C99 */
3980 ;
3981 if( rc<=0 ) return cson_rc.RangeError;
3982 else if(1)
3983 { /* Strip trailing zeroes before passing it on... */
3984 unsigned int urc = (unsigned int)rc;
3985 char * pos = b + urc - 1;
3986 for( ; ('0' == *pos) && urc && (*(pos-1) != '.'); --pos, --urc )
3987 {
3988 *pos = 0;
3989 }
3990 assert(urc && *pos);
3991 return f( state, b, urc );
3992 }
3993 else
3994 {
3995 unsigned int urc = (unsigned int)rc;
3996 return f( state, b, urc );
3997 }
3998 return 0;
3999 }
4000}
4001
4002static int cson_output_string( cson_value const * src, char escapeFwdSlash, cson_data_dest_f f, void * state )
4003{
4004 if( !f ) return cson_rc.ArgError;
4005 else if( ! cson_value_is_string(src) ) return cson_rc.TypeError;
4006 else
4007 {
4008 cson_string const * str = cson_value_get_string(src);
4009 assert( NULL != str );
4010 return cson_str_to_json(cson_string_cstr(str), str->length, escapeFwdSlash, f, state);
4011 }
4012}
4013
4014
4026static int cson_output_indent( cson_data_dest_f f, void * state,
4027 unsigned char blanks, unsigned int depth )
4028{
4029 if( 0 == blanks ) return 0;
4030 else
4031 {
4032#if 0
4033 /* FIXME: stuff the indention into the buffer and make a single
4034 call to f().
4035 */
4036 enum { BufLen = 200 };
4037 char buf[BufLen];
4038#endif
4039 unsigned int i;
4040 unsigned int x;
4041 char const ch = (1==blanks) ? '\t' : ' ';
4042 int rc = f(state, "\n", 1 );
4043 for( i = 0; (i < depth) && (0 == rc); ++i )
4044 {
4045 for( x = 0; (x < blanks) && (0 == rc); ++x )
4046 {
4047 rc = f(state, &ch, 1);
4048 }
4049 }
4050 return rc;
4051 }
4052}
4053
4054static int cson_output_array( cson_value const * src, cson_data_dest_f f, void * state,
4055 cson_output_opt const * fmt, unsigned int level );
4056static int cson_output_object( cson_value const * src, cson_data_dest_f f, void * state,
4057 cson_output_opt const * fmt, unsigned int level );
4064static int cson_output_impl( cson_value const * src, cson_data_dest_f f, void * state,
4065 cson_output_opt const * fmt, unsigned int level )
4066{
4067 if( ! src || !f || !src->api ) return cson_rc.ArgError;
4068 else
4069 {
4070 int rc = 0;
4071 assert(fmt);
4072 switch( src->api->typeID )
4073 {
4074 case CSON_TYPE_UNDEF:
4075 case CSON_TYPE_NULL:
4076 rc = cson_output_null(f, state);
4077 break;
4078 case CSON_TYPE_BOOL:
4079 rc = cson_output_bool(src, f, state);
4080 break;
4081 case CSON_TYPE_INTEGER:
4082 rc = cson_output_integer(src, f, state);
4083 break;
4084 case CSON_TYPE_DOUBLE:
4085 rc = cson_output_double(src, f, state);
4086 break;
4087 case CSON_TYPE_STRING:
4088 rc = cson_output_string(src, fmt->escapeForwardSlashes, f, state);
4089 break;
4090 case CSON_TYPE_ARRAY:
4091 rc = cson_output_array( src, f, state, fmt, level );
4092 break;
4093 case CSON_TYPE_OBJECT:
4094 rc = cson_output_object( src, f, state, fmt, level );
4095 break;
4096 default:
4097 rc = cson_rc.TypeError;
4098 break;
4099 }
4100 return rc;
4101 }
4102}
4103
4104
4105static int cson_output_array( cson_value const * src, cson_data_dest_f f, void * state,
4106 cson_output_opt const * fmt, unsigned int level )
4107{
4108 if( !src || !f || !fmt ) return cson_rc.ArgError;
4109 else if( ! cson_value_is_array(src) ) return cson_rc.TypeError;
4110 else if( level > fmt->maxDepth ) return cson_rc.RangeError;
4111 else
4112 {
4113 int rc;
4114 unsigned int i;
4115 cson_value const * v;
4116 char doIndent = fmt->indentation ? 1 : 0;
4117 cson_array const * ar = cson_value_get_array(src);
4118 assert( NULL != ar );
4119 if( 0 == ar->list.count )
4120 {
4121 return f(state, "[]", 2 );
4122 }
4123 else if( (1 == ar->list.count) && !fmt->indentSingleMemberValues ) doIndent = 0;
4124 rc = f(state, "[", 1);
4125 ++level;
4126 if( doIndent )
4127 {
4128 rc = cson_output_indent( f, state, fmt->indentation, level );
4129 }
4130 for( i = 0; (i < ar->list.count) && (0 == rc); ++i )
4131 {
4132 v = ar->list.list[i];
4133 if( v )
4134 {
4135 rc = cson_output_impl( v, f, state, fmt, level );
4136 }
4137 else
4138 {
4139 rc = cson_output_null( f, state );
4140 }
4141 if( 0 == rc )
4142 {
4143 if(i < (ar->list.count-1))
4144 {
4145 rc = f(state, ",", 1);
4146 if( 0 == rc )
4147 {
4148 rc = doIndent
4149 ? cson_output_indent( f, state, fmt->indentation, level )
4150 : 0 /*f( state, " ", 1 )*/;
4151 }
4152 }
4153 }
4154 }
4155 --level;
4156 if( doIndent && (0 == rc) )
4157 {
4158 rc = cson_output_indent( f, state, fmt->indentation, level );
4159 }
4160 return (0 == rc)
4161 ? f(state, "]", 1)
4162 : rc;
4163 }
4164}
4165
4166static int cson_output_object( cson_value const * src, cson_data_dest_f f, void * state,
4167 cson_output_opt const * fmt, unsigned int level )
4168{
4169 if( !src || !f || !fmt ) return cson_rc.ArgError;
4170 else if( ! cson_value_is_object(src) ) return cson_rc.TypeError;
4171 else if( level > fmt->maxDepth ) return cson_rc.RangeError;
4172 else
4173 {
4174 int rc;
4175 unsigned int i;
4176 cson_kvp const * kvp;
4177 char doIndent = fmt->indentation ? 1 : 0;
4178 cson_object const * obj = cson_value_get_object(src);
4179 assert( (NULL != obj) && (NULL != fmt));
4180 if( 0 == obj->kvp.count )
4181 {
4182 return f(state, "{}", 2 );
4183 }
4184 else if( (1 == obj->kvp.count) && !fmt->indentSingleMemberValues ) doIndent = 0;
4185 rc = f(state, "{", 1);
4186 ++level;
4187 if( doIndent )
4188 {
4189 rc = cson_output_indent( f, state, fmt->indentation, level );
4190 }
4191 for( i = 0; (i < obj->kvp.count) && (0 == rc); ++i )
4192 {
4193 kvp = obj->kvp.list[i];
4194 if( kvp && kvp->key )
4195 {
4196 cson_string const * sKey = cson_value_get_string(kvp->key);
4197 char const * cKey = cson_string_cstr(sKey);
4198 rc = cson_str_to_json(cKey, sKey->length,
4199 fmt->escapeForwardSlashes, f, state);
4200 if( 0 == rc )
4201 {
4202 rc = fmt->addSpaceAfterColon
4203 ? f(state, ": ", 2 )
4204 : f(state, ":", 1 )
4205 ;
4206 }
4207 if( 0 == rc)
4208 {
4209 rc = ( kvp->value )
4210 ? cson_output_impl( kvp->value, f, state, fmt, level )
4211 : cson_output_null( f, state );
4212 }
4213 }
4214 else
4215 {
4216 assert( 0 && "Possible internal error." );
4217 continue /* internal error? */;
4218 }
4219 if( 0 == rc )
4220 {
4221 if(i < (obj->kvp.count-1))
4222 {
4223 rc = f(state, ",", 1);
4224 if( 0 == rc )
4225 {
4226 rc = doIndent
4227 ? cson_output_indent( f, state, fmt->indentation, level )
4228 : 0 /*f( state, " ", 1 )*/;
4229 }
4230 }
4231 }
4232 }
4233 --level;
4234 if( doIndent && (0 == rc) )
4235 {
4236 rc = cson_output_indent( f, state, fmt->indentation, level );
4237 }
4238 return (0 == rc)
4239 ? f(state, "}", 1)
4240 : rc;
4241 }
4242}
4243
4244int cson_output( cson_value const * src, cson_data_dest_f f,
4245 void * state, cson_output_opt const * fmt )
4246{
4247 int rc;
4248 if(! fmt ) fmt = &cson_output_opt_empty;
4249 rc = cson_output_impl(src, f, state, fmt, 0 );
4250 if( (0 == rc) && fmt->addNewline )
4251 {
4252 rc = f(state, "\n", 1);
4253 }
4254 return rc;
4255}
4256
4257int cson_data_dest_FILE( void * state, void const * src, unsigned int n )
4258{
4259 if( ! state ) return cson_rc.ArgError;
4260 else if( !src || !n ) return 0;
4261 else
4262 {
4263 return ( 1 == fwrite( src, n, 1, (FILE*) state ) )
4264 ? 0
4265 : cson_rc.IOError;
4266 }
4267}
4268
4269int cson_output_FILE( cson_value const * src, FILE * dest, cson_output_opt const * fmt )
4270{
4271 int rc = 0;
4272 if( fmt )
4273 {
4274 rc = cson_output( src, cson_data_dest_FILE, dest, fmt );
4275 }
4276 else
4277 {
4278 /* We normally want a newline on FILE output. */
4279 cson_output_opt opt = cson_output_opt_empty;
4280 opt.addNewline = 1;
4281 rc = cson_output( src, cson_data_dest_FILE, dest, &opt );
4282 }
4283 if( 0 == rc )
4284 {
4285 fflush( dest );
4286 }
4287 return rc;
4288}
4289
4290int cson_output_filename( cson_value const * src, char const * dest, cson_output_opt const * fmt )
4291{
4292 if( !src || !dest ) return cson_rc.ArgError;
4293 else
4294 {
4295 FILE * f = fopen(dest,"wb");
4296 if( !f ) return cson_rc.IOError;
4297 else
4298 {
4299 int const rc = cson_output_FILE( src, f, fmt );
4300 fclose(f);
4301 return rc;
4302 }
4303 }
4304}
4305
4306int cson_parse_filename( cson_value ** tgt, char const * src,
4307 cson_parse_opt const * opt, cson_parse_info * err )
4308{
4309 if( !src || !tgt ) return cson_rc.ArgError;
4310 else
4311 {
4312 FILE * f = fopen(src, "r");
4313 if( !f ) return cson_rc.IOError;
4314 else
4315 {
4316 int const rc = cson_parse_FILE( tgt, f, opt, err );
4317 fclose(f);
4318 return rc;
4319 }
4320 }
4321}
4322
4326{
4328 char const * str;
4330 char const * pos;
4332 char const * end;
4334
4339static int cson_data_source_StringSource( void * state, void * dest, unsigned int * n )
4340{
4341 if( !state || !n || !dest ) return cson_rc.ArgError;
4342 else if( !*n ) return 0 /* ignore this */;
4343 else
4344 {
4345 unsigned int i;
4347 unsigned char * tgt = (unsigned char *)dest;
4348 for( i = 0; (i < *n) && (ss->pos < ss->end); ++i, ++ss->pos, ++tgt )
4349 {
4350 *tgt = *ss->pos;
4351 }
4352 *n = i;
4353 return 0;
4354 }
4355}
4356
4357int cson_parse_string( cson_value ** tgt, char const * src, unsigned int len,
4358 cson_parse_opt const * opt, cson_parse_info * err )
4359{
4360 if( ! tgt || !src ) return cson_rc.ArgError;
4361 else if( !*src || (len<2/*2==len of {} and []*/) ) return cson_rc.RangeError;
4362 else
4363 {
4365 ss.str = ss.pos = src;
4366 ss.end = src + len;
4367 return cson_parse( tgt, cson_data_source_StringSource, &ss, opt, err );
4368 }
4369
4370}
4371
4372int cson_parse_buffer( cson_value ** tgt,
4373 cson_buffer const * buf,
4374 cson_parse_opt const * opt,
4375 cson_parse_info * err )
4376{
4377 return ( !tgt || !buf || !buf->mem || !buf->used )
4378 ? cson_rc.ArgError
4379 : cson_parse_string( tgt, (char const *)buf->mem,
4380 buf->used, opt, err );
4381}
4382
4383int cson_buffer_reserve( cson_buffer * buf, cson_size_t n )
4384{
4385 if( ! buf ) return cson_rc.ArgError;
4386 else if( 0 == n )
4387 {
4388 cson_free(buf->mem, "cson_buffer::mem");
4389 *buf = cson_buffer_empty;
4390 return 0;
4391 }
4392 else if( buf->capacity >= n )
4393 {
4394 return 0;
4395 }
4396 else
4397 {
4398 unsigned char * x = (unsigned char *)cson_realloc( buf->mem, n, "cson_buffer::mem" );
4399 if( ! x ) return cson_rc.AllocError;
4400 memset( x + buf->used, 0, n - buf->used );
4401 buf->mem = x;
4402 buf->capacity = n;
4403 ++buf->timesExpanded;
4404 return 0;
4405 }
4406}
4407
4408cson_size_t cson_buffer_fill( cson_buffer * buf, char c )
4409{
4410 if( !buf || !buf->capacity || !buf->mem ) return 0;
4411 else
4412 {
4413 memset( buf->mem, c, buf->capacity );
4414 return buf->capacity;
4415 }
4416}
4417
4424static int cson_data_dest_cson_buffer( void * arg, void const * data_, unsigned int n )
4425{
4426 if( !arg ) return cson_rc.ArgError;
4427 else if( ! n ) return 0;
4428 else
4429 {
4430 cson_buffer * sb = (cson_buffer*)arg;
4431 char const * data = (char const *)data_;
4432 cson_size_t npos = sb->used + n;
4433 unsigned int i;
4434 if( npos >= sb->capacity )
4435 {
4436 const cson_size_t oldCap = sb->capacity;
4437 const cson_size_t asz = npos * 2;
4438 if( asz < npos ) return cson_rc.ArgError; /* overflow */
4439 else if( 0 != cson_buffer_reserve( sb, asz ) ) return cson_rc.AllocError;
4440 assert( (sb->capacity > oldCap) && "Internal error in memory buffer management!" );
4441 /* make sure it gets NUL terminated. */
4442 memset( sb->mem + oldCap, 0, (sb->capacity - oldCap) );
4443 }
4444 for( i = 0; i < n; ++i, ++sb->used )
4445 {
4446 sb->mem[sb->used] = data[i];
4447 }
4448 return 0;
4449 }
4450}
4451
4452
4453int cson_output_buffer( cson_value const * v, cson_buffer * buf,
4454 cson_output_opt const * opt )
4455{
4456 int rc = cson_output( v, cson_data_dest_cson_buffer, buf, opt );
4457 if( 0 == rc )
4458 { /* Ensure that the buffer is null-terminated. */
4459 rc = cson_buffer_reserve( buf, buf->used + 1 );
4460 if( 0 == rc )
4461 {
4462 buf->mem[buf->used] = 0;
4463 }
4464 }
4465 return rc;
4466}
4467
4505static char cson_next_token( char const ** inp, char separator, char const ** end )
4506{
4507 char const * pos = NULL;
4508 assert( inp && end && *inp );
4509 if( *inp == *end ) return 0;
4510 pos = *inp;
4511 if( !*pos )
4512 {
4513 *end = pos;
4514 return 0;
4515 }
4516 for( ; *pos && (*pos == separator); ++pos) { /* skip preceeding splitters */ }
4517 *inp = pos;
4518 for( ; *pos && (*pos != separator); ++pos) { /* find next splitter */ }
4519 *end = pos;
4520 return (pos > *inp) ? 1 : 0;
4521}
4522
4523int cson_object_fetch_sub2( cson_object const * obj, cson_value ** tgt, char const * path )
4524{
4525 if( ! obj || !path ) return cson_rc.ArgError;
4526 else if( !*path || !*(1+path) ) return cson_rc.RangeError;
4527 else return cson_object_fetch_sub(obj, tgt, path+1, *path);
4528}
4529
4530int cson_object_fetch_sub( cson_object const * obj, cson_value ** tgt, char const * path, char sep )
4531{
4532 if( ! obj || !path ) return cson_rc.ArgError;
4533 else if( !*path || !sep ) return cson_rc.RangeError;
4534 else
4535 {
4536 char const * beg = path;
4537 char const * end = NULL;
4538 int rc;
4539 unsigned int i, len;
4540 unsigned int tokenCount = 0;
4541 cson_value * cv = NULL;
4542 cson_object const * curObj = obj;
4543 enum { BufSize = 128 };
4544 char buf[BufSize];
4545 memset( buf, 0, BufSize );
4546
4547 while( cson_next_token( &beg, sep, &end ) )
4548 {
4549 if( beg == end ) break;
4550 else
4551 {
4552 ++tokenCount;
4553 beg = end;
4554 end = NULL;
4555 }
4556 }
4557 if( 0 == tokenCount ) return cson_rc.RangeError;
4558 beg = path;
4559 end = NULL;
4560 for( i = 0; i < tokenCount; ++i, beg=end, end=NULL )
4561 {
4562 rc = cson_next_token( &beg, sep, &end );
4563 assert( 1 == rc );
4564 assert( beg != end );
4565 assert( end > beg );
4566 len = (unsigned int)(end - beg);
4567 if( len > (BufSize-1) ) return cson_rc.RangeError;
4568 memset( buf, 0, len + 1 );
4569 memcpy( buf, beg, len );
4570 buf[len] = 0;
4571 cv = cson_object_get( curObj, buf );
4572 if( NULL == cv ) return cson_rc.NotFoundError;
4573 else if( i == (tokenCount-1) )
4574 {
4575 if(tgt) *tgt = cv;
4576 return 0;
4577 }
4578 else if( cson_value_is_object(cv) )
4579 {
4580 curObj = cson_value_get_object(cv);
4581 assert((NULL != curObj) && "Detected mis-management of internal memory!");
4582 }
4583 /* TODO: arrays. Requires numeric parsing for the index. */
4584 else
4585 {
4586 return cson_rc.NotFoundError;
4587 }
4588 }
4589 assert( i == tokenCount );
4590 return cson_rc.NotFoundError;
4591 }
4592}
4593
4594cson_value * cson_object_get_sub( cson_object const * obj, char const * path, char sep )
4595{
4596 cson_value * v = NULL;
4597 cson_object_fetch_sub( obj, &v, path, sep );
4598 return v;
4599}
4600
4601cson_value * cson_object_get_sub2( cson_object const * obj, char const * path )
4602{
4603 cson_value * v = NULL;
4604 cson_object_fetch_sub2( obj, &v, path );
4605 return v;
4606}
4607
4608
4614static cson_value * cson_value_clone_ref( cson_value * v )
4615{
4616 cson_value * rc = NULL;
4617#define TRY_SHARING 1
4618#if TRY_SHARING
4619 if(!v ) return rc;
4620 else if( cson_value_is_object(v)
4621 || cson_value_is_array(v))
4622 {
4623 rc = cson_value_clone( v );
4624 }
4625 else
4626 {
4627 rc = v;
4628 }
4629#else
4630 rc = cson_value_clone(v);
4631#endif
4632#undef TRY_SHARING
4633 cson_value_add_reference(rc);
4634 return rc;
4635}
4636
4637static cson_value * cson_value_clone_array( cson_value const * orig )
4638{
4639 unsigned int i = 0;
4640 cson_array const * asrc = cson_value_get_array( orig );
4641 unsigned int alen = cson_array_length_get( asrc );
4642 cson_value * destV = NULL;
4643 cson_array * destA = NULL;
4644 assert( orig && asrc );
4645 destV = cson_value_new_array();
4646 if( NULL == destV ) return NULL;
4647 destA = cson_value_get_array( destV );
4648 assert( destA );
4649 if( 0 != cson_array_reserve( destA, alen ) )
4650 {
4651 cson_value_free( destV );
4652 return NULL;
4653 }
4654 for( ; i < alen; ++i )
4655 {
4656 cson_value * ch = cson_array_get( asrc, i );
4657 if( NULL != ch )
4658 {
4659 cson_value * cl = cson_value_clone_ref( ch );
4660 if( NULL == cl )
4661 {
4662 cson_value_free( destV );
4663 return NULL;
4664 }
4665 if( 0 != cson_array_set( destA, i, cl ) )
4666 {
4667 cson_value_free( cl );
4668 cson_value_free( destV );
4669 return NULL;
4670 }
4671 cson_value_free(cl)/*remove our artificial reference */;
4672 }
4673 }
4674 return destV;
4675}
4676
4677static cson_value * cson_value_clone_object( cson_value const * orig )
4678{
4679 cson_object const * src = cson_value_get_object( orig );
4680 cson_value * destV = NULL;
4681 cson_object * dest = NULL;
4682 cson_kvp const * kvp = NULL;
4683 cson_object_iterator iter = cson_object_iterator_empty;
4684 assert( orig && src );
4685 if( 0 != cson_object_iter_init( src, &iter ) )
4686 {
4687 return NULL;
4688 }
4689 destV = cson_value_new_object();
4690 if( NULL == destV ) return NULL;
4691 dest = cson_value_get_object( destV );
4692 assert( dest );
4693 if( src->kvp.count > cson_kvp_list_reserve( &dest->kvp, src->kvp.count ) ){
4694 cson_value_free( destV );
4695 return NULL;
4696 }
4697 while( (kvp = cson_object_iter_next( &iter )) )
4698 {
4699 cson_value * key = NULL;
4700 cson_value * val = NULL;
4701 assert( kvp->key && (kvp->key->refcount>0) );
4702 key = cson_value_clone_ref(kvp->key);
4703 val = key ? cson_value_clone_ref(kvp->value) : NULL;
4704 if( ! key || !val ){
4705 goto error;
4706 }
4707 assert( CSON_STR(key) );
4708 if( 0 != cson_object_set_s( dest, CSON_STR(key), val ) )
4709 {
4710 goto error;
4711 }
4712 /* remove our references */
4713 cson_value_free(key);
4714 cson_value_free(val);
4715 continue;
4716 error:
4717 cson_value_free(key);
4718 cson_value_free(val);
4719 cson_value_free(destV);
4720 destV = NULL;
4721 break;
4722 }
4723 return destV;
4724}
4725
4726cson_value * cson_value_clone( cson_value const * orig )
4727{
4728 if( NULL == orig ) return NULL;
4729 else
4730 {
4731 switch( orig->api->typeID )
4732 {
4733 case CSON_TYPE_UNDEF:
4734 assert(0 && "This should never happen.");
4735 return NULL;
4736 case CSON_TYPE_NULL:
4737 return cson_value_null();
4738 case CSON_TYPE_BOOL:
4739 return cson_value_new_bool( cson_value_get_bool( orig ) );
4740 case CSON_TYPE_INTEGER:
4741 return cson_value_new_integer( cson_value_get_integer( orig ) );
4742 break;
4743 case CSON_TYPE_DOUBLE:
4744 return cson_value_new_double( cson_value_get_double( orig ) );
4745 break;
4746 case CSON_TYPE_STRING: {
4747 cson_string const * str = cson_value_get_string( orig );
4748 return cson_value_new_string( cson_string_cstr( str ),
4749 cson_string_length_bytes( str ) );
4750 }
4751 case CSON_TYPE_ARRAY:
4752 return cson_value_clone_array( orig );
4753 case CSON_TYPE_OBJECT:
4754 return cson_value_clone_object( orig );
4755 }
4756 assert( 0 && "We can't get this far." );
4757 return NULL;
4758 }
4759}
4760
4761cson_value * cson_string_value(cson_string const * s)
4762{
4763#define MT CSON_SPECIAL_VALUES[CSON_VAL_STR_EMPTY]
4764 return s
4765 ? ((s==MT.value) ? &MT : CSON_VCAST(s))
4766 : NULL;
4767#undef MT
4768}
4769
4770cson_value * cson_object_value(cson_object const * s)
4771{
4772 return s
4773 ? CSON_VCAST(s)
4774 : NULL;
4775}
4776
4777
4778cson_value * cson_array_value(cson_array const * s)
4779{
4780 return s
4781 ? CSON_VCAST(s)
4782 : NULL;
4783}
4784
4785void cson_free_object(cson_object *x)
4786{
4787 if(x) cson_value_free(cson_object_value(x));
4788}
4789void cson_free_array(cson_array *x)
4790{
4791 if(x) cson_value_free(cson_array_value(x));
4792}
4793
4794void cson_free_string(cson_string *x)
4795{
4796 if(x) cson_value_free(cson_string_value(x));
4797}
4798void cson_free_value(cson_value *x)
4799{
4800 if(x) cson_value_free(x);
4801}
4802
4803
4804#if 0
4805/* i'm not happy with this... */
4806char * cson_pod_to_string( cson_value const * orig )
4807{
4808 if( ! orig ) return NULL;
4809 else
4810 {
4811 enum { BufSize = 64 };
4812 char * v = NULL;
4813 switch( orig->api->typeID )
4814 {
4815 case CSON_TYPE_BOOL: {
4816 char const bv = cson_value_get_bool(orig);
4817 v = cson_strdup( bv ? "true" : "false",
4818 bv ? 4 : 5 );
4819 break;
4820 }
4821 case CSON_TYPE_UNDEF:
4822 case CSON_TYPE_NULL: {
4823 v = cson_strdup( "null", 4 );
4824 break;
4825 }
4826 case CSON_TYPE_STRING: {
4827 cson_string const * jstr = cson_value_get_string(orig);
4828 unsigned const int slen = cson_string_length_bytes( jstr );
4829 assert( NULL != jstr );
4830 v = cson_strdup( cson_string_cstr( jstr ), slen );
4831 break;
4832 }
4833 case CSON_TYPE_INTEGER: {
4834 char buf[BufSize] = {0};
4835 if( 0 < sprintf( v, "%"CSON_INT_T_PFMT, cson_value_get_integer(orig)) )
4836 {
4837 v = cson_strdup( buf, strlen(buf) );
4838 }
4839 break;
4840 }
4841 case CSON_TYPE_DOUBLE: {
4842 char buf[BufSize] = {0};
4843 if( 0 < sprintf( v, "%"CSON_DOUBLE_T_PFMT, cson_value_get_double(orig)) )
4844 {
4845 v = cson_strdup( buf, strlen(buf) );
4846 }
4847 break;
4848 }
4849 default:
4850 break;
4851 }
4852 return v;
4853 }
4854}
4855#endif
4856
4857#if 0
4858/* i'm not happy with this... */
4859char * cson_pod_to_string( cson_value const * orig )
4860{
4861 if( ! orig ) return NULL;
4862 else
4863 {
4864 enum { BufSize = 64 };
4865 char * v = NULL;
4866 switch( orig->api->typeID )
4867 {
4868 case CSON_TYPE_BOOL: {
4869 char const bv = cson_value_get_bool(orig);
4870 v = cson_strdup( bv ? "true" : "false",
4871 bv ? 4 : 5 );
4872 break;
4873 }
4874 case CSON_TYPE_UNDEF:
4875 case CSON_TYPE_NULL: {
4876 v = cson_strdup( "null", 4 );
4877 break;
4878 }
4879 case CSON_TYPE_STRING: {
4880 cson_string const * jstr = cson_value_get_string(orig);
4881 unsigned const int slen = cson_string_length_bytes( jstr );
4882 assert( NULL != jstr );
4883 v = cson_strdup( cson_string_cstr( jstr ), slen );
4884 break;
4885 }
4886 case CSON_TYPE_INTEGER: {
4887 char buf[BufSize] = {0};
4888 if( 0 < sprintf( v, "%"CSON_INT_T_PFMT, cson_value_get_integer(orig)) )
4889 {
4890 v = cson_strdup( buf, strlen(buf) );
4891 }
4892 break;
4893 }
4894 case CSON_TYPE_DOUBLE: {
4895 char buf[BufSize] = {0};
4896 if( 0 < sprintf( v, "%"CSON_DOUBLE_T_PFMT, cson_value_get_double(orig)) )
4897 {
4898 v = cson_strdup( buf, strlen(buf) );
4899 }
4900 break;
4901 }
4902 default:
4903 break;
4904 }
4905 return v;
4906 }
4907}
4908#endif
4909
4910unsigned int cson_value_msize(cson_value const * v)
4911{
4912 if(!v) return 0;
4913 else if( cson_value_is_builtin(v) ) return 0;
4914 else {
4915 unsigned int rc = sizeof(cson_value);
4916 assert(NULL != v->api);
4917 switch(v->api->typeID){
4918 case CSON_TYPE_INTEGER:
4919 assert( v != &CSON_SPECIAL_VALUES[CSON_VAL_INT_0]);
4920 rc += sizeof(cson_int_t);
4921 break;
4922 case CSON_TYPE_DOUBLE:
4923 assert( v != &CSON_SPECIAL_VALUES[CSON_VAL_DBL_0]);
4924 rc += sizeof(cson_double_t);
4925 break;
4926 case CSON_TYPE_STRING:
4927 rc += sizeof(cson_string)
4928 + CSON_STR(v)->length + 1/*NUL*/;
4929 break;
4930 case CSON_TYPE_ARRAY:{
4931 cson_array const * ar = CSON_ARRAY(v);
4932 cson_value_list const * li;
4933 unsigned int i = 0;
4934 assert( NULL != ar );
4935 li = &ar->list;
4936 rc += sizeof(cson_array)
4937 + (li->alloced * sizeof(cson_value *));
4938 for( ; i < li->count; ++i ){
4939 cson_value const * e = ar->list.list[i];
4940 if( e ) rc += cson_value_msize( e );
4941 }
4942 break;
4943 }
4944 case CSON_TYPE_OBJECT:{
4945 cson_object const * obj = CSON_OBJ(v);
4946 unsigned int i = 0;
4947 cson_kvp_list const * kl;
4948 assert(NULL != obj);
4949 kl = &obj->kvp;
4950 rc += sizeof(cson_object)
4951 + (kl->alloced * sizeof(cson_kvp*));
4952 for( ; i < kl->count; ++i ){
4953 cson_kvp const * kvp = kl->list[i];
4954 assert(NULL != kvp);
4955 rc += cson_value_msize(kvp->key);
4956 rc += cson_value_msize(kvp->value);
4957 }
4958 break;
4959 }
4960 case CSON_TYPE_UNDEF:
4961 case CSON_TYPE_NULL:
4962 case CSON_TYPE_BOOL:
4963 assert( 0 && "Should have been caught by is-builtin check!" );
4964 break;
4965 default:
4966 assert(0 && "Invalid typeID!");
4967 return 0;
4968#undef RCCHECK
4969 }
4970 return rc;
4971 }
4972}
4973
4974int cson_object_merge( cson_object * dest, cson_object const * src, int flags ){
4975 cson_object_iterator iter = cson_object_iterator_empty;
4976 int rc;
4977 char const replace = (flags & CSON_MERGE_REPLACE);
4978 char const recurse = !(flags & CSON_MERGE_NO_RECURSE);
4979 cson_kvp const * kvp;
4980 if((!dest || !src) || (dest==src)) return cson_rc.ArgError;
4981 rc = cson_object_iter_init( src, &iter );
4982 if(rc) return rc;
4983 while( (kvp = cson_object_iter_next(&iter) ) )
4984 {
4985 cson_string * key = cson_kvp_key(kvp);
4986 cson_value * val = cson_kvp_value(kvp);
4987 cson_value * check = cson_object_get_s( dest, key );
4988 if(!check){
4989 cson_object_set_s( dest, key, val );
4990 continue;
4991 }
4992 else if(!replace && !recurse) continue;
4993 else if(replace && !recurse){
4994 cson_object_set_s( dest, key, val );
4995 continue;
4996 }
4997 else if( recurse ){
4998 if( cson_value_is_object(check) &&
4999 cson_value_is_object(val) ){
5000 rc = cson_object_merge( cson_value_get_object(check),
5001 cson_value_get_object(val),
5002 flags );
5003 if(rc) return rc;
5004 else continue;
5005 }
5006 else continue;
5007 }
5008 else continue;
5009 }
5010 return 0;
5011}
5012
5013static cson_value * cson_guess_arg_type(char const *arg){
5014 char * end = NULL;
5015 if(!arg || !*arg) return cson_value_null();
5016 else if(('0'>*arg) || ('9'<*arg)){
5017 goto do_string;
5018 }
5019 else{ /* try numbers... */
5020 long const val = strtol(arg, &end, 10);
5021 if(!*end){
5022 return cson_value_new_integer( (cson_int_t)val);
5023 }
5024 else if( '.' != *end ) {
5025 goto do_string;
5026 }
5027 else {
5028 double const val = strtod(arg, &end);
5029 if(!*end){
5030 return cson_value_new_double(val);
5031 }
5032 }
5033 }
5034 do_string:
5035 return cson_value_new_string(arg, (unsigned int)strlen(arg));
5036}
5037
5038
5039int cson_parse_argv_flags( int argc, char const * const * argv,
5040 cson_object ** tgt, unsigned int * count ){
5041 cson_object * o = NULL;
5042 int rc = 0;
5043 int i = 0;
5044 if(argc<1 || !argc || !tgt) return cson_rc.ArgError;
5045 o = *tgt ? *tgt : cson_new_object();
5046 if(count) *count = 0;
5047 for( i = 0; i < argc; ++i ){
5048 char const * arg = argv[i];
5049 char const * key = arg;
5050 char const * pos;
5051 cson_string * k = NULL;
5052 cson_value * v = NULL;
5053 if('-' != *arg) continue;
5054 while('-'==*key) ++key;
5055 if(!*key) continue;
5056 pos = key;
5057 while( *pos && ('=' != *pos)) ++pos;
5058 k = cson_new_string(key, (unsigned int)(pos-key));
5059 if(!k){
5060 rc = cson_rc.AllocError;
5061 break;
5062 }
5063 if(!*pos){
5064 v = cson_value_true();
5065 }else{
5066 assert('=' == *pos);
5067 ++pos /*skip '='*/;
5068 v = cson_guess_arg_type(pos);
5069 }
5070 if(0 != (rc=cson_object_set_s(o, k, v))){
5071 cson_free_string(k);
5072 cson_value_free(v);
5073 break;
5074 }
5075 else if(count) ++*count;
5076 }
5077 if(o != *tgt){
5078 if(rc) cson_free_object(o);
5079 else *tgt = o;
5080 }
5081 return rc;
5082}
5083
5084#if defined(__cplusplus)
5085} /*extern "C"*/
5086#endif
5087
5088#undef MARKER
5089#undef CSON_OBJECT_PROPS_SORT
5090#undef CSON_OBJECT_PROPS_SORT_USE_LENGTH
5091#undef CSON_CAST
5092#undef CSON_INT
5093#undef CSON_DBL
5094#undef CSON_STR
5095#undef CSON_OBJ
5096#undef CSON_ARRAY
5097#undef CSON_VCAST
5098#undef CSON_MALLOC_IMPL
5099#undef CSON_FREE_IMPL
5100#undef CSON_REALLOC_IMPL
5101/* end file ./cson.c */
5102/* begin file ./cson_lists.h */
5103/* Auto-generated from cson_list.h. Edit at your own risk! */
5104unsigned int cson_value_list_reserve( cson_value_list * self, unsigned int n )
5105{
5106 if( !self ) return 0;
5107 else if(0 == n)
5108 {
5109 if(0 == self->alloced) return 0;
5110 cson_free(self->list, "cson_value_list_reserve");
5111 self->list = NULL;
5112 self->alloced = self->count = 0;
5113 return 0;
5114 }
5115 else if( self->alloced >= n )
5116 {
5117 return self->alloced;
5118 }
5119 else
5120 {
5121 size_t const sz = sizeof(cson_value *) * n;
5122 cson_value * * m = (cson_value **)cson_realloc( self->list, sz, "cson_value_list_reserve" );
5123 if( ! m ) return self->alloced;
5124
5125 memset( m + self->alloced, 0, (sizeof(cson_value *)*(n-self->alloced)));
5126 self->alloced = n;
5127 self->list = m;
5128 return n;
5129 }
5130}
5131int cson_value_list_append( cson_value_list * self, cson_value * cp )
5132{
5133 if( !self || !cp ) return cson_rc.ArgError;
5134 else if( self->alloced > cson_value_list_reserve(self, self->count+1) )
5135 {
5136 return cson_rc.AllocError;
5137 }
5138 else
5139 {
5140 self->list[self->count++] = cp;
5141 return 0;
5142 }
5143}
5144int cson_value_list_visit( cson_value_list * self,
5145
5146 int (*visitor)(cson_value * obj, void * visitorState ),
5147
5148
5149
5150 void * visitorState )
5151{
5152 int rc = cson_rc.ArgError;
5153 if( self && visitor )
5154 {
5155 unsigned int i = 0;
5156 for( rc = 0; (i < self->count) && (0 == rc); ++i )
5157 {
5158
5159 cson_value * obj = self->list[i];
5160
5161
5162
5163 if(obj) rc = visitor( obj, visitorState );
5164 }
5165 }
5166 return rc;
5167}
5168void cson_value_list_clean( cson_value_list * self,
5169
5170 void (*cleaner)(cson_value * obj)
5171
5172
5173
5174 )
5175{
5176 if( self && cleaner && self->count )
5177 {
5178 unsigned int i = 0;
5179 for( ; i < self->count; ++i )
5180 {
5181
5182 cson_value * obj = self->list[i];
5183
5184
5185
5186 if(obj) cleaner(obj);
5187 }
5188 }
5189 cson_value_list_reserve(self,0);
5190}
5191unsigned int cson_kvp_list_reserve( cson_kvp_list * self, unsigned int n )
5192{
5193 if( !self ) return 0;
5194 else if(0 == n)
5195 {
5196 if(0 == self->alloced) return 0;
5197 cson_free(self->list, "cson_kvp_list_reserve");
5198 self->list = NULL;
5199 self->alloced = self->count = 0;
5200 return 0;
5201 }
5202 else if( self->alloced >= n )
5203 {
5204 return self->alloced;
5205 }
5206 else
5207 {
5208 size_t const sz = sizeof(cson_kvp *) * n;
5209 cson_kvp * * m = (cson_kvp **)cson_realloc( self->list, sz, "cson_kvp_list_reserve" );
5210 if( ! m ) return self->alloced;
5211
5212 memset( m + self->alloced, 0, (sizeof(cson_kvp *)*(n-self->alloced)));
5213 self->alloced = n;
5214 self->list = m;
5215 return n;
5216 }
5217}
5218int cson_kvp_list_append( cson_kvp_list * self, cson_kvp * cp )
5219{
5220 if( !self || !cp ) return cson_rc.ArgError;
5221 else if( self->alloced > cson_kvp_list_reserve(self, self->count+1) )
5222 {
5223 return cson_rc.AllocError;
5224 }
5225 else
5226 {
5227 self->list[self->count++] = cp;
5228 return 0;
5229 }
5230}
5231int cson_kvp_list_visit( cson_kvp_list * self,
5232
5233 int (*visitor)(cson_kvp * obj, void * visitorState ),
5234
5235
5236
5237 void * visitorState )
5238{
5239 int rc = cson_rc.ArgError;
5240 if( self && visitor )
5241 {
5242 unsigned int i = 0;
5243 for( rc = 0; (i < self->count) && (0 == rc); ++i )
5244 {
5245
5246 cson_kvp * obj = self->list[i];
5247
5248
5249
5250 if(obj) rc = visitor( obj, visitorState );
5251 }
5252 }
5253 return rc;
5254}
5255void cson_kvp_list_clean( cson_kvp_list * self,
5256
5257 void (*cleaner)(cson_kvp * obj)
5258
5259
5260
5261 )
5262{
5263 if( self && cleaner && self->count )
5264 {
5265 unsigned int i = 0;
5266 for( ; i < self->count; ++i )
5267 {
5268
5269 cson_kvp * obj = self->list[i];
5270
5271
5272
5273 if(obj) cleaner(obj);
5274 }
5275 }
5276 cson_kvp_list_reserve(self,0);
5277}
5278/* end file ./cson_lists.h */
The structure used to configure a JSON parser object.
JSON_free_t free
The memory deallocation routine, which must be semantically compatible with free(3).
JSON_parser_callback callback
Pointer to a callback, called when the parser has something to tell the user.
int allow_comments
To allow C style comments in JSON, set to non-zero.
int depth
Specifies the levels of nested JSON to allow.
int handle_floats_manually
To decode floating point numbers manually set this parameter to non-zero.
JSON_malloc_t malloc
The memory allocation routine, which must be semantically compatible with malloc(3).
void * callback_ctx
Callback context - client-specified data to pass to the callback function.
cson_array is an opaque handle to an Array value.
A generic buffer class.
unsigned char * mem
The memory allocated for and owned by this buffer.
cson_size_t used
The number of bytes "used" by this object.
cson_size_t capacity
The number of bytes allocated for this object.
Internal type to hold state for a JSON input string.
char const * pos
Current iteration position.
char const * end
Logical EOF, one-past-the-end of str.
char const * str
Start of input string.
A key/value pair collection.
An iterator type for traversing object properties.
cson_object is an opaque handle to an Object value.
Client-configurable options for the cson_output() family of functions.
char addNewline
If true, a newline will be added to generated output, else not.
A class for holding JSON parser information.
unsigned int length
Length, in bytes.
unsigned int totalValueCount
The total number of object/array values successfully processed by the parser, including the root node...
unsigned int col
0-based column number.
int errorCode
Error code of the parse run (0 for no error).
unsigned int line
1-based line number.
unsigned int totalKeyCount
The total number of object keys successfully processed by the parser.
Client-configurable options for the cson_parse() family of functions.
char allowComments
Whether or not to allow C-style comments.
unsigned short maxDepth
Maximum object/array depth to traverse.
Strings are allocated as an instances of this class with N+1 trailing bytes, where N is the length of...
This type holds the "vtbl" for type-specific operations when working with cson_value objects.
void(* cleanup)(cson_value *self)
Must free any memory associated with self, but not free self.
const cson_type_id typeID
The logical JavaScript/JSON type associated with this object.
The core value type of this API.
cson_value_api const * api
The "vtbl" of type-specific operations.
cson_counter_t refcount
We use this to allow us to store cson_value instances in multiple containers or multiple times within...
void * value
The raw value.
Definition Viewer.h:139