Fossil SCM

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

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button