Fossil SCM

Latest upstream extsrc/cson_amalgamation.*, and update src/json*.c, to squelch warnings from OpenBSD.

stephan 2024-08-23 22:18 trunk
Commit 40a14c1debacc855faafeaac592edbc4320bd25ebc8bfda6a5f365ba6ef38210
--- extsrc/cson_amalgamation.c
+++ extsrc/cson_amalgamation.c
@@ -1435,11 +1435,10 @@
14351435
#if defined(__cplusplus)
14361436
extern "C" {
14371437
#endif
14381438
14391439
1440
-
14411440
/**
14421441
This type holds the "vtbl" for type-specific operations when
14431442
working with cson_value objects.
14441443
14451444
All cson_values of a given logical type share a pointer to a single
@@ -1686,12 +1685,12 @@
16861685
: 0;
16871686
}
16881687
16891688
char const * cson_rc_string(int rc)
16901689
{
1691
- if(0 == rc) return "OK";
1692
-#define CHECK(N) else if(cson_rc.N == rc ) return #N
1690
+ switch(rc){
1691
+#define CHECK(N) case CSON_RC_##N: return #N;
16931692
CHECK(OK);
16941693
CHECK(ArgError);
16951694
CHECK(RangeError);
16961695
CHECK(TypeError);
16971696
CHECK(IOError);
@@ -1708,11 +1707,12 @@
17081707
CHECK(Parse_INVALID_NUMBER);
17091708
CHECK(Parse_NESTING_DEPTH_REACHED);
17101709
CHECK(Parse_UNBALANCED_COLLECTION);
17111710
CHECK(Parse_EXPECTED_KEY);
17121711
CHECK(Parse_EXPECTED_COLON);
1713
- else return "UnknownError";
1712
+ default: return "UnknownError";
1713
+ }
17141714
#undef CHECK
17151715
}
17161716
17171717
/**
17181718
If CSON_LOG_ALLOC is true then the cson_malloc/realloc/free() routines
@@ -1854,11 +1854,11 @@
18541854
}
18551855
18561856
#if 0
18571857
int cson_value_refcount_set( cson_value * cv, unsigned short rc )
18581858
{
1859
- if( NULL == cv ) return cson_rc.ArgError;
1859
+ if( NULL == cv ) return CSON_RC_ArgError;
18601860
else
18611861
{
18621862
cv->refcount = rc;
18631863
return 0;
18641864
}
@@ -1865,14 +1865,14 @@
18651865
}
18661866
#endif
18671867
18681868
int cson_value_add_reference( cson_value * cv )
18691869
{
1870
- if( NULL == cv ) return cson_rc.ArgError;
1870
+ if( NULL == cv ) return CSON_RC_ArgError;
18711871
else if( (cv->refcount+1) < cv->refcount )
18721872
{
1873
- return cson_rc.RangeError;
1873
+ return CSON_RC_RangeError;
18741874
}
18751875
else
18761876
{
18771877
cson_refcount_incr( cv );
18781878
return 0;
@@ -2335,11 +2335,11 @@
23352335
val->refcount = rc;
23362336
}
23372337
}
23382338
}
23392339
2340
-static cson_value * cson_value_array_alloc()
2340
+static cson_value * cson_value_array_alloc(void)
23412341
{
23422342
cson_value * v = cson_value_new(CSON_TYPE_ARRAY,0);
23432343
if( NULL != v )
23442344
{
23452345
cson_array * ar = CSON_ARRAY(v);
@@ -2347,11 +2347,11 @@
23472347
*ar = cson_array_empty;
23482348
}
23492349
return v;
23502350
}
23512351
2352
-static cson_value * cson_value_object_alloc()
2352
+static cson_value * cson_value_object_alloc(void)
23532353
{
23542354
cson_value * v = cson_value_new(CSON_TYPE_OBJECT,0);
23552355
if( NULL != v )
23562356
{
23572357
cson_object * obj = CSON_OBJ(v);
@@ -2359,28 +2359,28 @@
23592359
*obj = cson_object_empty;
23602360
}
23612361
return v;
23622362
}
23632363
2364
-cson_value * cson_value_new_object()
2364
+cson_value * cson_value_new_object(void)
23652365
{
23662366
return cson_value_object_alloc();
23672367
}
23682368
2369
-cson_object * cson_new_object()
2369
+cson_object * cson_new_object(void)
23702370
{
23712371
23722372
return cson_value_get_object( cson_value_new_object() );
23732373
}
23742374
2375
-cson_value * cson_value_new_array()
2375
+cson_value * cson_value_new_array(void)
23762376
{
23772377
return cson_value_array_alloc();
23782378
}
23792379
23802380
2381
-cson_array * cson_new_array()
2381
+cson_array * cson_new_array(void)
23822382
{
23832383
return cson_value_get_array( cson_value_new_array() );
23842384
}
23852385
23862386
/**
@@ -2502,11 +2502,11 @@
25022502
int rc;
25032503
enum { BufSize = 1024 * 4 };
25042504
char rbuf[BufSize];
25052505
size_t total = 0;
25062506
unsigned int rlen = 0;
2507
- if( ! dest || ! src ) return cson_rc.ArgError;
2507
+ if( ! dest || ! src ) return CSON_RC_ArgError;
25082508
dest->used = 0;
25092509
while(1)
25102510
{
25112511
rlen = BufSize;
25122512
rc = src( state, rbuf, &rlen );
@@ -2530,16 +2530,16 @@
25302530
}
25312531
25322532
int cson_data_source_FILE( void * state, void * dest, unsigned int * n )
25332533
{
25342534
FILE * f = (FILE*) state;
2535
- if( ! state || ! n || !dest ) return cson_rc.ArgError;
2536
- else if( !*n ) return cson_rc.RangeError;
2535
+ if( ! state || ! n || !dest ) return CSON_RC_ArgError;
2536
+ else if( !*n ) return CSON_RC_RangeError;
25372537
*n = (unsigned int)fread( dest, 1, *n, f );
25382538
if( !*n )
25392539
{
2540
- return feof(f) ? 0 : cson_rc.IOError;
2540
+ return feof(f) ? 0 : CSON_RC_IOError;
25412541
}
25422542
return 0;
25432543
}
25442544
25452545
int cson_parse_FILE( cson_value ** tgt, FILE * src,
@@ -2553,11 +2553,11 @@
25532553
{
25542554
/**
25552555
FIXME: move the to-bool operation into cson_value_api, like we
25562556
do in the C++ API.
25572557
*/
2558
- if( ! val || !val->api ) return cson_rc.ArgError;
2558
+ if( ! val || !val->api ) return CSON_RC_ArgError;
25592559
else
25602560
{
25612561
int rc = 0;
25622562
char b = 0;
25632563
switch( val->api->typeID )
@@ -2588,11 +2588,11 @@
25882588
cson_value_fetch_double( val, &d );
25892589
b = (0.0==d) ? 0 : 1;
25902590
break;
25912591
}
25922592
default:
2593
- rc = cson_rc.TypeError;
2593
+ rc = CSON_RC_TypeError;
25942594
break;
25952595
}
25962596
if( v ) *v = b;
25972597
return rc;
25982598
}
@@ -2605,11 +2605,11 @@
26052605
return i;
26062606
}
26072607
26082608
int cson_value_fetch_integer( cson_value const * val, cson_int_t * v )
26092609
{
2610
- if( ! val || !val->api ) return cson_rc.ArgError;
2610
+ if( ! val || !val->api ) return CSON_RC_ArgError;
26112611
else
26122612
{
26132613
cson_int_t i = 0;
26142614
int rc = 0;
26152615
switch(val->api->typeID)
@@ -2641,11 +2641,11 @@
26412641
}
26422642
case CSON_TYPE_STRING:
26432643
case CSON_TYPE_ARRAY:
26442644
case CSON_TYPE_OBJECT:
26452645
default:
2646
- rc = cson_rc.TypeError;
2646
+ rc = CSON_RC_TypeError;
26472647
break;
26482648
}
26492649
if(!rc && v) *v = i;
26502650
return rc;
26512651
}
@@ -2658,11 +2658,11 @@
26582658
return i;
26592659
}
26602660
26612661
int cson_value_fetch_double( cson_value const * val, cson_double_t * v )
26622662
{
2663
- if( ! val || !val->api ) return cson_rc.ArgError;
2663
+ if( ! val || !val->api ) return CSON_RC_ArgError;
26642664
else
26652665
{
26662666
cson_double_t d = 0.0;
26672667
int rc = 0;
26682668
switch(val->api->typeID)
@@ -2687,11 +2687,11 @@
26872687
cson_double_t const* dv = CSON_DBL(val);
26882688
d = dv ? *dv : 0.0;
26892689
break;
26902690
}
26912691
default:
2692
- rc = cson_rc.TypeError;
2692
+ rc = CSON_RC_TypeError;
26932693
break;
26942694
}
26952695
if(v) *v = d;
26962696
return rc;
26972697
}
@@ -2704,12 +2704,12 @@
27042704
return i;
27052705
}
27062706
27072707
int cson_value_fetch_string( cson_value const * val, cson_string ** dest )
27082708
{
2709
- if( ! val || ! dest ) return cson_rc.ArgError;
2710
- else if( ! cson_value_is_string(val) ) return cson_rc.TypeError;
2709
+ if( ! val || ! dest ) return CSON_RC_ArgError;
2710
+ else if( ! cson_value_is_string(val) ) return CSON_RC_TypeError;
27112711
else
27122712
{
27132713
if( dest ) *dest = CSON_STR(val);
27142714
return 0;
27152715
}
@@ -2727,12 +2727,12 @@
27272727
return cson_string_cstr( cson_value_get_string(val) );
27282728
}
27292729
27302730
int cson_value_fetch_object( cson_value const * val, cson_object ** obj )
27312731
{
2732
- if( ! val ) return cson_rc.ArgError;
2733
- else if( ! cson_value_is_object(val) ) return cson_rc.TypeError;
2732
+ if( ! val ) return CSON_RC_ArgError;
2733
+ else if( ! cson_value_is_object(val) ) return CSON_RC_TypeError;
27342734
else
27352735
{
27362736
if(obj) *obj = CSON_OBJ(val);
27372737
return 0;
27382738
}
@@ -2744,12 +2744,12 @@
27442744
return obj;
27452745
}
27462746
27472747
int cson_value_fetch_array( cson_value const * val, cson_array ** ar)
27482748
{
2749
- if( ! val ) return cson_rc.ArgError;
2750
- else if( !cson_value_is_array(val) ) return cson_rc.TypeError;
2749
+ if( ! val ) return CSON_RC_ArgError;
2750
+ else if( !cson_value_is_array(val) ) return CSON_RC_TypeError;
27512751
else
27522752
{
27532753
if(ar) *ar = CSON_ARRAY(val);
27542754
return 0;
27552755
}
@@ -2760,11 +2760,11 @@
27602760
cson_array * ar = NULL;
27612761
cson_value_fetch_array( v, &ar );
27622762
return ar;
27632763
}
27642764
2765
-cson_kvp * cson_kvp_alloc()
2765
+cson_kvp * cson_kvp_alloc(void)
27662766
{
27672767
cson_kvp * kvp = (cson_kvp*)cson_malloc(sizeof(cson_kvp),"cson_kvp");
27682768
if( kvp )
27692769
{
27702770
*kvp = cson_kvp_empty;
@@ -2774,20 +2774,20 @@
27742774
27752775
27762776
27772777
int cson_array_append( cson_array * ar, cson_value * v )
27782778
{
2779
- if( !ar || !v ) return cson_rc.ArgError;
2780
- else if( (ar->list.count+1) < ar->list.count ) return cson_rc.RangeError;
2779
+ if( !ar || !v ) return CSON_RC_ArgError;
2780
+ else if( (ar->list.count+1) < ar->list.count ) return CSON_RC_RangeError;
27812781
else
27822782
{
27832783
if( !ar->list.alloced || (ar->list.count == ar->list.alloced-1))
27842784
{
27852785
unsigned int const n = ar->list.count ? (ar->list.count*2) : 7;
27862786
if( n > cson_value_list_reserve( &ar->list, n ) )
27872787
{
2788
- return cson_rc.AllocError;
2788
+ return CSON_RC_AllocError;
27892789
}
27902790
}
27912791
return cson_array_set( ar, ar->list.count, v );
27922792
}
27932793
}
@@ -2832,20 +2832,20 @@
28322832
cson_value * cson_value_new_bool( char v )
28332833
{
28342834
return v ? &CSON_SPECIAL_VALUES[CSON_VAL_TRUE] : &CSON_SPECIAL_VALUES[CSON_VAL_FALSE];
28352835
}
28362836
2837
-cson_value * cson_value_true()
2837
+cson_value * cson_value_true(void)
28382838
{
28392839
return &CSON_SPECIAL_VALUES[CSON_VAL_TRUE];
28402840
}
2841
-cson_value * cson_value_false()
2841
+cson_value * cson_value_false(void)
28422842
{
28432843
return &CSON_SPECIAL_VALUES[CSON_VAL_FALSE];
28442844
}
28452845
2846
-cson_value * cson_value_null()
2846
+cson_value * cson_value_null(void)
28472847
{
28482848
return &CSON_SPECIAL_VALUES[CSON_VAL_NULL];
28492849
}
28502850
28512851
cson_value * cson_new_int( cson_int_t v )
@@ -2917,12 +2917,12 @@
29172917
return cson_string_value( cson_new_string(str, len) );
29182918
}
29192919
29202920
int cson_array_value_fetch( cson_array const * ar, unsigned int pos, cson_value ** v )
29212921
{
2922
- if( !ar) return cson_rc.ArgError;
2923
- if( pos >= ar->list.count ) return cson_rc.RangeError;
2922
+ if( !ar) return CSON_RC_ArgError;
2923
+ if( pos >= ar->list.count ) return CSON_RC_RangeError;
29242924
else
29252925
{
29262926
if(v) *v = ar->list.list[pos];
29272927
return 0;
29282928
}
@@ -2935,11 +2935,11 @@
29352935
return v;
29362936
}
29372937
29382938
int cson_array_length_fetch( cson_array const * ar, unsigned int * v )
29392939
{
2940
- if( ! ar || !v ) return cson_rc.ArgError;
2940
+ if( ! ar || !v ) return CSON_RC_ArgError;
29412941
else
29422942
{
29432943
if(v) *v = ar->list.count;
29442944
return 0;
29452945
}
@@ -2952,11 +2952,11 @@
29522952
return i;
29532953
}
29542954
29552955
int cson_array_reserve( cson_array * ar, unsigned int size )
29562956
{
2957
- if( ! ar ) return cson_rc.ArgError;
2957
+ if( ! ar ) return CSON_RC_ArgError;
29582958
else if( size <= ar->list.alloced )
29592959
{
29602960
/* We don't want to introduce a can of worms by trying to
29612961
handle the cleanup from here.
29622962
*/
@@ -2963,24 +2963,24 @@
29632963
return 0;
29642964
}
29652965
else
29662966
{
29672967
return (ar->list.alloced > cson_value_list_reserve( &ar->list, size ))
2968
- ? cson_rc.AllocError
2968
+ ? CSON_RC_AllocError
29692969
: 0
29702970
;
29712971
}
29722972
}
29732973
29742974
int cson_array_set( cson_array * ar, unsigned int ndx, cson_value * v )
29752975
{
2976
- if( !ar || !v ) return cson_rc.ArgError;
2977
- else if( (ndx+1) < ndx) /* overflow */return cson_rc.RangeError;
2976
+ if( !ar || !v ) return CSON_RC_ArgError;
2977
+ else if( (ndx+1) < ndx) /* overflow */return CSON_RC_RangeError;
29782978
else
29792979
{
29802980
unsigned const int len = cson_value_list_reserve( &ar->list, ndx+1 );
2981
- if( len <= ndx ) return cson_rc.AllocError;
2981
+ if( len <= ndx ) return CSON_RC_AllocError;
29822982
else
29832983
{
29842984
cson_value * old = ar->list.list[ndx];
29852985
if( old )
29862986
{
@@ -3076,18 +3076,18 @@
30763076
}
30773077
#endif
30783078
30793079
int cson_object_unset( cson_object * obj, char const * key )
30803080
{
3081
- if( ! obj || !key || !*key ) return cson_rc.ArgError;
3081
+ if( ! obj || !key || !*key ) return CSON_RC_ArgError;
30823082
else
30833083
{
30843084
unsigned int ndx = 0;
30853085
cson_kvp * kvp = cson_object_search_impl( obj, key, &ndx );
30863086
if( ! kvp )
30873087
{
3088
- return cson_rc.NotFoundError;
3088
+ return CSON_RC_NotFoundError;
30893089
}
30903090
assert( obj->kvp.count > 0 );
30913091
assert( obj->kvp.list[ndx] == kvp );
30923092
cson_kvp_free( kvp );
30933093
obj->kvp.list[ndx] = NULL;
@@ -3109,21 +3109,21 @@
31093109
}
31103110
}
31113111
31123112
int cson_object_set_s( cson_object * obj, cson_string * key, cson_value * v )
31133113
{
3114
- if( !obj || !key ) return cson_rc.ArgError;
3114
+ if( !obj || !key ) return CSON_RC_ArgError;
31153115
else if( NULL == v ) return cson_object_unset( obj, cson_string_cstr(key) );
31163116
else
31173117
{
31183118
char const * cKey;
31193119
cson_value * vKey;
31203120
cson_kvp * kvp;
31213121
vKey = cson_string_value(key);
31223122
assert(vKey && (key==CSON_STR(vKey)));
31233123
if( vKey == CSON_VCAST(obj) ){
3124
- return cson_rc.ArgError;
3124
+ return CSON_RC_ArgError;
31253125
}
31263126
cKey = cson_string_cstr(key);
31273127
kvp = cson_object_search_impl( obj, cKey, NULL );
31283128
if( kvp )
31293129
{ /* "I told 'em we've already got one!" */
@@ -3142,19 +3142,19 @@
31423142
if( !obj->kvp.alloced || (obj->kvp.count == obj->kvp.alloced-1))
31433143
{ /* reserve space */
31443144
unsigned int const n = obj->kvp.count ? (obj->kvp.count*2) : 6;
31453145
if( n > cson_kvp_list_reserve( &obj->kvp, n ) )
31463146
{
3147
- return cson_rc.AllocError;
3147
+ return CSON_RC_AllocError;
31483148
}
31493149
}
31503150
{ /* insert new item... */
31513151
int rc = 0;
31523152
kvp = cson_kvp_alloc();
31533153
if( ! kvp )
31543154
{
3155
- return cson_rc.AllocError;
3155
+ return CSON_RC_AllocError;
31563156
}
31573157
rc = cson_kvp_list_append( &obj->kvp, kvp );
31583158
if( 0 != rc )
31593159
{
31603160
cson_kvp_free(kvp);
@@ -3174,19 +3174,19 @@
31743174
}
31753175
31763176
}
31773177
int cson_object_set( cson_object * obj, char const * key, cson_value * v )
31783178
{
3179
- if( ! obj || !key || !*key ) return cson_rc.ArgError;
3179
+ if( ! obj || !key || !*key ) return CSON_RC_ArgError;
31803180
else if( NULL == v )
31813181
{
31823182
return cson_object_unset( obj, key );
31833183
}
31843184
else
31853185
{
31863186
cson_string * cs = cson_new_string(key,strlen(key));
3187
- if(!cs) return cson_rc.AllocError;
3187
+ if(!cs) return CSON_RC_AllocError;
31883188
else
31893189
{
31903190
int const rc = cson_object_set_s(obj, cs, v);
31913191
if(rc) cson_value_free(cson_string_value(cs));
31923192
return rc;
@@ -3237,13 +3237,13 @@
32373237
}
32383238
}
32393239
/** @internal
32403240
32413241
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.
3242
+ using p->key. In any other case CSON_RC_InternalError is returned.
32433243
3244
- Returns cson_rc.AllocError if an allocation fails.
3244
+ Returns CSON_RC_AllocError if an allocation fails.
32453245
32463246
Returns 0 on success. On error, parsing must be ceased immediately.
32473247
32483248
Ownership of val is ALWAYS TRANSFERED to this function. If this
32493249
function fails, val will be cleaned up and destroyed. (This
@@ -3267,18 +3267,18 @@
32673267
if( !obj->kvp.alloced || (obj->kvp.count == obj->kvp.alloced-1))
32683268
{
32693269
if( obj->kvp.alloced > cson_kvp_list_reserve( &obj->kvp, obj->kvp.count ? (obj->kvp.count*2) : 5 ) )
32703270
{
32713271
cson_value_free(val);
3272
- return cson_rc.AllocError;
3272
+ return CSON_RC_AllocError;
32733273
}
32743274
}
32753275
kvp = cson_kvp_alloc();
32763276
if( ! kvp )
32773277
{
32783278
cson_value_free(val);
3279
- return cson_rc.AllocError;
3279
+ return CSON_RC_AllocError;
32803280
}
32813281
kvp->key = cson_string_value(p->ckey)/*transfer ownership*/;
32823282
assert(0 == kvp->key->refcount);
32833283
cson_refcount_incr(kvp->key);
32843284
p->ckey = NULL;
@@ -3296,11 +3296,11 @@
32963296
return rc;
32973297
}
32983298
else
32993299
{
33003300
if(val) cson_value_free(val);
3301
- return p->errNo = cson_rc.InternalError;
3301
+ return p->errNo = CSON_RC_InternalError;
33023302
}
33033303
33043304
}
33053305
33063306
/** @internal
@@ -3337,11 +3337,11 @@
33373337
return rc;
33383338
}
33393339
else
33403340
{ /* WTF? */
33413341
assert( 0 && "Internal error in cson_parser code" );
3342
- return p->errNo = cson_rc.InternalError;
3342
+ return p->errNo = CSON_RC_InternalError;
33433343
}
33443344
}
33453345
33463346
/**
33473347
Callback for JSON_parser API. Reminder: it returns 0 (meaning false)
@@ -3349,20 +3349,20 @@
33493349
*/
33503350
static int cson_parse_callback( void * cx, int type, JSON_value const * value )
33513351
{
33523352
cson_parser * p = (cson_parser *)cx;
33533353
int rc = 0;
3354
-#define ALLOC_V(T,V) cson_value * v = cson_value_new_##T(V); if( ! v ) { rc = cson_rc.AllocError; break; }
3354
+#define ALLOC_V(T,V) cson_value * v = cson_value_new_##T(V); if( ! v ) { rc = CSON_RC_AllocError; break; }
33553355
switch(type) {
33563356
case JSON_T_ARRAY_BEGIN:
33573357
case JSON_T_OBJECT_BEGIN: {
33583358
cson_value * obja = (JSON_T_ARRAY_BEGIN == type)
33593359
? cson_value_new_array()
33603360
: cson_value_new_object();
33613361
if( ! obja )
33623362
{
3363
- p->errNo = cson_rc.AllocError;
3363
+ p->errNo = CSON_RC_AllocError;
33643364
break;
33653365
}
33663366
if( 0 != rc ) break;
33673367
if( ! p->root )
33683368
{
@@ -3395,11 +3395,11 @@
33953395
}
33963396
case JSON_T_ARRAY_END:
33973397
case JSON_T_OBJECT_END: {
33983398
if( 0 == p->stack.list.count )
33993399
{
3400
- rc = cson_rc.RangeError;
3400
+ rc = CSON_RC_RangeError;
34013401
break;
34023402
}
34033403
#if CSON_OBJECT_PROPS_SORT
34043404
if( cson_value_is_object(p->node) )
34053405
{/* kludge: the parser uses custom cson_object property
@@ -3481,26 +3481,26 @@
34813481
case JSON_T_KEY: {
34823482
assert(!p->ckey);
34833483
p->ckey = cson_new_string( value->vu.str.value, value->vu.str.length );
34843484
if( ! p->ckey )
34853485
{
3486
- rc = cson_rc.AllocError;
3486
+ rc = CSON_RC_AllocError;
34873487
break;
34883488
}
34893489
++p->totalKeyCount;
34903490
break;
34913491
}
34923492
case JSON_T_STRING: {
34933493
cson_value * v = cson_value_new_string( value->vu.str.value, value->vu.str.length );
34943494
rc = ( NULL == v )
3495
- ? cson_rc.AllocError
3495
+ ? CSON_RC_AllocError
34963496
: cson_parser_push_value( p, v );
34973497
break;
34983498
}
34993499
default:
35003500
assert(0);
3501
- rc = cson_rc.InternalError;
3501
+ rc = CSON_RC_InternalError;
35023502
break;
35033503
}
35043504
#undef ALLOC_V
35053505
return ((p->errNo = rc)) ? 0 : 1;
35063506
}
@@ -3512,22 +3512,22 @@
35123512
static int cson_json_err_to_rc( JSON_error jrc )
35133513
{
35143514
switch(jrc)
35153515
{
35163516
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;
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;
35273527
default:
3528
- return cson_rc.InternalError;
3528
+ return CSON_RC_InternalError;
35293529
}
35303530
}
35313531
35323532
/** @internal
35333533
@@ -3543,11 +3543,11 @@
35433543
any other items inserted into it (or under it) during the parsing
35443544
process.
35453545
*/
35463546
static int cson_parser_clean( cson_parser * p )
35473547
{
3548
- if( ! p ) return cson_rc.ArgError;
3548
+ if( ! p ) return CSON_RC_ArgError;
35493549
else
35503550
{
35513551
if( p->p )
35523552
{
35533553
delete_JSON_parser(p->p);
@@ -3574,11 +3574,11 @@
35743574
cson_parse_opt const opt = opt_ ? *opt_ : cson_parse_opt_empty;
35753575
int rc = 0;
35763576
unsigned int len = 1;
35773577
cson_parse_info info = info_ ? *info_ : cson_parse_info_empty;
35783578
cson_parser p = cson_parser_empty;
3579
- if( ! tgt || ! src ) return cson_rc.ArgError;
3579
+ if( ! tgt || ! src ) return CSON_RC_ArgError;
35803580
35813581
{
35823582
JSON_config jopt = {0};
35833583
init_JSON_config( &jopt );
35843584
jopt.allow_comments = opt.allowComments;
@@ -3587,11 +3587,11 @@
35873587
jopt.handle_floats_manually = 0;
35883588
jopt.callback = cson_parse_callback;
35893589
p.p = new_JSON_parser(&jopt);
35903590
if( ! p.p )
35913591
{
3592
- return cson_rc.AllocError;
3592
+ return CSON_RC_AllocError;
35933593
}
35943594
}
35953595
35963596
do
35973597
{ /* FIXME: buffer the input in multi-kb chunks. */
@@ -3608,11 +3608,11 @@
36083608
}
36093609
if( ! JSON_parser_char(p.p, ch[0]) )
36103610
{
36113611
rc = cson_json_err_to_rc( JSON_parser_get_last_error(p.p) );
36123612
if(0==rc) rc = p.errNo;
3613
- if(0==rc) rc = cson_rc.InternalError;
3613
+ if(0==rc) rc = CSON_RC_InternalError;
36143614
info.errorCode = rc;
36153615
break;
36163616
}
36173617
if( '\n' != ch[0]) ++info.col;
36183618
} while(1);
@@ -3630,11 +3630,11 @@
36303630
if( ! JSON_parser_done(p.p) )
36313631
{
36323632
rc = cson_json_err_to_rc( JSON_parser_get_last_error(p.p) );
36333633
cson_parser_clean(&p);
36343634
if(0==rc) rc = p.errNo;
3635
- if(0==rc) rc = cson_rc.InternalError;
3635
+ if(0==rc) rc = CSON_RC_InternalError;
36363636
}
36373637
else
36383638
{
36393639
cson_value * root = p.root;
36403640
p.root = NULL;
@@ -3652,11 +3652,11 @@
36523652
*/;
36533653
*tgt = root;
36543654
}
36553655
else
36563656
{ /* then can happen on empty input. */
3657
- rc = cson_rc.UnknownError;
3657
+ rc = CSON_RC_UnknownError;
36583658
}
36593659
}
36603660
return rc;
36613661
}
36623662
@@ -3771,11 +3771,11 @@
37713771
*/
37723772
static int cson_str_to_json( char const * str, unsigned int len,
37733773
char escapeFwdSlash,
37743774
cson_data_dest_f f, void * state )
37753775
{
3776
- if( NULL == f ) return cson_rc.ArgError;
3776
+ if( NULL == f ) return CSON_RC_ArgError;
37773777
else if( !str || !*str || (0 == len) )
37783778
{ /* special case for 0-length strings. */
37793779
return f( state, "\"\"", 2 );
37803780
}
37813781
else
@@ -3877,26 +3877,26 @@
38773877
#if defined(CSON_FOSSIL_MODE)
38783878
assume_latin1:
38793879
#endif
38803880
memset(ubuf,0,UBLen);
38813881
if(ch <= 0xFFFF){
3882
- rc = sprintf(ubuf, "\\u%04x",ch);
3882
+ rc = snprintf(ubuf, (size_t)UBLen, "\\u%04x",ch);
38833883
if( rc != 6 )
38843884
{
3885
- rc = cson_rc.RangeError;
3885
+ rc = CSON_RC_RangeError;
38863886
break;
38873887
}
38883888
rc = f( state, ubuf, 6 );
38893889
}else{ /* encode as a UTF16 surrogate pair */
38903890
/* http://unicodebook.readthedocs.org/en/latest/unicode_encodings.html#surrogates */
38913891
ch -= 0x10000;
3892
- rc = sprintf(ubuf, "\\u%04x\\u%04x",
3893
- (0xd800 | (ch>>10)),
3894
- (0xdc00 | (ch & 0x3ff)));
3892
+ rc = snprintf(ubuf, (size_t)UBLen, "\\u%04x\\u%04x",
3893
+ (0xd800 | (ch>>10)),
3894
+ (0xdc00 | (ch & 0x3ff)));
38953895
if( rc != 12 )
38963896
{
3897
- rc = cson_rc.RangeError;
3897
+ rc = CSON_RC_RangeError;
38983898
break;
38993899
}
39003900
rc = f( state, ubuf, 12 );
39013901
}
39023902
continue;
@@ -3910,11 +3910,11 @@
39103910
}
39113911
}
39123912
39133913
int cson_object_iter_init( cson_object const * obj, cson_object_iterator * iter )
39143914
{
3915
- if( ! obj || !iter ) return cson_rc.ArgError;
3915
+ if( ! obj || !iter ) return CSON_RC_ArgError;
39163916
else
39173917
{
39183918
iter->obj = obj;
39193919
iter->pos = 0;
39203920
return 0;
@@ -3936,64 +3936,62 @@
39363936
}
39373937
}
39383938
39393939
static int cson_output_null( cson_data_dest_f f, void * state )
39403940
{
3941
- if( !f ) return cson_rc.ArgError;
3941
+ if( !f ) return CSON_RC_ArgError;
39423942
else
39433943
{
39443944
return f(state, "null", 4);
39453945
}
39463946
}
39473947
39483948
static int cson_output_bool( cson_value const * src, cson_data_dest_f f, void * state )
39493949
{
3950
- if( !f ) return cson_rc.ArgError;
3950
+ if( !f ) return CSON_RC_ArgError;
39513951
else
39523952
{
39533953
char const v = cson_value_get_bool(src);
39543954
return f(state, v ? "true" : "false", v ? 4 : 5);
39553955
}
39563956
}
39573957
39583958
static int cson_output_integer( cson_value const * src, cson_data_dest_f f, void * state )
39593959
{
3960
- if( !f ) return cson_rc.ArgError;
3961
- else if( !cson_value_is_integer(src) ) return cson_rc.TypeError;
3960
+ if( !f ) return CSON_RC_ArgError;
3961
+ else if( !cson_value_is_integer(src) ) return CSON_RC_TypeError;
39623962
else
39633963
{
39643964
enum { BufLen = 100 };
39653965
char b[BufLen];
39663966
int rc;
39673967
memset( b, 0, BufLen );
3968
- rc = sprintf( b, "%"CSON_INT_T_PFMT, cson_value_get_integer(src) )
3969
- /* Reminder: snprintf() is C99 */
3970
- ;
3968
+ rc = snprintf( b, (size_t)BufLen, "%"CSON_INT_T_PFMT,
3969
+ cson_value_get_integer(src) );
39713970
return ( rc<=0 )
3972
- ? cson_rc.RangeError
3971
+ ? CSON_RC_RangeError
39733972
: f( state, b, (unsigned int)rc )
39743973
;
39753974
}
39763975
}
39773976
39783977
static int cson_output_double( cson_value const * src, cson_data_dest_f f, void * state )
39793978
{
3980
- if( !f ) return cson_rc.ArgError;
3981
- else if( !cson_value_is_double(src) ) return cson_rc.TypeError;
3979
+ if( !f ) return CSON_RC_ArgError;
3980
+ else if( !cson_value_is_double(src) ) return CSON_RC_TypeError;
39823981
else
39833982
{
39843983
enum { BufLen = 128 /* this must be relatively large or huge
39853984
doubles can cause us to overrun here,
39863985
resulting in stack-smashing errors.
39873986
*/};
39883987
char b[BufLen];
39893988
int rc;
39903989
memset( b, 0, BufLen );
3991
- rc = sprintf( b, "%"CSON_DOUBLE_T_PFMT, cson_value_get_double(src) )
3992
- /* Reminder: snprintf() is C99 */
3993
- ;
3994
- if( rc<=0 ) return cson_rc.RangeError;
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;
39953993
else if(1)
39963994
{ /* Strip trailing zeroes before passing it on... */
39973995
unsigned int urc = (unsigned int)rc;
39983996
char * pos = b + urc - 1;
39993997
for( ; ('0' == *pos) && urc && (*(pos-1) != '.'); --pos, --urc )
@@ -4012,12 +4010,12 @@
40124010
}
40134011
}
40144012
40154013
static int cson_output_string( cson_value const * src, char escapeFwdSlash, cson_data_dest_f f, void * state )
40164014
{
4017
- if( !f ) return cson_rc.ArgError;
4018
- else if( ! cson_value_is_string(src) ) return cson_rc.TypeError;
4015
+ if( !f ) return CSON_RC_ArgError;
4016
+ else if( ! cson_value_is_string(src) ) return CSON_RC_TypeError;
40194017
else
40204018
{
40214019
cson_string const * str = cson_value_get_string(src);
40224020
assert( NULL != str );
40234021
return cson_str_to_json(cson_string_cstr(str), str->length, escapeFwdSlash, f, state);
@@ -4075,11 +4073,11 @@
40754073
Returns 0 on success.
40764074
*/
40774075
static int cson_output_impl( cson_value const * src, cson_data_dest_f f, void * state,
40784076
cson_output_opt const * fmt, unsigned int level )
40794077
{
4080
- if( ! src || !f || !src->api ) return cson_rc.ArgError;
4078
+ if( ! src || !f || !src->api ) return CSON_RC_ArgError;
40814079
else
40824080
{
40834081
int rc = 0;
40844082
assert(fmt);
40854083
switch( src->api->typeID )
@@ -4105,11 +4103,11 @@
41054103
break;
41064104
case CSON_TYPE_OBJECT:
41074105
rc = cson_output_object( src, f, state, fmt, level );
41084106
break;
41094107
default:
4110
- rc = cson_rc.TypeError;
4108
+ rc = CSON_RC_TypeError;
41114109
break;
41124110
}
41134111
return rc;
41144112
}
41154113
}
@@ -4116,13 +4114,13 @@
41164114
41174115
41184116
static int cson_output_array( cson_value const * src, cson_data_dest_f f, void * state,
41194117
cson_output_opt const * fmt, unsigned int level )
41204118
{
4121
- if( !src || !f || !fmt ) return cson_rc.ArgError;
4122
- else if( ! cson_value_is_array(src) ) return cson_rc.TypeError;
4123
- else if( level > fmt->maxDepth ) return cson_rc.RangeError;
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;
41244122
else
41254123
{
41264124
int rc;
41274125
unsigned int i;
41284126
cson_value const * v;
@@ -4177,13 +4175,13 @@
41774175
}
41784176
41794177
static int cson_output_object( cson_value const * src, cson_data_dest_f f, void * state,
41804178
cson_output_opt const * fmt, unsigned int level )
41814179
{
4182
- if( !src || !f || !fmt ) return cson_rc.ArgError;
4183
- else if( ! cson_value_is_object(src) ) return cson_rc.TypeError;
4184
- else if( level > fmt->maxDepth ) return cson_rc.RangeError;
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;
41854183
else
41864184
{
41874185
int rc;
41884186
unsigned int i;
41894187
cson_kvp const * kvp;
@@ -4267,17 +4265,17 @@
42674265
return rc;
42684266
}
42694267
42704268
int cson_data_dest_FILE( void * state, void const * src, unsigned int n )
42714269
{
4272
- if( ! state ) return cson_rc.ArgError;
4270
+ if( ! state ) return CSON_RC_ArgError;
42734271
else if( !src || !n ) return 0;
42744272
else
42754273
{
42764274
return ( 1 == fwrite( src, n, 1, (FILE*) state ) )
42774275
? 0
4278
- : cson_rc.IOError;
4276
+ : CSON_RC_IOError;
42794277
}
42804278
}
42814279
42824280
int cson_output_FILE( cson_value const * src, FILE * dest, cson_output_opt const * fmt )
42834281
{
@@ -4300,15 +4298,15 @@
43004298
return rc;
43014299
}
43024300
43034301
int cson_output_filename( cson_value const * src, char const * dest, cson_output_opt const * fmt )
43044302
{
4305
- if( !src || !dest ) return cson_rc.ArgError;
4303
+ if( !src || !dest ) return CSON_RC_ArgError;
43064304
else
43074305
{
43084306
FILE * f = fopen(dest,"wb");
4309
- if( !f ) return cson_rc.IOError;
4307
+ if( !f ) return CSON_RC_IOError;
43104308
else
43114309
{
43124310
int const rc = cson_output_FILE( src, f, fmt );
43134311
fclose(f);
43144312
return rc;
@@ -4317,15 +4315,15 @@
43174315
}
43184316
43194317
int cson_parse_filename( cson_value ** tgt, char const * src,
43204318
cson_parse_opt const * opt, cson_parse_info * err )
43214319
{
4322
- if( !src || !tgt ) return cson_rc.ArgError;
4320
+ if( !src || !tgt ) return CSON_RC_ArgError;
43234321
else
43244322
{
43254323
FILE * f = fopen(src, "r");
4326
- if( !f ) return cson_rc.IOError;
4324
+ if( !f ) return CSON_RC_IOError;
43274325
else
43284326
{
43294327
int const rc = cson_parse_FILE( tgt, f, opt, err );
43304328
fclose(f);
43314329
return rc;
@@ -4349,11 +4347,11 @@
43494347
A cson_data_source_f() implementation which requires the state argument
43504348
to be a properly populated (cson_data_source_StringSource_t*).
43514349
*/
43524350
static int cson_data_source_StringSource( void * state, void * dest, unsigned int * n )
43534351
{
4354
- if( !state || !n || !dest ) return cson_rc.ArgError;
4352
+ if( !state || !n || !dest ) return CSON_RC_ArgError;
43554353
else if( !*n ) return 0 /* ignore this */;
43564354
else
43574355
{
43584356
unsigned int i;
43594357
cson_data_source_StringSource_t * ss = (cson_data_source_StringSource_t*) state;
@@ -4368,12 +4366,12 @@
43684366
}
43694367
43704368
int cson_parse_string( cson_value ** tgt, char const * src, unsigned int len,
43714369
cson_parse_opt const * opt, cson_parse_info * err )
43724370
{
4373
- if( ! tgt || !src ) return cson_rc.ArgError;
4374
- else if( !*src || (len<2/*2==len of {} and []*/) ) return cson_rc.RangeError;
4371
+ if( ! tgt || !src ) return CSON_RC_ArgError;
4372
+ else if( !*src || (len<2/*2==len of {} and []*/) ) return CSON_RC_RangeError;
43754373
else
43764374
{
43774375
cson_data_source_StringSource_t ss;
43784376
ss.str = ss.pos = src;
43794377
ss.end = src + len;
@@ -4386,18 +4384,18 @@
43864384
cson_buffer const * buf,
43874385
cson_parse_opt const * opt,
43884386
cson_parse_info * err )
43894387
{
43904388
return ( !tgt || !buf || !buf->mem || !buf->used )
4391
- ? cson_rc.ArgError
4389
+ ? CSON_RC_ArgError
43924390
: cson_parse_string( tgt, (char const *)buf->mem,
43934391
buf->used, opt, err );
43944392
}
43954393
43964394
int cson_buffer_reserve( cson_buffer * buf, cson_size_t n )
43974395
{
4398
- if( ! buf ) return cson_rc.ArgError;
4396
+ if( ! buf ) return CSON_RC_ArgError;
43994397
else if( 0 == n )
44004398
{
44014399
cson_free(buf->mem, "cson_buffer::mem");
44024400
*buf = cson_buffer_empty;
44034401
return 0;
@@ -4407,11 +4405,11 @@
44074405
return 0;
44084406
}
44094407
else
44104408
{
44114409
unsigned char * x = (unsigned char *)cson_realloc( buf->mem, n, "cson_buffer::mem" );
4412
- if( ! x ) return cson_rc.AllocError;
4410
+ if( ! x ) return CSON_RC_AllocError;
44134411
memset( x + buf->used, 0, n - buf->used );
44144412
buf->mem = x;
44154413
buf->capacity = n;
44164414
++buf->timesExpanded;
44174415
return 0;
@@ -4434,11 +4432,11 @@
44344432
arg MUST be a (cson_buffer*). This function appends n bytes at
44354433
position arg->used, expanding the buffer as necessary.
44364434
*/
44374435
static int cson_data_dest_cson_buffer( void * arg, void const * data_, unsigned int n )
44384436
{
4439
- if( !arg ) return cson_rc.ArgError;
4437
+ if( !arg ) return CSON_RC_ArgError;
44404438
else if( ! n ) return 0;
44414439
else
44424440
{
44434441
cson_buffer * sb = (cson_buffer*)arg;
44444442
char const * data = (char const *)data_;
@@ -4446,12 +4444,12 @@
44464444
unsigned int i;
44474445
if( npos >= sb->capacity )
44484446
{
44494447
const cson_size_t oldCap = sb->capacity;
44504448
const cson_size_t asz = npos * 2;
4451
- if( asz < npos ) return cson_rc.ArgError; /* overflow */
4452
- else if( 0 != cson_buffer_reserve( sb, asz ) ) return cson_rc.AllocError;
4449
+ if( asz < npos ) return CSON_RC_ArgError; /* overflow */
4450
+ else if( 0 != cson_buffer_reserve( sb, asz ) ) return CSON_RC_AllocError;
44534451
assert( (sb->capacity > oldCap) && "Internal error in memory buffer management!" );
44544452
/* make sure it gets NUL terminated. */
44554453
memset( sb->mem + oldCap, 0, (sb->capacity - oldCap) );
44564454
}
44574455
for( i = 0; i < n; ++i, ++sb->used )
@@ -4533,19 +4531,19 @@
45334531
return (pos > *inp) ? 1 : 0;
45344532
}
45354533
45364534
int cson_object_fetch_sub2( cson_object const * obj, cson_value ** tgt, char const * path )
45374535
{
4538
- if( ! obj || !path ) return cson_rc.ArgError;
4539
- else if( !*path || !*(1+path) ) return cson_rc.RangeError;
4536
+ if( ! obj || !path ) return CSON_RC_ArgError;
4537
+ else if( !*path || !*(1+path) ) return CSON_RC_RangeError;
45404538
else return cson_object_fetch_sub(obj, tgt, path+1, *path);
45414539
}
45424540
45434541
int cson_object_fetch_sub( cson_object const * obj, cson_value ** tgt, char const * path, char sep )
45444542
{
4545
- if( ! obj || !path ) return cson_rc.ArgError;
4546
- else if( !*path || !sep ) return cson_rc.RangeError;
4543
+ if( ! obj || !path ) return CSON_RC_ArgError;
4544
+ else if( !*path || !sep ) return CSON_RC_RangeError;
45474545
else
45484546
{
45494547
char const * beg = path;
45504548
char const * end = NULL;
45514549
int rc;
@@ -4565,26 +4563,26 @@
45654563
++tokenCount;
45664564
beg = end;
45674565
end = NULL;
45684566
}
45694567
}
4570
- if( 0 == tokenCount ) return cson_rc.RangeError;
4568
+ if( 0 == tokenCount ) return CSON_RC_RangeError;
45714569
beg = path;
45724570
end = NULL;
45734571
for( i = 0; i < tokenCount; ++i, beg=end, end=NULL )
45744572
{
45754573
rc = cson_next_token( &beg, sep, &end );
45764574
assert( 1 == rc );
45774575
assert( beg != end );
45784576
assert( end > beg );
45794577
len = end - beg;
4580
- if( len > (BufSize-1) ) return cson_rc.RangeError;
4578
+ if( len > (BufSize-1) ) return CSON_RC_RangeError;
45814579
memset( buf, 0, len + 1 );
45824580
memcpy( buf, beg, len );
45834581
buf[len] = 0;
45844582
cv = cson_object_get( curObj, buf );
4585
- if( NULL == cv ) return cson_rc.NotFoundError;
4583
+ if( NULL == cv ) return CSON_RC_NotFoundError;
45864584
else if( i == (tokenCount-1) )
45874585
{
45884586
if(tgt) *tgt = cv;
45894587
return 0;
45904588
}
@@ -4594,15 +4592,15 @@
45944592
assert((NULL != curObj) && "Detected mis-management of internal memory!");
45954593
}
45964594
/* TODO: arrays. Requires numeric parsing for the index. */
45974595
else
45984596
{
4599
- return cson_rc.NotFoundError;
4597
+ return CSON_RC_NotFoundError;
46004598
}
46014599
}
46024600
assert( i == tokenCount );
4603
- return cson_rc.NotFoundError;
4601
+ return CSON_RC_NotFoundError;
46044602
}
46054603
}
46064604
46074605
cson_value * cson_object_get_sub( cson_object const * obj, char const * path, char sep )
46084606
{
@@ -4838,24 +4836,26 @@
48384836
}
48394837
case CSON_TYPE_STRING: {
48404838
cson_string const * jstr = cson_value_get_string(orig);
48414839
unsigned const int slen = cson_string_length_bytes( jstr );
48424840
assert( NULL != jstr );
4843
- v = cson_strdup( cson_string_cstr( jstr ), slen );
4841
+ v = cson_strdup( cson_string_cstr( jstr ), slen );
48444842
break;
48454843
}
48464844
case CSON_TYPE_INTEGER: {
48474845
char buf[BufSize] = {0};
4848
- if( 0 < sprintf( v, "%"CSON_INT_T_PFMT, cson_value_get_integer(orig)) )
4846
+ if( 0 < snprintf( v, (size_t)BufSize, "%"CSON_INT_T_PFMT,
4847
+ cson_value_get_integer(orig)) )
48494848
{
48504849
v = cson_strdup( buf, strlen(buf) );
48514850
}
48524851
break;
48534852
}
48544853
case CSON_TYPE_DOUBLE: {
48554854
char buf[BufSize] = {0};
4856
- if( 0 < sprintf( v, "%"CSON_DOUBLE_T_PFMT, cson_value_get_double(orig)) )
4855
+ if( 0 < snprintf( v, (size_t)BufSize, "%"CSON_DOUBLE_T_PFMT,
4856
+ cson_value_get_double(orig)) )
48574857
{
48584858
v = cson_strdup( buf, strlen(buf) );
48594859
}
48604860
break;
48614861
}
@@ -4891,24 +4891,26 @@
48914891
}
48924892
case CSON_TYPE_STRING: {
48934893
cson_string const * jstr = cson_value_get_string(orig);
48944894
unsigned const int slen = cson_string_length_bytes( jstr );
48954895
assert( NULL != jstr );
4896
- v = cson_strdup( cson_string_cstr( jstr ), slen );
4896
+ v = cson_strdup( cson_string_cstr( jstr ), slen );
48974897
break;
48984898
}
48994899
case CSON_TYPE_INTEGER: {
49004900
char buf[BufSize] = {0};
4901
- if( 0 < sprintf( v, "%"CSON_INT_T_PFMT, cson_value_get_integer(orig)) )
4901
+ if( 0 < snprintf( v, (size_t)BufSize, "%"CSON_INT_T_PFMT,
4902
+ cson_value_get_integer(orig)) )
49024903
{
49034904
v = cson_strdup( buf, strlen(buf) );
49044905
}
49054906
break;
49064907
}
49074908
case CSON_TYPE_DOUBLE: {
49084909
char buf[BufSize] = {0};
4909
- if( 0 < sprintf( v, "%"CSON_DOUBLE_T_PFMT, cson_value_get_double(orig)) )
4910
+ if( 0 < snprintf( v, (size_t)BufSize, "%"CSON_DOUBLE_T_PFMT,
4911
+ cson_value_get_double(orig)) )
49104912
{
49114913
v = cson_strdup( buf, strlen(buf) );
49124914
}
49134915
break;
49144916
}
@@ -4988,11 +4990,11 @@
49884990
cson_object_iterator iter = cson_object_iterator_empty;
49894991
int rc;
49904992
char const replace = (flags & CSON_MERGE_REPLACE);
49914993
char const recurse = !(flags & CSON_MERGE_NO_RECURSE);
49924994
cson_kvp const * kvp;
4993
- if((!dest || !src) || (dest==src)) return cson_rc.ArgError;
4995
+ if((!dest || !src) || (dest==src)) return CSON_RC_ArgError;
49944996
rc = cson_object_iter_init( src, &iter );
49954997
if(rc) return rc;
49964998
while( (kvp = cson_object_iter_next(&iter) ) )
49974999
{
49985000
cson_string * key = cson_kvp_key(kvp);
@@ -5052,11 +5054,11 @@
50525054
int cson_parse_argv_flags( int argc, char const * const * argv,
50535055
cson_object ** tgt, unsigned int * count ){
50545056
cson_object * o = NULL;
50555057
int rc = 0;
50565058
int i = 0;
5057
- if(argc<1 || !argc || !tgt) return cson_rc.ArgError;
5059
+ if(argc<1 || !argc || !tgt) return CSON_RC_ArgError;
50585060
o = *tgt ? *tgt : cson_new_object();
50595061
if(count) *count = 0;
50605062
for( i = 0; i < argc; ++i ){
50615063
char const * arg = argv[i];
50625064
char const * key = arg;
@@ -5068,11 +5070,11 @@
50685070
if(!*key) continue;
50695071
pos = key;
50705072
while( *pos && ('=' != *pos)) ++pos;
50715073
k = cson_new_string(key, pos-key);
50725074
if(!k){
5073
- rc = cson_rc.AllocError;
5075
+ rc = CSON_RC_AllocError;
50745076
break;
50755077
}
50765078
if(!*pos){ /** --key */
50775079
v = cson_value_true();
50785080
}else{ /** --key=...*/
@@ -5110,10 +5112,1087 @@
51105112
#undef CSON_VCAST
51115113
#undef CSON_MALLOC_IMPL
51125114
#undef CSON_FREE_IMPL
51135115
#undef CSON_REALLOC_IMPL
51145116
/* end file ./cson.c */
5117
+/* begin file ./cson_pack.c */
5118
+/* LICENSE
5119
+
5120
+Copyright (c) 2018 Guido Berhoerster <[email protected]>
5121
+
5122
+Permission is hereby granted, free of charge, to any person
5123
+obtaining a copy of this software and associated documentation
5124
+files (the "Software"), to deal in the Software without
5125
+restriction, including without limitation the rights to use,
5126
+copy, modify, merge, publish, distribute, sublicense, and/or sell
5127
+copies of the Software, and to permit persons to whom the
5128
+Software is furnished to do so, subject to the following
5129
+conditions:
5130
+
5131
+The above copyright notice and this permission notice shall be
5132
+included in all copies or substantial portions of the Software.
5133
+
5134
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
5135
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
5136
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
5137
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
5138
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
5139
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
5140
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
5141
+OTHER DEALINGS IN THE SOFTWARE.
5142
+
5143
+*/
5144
+
5145
+#include <assert.h>
5146
+#include <stdlib.h>
5147
+#include <string.h>
5148
+
5149
+
5150
+#if __STDC_VERSION__ >= 199901L
5151
+#define INLINE inline
5152
+#else
5153
+#define INLINE
5154
+#endif /* __STDC_VERSION__ >= 199901L */
5155
+
5156
+#define PACK_IGNORED_CHARS " \t\r\n:,"
5157
+
5158
+enum parser_state {
5159
+ STATE_INVALID,
5160
+ STATE_INITIAL,
5161
+ STATE_END,
5162
+ STATE_ARRAY_VALUE,
5163
+ STATE_PROPERTY_NAME,
5164
+ STATE_PROPERTY_VALUE
5165
+};
5166
+
5167
+struct token
5168
+{
5169
+ int type; /* type specifier */
5170
+ int optional; /* optional property modifier */
5171
+ int suppress; /* suppress assignment modifier */
5172
+ int alloc; /* assignment allocation modifier */
5173
+ int len_l; /* long length modifier */
5174
+};
5175
+
5176
+struct state
5177
+{
5178
+ cson_value * parent_value;
5179
+ const char * property_name;
5180
+ enum parser_state parser_state;
5181
+ int property_optional;
5182
+ unsigned int index;
5183
+};
5184
+
5185
+struct state_stack
5186
+{
5187
+ size_t capacity;
5188
+ size_t top;
5189
+ struct state *state;
5190
+};
5191
+
5192
+union pack_value
5193
+{
5194
+ cson_array * array;
5195
+ cson_object * object;
5196
+ const char * string;
5197
+ cson_int_t i;
5198
+ double d;
5199
+ char b;
5200
+};
5201
+
5202
+union unpack_value
5203
+{
5204
+ cson_array ** arrayp;
5205
+ cson_object ** objectp;
5206
+ const char ** stringp;
5207
+ char ** astringp;
5208
+ cson_int_t * ip;
5209
+ double * dp;
5210
+ char * bp;
5211
+};
5212
+
5213
+static const char * next_token( const char * s, struct token * tok )
5214
+{
5215
+ tok->type = -1;
5216
+ tok->optional = 0;
5217
+ tok->suppress = 0;
5218
+ tok->alloc = 0;
5219
+ tok->len_l = 0;
5220
+
5221
+ /* skip ignored characters */
5222
+ while( ( *s != '\0' ) && ( strchr( PACK_IGNORED_CHARS, *s ) != NULL ) )
5223
+ {
5224
+ s++;
5225
+ }
5226
+
5227
+ switch( *s )
5228
+ {
5229
+ case '%':
5230
+ for( s++; *s != '\0'; s++ )
5231
+ {
5232
+ switch( *s )
5233
+ {
5234
+ case '?':
5235
+ tok->optional++;
5236
+ break;
5237
+ case '*':
5238
+ tok->suppress++;
5239
+ break;
5240
+ case 'm':
5241
+ tok->alloc++;
5242
+ break;
5243
+ case 'l':
5244
+ tok->len_l++;
5245
+ break;
5246
+ case 'D':
5247
+ /* short form of "lld" */
5248
+ tok->len_l += 2;
5249
+ tok->type = 'd';
5250
+ s++;
5251
+ goto out;
5252
+ case 'i':
5253
+ /* same as 'd' */
5254
+ tok->type = 'd';
5255
+ s++;
5256
+ goto out;
5257
+ case 's': /* FALLTHROUGH */
5258
+ case 'd': /* FALLTHROUGH */
5259
+ case 'f': /* FALLTHROUGH */
5260
+ case 'b': /* FALLTHROUGH */
5261
+ case 'N': /* FALLTHROUGH */
5262
+ case '[': /* FALLTHROUGH */
5263
+ case '{':
5264
+ tok->type = *s++;
5265
+ goto out;
5266
+ default:
5267
+ return ( NULL );
5268
+ }
5269
+ }
5270
+ return ( NULL );
5271
+ case '[': /* FALLTHROUGH */
5272
+ case '{':
5273
+ /* short form of "*[" or "*{" */
5274
+ tok->type = *s++;
5275
+ tok->suppress = 1;
5276
+ break;
5277
+ case ']': /* FALLTHROUGH */
5278
+ case '}':
5279
+ tok->type = *s++;
5280
+ break;
5281
+ case '\0':
5282
+ tok->type = *s;
5283
+ break;
5284
+ default:
5285
+ return ( NULL );
5286
+ }
5287
+
5288
+out:
5289
+ if( ( tok->optional > 1 ) || ( tok->suppress > 1 ) || ( tok->alloc > 1 ) ||
5290
+ ( tok->len_l > 2 ) || ( ( tok->type != 'd' ) && ( tok->len_l > 0 ) ) )
5291
+ {
5292
+ return ( NULL );
5293
+ }
5294
+
5295
+ return ( s );
5296
+}
5297
+
5298
+static struct state_stack * state_stack_create( size_t capacity )
5299
+{
5300
+ struct state_stack * stack;
5301
+
5302
+ assert( capacity >= 2 );
5303
+
5304
+ stack = malloc( sizeof( struct state_stack ) );
5305
+ if( stack == NULL )
5306
+ {
5307
+ return ( NULL );
5308
+ }
5309
+ stack->state = malloc( capacity * sizeof( struct state ) );
5310
+ if( stack->state == NULL )
5311
+ {
5312
+ return ( NULL );
5313
+ }
5314
+ stack->top = 0;
5315
+ stack->capacity = capacity;
5316
+ /* initialize bottom of the stack */
5317
+ stack->state[0].parser_state = STATE_INVALID;
5318
+ stack->state[0].parent_value = NULL;
5319
+ stack->state[0].property_name = NULL;
5320
+ stack->state[0].property_optional = 0;
5321
+ stack->state[0].index = 0;
5322
+
5323
+ return ( stack );
5324
+}
5325
+
5326
+static INLINE struct state * state_stack_top( struct state_stack * stack )
5327
+{
5328
+ assert( stack->top >= 1 );
5329
+
5330
+ return ( &stack->state[stack->top] );
5331
+}
5332
+
5333
+static INLINE void state_stack_push( struct state_stack * stack,
5334
+ enum parser_state parser_state,
5335
+ cson_value * parent_value,
5336
+ const char * property_name,
5337
+ int property_optional,
5338
+ unsigned int index )
5339
+{
5340
+ struct state * state = &stack->state[++stack->top];
5341
+
5342
+ state->parser_state = parser_state;
5343
+ state->parent_value = parent_value;
5344
+ state->property_name = property_name;
5345
+ state->property_optional = property_optional;
5346
+ state->index = index;
5347
+}
5348
+
5349
+static INLINE void state_stack_pop( struct state_stack * stack )
5350
+{
5351
+ assert( stack->top >= 1 );
5352
+
5353
+ stack->top--;
5354
+}
5355
+
5356
+static int
5357
+on_pack_initial( struct state_stack * stack,
5358
+ struct token * tok,
5359
+ union pack_value * pack_value,
5360
+ cson_value ** root_valuep )
5361
+{
5362
+ cson_value * value;
5363
+ cson_value * root_value;
5364
+
5365
+ if( tok->optional || tok->alloc )
5366
+ {
5367
+ /* invalid modifier */
5368
+ return ( CSON_PACK_ARG_ERROR );
5369
+ }
5370
+
5371
+ if( tok->type == '[' )
5372
+ {
5373
+ if( tok->suppress )
5374
+ {
5375
+ root_value = cson_value_new_array( );
5376
+ if( root_value == NULL )
5377
+ {
5378
+ return ( CSON_PACK_ALLOC_ERROR );
5379
+ }
5380
+ }
5381
+ else
5382
+ {
5383
+ value = cson_array_value( pack_value->array );
5384
+ root_value = cson_value_clone( value );
5385
+ }
5386
+
5387
+ state_stack_pop( stack );
5388
+ state_stack_push( stack, STATE_END, NULL, NULL, 0, 0 );
5389
+ state_stack_push( stack, STATE_ARRAY_VALUE, root_value, NULL, 0, 0 );
5390
+ }
5391
+ else if( tok->type == '{' )
5392
+ {
5393
+ if( tok->suppress )
5394
+ {
5395
+ root_value = cson_value_new_object( );
5396
+ if( root_value == NULL )
5397
+ {
5398
+ return ( CSON_PACK_ALLOC_ERROR );
5399
+ }
5400
+ }
5401
+ else
5402
+ {
5403
+ value = cson_object_value( pack_value->object );
5404
+ root_value = cson_value_clone( value );
5405
+ }
5406
+
5407
+ state_stack_pop( stack );
5408
+ state_stack_push( stack, STATE_END, NULL, NULL, 0, 0 );
5409
+ state_stack_push( stack, STATE_PROPERTY_NAME, root_value, NULL, 0, 0 );
5410
+ }
5411
+ else
5412
+ {
5413
+ /* root value is neither an object nor an array */
5414
+ return ( CSON_PACK_ARG_ERROR );
5415
+ }
5416
+
5417
+ *root_valuep = root_value;
5418
+
5419
+ return ( 0 );
5420
+}
5421
+
5422
+static int on_pack_property_name( struct state_stack * stack, struct token * tok, const char * property_name )
5423
+{
5424
+ cson_value * parent_value;
5425
+
5426
+ if( tok->optional || tok->suppress || tok->alloc )
5427
+ {
5428
+ /* invalid modifier */
5429
+ return ( CSON_PACK_ARG_ERROR );
5430
+ }
5431
+
5432
+ if( tok->type == 's' )
5433
+ {
5434
+ parent_value = state_stack_top( stack )->parent_value;
5435
+ state_stack_pop( stack );
5436
+ state_stack_push( stack, STATE_PROPERTY_VALUE, parent_value, property_name, 0, 0 );
5437
+ }
5438
+ else if( tok->type == '}' )
5439
+ {
5440
+ state_stack_pop( stack );
5441
+ }
5442
+ else
5443
+ {
5444
+ /* neither property specifier nor end of object */
5445
+ return ( CSON_PACK_ARG_ERROR );
5446
+ }
5447
+
5448
+ return ( 0 );
5449
+}
5450
+
5451
+static int
5452
+handle_pack_value( struct state_stack * stack,
5453
+ struct token * tok,
5454
+ union pack_value * pack_value,
5455
+ enum parser_state new_parser_state )
5456
+{
5457
+ cson_value * value;
5458
+ cson_object * object;
5459
+ cson_array * array;
5460
+ int cson_retval;
5461
+ struct state * state;
5462
+ cson_value * parent_value;
5463
+
5464
+ /* create value */
5465
+ switch( tok->type )
5466
+ {
5467
+ case '[':
5468
+ value = tok->suppress ? cson_value_new_array( ) :
5469
+ cson_value_clone( cson_array_value( pack_value->array ) );
5470
+ if( value == NULL )
5471
+ {
5472
+ return ( CSON_PACK_ALLOC_ERROR );
5473
+ }
5474
+ break;
5475
+ case '{':
5476
+ value = tok->suppress ? cson_value_new_object( ) :
5477
+ cson_value_clone( cson_object_value( pack_value->object ) );
5478
+ if( value == NULL )
5479
+ {
5480
+ return ( CSON_PACK_ALLOC_ERROR );
5481
+ }
5482
+ break;
5483
+ case 's':
5484
+ value = cson_value_new_string( pack_value->string, strlen( pack_value->string ) );
5485
+ if( value == NULL )
5486
+ {
5487
+ return ( CSON_PACK_ALLOC_ERROR );
5488
+ }
5489
+ break;
5490
+ case 'd':
5491
+ value = cson_value_new_integer( pack_value->i );
5492
+ if( value == NULL )
5493
+ {
5494
+ return ( CSON_PACK_ALLOC_ERROR );
5495
+ }
5496
+ break;
5497
+ case 'f':
5498
+ value = cson_value_new_double( pack_value->d );
5499
+ if( value == NULL )
5500
+ {
5501
+ return ( CSON_PACK_ALLOC_ERROR );
5502
+ }
5503
+ break;
5504
+ case 'b':
5505
+ value = cson_value_new_bool( pack_value->b );
5506
+ if( value == NULL )
5507
+ {
5508
+ return ( CSON_PACK_ALLOC_ERROR );
5509
+ }
5510
+ break;
5511
+ case 'N':
5512
+ value = cson_value_null( );
5513
+ break;
5514
+ default:
5515
+ /* invalid token type */
5516
+ return ( CSON_PACK_ARG_ERROR );
5517
+ }
5518
+
5519
+ state = state_stack_top( stack );
5520
+ parent_value = state->parent_value;
5521
+ if( cson_value_is_object( parent_value ) )
5522
+ {
5523
+ /* set object property to value */
5524
+ object = cson_value_get_object( parent_value );
5525
+ cson_retval = cson_object_set( object, state->property_name, value );
5526
+ if( cson_retval != 0 )
5527
+ {
5528
+ cson_value_free( value );
5529
+ return ( CSON_PACK_ALLOC_ERROR );
5530
+ }
5531
+ }
5532
+ else if( cson_value_is_array( parent_value ) )
5533
+ {
5534
+ /* append array value */
5535
+ array = cson_value_get_array( parent_value );
5536
+ cson_retval = cson_array_append( array, value );
5537
+ if( cson_retval != 0 )
5538
+ {
5539
+ cson_value_free( value );
5540
+ return ( CSON_PACK_ALLOC_ERROR );
5541
+ }
5542
+ }
5543
+
5544
+ if( tok->type == '[' )
5545
+ {
5546
+ state_stack_pop( stack );
5547
+ state_stack_push( stack, new_parser_state, parent_value, NULL, 0, 0 );
5548
+ state_stack_push( stack, STATE_ARRAY_VALUE, value, NULL, 0, 0 );
5549
+ }
5550
+ else if( tok->type == '{' )
5551
+ {
5552
+ state_stack_pop( stack );
5553
+ state_stack_push( stack, new_parser_state, parent_value, NULL, 0, 0 );
5554
+ state_stack_push( stack, STATE_PROPERTY_NAME, value, NULL, 0, 0 );
5555
+ }
5556
+ else
5557
+ {
5558
+ state_stack_pop( stack );
5559
+ state_stack_push( stack, new_parser_state, parent_value, NULL, 0, 0 );
5560
+ }
5561
+
5562
+ return ( 0 );
5563
+}
5564
+
5565
+static int on_pack_array_value( struct state_stack * stack, struct token * tok, union pack_value * pack_value )
5566
+{
5567
+ if( tok->optional || tok->alloc || ( tok->suppress && ( tok->type != '{' ) && ( tok->type != '[' ) ) )
5568
+ {
5569
+ /* invalid modifier */
5570
+ return ( CSON_PACK_ARG_ERROR );
5571
+ }
5572
+
5573
+ if( tok->type == ']' )
5574
+ {
5575
+ /* end of array specifier */
5576
+ state_stack_pop( stack );
5577
+
5578
+ return ( 0 );
5579
+ }
5580
+
5581
+ return ( handle_pack_value( stack, tok, pack_value, STATE_ARRAY_VALUE ) );
5582
+}
5583
+
5584
+static int on_pack_property_value( struct state_stack * stack, struct token * tok, union pack_value * pack_value )
5585
+{
5586
+ if( tok->optional || tok->alloc || ( tok->suppress && ( tok->type != '{' ) && ( tok->type != '[' ) ) )
5587
+ {
5588
+ /* invalid modifier */
5589
+ return ( CSON_PACK_ARG_ERROR );
5590
+ }
5591
+
5592
+ return ( handle_pack_value( stack, tok, pack_value, STATE_PROPERTY_NAME ) );
5593
+}
5594
+
5595
+int cson_vpack( cson_value ** root_valuep, const char * fmt, va_list args )
5596
+{
5597
+ int retval = CSON_PACK_INTERNAL_ERROR;
5598
+ cson_value * root_value = NULL;
5599
+ struct state_stack * stack = NULL;
5600
+ const char * p = fmt;
5601
+ struct token tok = { 0 };
5602
+ struct state * state;
5603
+ union pack_value pack_value = { 0 };
5604
+ const char * property_name;
5605
+
5606
+ stack = state_stack_create( strlen( fmt ) + 2 );
5607
+ if( stack == NULL )
5608
+ {
5609
+ retval = CSON_PACK_ALLOC_ERROR;
5610
+ goto out;
5611
+ }
5612
+ state_stack_push( stack, STATE_INITIAL, NULL, NULL, 0, 0 );
5613
+
5614
+ for( p = next_token( p, &tok ); p != NULL; p = next_token( p, &tok ) )
5615
+ {
5616
+ state = state_stack_top( stack );
5617
+ if( state->parser_state == STATE_PROPERTY_NAME )
5618
+ {
5619
+ property_name = ( tok.type == 's' ) ? va_arg( args, const char * ) : NULL;
5620
+ }
5621
+ else if( !tok.suppress )
5622
+ {
5623
+ switch( tok.type )
5624
+ {
5625
+ case '[':
5626
+ pack_value.array = va_arg( args, cson_array * );
5627
+ break;
5628
+ case '{':
5629
+ pack_value.object = va_arg( args, cson_object * );
5630
+ break;
5631
+ case 's':
5632
+ pack_value.string = va_arg( args, const char * );
5633
+ break;
5634
+ case 'd':
5635
+ if( tok.len_l == 0 )
5636
+ {
5637
+ pack_value.i = va_arg( args, int );
5638
+ }
5639
+ else if( tok.len_l == 1 )
5640
+ {
5641
+ pack_value.i = va_arg( args, long );
5642
+ }
5643
+ else
5644
+ {
5645
+ pack_value.i = va_arg( args, cson_int_t );
5646
+ }
5647
+ break;
5648
+ case 'f':
5649
+ pack_value.d = va_arg( args, double );
5650
+ break;
5651
+ case 'b':
5652
+ pack_value.b = va_arg( args, int );
5653
+ break;
5654
+ }
5655
+ }
5656
+
5657
+ switch( state->parser_state )
5658
+ {
5659
+ case STATE_INITIAL:
5660
+ retval = on_pack_initial( stack, &tok, &pack_value, &root_value );
5661
+ if( retval != 0 )
5662
+ {
5663
+ goto out;
5664
+ }
5665
+ break;
5666
+ case STATE_END:
5667
+ /* check for trailing characters */
5668
+ retval = ( tok.type == '\0' ) ? 0 : CSON_PACK_ARG_ERROR;
5669
+ goto out;
5670
+ case STATE_PROPERTY_NAME:
5671
+ retval = on_pack_property_name( stack, &tok, property_name );
5672
+ if( retval != 0 )
5673
+ {
5674
+ goto out;
5675
+ }
5676
+ break;
5677
+ case STATE_PROPERTY_VALUE:
5678
+ retval = on_pack_property_value( stack, &tok, &pack_value );
5679
+ if( retval != 0 )
5680
+ {
5681
+ goto out;
5682
+ }
5683
+ break;
5684
+ case STATE_ARRAY_VALUE:
5685
+ retval = on_pack_array_value( stack, &tok, &pack_value );
5686
+ if( retval != 0 )
5687
+ {
5688
+ goto out;
5689
+ }
5690
+ break;
5691
+ default:
5692
+ retval = CSON_PACK_INTERNAL_ERROR;
5693
+ goto out;
5694
+ }
5695
+ }
5696
+ if( p == NULL )
5697
+ {
5698
+ /* parse error */
5699
+ retval = CSON_PACK_ARG_ERROR;
5700
+ }
5701
+
5702
+out:
5703
+ if( retval == 0 )
5704
+ {
5705
+ *root_valuep = root_value;
5706
+ }
5707
+ else
5708
+ {
5709
+ cson_value_free( root_value );
5710
+ }
5711
+ if( stack != NULL ) {
5712
+ free( stack->state );
5713
+ free( stack );
5714
+ }
5715
+
5716
+ return ( retval );
5717
+}
5718
+
5719
+int cson_pack( cson_value ** root_valuep, const char * fmt, ... )
5720
+{
5721
+ int retval;
5722
+ va_list args;
5723
+
5724
+ va_start( args, fmt );
5725
+ retval = cson_vpack( root_valuep, fmt, args );
5726
+ va_end( args );
5727
+
5728
+ return ( retval );
5729
+}
5730
+
5731
+static int on_unpack_initial( struct state_stack * stack, struct token * tok, union unpack_value * unpack_value )
5732
+{
5733
+ int subst = 0;
5734
+ cson_value * root_value;
5735
+
5736
+ if( tok->optional || tok->alloc )
5737
+ {
5738
+ /* invalid modifier */
5739
+ return ( CSON_PACK_ARG_ERROR );
5740
+ }
5741
+
5742
+ root_value = state_stack_top( stack )->parent_value;
5743
+ if( tok->type == '[' )
5744
+ {
5745
+ if( !cson_value_is_array( root_value ) )
5746
+ {
5747
+ return ( CSON_PACK_VALIDATION_ERROR );
5748
+ }
5749
+
5750
+ if( !tok->suppress )
5751
+ {
5752
+ *unpack_value->arrayp = cson_value_get_array( root_value );
5753
+ subst = 1;
5754
+ }
5755
+
5756
+ state_stack_pop( stack );
5757
+ state_stack_push( stack, STATE_END, NULL, NULL, 0, 0 );
5758
+ state_stack_push( stack, STATE_ARRAY_VALUE, root_value, NULL, 0, 0 );
5759
+ }
5760
+ else if( tok->type == '{' )
5761
+ {
5762
+ if( !cson_value_is_object( root_value ) )
5763
+ {
5764
+ return ( CSON_PACK_VALIDATION_ERROR );
5765
+ }
5766
+
5767
+ if( !tok->suppress )
5768
+ {
5769
+ *unpack_value->objectp = cson_value_get_object( root_value );
5770
+ subst = 1;
5771
+ }
5772
+
5773
+ state_stack_pop( stack );
5774
+ state_stack_push( stack, STATE_END, NULL, NULL, 0, 0 );
5775
+ state_stack_push( stack, STATE_PROPERTY_NAME, root_value, NULL, 0, 0 );
5776
+ }
5777
+ else
5778
+ {
5779
+ return ( CSON_PACK_ARG_ERROR );
5780
+ }
5781
+
5782
+ return ( subst );
5783
+}
5784
+
5785
+static int on_unpack_property_name( struct state_stack * stack, struct token * tok, const char * property_name )
5786
+{
5787
+ cson_value * parent_value;
5788
+
5789
+ if( tok->type == '}' )
5790
+ {
5791
+ state_stack_pop( stack );
5792
+ }
5793
+ else if( tok->type == 's' )
5794
+ {
5795
+ if( tok->suppress || tok->alloc )
5796
+ {
5797
+ /* invalid modifier */
5798
+ return ( CSON_PACK_ARG_ERROR );
5799
+ }
5800
+
5801
+ parent_value = state_stack_top( stack )->parent_value;
5802
+ state_stack_pop( stack );
5803
+ state_stack_push( stack, STATE_PROPERTY_VALUE, parent_value, property_name, tok->optional, 0 );
5804
+ }
5805
+ else
5806
+ {
5807
+ /* neither property specifier nor end of object */
5808
+ return ( CSON_PACK_ARG_ERROR );
5809
+ }
5810
+
5811
+ return ( 0 );
5812
+}
5813
+
5814
+static int handle_unpack_value( struct state_stack * stack,
5815
+ struct token * tok,
5816
+ cson_value * value,
5817
+ union unpack_value * unpack_value,
5818
+ enum parser_state new_parser_state )
5819
+{
5820
+ int subst = 0;
5821
+ struct state * state;
5822
+ cson_value * parent_value;
5823
+ unsigned int index;
5824
+ int skip;
5825
+ const char * string;
5826
+ char * astring;
5827
+ size_t len;
5828
+
5829
+ state = state_stack_top( stack );
5830
+ parent_value = state->parent_value;
5831
+ index = state->index;
5832
+ skip = ( parent_value == NULL ) || ( value == NULL );
5833
+
5834
+ switch( tok->type )
5835
+ {
5836
+ case 's':
5837
+ if( !skip )
5838
+ {
5839
+ if( !cson_value_is_string( value ) )
5840
+ {
5841
+ /* property value is not a string */
5842
+ return ( CSON_PACK_VALIDATION_ERROR );
5843
+ }
5844
+
5845
+ if( !tok->suppress )
5846
+ {
5847
+ string = cson_value_get_cstr( value );
5848
+ if( tok->alloc )
5849
+ {
5850
+ len = strlen ( string );
5851
+ astring = malloc( len + 1 );
5852
+ if( astring == NULL )
5853
+ {
5854
+ return ( CSON_PACK_ALLOC_ERROR );
5855
+ }
5856
+ memcpy( astring, string, len + 1 );
5857
+ *unpack_value->astringp = astring;
5858
+ }
5859
+ else
5860
+ {
5861
+ *unpack_value->stringp = string;
5862
+ }
5863
+ subst = 1;
5864
+ }
5865
+ }
5866
+
5867
+ state_stack_pop( stack );
5868
+ state_stack_push( stack, new_parser_state, parent_value, NULL, 0, index );
5869
+ break;
5870
+ case 'd':
5871
+ if( !skip )
5872
+ {
5873
+ if( !cson_value_is_integer( value ) )
5874
+ {
5875
+ /* property value is not an integer */
5876
+ return ( CSON_PACK_VALIDATION_ERROR );
5877
+ }
5878
+
5879
+ if( !tok->suppress )
5880
+ {
5881
+ *unpack_value->ip = cson_value_get_integer( value );
5882
+ subst = 1;
5883
+ }
5884
+ }
5885
+
5886
+ state_stack_pop( stack );
5887
+ state_stack_push( stack, new_parser_state, parent_value, NULL, 0, index );
5888
+ break;
5889
+ case 'f':
5890
+ if( !skip )
5891
+ {
5892
+ if( !cson_value_is_double( value ) )
5893
+ {
5894
+ /* property value is not a float */
5895
+ return ( CSON_PACK_VALIDATION_ERROR );
5896
+ }
5897
+
5898
+ if( !tok->suppress )
5899
+ {
5900
+ *unpack_value->dp = cson_value_get_double( value );
5901
+ subst = 1;
5902
+ }
5903
+ }
5904
+
5905
+ state_stack_pop( stack );
5906
+ state_stack_push( stack, new_parser_state, parent_value, NULL, 0, index );
5907
+ break;
5908
+ case 'b':
5909
+ if( !skip )
5910
+ {
5911
+ if( !cson_value_is_bool( value ) )
5912
+ {
5913
+ /* property value is not a boolean */
5914
+ return ( CSON_PACK_VALIDATION_ERROR );
5915
+ }
5916
+
5917
+ if( !tok->suppress )
5918
+ {
5919
+ *unpack_value->bp = cson_value_get_bool( value );
5920
+ subst = 1;
5921
+ }
5922
+ }
5923
+
5924
+ state_stack_pop( stack );
5925
+ state_stack_push( stack, new_parser_state, parent_value, NULL, 0, index );
5926
+ break;
5927
+ case 'N':
5928
+ if( !skip )
5929
+ {
5930
+ if( !cson_value_is_null( value ) )
5931
+ {
5932
+ /* property value is not an array */
5933
+ return ( CSON_PACK_VALIDATION_ERROR );
5934
+ }
5935
+ }
5936
+
5937
+ state_stack_pop( stack );
5938
+ state_stack_push( stack, new_parser_state, parent_value, NULL, 0, index );
5939
+ break;
5940
+ case '[':
5941
+ if( !skip )
5942
+ {
5943
+ if( !cson_value_is_array( value ) )
5944
+ {
5945
+ /* property value is not an array */
5946
+ return ( CSON_PACK_VALIDATION_ERROR );
5947
+ }
5948
+
5949
+ if( !tok->suppress )
5950
+ {
5951
+ *unpack_value->arrayp = cson_value_get_array( value );
5952
+ subst = 1;
5953
+ }
5954
+ }
5955
+
5956
+ state_stack_pop( stack );
5957
+ state_stack_push( stack, new_parser_state, parent_value, NULL, 0, index );
5958
+ state_stack_push( stack, STATE_ARRAY_VALUE, value, NULL, 0, 0 );
5959
+ break;
5960
+ case '{':
5961
+ if( !skip )
5962
+ {
5963
+ if( !cson_value_is_object( value ) )
5964
+ {
5965
+ /* property value is not an object */
5966
+ return ( CSON_PACK_VALIDATION_ERROR );
5967
+ }
5968
+
5969
+ if( !tok->suppress )
5970
+ {
5971
+ *unpack_value->objectp = cson_value_get_object( value );
5972
+ subst = 1;
5973
+ }
5974
+ }
5975
+
5976
+ state_stack_pop( stack );
5977
+ state_stack_push( stack, new_parser_state, parent_value, NULL, 0, index );
5978
+ state_stack_push( stack, STATE_PROPERTY_NAME, value, NULL, 0, 0 );
5979
+ break;
5980
+ default:
5981
+ return ( CSON_PACK_INTERNAL_ERROR );
5982
+ }
5983
+
5984
+ return ( subst );
5985
+}
5986
+
5987
+static int on_unpack_array_value( struct state_stack * stack, struct token * tok, union unpack_value * unpack_value )
5988
+{
5989
+ struct state * state;
5990
+ cson_array * array;
5991
+ cson_value * value = NULL;
5992
+
5993
+ if( tok->optional )
5994
+ {
5995
+ /* invalid modifier */
5996
+ return ( CSON_PACK_ARG_ERROR );
5997
+ }
5998
+
5999
+ if( tok->type == ']' )
6000
+ {
6001
+ state_stack_pop( stack );
6002
+
6003
+ return ( 0 );
6004
+ }
6005
+ else if( ( tok->type != 's' ) && tok->alloc )
6006
+ {
6007
+ /* invalid modifier */
6008
+ return ( CSON_PACK_ARG_ERROR );
6009
+ }
6010
+
6011
+ state = state_stack_top( stack );
6012
+ if( state->parent_value != NULL )
6013
+ {
6014
+ /* get next array value */
6015
+ array = cson_value_get_array( state->parent_value );
6016
+ value = cson_array_get( array, state->index );
6017
+ if( value == NULL )
6018
+ {
6019
+ /* index out of bounds */
6020
+ return ( CSON_PACK_VALIDATION_ERROR );
6021
+ }
6022
+ }
6023
+ state->index++;
6024
+
6025
+ return ( handle_unpack_value( stack, tok, value, unpack_value, STATE_ARRAY_VALUE ) );
6026
+}
6027
+
6028
+static int on_unpack_property_value( struct state_stack * stack, struct token * tok, union unpack_value * unpack_value )
6029
+{
6030
+ struct state * state;
6031
+ cson_object * object;
6032
+ cson_value * value;
6033
+
6034
+ if( ( tok->optional ) || ( ( tok->type != 's' ) && tok->alloc ) )
6035
+ {
6036
+ /* invalid modifier */
6037
+ return ( CSON_PACK_ARG_ERROR );
6038
+ }
6039
+
6040
+ state = state_stack_top( stack );
6041
+ object = cson_value_get_object( state->parent_value );
6042
+ value = cson_object_get( object, state->property_name );
6043
+ if( !state->property_optional && ( value == NULL ) )
6044
+ {
6045
+ /* missing mandatory property */
6046
+ return ( CSON_PACK_VALIDATION_ERROR );
6047
+ }
6048
+
6049
+ return ( handle_unpack_value( stack, tok, value, unpack_value, STATE_PROPERTY_NAME ) );
6050
+}
6051
+
6052
+int cson_vunpack( cson_value * root_value, const char * fmt, va_list args )
6053
+{
6054
+ int retval = CSON_PACK_INTERNAL_ERROR;
6055
+ int subst = 0;
6056
+ struct state_stack * stack = NULL;
6057
+ struct state * state;
6058
+ const char * p = fmt;
6059
+ struct token tok = { 0 };
6060
+ union unpack_value unpack_value = { 0 };
6061
+ const char * property_name;
6062
+
6063
+ if( root_value == NULL )
6064
+ {
6065
+ retval = CSON_PACK_ARG_ERROR;
6066
+ goto out;
6067
+ }
6068
+
6069
+ stack = state_stack_create( strlen( fmt ) + 2 ); /* worst case */
6070
+ if( stack == NULL )
6071
+ {
6072
+ retval = CSON_PACK_ALLOC_ERROR;
6073
+ goto out;
6074
+ }
6075
+ state_stack_push( stack, STATE_INITIAL, root_value, NULL, 0, 0 );
6076
+
6077
+ for( p = next_token( p, &tok ); p != NULL; p = next_token( p, &tok ) )
6078
+ {
6079
+ state = state_stack_top( stack );
6080
+ if( state->parser_state == STATE_PROPERTY_NAME )
6081
+ {
6082
+ property_name = ( tok.type == 's' ) ? va_arg( args, const char * ) : NULL;
6083
+ }
6084
+ else if( !tok.suppress )
6085
+ {
6086
+ switch( tok.type )
6087
+ {
6088
+ case '[':
6089
+ unpack_value.arrayp = va_arg( args, cson_array ** );
6090
+ break;
6091
+ case '{':
6092
+ unpack_value.objectp = va_arg( args, cson_object ** );
6093
+ break;
6094
+ case 's':
6095
+ if( tok.alloc )
6096
+ {
6097
+ unpack_value.astringp = va_arg( args, char ** );
6098
+ }
6099
+ else
6100
+ {
6101
+ unpack_value.stringp = va_arg( args, const char ** );
6102
+ }
6103
+ break;
6104
+ case 'd':
6105
+ if( tok.len_l != 2 )
6106
+ {
6107
+ /*
6108
+ * parsed values are always of type
6109
+ * cson_int_t
6110
+ */
6111
+ retval = CSON_PACK_ARG_ERROR;
6112
+ goto out;
6113
+ }
6114
+ unpack_value.ip = va_arg( args, cson_int_t * );
6115
+ break;
6116
+ case 'f':
6117
+ unpack_value.dp = va_arg( args, double * );
6118
+ break;
6119
+ case 'b':
6120
+ unpack_value.bp = va_arg( args, char * );
6121
+ break;
6122
+ }
6123
+ }
6124
+
6125
+ switch( state->parser_state )
6126
+ {
6127
+ case STATE_INITIAL:
6128
+ retval = on_unpack_initial( stack, &tok, &unpack_value );
6129
+ if( retval < 0 )
6130
+ {
6131
+ goto out;
6132
+ }
6133
+ subst += retval;
6134
+ break;
6135
+ case STATE_END:
6136
+ /* check for trailing characters */
6137
+ retval = ( tok.type == '\0' ) ? subst : CSON_PACK_ARG_ERROR;
6138
+ goto out;
6139
+ case STATE_PROPERTY_NAME:
6140
+ retval = on_unpack_property_name( stack, &tok, property_name );
6141
+ if( retval != 0 )
6142
+ {
6143
+ goto out;
6144
+ }
6145
+ break;
6146
+ case STATE_PROPERTY_VALUE:
6147
+ retval = on_unpack_property_value( stack, &tok, &unpack_value );
6148
+ if( retval < 0 )
6149
+ {
6150
+ goto out;
6151
+ }
6152
+ subst += retval;
6153
+ break;
6154
+ case STATE_ARRAY_VALUE:
6155
+ retval = on_unpack_array_value( stack, &tok, &unpack_value );
6156
+ if( retval < 0 )
6157
+ {
6158
+ goto out;
6159
+ }
6160
+ subst += retval;
6161
+ break;
6162
+ default:
6163
+ retval = CSON_PACK_INTERNAL_ERROR;
6164
+ goto out;
6165
+ }
6166
+ }
6167
+ if( p == NULL )
6168
+ {
6169
+ /* parse error */
6170
+ retval = CSON_PACK_ARG_ERROR;
6171
+ }
6172
+
6173
+out:
6174
+ if( stack != NULL ) {
6175
+ free( stack->state );
6176
+ free( stack );
6177
+ }
6178
+
6179
+ return ( retval );
6180
+}
6181
+
6182
+int cson_unpack( cson_value * root_value, const char * fmt, ... )
6183
+{
6184
+ int retval;
6185
+ va_list args;
6186
+
6187
+ va_start( args, fmt );
6188
+ retval = cson_vunpack( root_value, fmt, args );
6189
+ va_end( args );
6190
+
6191
+ return ( retval );
6192
+}
6193
+/* end file ./cson_pack.c */
51156194
/* begin file ./cson_lists.h */
51166195
/* Auto-generated from cson_list.h. Edit at your own risk! */
51176196
unsigned int cson_value_list_reserve( cson_value_list * self, unsigned int n )
51186197
{
51196198
if( !self ) return 0;
@@ -5389,11 +6468,11 @@
53896468
cson_string * colName = NULL;
53906469
int i = 0;
53916470
int rc = 0;
53926471
cson_value * currentValue = NULL;
53936472
int const colCount = sqlite3_column_count(st);
5394
- if( !colCount || (colCount>(int)cson_array_length_get(colNames)) ) {
6473
+ if( !colCount || (colCount>cson_array_length_get(colNames)) ) {
53956474
return NULL;
53966475
}
53976476
rootV = cson_value_new_object();
53986477
if(!rootV) return NULL;
53996478
root = cson_value_get_object(rootV);
54006479
--- extsrc/cson_amalgamation.c
+++ extsrc/cson_amalgamation.c
@@ -1435,11 +1435,10 @@
1435 #if defined(__cplusplus)
1436 extern "C" {
1437 #endif
1438
1439
1440
1441 /**
1442 This type holds the "vtbl" for type-specific operations when
1443 working with cson_value objects.
1444
1445 All cson_values of a given logical type share a pointer to a single
@@ -1686,12 +1685,12 @@
1686 : 0;
1687 }
1688
1689 char const * cson_rc_string(int rc)
1690 {
1691 if(0 == rc) return "OK";
1692 #define CHECK(N) else if(cson_rc.N == rc ) return #N
1693 CHECK(OK);
1694 CHECK(ArgError);
1695 CHECK(RangeError);
1696 CHECK(TypeError);
1697 CHECK(IOError);
@@ -1708,11 +1707,12 @@
1708 CHECK(Parse_INVALID_NUMBER);
1709 CHECK(Parse_NESTING_DEPTH_REACHED);
1710 CHECK(Parse_UNBALANCED_COLLECTION);
1711 CHECK(Parse_EXPECTED_KEY);
1712 CHECK(Parse_EXPECTED_COLON);
1713 else return "UnknownError";
 
1714 #undef CHECK
1715 }
1716
1717 /**
1718 If CSON_LOG_ALLOC is true then the cson_malloc/realloc/free() routines
@@ -1854,11 +1854,11 @@
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,14 +1865,14 @@
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;
@@ -2335,11 +2335,11 @@
2335 val->refcount = rc;
2336 }
2337 }
2338 }
2339
2340 static cson_value * cson_value_array_alloc()
2341 {
2342 cson_value * v = cson_value_new(CSON_TYPE_ARRAY,0);
2343 if( NULL != v )
2344 {
2345 cson_array * ar = CSON_ARRAY(v);
@@ -2347,11 +2347,11 @@
2347 *ar = cson_array_empty;
2348 }
2349 return v;
2350 }
2351
2352 static cson_value * cson_value_object_alloc()
2353 {
2354 cson_value * v = cson_value_new(CSON_TYPE_OBJECT,0);
2355 if( NULL != v )
2356 {
2357 cson_object * obj = CSON_OBJ(v);
@@ -2359,28 +2359,28 @@
2359 *obj = cson_object_empty;
2360 }
2361 return v;
2362 }
2363
2364 cson_value * cson_value_new_object()
2365 {
2366 return cson_value_object_alloc();
2367 }
2368
2369 cson_object * cson_new_object()
2370 {
2371
2372 return cson_value_get_object( cson_value_new_object() );
2373 }
2374
2375 cson_value * cson_value_new_array()
2376 {
2377 return cson_value_array_alloc();
2378 }
2379
2380
2381 cson_array * cson_new_array()
2382 {
2383 return cson_value_get_array( cson_value_new_array() );
2384 }
2385
2386 /**
@@ -2502,11 +2502,11 @@
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 );
@@ -2530,16 +2530,16 @@
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,
@@ -2553,11 +2553,11 @@
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 )
@@ -2588,11 +2588,11 @@
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 }
@@ -2605,11 +2605,11 @@
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)
@@ -2641,11 +2641,11 @@
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 }
@@ -2658,11 +2658,11 @@
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)
@@ -2687,11 +2687,11 @@
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 }
@@ -2704,12 +2704,12 @@
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 }
@@ -2727,12 +2727,12 @@
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 }
@@ -2744,12 +2744,12 @@
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 }
@@ -2760,11 +2760,11 @@
2760 cson_array * ar = NULL;
2761 cson_value_fetch_array( v, &ar );
2762 return ar;
2763 }
2764
2765 cson_kvp * cson_kvp_alloc()
2766 {
2767 cson_kvp * kvp = (cson_kvp*)cson_malloc(sizeof(cson_kvp),"cson_kvp");
2768 if( kvp )
2769 {
2770 *kvp = cson_kvp_empty;
@@ -2774,20 +2774,20 @@
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 }
@@ -2832,20 +2832,20 @@
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()
2838 {
2839 return &CSON_SPECIAL_VALUES[CSON_VAL_TRUE];
2840 }
2841 cson_value * cson_value_false()
2842 {
2843 return &CSON_SPECIAL_VALUES[CSON_VAL_FALSE];
2844 }
2845
2846 cson_value * cson_value_null()
2847 {
2848 return &CSON_SPECIAL_VALUES[CSON_VAL_NULL];
2849 }
2850
2851 cson_value * cson_new_int( cson_int_t v )
@@ -2917,12 +2917,12 @@
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 }
@@ -2935,11 +2935,11 @@
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 }
@@ -2952,11 +2952,11 @@
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,24 +2963,24 @@
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 {
@@ -3076,18 +3076,18 @@
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;
@@ -3109,21 +3109,21 @@
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!" */
@@ -3142,19 +3142,19 @@
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);
@@ -3174,19 +3174,19 @@
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;
@@ -3237,13 +3237,13 @@
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
@@ -3267,18 +3267,18 @@
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;
@@ -3296,11 +3296,11 @@
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
@@ -3337,11 +3337,11 @@
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)
@@ -3349,20 +3349,20 @@
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 {
@@ -3395,11 +3395,11 @@
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
@@ -3481,26 +3481,26 @@
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 }
@@ -3512,22 +3512,22 @@
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
@@ -3543,11 +3543,11 @@
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);
@@ -3574,11 +3574,11 @@
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;
@@ -3587,11 +3587,11 @@
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. */
@@ -3608,11 +3608,11 @@
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);
@@ -3630,11 +3630,11 @@
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;
@@ -3652,11 +3652,11 @@
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
@@ -3771,11 +3771,11 @@
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
@@ -3877,26 +3877,26 @@
3877 #if defined(CSON_FOSSIL_MODE)
3878 assume_latin1:
3879 #endif
3880 memset(ubuf,0,UBLen);
3881 if(ch <= 0xFFFF){
3882 rc = sprintf(ubuf, "\\u%04x",ch);
3883 if( rc != 6 )
3884 {
3885 rc = cson_rc.RangeError;
3886 break;
3887 }
3888 rc = f( state, ubuf, 6 );
3889 }else{ /* encode as a UTF16 surrogate pair */
3890 /* http://unicodebook.readthedocs.org/en/latest/unicode_encodings.html#surrogates */
3891 ch -= 0x10000;
3892 rc = sprintf(ubuf, "\\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;
@@ -3910,11 +3910,11 @@
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;
@@ -3936,64 +3936,62 @@
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 = sprintf( b, "%"CSON_INT_T_PFMT, cson_value_get_integer(src) )
3969 /* Reminder: snprintf() is C99 */
3970 ;
3971 return ( rc<=0 )
3972 ? cson_rc.RangeError
3973 : f( state, b, (unsigned int)rc )
3974 ;
3975 }
3976 }
3977
3978 static int cson_output_double( cson_value const * src, cson_data_dest_f f, void * state )
3979 {
3980 if( !f ) return cson_rc.ArgError;
3981 else if( !cson_value_is_double(src) ) return cson_rc.TypeError;
3982 else
3983 {
3984 enum { BufLen = 128 /* this must be relatively large or huge
3985 doubles can cause us to overrun here,
3986 resulting in stack-smashing errors.
3987 */};
3988 char b[BufLen];
3989 int rc;
3990 memset( b, 0, BufLen );
3991 rc = sprintf( b, "%"CSON_DOUBLE_T_PFMT, cson_value_get_double(src) )
3992 /* Reminder: snprintf() is C99 */
3993 ;
3994 if( rc<=0 ) return cson_rc.RangeError;
3995 else if(1)
3996 { /* Strip trailing zeroes before passing it on... */
3997 unsigned int urc = (unsigned int)rc;
3998 char * pos = b + urc - 1;
3999 for( ; ('0' == *pos) && urc && (*(pos-1) != '.'); --pos, --urc )
@@ -4012,12 +4010,12 @@
4012 }
4013 }
4014
4015 static int cson_output_string( cson_value const * src, char escapeFwdSlash, cson_data_dest_f f, void * state )
4016 {
4017 if( !f ) return cson_rc.ArgError;
4018 else if( ! cson_value_is_string(src) ) return cson_rc.TypeError;
4019 else
4020 {
4021 cson_string const * str = cson_value_get_string(src);
4022 assert( NULL != str );
4023 return cson_str_to_json(cson_string_cstr(str), str->length, escapeFwdSlash, f, state);
@@ -4075,11 +4073,11 @@
4075 Returns 0 on success.
4076 */
4077 static int cson_output_impl( cson_value const * src, cson_data_dest_f f, void * state,
4078 cson_output_opt const * fmt, unsigned int level )
4079 {
4080 if( ! src || !f || !src->api ) return cson_rc.ArgError;
4081 else
4082 {
4083 int rc = 0;
4084 assert(fmt);
4085 switch( src->api->typeID )
@@ -4105,11 +4103,11 @@
4105 break;
4106 case CSON_TYPE_OBJECT:
4107 rc = cson_output_object( src, f, state, fmt, level );
4108 break;
4109 default:
4110 rc = cson_rc.TypeError;
4111 break;
4112 }
4113 return rc;
4114 }
4115 }
@@ -4116,13 +4114,13 @@
4116
4117
4118 static int cson_output_array( cson_value const * src, cson_data_dest_f f, void * state,
4119 cson_output_opt const * fmt, unsigned int level )
4120 {
4121 if( !src || !f || !fmt ) return cson_rc.ArgError;
4122 else if( ! cson_value_is_array(src) ) return cson_rc.TypeError;
4123 else if( level > fmt->maxDepth ) return cson_rc.RangeError;
4124 else
4125 {
4126 int rc;
4127 unsigned int i;
4128 cson_value const * v;
@@ -4177,13 +4175,13 @@
4177 }
4178
4179 static int cson_output_object( cson_value const * src, cson_data_dest_f f, void * state,
4180 cson_output_opt const * fmt, unsigned int level )
4181 {
4182 if( !src || !f || !fmt ) return cson_rc.ArgError;
4183 else if( ! cson_value_is_object(src) ) return cson_rc.TypeError;
4184 else if( level > fmt->maxDepth ) return cson_rc.RangeError;
4185 else
4186 {
4187 int rc;
4188 unsigned int i;
4189 cson_kvp const * kvp;
@@ -4267,17 +4265,17 @@
4267 return rc;
4268 }
4269
4270 int cson_data_dest_FILE( void * state, void const * src, unsigned int n )
4271 {
4272 if( ! state ) return cson_rc.ArgError;
4273 else if( !src || !n ) return 0;
4274 else
4275 {
4276 return ( 1 == fwrite( src, n, 1, (FILE*) state ) )
4277 ? 0
4278 : cson_rc.IOError;
4279 }
4280 }
4281
4282 int cson_output_FILE( cson_value const * src, FILE * dest, cson_output_opt const * fmt )
4283 {
@@ -4300,15 +4298,15 @@
4300 return rc;
4301 }
4302
4303 int cson_output_filename( cson_value const * src, char const * dest, cson_output_opt const * fmt )
4304 {
4305 if( !src || !dest ) return cson_rc.ArgError;
4306 else
4307 {
4308 FILE * f = fopen(dest,"wb");
4309 if( !f ) return cson_rc.IOError;
4310 else
4311 {
4312 int const rc = cson_output_FILE( src, f, fmt );
4313 fclose(f);
4314 return rc;
@@ -4317,15 +4315,15 @@
4317 }
4318
4319 int cson_parse_filename( cson_value ** tgt, char const * src,
4320 cson_parse_opt const * opt, cson_parse_info * err )
4321 {
4322 if( !src || !tgt ) return cson_rc.ArgError;
4323 else
4324 {
4325 FILE * f = fopen(src, "r");
4326 if( !f ) return cson_rc.IOError;
4327 else
4328 {
4329 int const rc = cson_parse_FILE( tgt, f, opt, err );
4330 fclose(f);
4331 return rc;
@@ -4349,11 +4347,11 @@
4349 A cson_data_source_f() implementation which requires the state argument
4350 to be a properly populated (cson_data_source_StringSource_t*).
4351 */
4352 static int cson_data_source_StringSource( void * state, void * dest, unsigned int * n )
4353 {
4354 if( !state || !n || !dest ) return cson_rc.ArgError;
4355 else if( !*n ) return 0 /* ignore this */;
4356 else
4357 {
4358 unsigned int i;
4359 cson_data_source_StringSource_t * ss = (cson_data_source_StringSource_t*) state;
@@ -4368,12 +4366,12 @@
4368 }
4369
4370 int cson_parse_string( cson_value ** tgt, char const * src, unsigned int len,
4371 cson_parse_opt const * opt, cson_parse_info * err )
4372 {
4373 if( ! tgt || !src ) return cson_rc.ArgError;
4374 else if( !*src || (len<2/*2==len of {} and []*/) ) return cson_rc.RangeError;
4375 else
4376 {
4377 cson_data_source_StringSource_t ss;
4378 ss.str = ss.pos = src;
4379 ss.end = src + len;
@@ -4386,18 +4384,18 @@
4386 cson_buffer const * buf,
4387 cson_parse_opt const * opt,
4388 cson_parse_info * err )
4389 {
4390 return ( !tgt || !buf || !buf->mem || !buf->used )
4391 ? cson_rc.ArgError
4392 : cson_parse_string( tgt, (char const *)buf->mem,
4393 buf->used, opt, err );
4394 }
4395
4396 int cson_buffer_reserve( cson_buffer * buf, cson_size_t n )
4397 {
4398 if( ! buf ) return cson_rc.ArgError;
4399 else if( 0 == n )
4400 {
4401 cson_free(buf->mem, "cson_buffer::mem");
4402 *buf = cson_buffer_empty;
4403 return 0;
@@ -4407,11 +4405,11 @@
4407 return 0;
4408 }
4409 else
4410 {
4411 unsigned char * x = (unsigned char *)cson_realloc( buf->mem, n, "cson_buffer::mem" );
4412 if( ! x ) return cson_rc.AllocError;
4413 memset( x + buf->used, 0, n - buf->used );
4414 buf->mem = x;
4415 buf->capacity = n;
4416 ++buf->timesExpanded;
4417 return 0;
@@ -4434,11 +4432,11 @@
4434 arg MUST be a (cson_buffer*). This function appends n bytes at
4435 position arg->used, expanding the buffer as necessary.
4436 */
4437 static int cson_data_dest_cson_buffer( void * arg, void const * data_, unsigned int n )
4438 {
4439 if( !arg ) return cson_rc.ArgError;
4440 else if( ! n ) return 0;
4441 else
4442 {
4443 cson_buffer * sb = (cson_buffer*)arg;
4444 char const * data = (char const *)data_;
@@ -4446,12 +4444,12 @@
4446 unsigned int i;
4447 if( npos >= sb->capacity )
4448 {
4449 const cson_size_t oldCap = sb->capacity;
4450 const cson_size_t asz = npos * 2;
4451 if( asz < npos ) return cson_rc.ArgError; /* overflow */
4452 else if( 0 != cson_buffer_reserve( sb, asz ) ) return cson_rc.AllocError;
4453 assert( (sb->capacity > oldCap) && "Internal error in memory buffer management!" );
4454 /* make sure it gets NUL terminated. */
4455 memset( sb->mem + oldCap, 0, (sb->capacity - oldCap) );
4456 }
4457 for( i = 0; i < n; ++i, ++sb->used )
@@ -4533,19 +4531,19 @@
4533 return (pos > *inp) ? 1 : 0;
4534 }
4535
4536 int cson_object_fetch_sub2( cson_object const * obj, cson_value ** tgt, char const * path )
4537 {
4538 if( ! obj || !path ) return cson_rc.ArgError;
4539 else if( !*path || !*(1+path) ) return cson_rc.RangeError;
4540 else return cson_object_fetch_sub(obj, tgt, path+1, *path);
4541 }
4542
4543 int cson_object_fetch_sub( cson_object const * obj, cson_value ** tgt, char const * path, char sep )
4544 {
4545 if( ! obj || !path ) return cson_rc.ArgError;
4546 else if( !*path || !sep ) return cson_rc.RangeError;
4547 else
4548 {
4549 char const * beg = path;
4550 char const * end = NULL;
4551 int rc;
@@ -4565,26 +4563,26 @@
4565 ++tokenCount;
4566 beg = end;
4567 end = NULL;
4568 }
4569 }
4570 if( 0 == tokenCount ) return cson_rc.RangeError;
4571 beg = path;
4572 end = NULL;
4573 for( i = 0; i < tokenCount; ++i, beg=end, end=NULL )
4574 {
4575 rc = cson_next_token( &beg, sep, &end );
4576 assert( 1 == rc );
4577 assert( beg != end );
4578 assert( end > beg );
4579 len = end - beg;
4580 if( len > (BufSize-1) ) return cson_rc.RangeError;
4581 memset( buf, 0, len + 1 );
4582 memcpy( buf, beg, len );
4583 buf[len] = 0;
4584 cv = cson_object_get( curObj, buf );
4585 if( NULL == cv ) return cson_rc.NotFoundError;
4586 else if( i == (tokenCount-1) )
4587 {
4588 if(tgt) *tgt = cv;
4589 return 0;
4590 }
@@ -4594,15 +4592,15 @@
4594 assert((NULL != curObj) && "Detected mis-management of internal memory!");
4595 }
4596 /* TODO: arrays. Requires numeric parsing for the index. */
4597 else
4598 {
4599 return cson_rc.NotFoundError;
4600 }
4601 }
4602 assert( i == tokenCount );
4603 return cson_rc.NotFoundError;
4604 }
4605 }
4606
4607 cson_value * cson_object_get_sub( cson_object const * obj, char const * path, char sep )
4608 {
@@ -4838,24 +4836,26 @@
4838 }
4839 case CSON_TYPE_STRING: {
4840 cson_string const * jstr = cson_value_get_string(orig);
4841 unsigned const int slen = cson_string_length_bytes( jstr );
4842 assert( NULL != jstr );
4843 v = cson_strdup( cson_string_cstr( jstr ), slen );
4844 break;
4845 }
4846 case CSON_TYPE_INTEGER: {
4847 char buf[BufSize] = {0};
4848 if( 0 < sprintf( v, "%"CSON_INT_T_PFMT, cson_value_get_integer(orig)) )
 
4849 {
4850 v = cson_strdup( buf, strlen(buf) );
4851 }
4852 break;
4853 }
4854 case CSON_TYPE_DOUBLE: {
4855 char buf[BufSize] = {0};
4856 if( 0 < sprintf( v, "%"CSON_DOUBLE_T_PFMT, cson_value_get_double(orig)) )
 
4857 {
4858 v = cson_strdup( buf, strlen(buf) );
4859 }
4860 break;
4861 }
@@ -4891,24 +4891,26 @@
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 < sprintf( v, "%"CSON_INT_T_PFMT, cson_value_get_integer(orig)) )
 
4902 {
4903 v = cson_strdup( buf, strlen(buf) );
4904 }
4905 break;
4906 }
4907 case CSON_TYPE_DOUBLE: {
4908 char buf[BufSize] = {0};
4909 if( 0 < sprintf( v, "%"CSON_DOUBLE_T_PFMT, cson_value_get_double(orig)) )
 
4910 {
4911 v = cson_strdup( buf, strlen(buf) );
4912 }
4913 break;
4914 }
@@ -4988,11 +4990,11 @@
4988 cson_object_iterator iter = cson_object_iterator_empty;
4989 int rc;
4990 char const replace = (flags & CSON_MERGE_REPLACE);
4991 char const recurse = !(flags & CSON_MERGE_NO_RECURSE);
4992 cson_kvp const * kvp;
4993 if((!dest || !src) || (dest==src)) return cson_rc.ArgError;
4994 rc = cson_object_iter_init( src, &iter );
4995 if(rc) return rc;
4996 while( (kvp = cson_object_iter_next(&iter) ) )
4997 {
4998 cson_string * key = cson_kvp_key(kvp);
@@ -5052,11 +5054,11 @@
5052 int cson_parse_argv_flags( int argc, char const * const * argv,
5053 cson_object ** tgt, unsigned int * count ){
5054 cson_object * o = NULL;
5055 int rc = 0;
5056 int i = 0;
5057 if(argc<1 || !argc || !tgt) return cson_rc.ArgError;
5058 o = *tgt ? *tgt : cson_new_object();
5059 if(count) *count = 0;
5060 for( i = 0; i < argc; ++i ){
5061 char const * arg = argv[i];
5062 char const * key = arg;
@@ -5068,11 +5070,11 @@
5068 if(!*key) continue;
5069 pos = key;
5070 while( *pos && ('=' != *pos)) ++pos;
5071 k = cson_new_string(key, pos-key);
5072 if(!k){
5073 rc = cson_rc.AllocError;
5074 break;
5075 }
5076 if(!*pos){ /** --key */
5077 v = cson_value_true();
5078 }else{ /** --key=...*/
@@ -5110,10 +5112,1087 @@
5110 #undef CSON_VCAST
5111 #undef CSON_MALLOC_IMPL
5112 #undef CSON_FREE_IMPL
5113 #undef CSON_REALLOC_IMPL
5114 /* end file ./cson.c */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5115 /* begin file ./cson_lists.h */
5116 /* Auto-generated from cson_list.h. Edit at your own risk! */
5117 unsigned int cson_value_list_reserve( cson_value_list * self, unsigned int n )
5118 {
5119 if( !self ) return 0;
@@ -5389,11 +6468,11 @@
5389 cson_string * colName = NULL;
5390 int i = 0;
5391 int rc = 0;
5392 cson_value * currentValue = NULL;
5393 int const colCount = sqlite3_column_count(st);
5394 if( !colCount || (colCount>(int)cson_array_length_get(colNames)) ) {
5395 return NULL;
5396 }
5397 rootV = cson_value_new_object();
5398 if(!rootV) return NULL;
5399 root = cson_value_get_object(rootV);
5400
--- extsrc/cson_amalgamation.c
+++ extsrc/cson_amalgamation.c
@@ -1435,11 +1435,10 @@
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
@@ -1686,12 +1685,12 @@
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);
@@ -1708,11 +1707,12 @@
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
@@ -1854,11 +1854,11 @@
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,14 +1865,14 @@
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;
@@ -2335,11 +2335,11 @@
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);
@@ -2347,11 +2347,11 @@
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);
@@ -2359,28 +2359,28 @@
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 /**
@@ -2502,11 +2502,11 @@
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 );
@@ -2530,16 +2530,16 @@
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,
@@ -2553,11 +2553,11 @@
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 )
@@ -2588,11 +2588,11 @@
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 }
@@ -2605,11 +2605,11 @@
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)
@@ -2641,11 +2641,11 @@
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 }
@@ -2658,11 +2658,11 @@
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)
@@ -2687,11 +2687,11 @@
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 }
@@ -2704,12 +2704,12 @@
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 }
@@ -2727,12 +2727,12 @@
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 }
@@ -2744,12 +2744,12 @@
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 }
@@ -2760,11 +2760,11 @@
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;
@@ -2774,20 +2774,20 @@
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 }
@@ -2832,20 +2832,20 @@
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 )
@@ -2917,12 +2917,12 @@
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 }
@@ -2935,11 +2935,11 @@
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 }
@@ -2952,11 +2952,11 @@
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,24 +2963,24 @@
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 {
@@ -3076,18 +3076,18 @@
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;
@@ -3109,21 +3109,21 @@
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!" */
@@ -3142,19 +3142,19 @@
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);
@@ -3174,19 +3174,19 @@
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;
@@ -3237,13 +3237,13 @@
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
@@ -3267,18 +3267,18 @@
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;
@@ -3296,11 +3296,11 @@
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
@@ -3337,11 +3337,11 @@
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)
@@ -3349,20 +3349,20 @@
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 {
@@ -3395,11 +3395,11 @@
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
@@ -3481,26 +3481,26 @@
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 }
@@ -3512,22 +3512,22 @@
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
@@ -3543,11 +3543,11 @@
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);
@@ -3574,11 +3574,11 @@
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;
@@ -3587,11 +3587,11 @@
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. */
@@ -3608,11 +3608,11 @@
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);
@@ -3630,11 +3630,11 @@
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;
@@ -3652,11 +3652,11 @@
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
@@ -3771,11 +3771,11 @@
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
@@ -3877,26 +3877,26 @@
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;
@@ -3910,11 +3910,11 @@
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;
@@ -3936,64 +3936,62 @@
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 )
@@ -4012,12 +4010,12 @@
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);
@@ -4075,11 +4073,11 @@
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 )
@@ -4105,11 +4103,11 @@
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 }
@@ -4116,13 +4114,13 @@
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;
@@ -4177,13 +4175,13 @@
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;
@@ -4267,17 +4265,17 @@
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 {
@@ -4300,15 +4298,15 @@
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;
@@ -4317,15 +4315,15 @@
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;
@@ -4349,11 +4347,11 @@
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;
@@ -4368,12 +4366,12 @@
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;
@@ -4386,18 +4384,18 @@
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;
@@ -4407,11 +4405,11 @@
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;
@@ -4434,11 +4432,11 @@
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_;
@@ -4446,12 +4444,12 @@
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 )
@@ -4533,19 +4531,19 @@
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;
@@ -4565,26 +4563,26 @@
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 }
@@ -4594,15 +4592,15 @@
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 {
@@ -4838,24 +4836,26 @@
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 }
@@ -4891,24 +4891,26 @@
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 }
@@ -4988,11 +4990,11 @@
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);
@@ -5052,11 +5054,11 @@
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;
@@ -5068,11 +5070,11 @@
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=...*/
@@ -5110,10 +5112,1087 @@
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_pack.c */
5118 /* LICENSE
5119
5120 Copyright (c) 2018 Guido Berhoerster <[email protected]>
5121
5122 Permission is hereby granted, free of charge, to any person
5123 obtaining a copy of this software and associated documentation
5124 files (the "Software"), to deal in the Software without
5125 restriction, including without limitation the rights to use,
5126 copy, modify, merge, publish, distribute, sublicense, and/or sell
5127 copies of the Software, and to permit persons to whom the
5128 Software is furnished to do so, subject to the following
5129 conditions:
5130
5131 The above copyright notice and this permission notice shall be
5132 included in all copies or substantial portions of the Software.
5133
5134 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
5135 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
5136 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
5137 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
5138 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
5139 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
5140 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
5141 OTHER DEALINGS IN THE SOFTWARE.
5142
5143 */
5144
5145 #include <assert.h>
5146 #include <stdlib.h>
5147 #include <string.h>
5148
5149
5150 #if __STDC_VERSION__ >= 199901L
5151 #define INLINE inline
5152 #else
5153 #define INLINE
5154 #endif /* __STDC_VERSION__ >= 199901L */
5155
5156 #define PACK_IGNORED_CHARS " \t\r\n:,"
5157
5158 enum parser_state {
5159 STATE_INVALID,
5160 STATE_INITIAL,
5161 STATE_END,
5162 STATE_ARRAY_VALUE,
5163 STATE_PROPERTY_NAME,
5164 STATE_PROPERTY_VALUE
5165 };
5166
5167 struct token
5168 {
5169 int type; /* type specifier */
5170 int optional; /* optional property modifier */
5171 int suppress; /* suppress assignment modifier */
5172 int alloc; /* assignment allocation modifier */
5173 int len_l; /* long length modifier */
5174 };
5175
5176 struct state
5177 {
5178 cson_value * parent_value;
5179 const char * property_name;
5180 enum parser_state parser_state;
5181 int property_optional;
5182 unsigned int index;
5183 };
5184
5185 struct state_stack
5186 {
5187 size_t capacity;
5188 size_t top;
5189 struct state *state;
5190 };
5191
5192 union pack_value
5193 {
5194 cson_array * array;
5195 cson_object * object;
5196 const char * string;
5197 cson_int_t i;
5198 double d;
5199 char b;
5200 };
5201
5202 union unpack_value
5203 {
5204 cson_array ** arrayp;
5205 cson_object ** objectp;
5206 const char ** stringp;
5207 char ** astringp;
5208 cson_int_t * ip;
5209 double * dp;
5210 char * bp;
5211 };
5212
5213 static const char * next_token( const char * s, struct token * tok )
5214 {
5215 tok->type = -1;
5216 tok->optional = 0;
5217 tok->suppress = 0;
5218 tok->alloc = 0;
5219 tok->len_l = 0;
5220
5221 /* skip ignored characters */
5222 while( ( *s != '\0' ) && ( strchr( PACK_IGNORED_CHARS, *s ) != NULL ) )
5223 {
5224 s++;
5225 }
5226
5227 switch( *s )
5228 {
5229 case '%':
5230 for( s++; *s != '\0'; s++ )
5231 {
5232 switch( *s )
5233 {
5234 case '?':
5235 tok->optional++;
5236 break;
5237 case '*':
5238 tok->suppress++;
5239 break;
5240 case 'm':
5241 tok->alloc++;
5242 break;
5243 case 'l':
5244 tok->len_l++;
5245 break;
5246 case 'D':
5247 /* short form of "lld" */
5248 tok->len_l += 2;
5249 tok->type = 'd';
5250 s++;
5251 goto out;
5252 case 'i':
5253 /* same as 'd' */
5254 tok->type = 'd';
5255 s++;
5256 goto out;
5257 case 's': /* FALLTHROUGH */
5258 case 'd': /* FALLTHROUGH */
5259 case 'f': /* FALLTHROUGH */
5260 case 'b': /* FALLTHROUGH */
5261 case 'N': /* FALLTHROUGH */
5262 case '[': /* FALLTHROUGH */
5263 case '{':
5264 tok->type = *s++;
5265 goto out;
5266 default:
5267 return ( NULL );
5268 }
5269 }
5270 return ( NULL );
5271 case '[': /* FALLTHROUGH */
5272 case '{':
5273 /* short form of "*[" or "*{" */
5274 tok->type = *s++;
5275 tok->suppress = 1;
5276 break;
5277 case ']': /* FALLTHROUGH */
5278 case '}':
5279 tok->type = *s++;
5280 break;
5281 case '\0':
5282 tok->type = *s;
5283 break;
5284 default:
5285 return ( NULL );
5286 }
5287
5288 out:
5289 if( ( tok->optional > 1 ) || ( tok->suppress > 1 ) || ( tok->alloc > 1 ) ||
5290 ( tok->len_l > 2 ) || ( ( tok->type != 'd' ) && ( tok->len_l > 0 ) ) )
5291 {
5292 return ( NULL );
5293 }
5294
5295 return ( s );
5296 }
5297
5298 static struct state_stack * state_stack_create( size_t capacity )
5299 {
5300 struct state_stack * stack;
5301
5302 assert( capacity >= 2 );
5303
5304 stack = malloc( sizeof( struct state_stack ) );
5305 if( stack == NULL )
5306 {
5307 return ( NULL );
5308 }
5309 stack->state = malloc( capacity * sizeof( struct state ) );
5310 if( stack->state == NULL )
5311 {
5312 return ( NULL );
5313 }
5314 stack->top = 0;
5315 stack->capacity = capacity;
5316 /* initialize bottom of the stack */
5317 stack->state[0].parser_state = STATE_INVALID;
5318 stack->state[0].parent_value = NULL;
5319 stack->state[0].property_name = NULL;
5320 stack->state[0].property_optional = 0;
5321 stack->state[0].index = 0;
5322
5323 return ( stack );
5324 }
5325
5326 static INLINE struct state * state_stack_top( struct state_stack * stack )
5327 {
5328 assert( stack->top >= 1 );
5329
5330 return ( &stack->state[stack->top] );
5331 }
5332
5333 static INLINE void state_stack_push( struct state_stack * stack,
5334 enum parser_state parser_state,
5335 cson_value * parent_value,
5336 const char * property_name,
5337 int property_optional,
5338 unsigned int index )
5339 {
5340 struct state * state = &stack->state[++stack->top];
5341
5342 state->parser_state = parser_state;
5343 state->parent_value = parent_value;
5344 state->property_name = property_name;
5345 state->property_optional = property_optional;
5346 state->index = index;
5347 }
5348
5349 static INLINE void state_stack_pop( struct state_stack * stack )
5350 {
5351 assert( stack->top >= 1 );
5352
5353 stack->top--;
5354 }
5355
5356 static int
5357 on_pack_initial( struct state_stack * stack,
5358 struct token * tok,
5359 union pack_value * pack_value,
5360 cson_value ** root_valuep )
5361 {
5362 cson_value * value;
5363 cson_value * root_value;
5364
5365 if( tok->optional || tok->alloc )
5366 {
5367 /* invalid modifier */
5368 return ( CSON_PACK_ARG_ERROR );
5369 }
5370
5371 if( tok->type == '[' )
5372 {
5373 if( tok->suppress )
5374 {
5375 root_value = cson_value_new_array( );
5376 if( root_value == NULL )
5377 {
5378 return ( CSON_PACK_ALLOC_ERROR );
5379 }
5380 }
5381 else
5382 {
5383 value = cson_array_value( pack_value->array );
5384 root_value = cson_value_clone( value );
5385 }
5386
5387 state_stack_pop( stack );
5388 state_stack_push( stack, STATE_END, NULL, NULL, 0, 0 );
5389 state_stack_push( stack, STATE_ARRAY_VALUE, root_value, NULL, 0, 0 );
5390 }
5391 else if( tok->type == '{' )
5392 {
5393 if( tok->suppress )
5394 {
5395 root_value = cson_value_new_object( );
5396 if( root_value == NULL )
5397 {
5398 return ( CSON_PACK_ALLOC_ERROR );
5399 }
5400 }
5401 else
5402 {
5403 value = cson_object_value( pack_value->object );
5404 root_value = cson_value_clone( value );
5405 }
5406
5407 state_stack_pop( stack );
5408 state_stack_push( stack, STATE_END, NULL, NULL, 0, 0 );
5409 state_stack_push( stack, STATE_PROPERTY_NAME, root_value, NULL, 0, 0 );
5410 }
5411 else
5412 {
5413 /* root value is neither an object nor an array */
5414 return ( CSON_PACK_ARG_ERROR );
5415 }
5416
5417 *root_valuep = root_value;
5418
5419 return ( 0 );
5420 }
5421
5422 static int on_pack_property_name( struct state_stack * stack, struct token * tok, const char * property_name )
5423 {
5424 cson_value * parent_value;
5425
5426 if( tok->optional || tok->suppress || tok->alloc )
5427 {
5428 /* invalid modifier */
5429 return ( CSON_PACK_ARG_ERROR );
5430 }
5431
5432 if( tok->type == 's' )
5433 {
5434 parent_value = state_stack_top( stack )->parent_value;
5435 state_stack_pop( stack );
5436 state_stack_push( stack, STATE_PROPERTY_VALUE, parent_value, property_name, 0, 0 );
5437 }
5438 else if( tok->type == '}' )
5439 {
5440 state_stack_pop( stack );
5441 }
5442 else
5443 {
5444 /* neither property specifier nor end of object */
5445 return ( CSON_PACK_ARG_ERROR );
5446 }
5447
5448 return ( 0 );
5449 }
5450
5451 static int
5452 handle_pack_value( struct state_stack * stack,
5453 struct token * tok,
5454 union pack_value * pack_value,
5455 enum parser_state new_parser_state )
5456 {
5457 cson_value * value;
5458 cson_object * object;
5459 cson_array * array;
5460 int cson_retval;
5461 struct state * state;
5462 cson_value * parent_value;
5463
5464 /* create value */
5465 switch( tok->type )
5466 {
5467 case '[':
5468 value = tok->suppress ? cson_value_new_array( ) :
5469 cson_value_clone( cson_array_value( pack_value->array ) );
5470 if( value == NULL )
5471 {
5472 return ( CSON_PACK_ALLOC_ERROR );
5473 }
5474 break;
5475 case '{':
5476 value = tok->suppress ? cson_value_new_object( ) :
5477 cson_value_clone( cson_object_value( pack_value->object ) );
5478 if( value == NULL )
5479 {
5480 return ( CSON_PACK_ALLOC_ERROR );
5481 }
5482 break;
5483 case 's':
5484 value = cson_value_new_string( pack_value->string, strlen( pack_value->string ) );
5485 if( value == NULL )
5486 {
5487 return ( CSON_PACK_ALLOC_ERROR );
5488 }
5489 break;
5490 case 'd':
5491 value = cson_value_new_integer( pack_value->i );
5492 if( value == NULL )
5493 {
5494 return ( CSON_PACK_ALLOC_ERROR );
5495 }
5496 break;
5497 case 'f':
5498 value = cson_value_new_double( pack_value->d );
5499 if( value == NULL )
5500 {
5501 return ( CSON_PACK_ALLOC_ERROR );
5502 }
5503 break;
5504 case 'b':
5505 value = cson_value_new_bool( pack_value->b );
5506 if( value == NULL )
5507 {
5508 return ( CSON_PACK_ALLOC_ERROR );
5509 }
5510 break;
5511 case 'N':
5512 value = cson_value_null( );
5513 break;
5514 default:
5515 /* invalid token type */
5516 return ( CSON_PACK_ARG_ERROR );
5517 }
5518
5519 state = state_stack_top( stack );
5520 parent_value = state->parent_value;
5521 if( cson_value_is_object( parent_value ) )
5522 {
5523 /* set object property to value */
5524 object = cson_value_get_object( parent_value );
5525 cson_retval = cson_object_set( object, state->property_name, value );
5526 if( cson_retval != 0 )
5527 {
5528 cson_value_free( value );
5529 return ( CSON_PACK_ALLOC_ERROR );
5530 }
5531 }
5532 else if( cson_value_is_array( parent_value ) )
5533 {
5534 /* append array value */
5535 array = cson_value_get_array( parent_value );
5536 cson_retval = cson_array_append( array, value );
5537 if( cson_retval != 0 )
5538 {
5539 cson_value_free( value );
5540 return ( CSON_PACK_ALLOC_ERROR );
5541 }
5542 }
5543
5544 if( tok->type == '[' )
5545 {
5546 state_stack_pop( stack );
5547 state_stack_push( stack, new_parser_state, parent_value, NULL, 0, 0 );
5548 state_stack_push( stack, STATE_ARRAY_VALUE, value, NULL, 0, 0 );
5549 }
5550 else if( tok->type == '{' )
5551 {
5552 state_stack_pop( stack );
5553 state_stack_push( stack, new_parser_state, parent_value, NULL, 0, 0 );
5554 state_stack_push( stack, STATE_PROPERTY_NAME, value, NULL, 0, 0 );
5555 }
5556 else
5557 {
5558 state_stack_pop( stack );
5559 state_stack_push( stack, new_parser_state, parent_value, NULL, 0, 0 );
5560 }
5561
5562 return ( 0 );
5563 }
5564
5565 static int on_pack_array_value( struct state_stack * stack, struct token * tok, union pack_value * pack_value )
5566 {
5567 if( tok->optional || tok->alloc || ( tok->suppress && ( tok->type != '{' ) && ( tok->type != '[' ) ) )
5568 {
5569 /* invalid modifier */
5570 return ( CSON_PACK_ARG_ERROR );
5571 }
5572
5573 if( tok->type == ']' )
5574 {
5575 /* end of array specifier */
5576 state_stack_pop( stack );
5577
5578 return ( 0 );
5579 }
5580
5581 return ( handle_pack_value( stack, tok, pack_value, STATE_ARRAY_VALUE ) );
5582 }
5583
5584 static int on_pack_property_value( struct state_stack * stack, struct token * tok, union pack_value * pack_value )
5585 {
5586 if( tok->optional || tok->alloc || ( tok->suppress && ( tok->type != '{' ) && ( tok->type != '[' ) ) )
5587 {
5588 /* invalid modifier */
5589 return ( CSON_PACK_ARG_ERROR );
5590 }
5591
5592 return ( handle_pack_value( stack, tok, pack_value, STATE_PROPERTY_NAME ) );
5593 }
5594
5595 int cson_vpack( cson_value ** root_valuep, const char * fmt, va_list args )
5596 {
5597 int retval = CSON_PACK_INTERNAL_ERROR;
5598 cson_value * root_value = NULL;
5599 struct state_stack * stack = NULL;
5600 const char * p = fmt;
5601 struct token tok = { 0 };
5602 struct state * state;
5603 union pack_value pack_value = { 0 };
5604 const char * property_name;
5605
5606 stack = state_stack_create( strlen( fmt ) + 2 );
5607 if( stack == NULL )
5608 {
5609 retval = CSON_PACK_ALLOC_ERROR;
5610 goto out;
5611 }
5612 state_stack_push( stack, STATE_INITIAL, NULL, NULL, 0, 0 );
5613
5614 for( p = next_token( p, &tok ); p != NULL; p = next_token( p, &tok ) )
5615 {
5616 state = state_stack_top( stack );
5617 if( state->parser_state == STATE_PROPERTY_NAME )
5618 {
5619 property_name = ( tok.type == 's' ) ? va_arg( args, const char * ) : NULL;
5620 }
5621 else if( !tok.suppress )
5622 {
5623 switch( tok.type )
5624 {
5625 case '[':
5626 pack_value.array = va_arg( args, cson_array * );
5627 break;
5628 case '{':
5629 pack_value.object = va_arg( args, cson_object * );
5630 break;
5631 case 's':
5632 pack_value.string = va_arg( args, const char * );
5633 break;
5634 case 'd':
5635 if( tok.len_l == 0 )
5636 {
5637 pack_value.i = va_arg( args, int );
5638 }
5639 else if( tok.len_l == 1 )
5640 {
5641 pack_value.i = va_arg( args, long );
5642 }
5643 else
5644 {
5645 pack_value.i = va_arg( args, cson_int_t );
5646 }
5647 break;
5648 case 'f':
5649 pack_value.d = va_arg( args, double );
5650 break;
5651 case 'b':
5652 pack_value.b = va_arg( args, int );
5653 break;
5654 }
5655 }
5656
5657 switch( state->parser_state )
5658 {
5659 case STATE_INITIAL:
5660 retval = on_pack_initial( stack, &tok, &pack_value, &root_value );
5661 if( retval != 0 )
5662 {
5663 goto out;
5664 }
5665 break;
5666 case STATE_END:
5667 /* check for trailing characters */
5668 retval = ( tok.type == '\0' ) ? 0 : CSON_PACK_ARG_ERROR;
5669 goto out;
5670 case STATE_PROPERTY_NAME:
5671 retval = on_pack_property_name( stack, &tok, property_name );
5672 if( retval != 0 )
5673 {
5674 goto out;
5675 }
5676 break;
5677 case STATE_PROPERTY_VALUE:
5678 retval = on_pack_property_value( stack, &tok, &pack_value );
5679 if( retval != 0 )
5680 {
5681 goto out;
5682 }
5683 break;
5684 case STATE_ARRAY_VALUE:
5685 retval = on_pack_array_value( stack, &tok, &pack_value );
5686 if( retval != 0 )
5687 {
5688 goto out;
5689 }
5690 break;
5691 default:
5692 retval = CSON_PACK_INTERNAL_ERROR;
5693 goto out;
5694 }
5695 }
5696 if( p == NULL )
5697 {
5698 /* parse error */
5699 retval = CSON_PACK_ARG_ERROR;
5700 }
5701
5702 out:
5703 if( retval == 0 )
5704 {
5705 *root_valuep = root_value;
5706 }
5707 else
5708 {
5709 cson_value_free( root_value );
5710 }
5711 if( stack != NULL ) {
5712 free( stack->state );
5713 free( stack );
5714 }
5715
5716 return ( retval );
5717 }
5718
5719 int cson_pack( cson_value ** root_valuep, const char * fmt, ... )
5720 {
5721 int retval;
5722 va_list args;
5723
5724 va_start( args, fmt );
5725 retval = cson_vpack( root_valuep, fmt, args );
5726 va_end( args );
5727
5728 return ( retval );
5729 }
5730
5731 static int on_unpack_initial( struct state_stack * stack, struct token * tok, union unpack_value * unpack_value )
5732 {
5733 int subst = 0;
5734 cson_value * root_value;
5735
5736 if( tok->optional || tok->alloc )
5737 {
5738 /* invalid modifier */
5739 return ( CSON_PACK_ARG_ERROR );
5740 }
5741
5742 root_value = state_stack_top( stack )->parent_value;
5743 if( tok->type == '[' )
5744 {
5745 if( !cson_value_is_array( root_value ) )
5746 {
5747 return ( CSON_PACK_VALIDATION_ERROR );
5748 }
5749
5750 if( !tok->suppress )
5751 {
5752 *unpack_value->arrayp = cson_value_get_array( root_value );
5753 subst = 1;
5754 }
5755
5756 state_stack_pop( stack );
5757 state_stack_push( stack, STATE_END, NULL, NULL, 0, 0 );
5758 state_stack_push( stack, STATE_ARRAY_VALUE, root_value, NULL, 0, 0 );
5759 }
5760 else if( tok->type == '{' )
5761 {
5762 if( !cson_value_is_object( root_value ) )
5763 {
5764 return ( CSON_PACK_VALIDATION_ERROR );
5765 }
5766
5767 if( !tok->suppress )
5768 {
5769 *unpack_value->objectp = cson_value_get_object( root_value );
5770 subst = 1;
5771 }
5772
5773 state_stack_pop( stack );
5774 state_stack_push( stack, STATE_END, NULL, NULL, 0, 0 );
5775 state_stack_push( stack, STATE_PROPERTY_NAME, root_value, NULL, 0, 0 );
5776 }
5777 else
5778 {
5779 return ( CSON_PACK_ARG_ERROR );
5780 }
5781
5782 return ( subst );
5783 }
5784
5785 static int on_unpack_property_name( struct state_stack * stack, struct token * tok, const char * property_name )
5786 {
5787 cson_value * parent_value;
5788
5789 if( tok->type == '}' )
5790 {
5791 state_stack_pop( stack );
5792 }
5793 else if( tok->type == 's' )
5794 {
5795 if( tok->suppress || tok->alloc )
5796 {
5797 /* invalid modifier */
5798 return ( CSON_PACK_ARG_ERROR );
5799 }
5800
5801 parent_value = state_stack_top( stack )->parent_value;
5802 state_stack_pop( stack );
5803 state_stack_push( stack, STATE_PROPERTY_VALUE, parent_value, property_name, tok->optional, 0 );
5804 }
5805 else
5806 {
5807 /* neither property specifier nor end of object */
5808 return ( CSON_PACK_ARG_ERROR );
5809 }
5810
5811 return ( 0 );
5812 }
5813
5814 static int handle_unpack_value( struct state_stack * stack,
5815 struct token * tok,
5816 cson_value * value,
5817 union unpack_value * unpack_value,
5818 enum parser_state new_parser_state )
5819 {
5820 int subst = 0;
5821 struct state * state;
5822 cson_value * parent_value;
5823 unsigned int index;
5824 int skip;
5825 const char * string;
5826 char * astring;
5827 size_t len;
5828
5829 state = state_stack_top( stack );
5830 parent_value = state->parent_value;
5831 index = state->index;
5832 skip = ( parent_value == NULL ) || ( value == NULL );
5833
5834 switch( tok->type )
5835 {
5836 case 's':
5837 if( !skip )
5838 {
5839 if( !cson_value_is_string( value ) )
5840 {
5841 /* property value is not a string */
5842 return ( CSON_PACK_VALIDATION_ERROR );
5843 }
5844
5845 if( !tok->suppress )
5846 {
5847 string = cson_value_get_cstr( value );
5848 if( tok->alloc )
5849 {
5850 len = strlen ( string );
5851 astring = malloc( len + 1 );
5852 if( astring == NULL )
5853 {
5854 return ( CSON_PACK_ALLOC_ERROR );
5855 }
5856 memcpy( astring, string, len + 1 );
5857 *unpack_value->astringp = astring;
5858 }
5859 else
5860 {
5861 *unpack_value->stringp = string;
5862 }
5863 subst = 1;
5864 }
5865 }
5866
5867 state_stack_pop( stack );
5868 state_stack_push( stack, new_parser_state, parent_value, NULL, 0, index );
5869 break;
5870 case 'd':
5871 if( !skip )
5872 {
5873 if( !cson_value_is_integer( value ) )
5874 {
5875 /* property value is not an integer */
5876 return ( CSON_PACK_VALIDATION_ERROR );
5877 }
5878
5879 if( !tok->suppress )
5880 {
5881 *unpack_value->ip = cson_value_get_integer( value );
5882 subst = 1;
5883 }
5884 }
5885
5886 state_stack_pop( stack );
5887 state_stack_push( stack, new_parser_state, parent_value, NULL, 0, index );
5888 break;
5889 case 'f':
5890 if( !skip )
5891 {
5892 if( !cson_value_is_double( value ) )
5893 {
5894 /* property value is not a float */
5895 return ( CSON_PACK_VALIDATION_ERROR );
5896 }
5897
5898 if( !tok->suppress )
5899 {
5900 *unpack_value->dp = cson_value_get_double( value );
5901 subst = 1;
5902 }
5903 }
5904
5905 state_stack_pop( stack );
5906 state_stack_push( stack, new_parser_state, parent_value, NULL, 0, index );
5907 break;
5908 case 'b':
5909 if( !skip )
5910 {
5911 if( !cson_value_is_bool( value ) )
5912 {
5913 /* property value is not a boolean */
5914 return ( CSON_PACK_VALIDATION_ERROR );
5915 }
5916
5917 if( !tok->suppress )
5918 {
5919 *unpack_value->bp = cson_value_get_bool( value );
5920 subst = 1;
5921 }
5922 }
5923
5924 state_stack_pop( stack );
5925 state_stack_push( stack, new_parser_state, parent_value, NULL, 0, index );
5926 break;
5927 case 'N':
5928 if( !skip )
5929 {
5930 if( !cson_value_is_null( value ) )
5931 {
5932 /* property value is not an array */
5933 return ( CSON_PACK_VALIDATION_ERROR );
5934 }
5935 }
5936
5937 state_stack_pop( stack );
5938 state_stack_push( stack, new_parser_state, parent_value, NULL, 0, index );
5939 break;
5940 case '[':
5941 if( !skip )
5942 {
5943 if( !cson_value_is_array( value ) )
5944 {
5945 /* property value is not an array */
5946 return ( CSON_PACK_VALIDATION_ERROR );
5947 }
5948
5949 if( !tok->suppress )
5950 {
5951 *unpack_value->arrayp = cson_value_get_array( value );
5952 subst = 1;
5953 }
5954 }
5955
5956 state_stack_pop( stack );
5957 state_stack_push( stack, new_parser_state, parent_value, NULL, 0, index );
5958 state_stack_push( stack, STATE_ARRAY_VALUE, value, NULL, 0, 0 );
5959 break;
5960 case '{':
5961 if( !skip )
5962 {
5963 if( !cson_value_is_object( value ) )
5964 {
5965 /* property value is not an object */
5966 return ( CSON_PACK_VALIDATION_ERROR );
5967 }
5968
5969 if( !tok->suppress )
5970 {
5971 *unpack_value->objectp = cson_value_get_object( value );
5972 subst = 1;
5973 }
5974 }
5975
5976 state_stack_pop( stack );
5977 state_stack_push( stack, new_parser_state, parent_value, NULL, 0, index );
5978 state_stack_push( stack, STATE_PROPERTY_NAME, value, NULL, 0, 0 );
5979 break;
5980 default:
5981 return ( CSON_PACK_INTERNAL_ERROR );
5982 }
5983
5984 return ( subst );
5985 }
5986
5987 static int on_unpack_array_value( struct state_stack * stack, struct token * tok, union unpack_value * unpack_value )
5988 {
5989 struct state * state;
5990 cson_array * array;
5991 cson_value * value = NULL;
5992
5993 if( tok->optional )
5994 {
5995 /* invalid modifier */
5996 return ( CSON_PACK_ARG_ERROR );
5997 }
5998
5999 if( tok->type == ']' )
6000 {
6001 state_stack_pop( stack );
6002
6003 return ( 0 );
6004 }
6005 else if( ( tok->type != 's' ) && tok->alloc )
6006 {
6007 /* invalid modifier */
6008 return ( CSON_PACK_ARG_ERROR );
6009 }
6010
6011 state = state_stack_top( stack );
6012 if( state->parent_value != NULL )
6013 {
6014 /* get next array value */
6015 array = cson_value_get_array( state->parent_value );
6016 value = cson_array_get( array, state->index );
6017 if( value == NULL )
6018 {
6019 /* index out of bounds */
6020 return ( CSON_PACK_VALIDATION_ERROR );
6021 }
6022 }
6023 state->index++;
6024
6025 return ( handle_unpack_value( stack, tok, value, unpack_value, STATE_ARRAY_VALUE ) );
6026 }
6027
6028 static int on_unpack_property_value( struct state_stack * stack, struct token * tok, union unpack_value * unpack_value )
6029 {
6030 struct state * state;
6031 cson_object * object;
6032 cson_value * value;
6033
6034 if( ( tok->optional ) || ( ( tok->type != 's' ) && tok->alloc ) )
6035 {
6036 /* invalid modifier */
6037 return ( CSON_PACK_ARG_ERROR );
6038 }
6039
6040 state = state_stack_top( stack );
6041 object = cson_value_get_object( state->parent_value );
6042 value = cson_object_get( object, state->property_name );
6043 if( !state->property_optional && ( value == NULL ) )
6044 {
6045 /* missing mandatory property */
6046 return ( CSON_PACK_VALIDATION_ERROR );
6047 }
6048
6049 return ( handle_unpack_value( stack, tok, value, unpack_value, STATE_PROPERTY_NAME ) );
6050 }
6051
6052 int cson_vunpack( cson_value * root_value, const char * fmt, va_list args )
6053 {
6054 int retval = CSON_PACK_INTERNAL_ERROR;
6055 int subst = 0;
6056 struct state_stack * stack = NULL;
6057 struct state * state;
6058 const char * p = fmt;
6059 struct token tok = { 0 };
6060 union unpack_value unpack_value = { 0 };
6061 const char * property_name;
6062
6063 if( root_value == NULL )
6064 {
6065 retval = CSON_PACK_ARG_ERROR;
6066 goto out;
6067 }
6068
6069 stack = state_stack_create( strlen( fmt ) + 2 ); /* worst case */
6070 if( stack == NULL )
6071 {
6072 retval = CSON_PACK_ALLOC_ERROR;
6073 goto out;
6074 }
6075 state_stack_push( stack, STATE_INITIAL, root_value, NULL, 0, 0 );
6076
6077 for( p = next_token( p, &tok ); p != NULL; p = next_token( p, &tok ) )
6078 {
6079 state = state_stack_top( stack );
6080 if( state->parser_state == STATE_PROPERTY_NAME )
6081 {
6082 property_name = ( tok.type == 's' ) ? va_arg( args, const char * ) : NULL;
6083 }
6084 else if( !tok.suppress )
6085 {
6086 switch( tok.type )
6087 {
6088 case '[':
6089 unpack_value.arrayp = va_arg( args, cson_array ** );
6090 break;
6091 case '{':
6092 unpack_value.objectp = va_arg( args, cson_object ** );
6093 break;
6094 case 's':
6095 if( tok.alloc )
6096 {
6097 unpack_value.astringp = va_arg( args, char ** );
6098 }
6099 else
6100 {
6101 unpack_value.stringp = va_arg( args, const char ** );
6102 }
6103 break;
6104 case 'd':
6105 if( tok.len_l != 2 )
6106 {
6107 /*
6108 * parsed values are always of type
6109 * cson_int_t
6110 */
6111 retval = CSON_PACK_ARG_ERROR;
6112 goto out;
6113 }
6114 unpack_value.ip = va_arg( args, cson_int_t * );
6115 break;
6116 case 'f':
6117 unpack_value.dp = va_arg( args, double * );
6118 break;
6119 case 'b':
6120 unpack_value.bp = va_arg( args, char * );
6121 break;
6122 }
6123 }
6124
6125 switch( state->parser_state )
6126 {
6127 case STATE_INITIAL:
6128 retval = on_unpack_initial( stack, &tok, &unpack_value );
6129 if( retval < 0 )
6130 {
6131 goto out;
6132 }
6133 subst += retval;
6134 break;
6135 case STATE_END:
6136 /* check for trailing characters */
6137 retval = ( tok.type == '\0' ) ? subst : CSON_PACK_ARG_ERROR;
6138 goto out;
6139 case STATE_PROPERTY_NAME:
6140 retval = on_unpack_property_name( stack, &tok, property_name );
6141 if( retval != 0 )
6142 {
6143 goto out;
6144 }
6145 break;
6146 case STATE_PROPERTY_VALUE:
6147 retval = on_unpack_property_value( stack, &tok, &unpack_value );
6148 if( retval < 0 )
6149 {
6150 goto out;
6151 }
6152 subst += retval;
6153 break;
6154 case STATE_ARRAY_VALUE:
6155 retval = on_unpack_array_value( stack, &tok, &unpack_value );
6156 if( retval < 0 )
6157 {
6158 goto out;
6159 }
6160 subst += retval;
6161 break;
6162 default:
6163 retval = CSON_PACK_INTERNAL_ERROR;
6164 goto out;
6165 }
6166 }
6167 if( p == NULL )
6168 {
6169 /* parse error */
6170 retval = CSON_PACK_ARG_ERROR;
6171 }
6172
6173 out:
6174 if( stack != NULL ) {
6175 free( stack->state );
6176 free( stack );
6177 }
6178
6179 return ( retval );
6180 }
6181
6182 int cson_unpack( cson_value * root_value, const char * fmt, ... )
6183 {
6184 int retval;
6185 va_list args;
6186
6187 va_start( args, fmt );
6188 retval = cson_vunpack( root_value, fmt, args );
6189 va_end( args );
6190
6191 return ( retval );
6192 }
6193 /* end file ./cson_pack.c */
6194 /* begin file ./cson_lists.h */
6195 /* Auto-generated from cson_list.h. Edit at your own risk! */
6196 unsigned int cson_value_list_reserve( cson_value_list * self, unsigned int n )
6197 {
6198 if( !self ) return 0;
@@ -5389,11 +6468,11 @@
6468 cson_string * colName = NULL;
6469 int i = 0;
6470 int rc = 0;
6471 cson_value * currentValue = NULL;
6472 int const colCount = sqlite3_column_count(st);
6473 if( !colCount || (colCount>cson_array_length_get(colNames)) ) {
6474 return NULL;
6475 }
6476 rootV = cson_value_new_object();
6477 if(!rootV) return NULL;
6478 root = cson_value_get_object(rootV);
6479
--- extsrc/cson_amalgamation.h
+++ extsrc/cson_amalgamation.h
@@ -7,10 +7,12 @@
77
#if !defined(WANDERINGHORSE_NET_CSON_H_INCLUDED)
88
#define WANDERINGHORSE_NET_CSON_H_INCLUDED 1
99
1010
/*#include <stdint.h> C99: fixed-size int types. */
1111
#include <stdio.h> /* FILE decl */
12
+
13
+#include <stdarg.h>
1214
1315
/** @page page_cson cson JSON API
1416
1517
cson (pronounced "season") is an object-oriented C API for generating
1618
and consuming JSON (http://www.json.org) data.
@@ -19,24 +21,22 @@
1921
to, damned near anywhere. The i/o routines use a callback function to
2022
fetch/emit JSON data, allowing clients to easily plug in their own
2123
implementations. Implementations are provided for string- and
2224
FILE-based i/o.
2325
24
-Project home page: http://fossil.wanderinghorse.net/repos/cson
26
+Project home page: https://fossil.wanderinghorse.net/r/cson
2527
26
-Author: Stephan Beal (http://www.wanderinghorse.net/home/stephan/)
28
+Author: Stephan Beal (https://www.wanderinghorse.net/home/stephan/)
2729
2830
License: Dual Public Domain/MIT
2931
3032
The full license text is at the bottom of the main header file
3133
(cson.h).
3234
3335
Examples of how to use the library are scattered throughout
3436
the API documentation, in the test.c file in the source repo,
3537
and in the wiki on the project's home page.
36
-
37
-
3838
*/
3939
4040
#if defined(__cplusplus)
4141
extern "C" {
4242
#endif
@@ -296,10 +296,14 @@
296296
@see cson_value_type_id()
297297
*/
298298
299299
/** @var cson_rc
300300
301
+ Deprecated: clients are encouraged to use the CSON_RC_xxx values
302
+ which correspond to cson_rc.xxx, as those are more efficient. Some
303
+ docs and code may still refer to cson_rc, though.
304
+
301305
This object defines the error codes used by cson.
302306
303307
Library routines which return int values almost always return a
304308
value from this structure. None of the members in this struct have
305309
published values except for the OK member, which has the value 0.
@@ -315,14 +319,106 @@
315319
if( 0 == rc ) {...success...}
316320
else if( cson_rc.ArgError == rc ) { ... some argument was wrong ... }
317321
else if( cson_rc.AllocError == rc ) { ... allocation error ... }
318322
...
319323
@endcode
324
+
325
+ Or with the preferred/newer method:
326
+
327
+ @code
328
+ int rc = cson_some_func(...);
329
+ switch(rc){
330
+ case 0: ...success...;
331
+ case CSON_RC_ArgError: ... some argument was wrong ...
332
+ case CSON_RC_AllocError: ... allocation error ...
333
+ ...
334
+ }
335
+ @endcode
320336
321337
The entries named Parse_XXX are generally only returned by
322338
cson_parse() and friends.
339
+
340
+ @deprecated
323341
*/
342
+
343
+/**
344
+ The CSON_RC_xxx values are intended to replace the older
345
+ cson_rc.xxx values.
346
+*/
347
+enum cson_rc_values {
348
+ /** The generic success value. Guaranteed to be 0. */
349
+ CSON_RC_OK = 0,
350
+ /** Signifies an error in one or more arguments (e.g. NULL where it is not allowed). */
351
+ CSON_RC_ArgError,
352
+ /** Signifies that some argument is not in a valid range. */
353
+ CSON_RC_RangeError,
354
+ /** Signifies that some argument is not of the correct logical cson type. */
355
+ CSON_RC_TypeError,
356
+ /** Signifies an input/ouput error. */
357
+ CSON_RC_IOError,
358
+ /** Signifies an out-of-memory error. */
359
+ CSON_RC_AllocError,
360
+ /** Signifies that the called code is "NYI" (Not Yet Implemented). */
361
+ CSON_RC_NYIError,
362
+ /** Signifies that an internal error was triggered. If it happens, please report this as a bug! */
363
+ CSON_RC_InternalError,
364
+ /** Signifies that the called operation is not supported in the
365
+ current environment. e.g. missing support from 3rd-party or
366
+ platform-specific code.
367
+ */
368
+ CSON_RC_UnsupportedError,
369
+ /**
370
+ Signifies that the request resource could not be found.
371
+ */
372
+ CSON_RC_NotFoundError,
373
+ /**
374
+ Signifies an unknown error, possibly because an underlying
375
+ 3rd-party API produced an error and we have no other reasonable
376
+ error code to convert it to.
377
+ */
378
+ CSON_RC_UnknownError,
379
+ /**
380
+ Signifies that the parser found an unexpected character.
381
+ */
382
+ CSON_RC_Parse_INVALID_CHAR,
383
+ /**
384
+ Signifies that the parser found an invalid keyword (possibly
385
+ an unquoted string).
386
+ */
387
+ CSON_RC_Parse_INVALID_KEYWORD,
388
+ /**
389
+ Signifies that the parser found an invalid escape sequence.
390
+ */
391
+ CSON_RC_Parse_INVALID_ESCAPE_SEQUENCE,
392
+ /**
393
+ Signifies that the parser found an invalid Unicode character
394
+ sequence.
395
+ */
396
+ CSON_RC_Parse_INVALID_UNICODE_SEQUENCE,
397
+ /**
398
+ Signifies that the parser found an invalid numeric token.
399
+ */
400
+ CSON_RC_Parse_INVALID_NUMBER,
401
+ /**
402
+ Signifies that the parser reached its maximum defined
403
+ parsing depth before finishing the input.
404
+ */
405
+ CSON_RC_Parse_NESTING_DEPTH_REACHED,
406
+ /**
407
+ Signifies that the parser found an unclosed object or array.
408
+ */
409
+ CSON_RC_Parse_UNBALANCED_COLLECTION,
410
+ /**
411
+ Signifies that the parser found an key in an unexpected place.
412
+ */
413
+ CSON_RC_Parse_EXPECTED_KEY,
414
+ /**
415
+ Signifies that the parser expected to find a colon but
416
+ found none (e.g. between keys and values in an object).
417
+ */
418
+ CSON_RC_Parse_EXPECTED_COLON
419
+};
324420
325421
/** @struct cson_rc_
326422
See \ref cson_rc for details.
327423
*/
328424
static const struct cson_rc_
@@ -397,30 +493,30 @@
397493
Signifies that the parser expected to find a colon but
398494
found none (e.g. between keys and values in an object).
399495
*/
400496
const int Parse_EXPECTED_COLON;
401497
} cson_rc = {
402
-0/*OK*/,
403
-1/*ArgError*/,
404
-2/*RangeError*/,
405
-3/*TypeError*/,
406
-4/*IOError*/,
407
-5/*AllocError*/,
408
-6/*NYIError*/,
409
-7/*InternalError*/,
410
-8/*UnsupportedError*/,
411
-9/*NotFoundError*/,
412
-10/*UnknownError*/,
413
-11/*Parse_INVALID_CHAR*/,
414
-12/*Parse_INVALID_KEYWORD*/,
415
-13/*Parse_INVALID_ESCAPE_SEQUENCE*/,
416
-14/*Parse_INVALID_UNICODE_SEQUENCE*/,
417
-15/*Parse_INVALID_NUMBER*/,
418
-16/*Parse_NESTING_DEPTH_REACHED*/,
419
-17/*Parse_UNBALANCED_COLLECTION*/,
420
-18/*Parse_EXPECTED_KEY*/,
421
-19/*Parse_EXPECTED_COLON*/
498
+ CSON_RC_OK,
499
+ CSON_RC_ArgError,
500
+ CSON_RC_RangeError,
501
+ CSON_RC_TypeError,
502
+ CSON_RC_IOError,
503
+ CSON_RC_AllocError,
504
+ CSON_RC_NYIError,
505
+ CSON_RC_InternalError,
506
+ CSON_RC_UnsupportedError,
507
+ CSON_RC_NotFoundError,
508
+ CSON_RC_UnknownError,
509
+ CSON_RC_Parse_INVALID_CHAR,
510
+ CSON_RC_Parse_INVALID_KEYWORD,
511
+ CSON_RC_Parse_INVALID_ESCAPE_SEQUENCE,
512
+ CSON_RC_Parse_INVALID_UNICODE_SEQUENCE,
513
+ CSON_RC_Parse_INVALID_NUMBER,
514
+ CSON_RC_Parse_NESTING_DEPTH_REACHED,
515
+ CSON_RC_Parse_UNBALANCED_COLLECTION,
516
+ CSON_RC_Parse_EXPECTED_KEY,
517
+ CSON_RC_Parse_EXPECTED_COLON
422518
};
423519
424520
/**
425521
Returns the string form of the cson_rc code corresponding to rc, or
426522
some unspecified, non-NULL string if it is an unknown code.
@@ -671,12 +767,12 @@
671767
so any output-destination-specific state can be stored there and accessed
672768
via the src callback.
673769
674770
Non-parse error conditions include:
675771
676
- - (!tgt) or !src: cson_rc.ArgError
677
- - cson_rc.AllocError can happen at any time during the input phase
772
+ - (!tgt) or !src: CSON_RC_ArgError
773
+ - CSON_RC_AllocError can happen at any time during the input phase
678774
679775
Here's a complete example of using a custom input source:
680776
681777
@code
682778
// Internal type to hold state for a JSON input string.
@@ -692,12 +788,12 @@
692788
unsigned int * n )
693789
{
694790
StringSource * ss = (StringSource*) state;
695791
unsigned int i;
696792
unsigned char * tgt = (unsigned char *)dest;
697
- if( ! ss || ! n || !dest ) return cson_rc.ArgError;
698
- else if( !*n ) return cson_rc.RangeError;
793
+ if( ! ss || ! n || !dest ) return CSON_RC_ArgError;
794
+ else if( !*n ) return CSON_RC_RangeError;
699795
for( i = 0;
700796
(i < *n) && (ss->pos < ss->end);
701797
++i, ++ss->pos, ++tgt )
702798
{
703799
*tgt = *ss->pos;
@@ -748,11 +844,11 @@
748844
cson_parse_opt const * opt, cson_parse_info * info );
749845
750846
/**
751847
Convenience wrapper around cson_parse_FILE() which opens the given filename.
752848
753
- Returns cson_rc.IOError if the file cannot be opened.
849
+ Returns CSON_RC_IOError if the file cannot be opened.
754850
755851
@see cson_parse_FILE()
756852
*/
757853
int cson_parse_filename( cson_value ** tgt, char const * src,
758854
cson_parse_opt const * opt, cson_parse_info * info );
@@ -763,11 +859,11 @@
763859
764860
src must be a string containing JSON code, at least len bytes long,
765861
and the parser will attempt to parse exactly len bytes from src.
766862
767863
If len is less than 2 (the minimum length of a legal top-node JSON
768
- object) then cson_rc.RangeError is returned.
864
+ object) then CSON_RC_RangeError is returned.
769865
*/
770866
int cson_parse_string( cson_value ** tgt, char const * src, unsigned int len,
771867
cson_parse_opt const * opt, cson_parse_info * info );
772868
773869
@@ -779,11 +875,11 @@
779875
780876
If opt is NULL then default options (the values defined in
781877
cson_output_opt_empty) are used.
782878
783879
If opt->maxDepth is exceeded while traversing the value tree,
784
- cson_rc.RangeError is returned.
880
+ CSON_RC_RangeError is returned.
785881
786882
The destState parameter is ignored by this function and is passed
787883
on to the dest function.
788884
789885
Returns 0 on success. On error, any amount of output might have been
@@ -816,11 +912,11 @@
816912
@see cson_output_filename()
817913
*/
818914
int cson_output_FILE( cson_value const * src, FILE * dest, cson_output_opt const * opt );
819915
/**
820916
Convenience wrapper around cson_output_FILE() which writes to the given filename, destroying
821
- any existing contents. Returns cson_rc.IOError if the file cannot be opened.
917
+ any existing contents. Returns CSON_RC_IOError if the file cannot be opened.
822918
823919
@see cson_output_FILE()
824920
*/
825921
int cson_output_filename( cson_value const * src, char const * dest, cson_output_opt const * fmt );
826922
@@ -947,11 +1043,11 @@
9471043
The conversion, if any, depends on the concrete type of val:
9481044
9491045
NULL, null, undefined: *v is set to 0 and 0 is returned.
9501046
9511047
string, object, array: *v is set to 0 and
952
- cson_rc.TypeError is returned. The error may normally be safely
1048
+ CSON_RC_TypeError is returned. The error may normally be safely
9531049
ignored, but it is provided for those wanted to know whether a direct
9541050
conversion was possible.
9551051
9561052
integer: *v is set to the int value and 0 is returned.
9571053
@@ -1178,19 +1274,19 @@
11781274
changes its logical size, but may pre-allocate space in the
11791275
array for storing new (as-yet-unassigned) values.
11801276
11811277
Returns 0 on success, or non-zero on error:
11821278
1183
- - If ar is NULL: cson_rc.ArgError
1279
+ - If ar is NULL: CSON_RC_ArgError
11841280
1185
- - If allocation fails: cson_rc.AllocError
1281
+ - If allocation fails: CSON_RC_AllocError
11861282
*/
11871283
int cson_array_reserve( cson_array * ar, unsigned int size );
11881284
11891285
/**
11901286
If ar is not NULL, sets *v (if v is not NULL) to the length of the array
1191
- and returns 0. Returns cson_rc.ArgError if ar is NULL.
1287
+ and returns 0. Returns CSON_RC_ArgError if ar is NULL.
11921288
*/
11931289
int cson_array_length_fetch( cson_array const * ar, unsigned int * v );
11941290
11951291
/**
11961292
Simplified form of cson_array_length_fetch() which returns 0 if ar
@@ -1243,16 +1339,16 @@
12431339
implementation has slightly different array-preallocation policy
12441340
(it grows more eagerly).
12451341
12461342
Returns 0 on success, non-zero on error. Error cases include:
12471343
1248
- - ar or v are NULL: cson_rc.ArgError
1344
+ - ar or v are NULL: CSON_RC_ArgError
12491345
1250
- - Array cannot be expanded to hold enough elements: cson_rc.AllocError.
1346
+ - Array cannot be expanded to hold enough elements: CSON_RC_AllocError.
12511347
12521348
- Appending would cause a numeric overlow in the array's size:
1253
- cson_rc.RangeError. (However, you'll get an AllocError long before
1349
+ CSON_RC_RangeError. (However, you'll get an AllocError long before
12541350
that happens!)
12551351
12561352
On error ownership of v is NOT modified, and the caller may still
12571353
need to clean it up. See cson_array_set() for the details.
12581354
@@ -1449,13 +1545,13 @@
14491545
show up later, e.g. during output.
14501546
14511547
Returns 0 on success, non-0 on error. It has the following error
14521548
cases:
14531549
1454
- - cson_rc.ArgError: obj or key are NULL or strlen(key) is 0.
1550
+ - CSON_RC_ArgError: obj or key are NULL or strlen(key) is 0.
14551551
1456
- - cson_rc.AllocError: an out-of-memory error
1552
+ - CSON_RC_AllocError: an out-of-memory error
14571553
14581554
On error ownership of v is NOT modified, and the caller may still
14591555
need to clean it up. For example, the following code will introduce
14601556
a leak if this function fails:
14611557
@@ -1500,14 +1596,14 @@
15001596
15011597
/**
15021598
Removes a property from an object.
15031599
15041600
If obj contains the given key, it is removed and 0 is returned. If
1505
- it is not found, cson_rc.NotFoundError is returned (which can
1601
+ it is not found, CSON_RC_NotFoundError is returned (which can
15061602
normally be ignored by client code).
15071603
1508
- cson_rc.ArgError is returned if obj or key are NULL or key has
1604
+ CSON_RC_ArgError is returned if obj or key are NULL or key has
15091605
a length of 0.
15101606
15111607
Returns 0 if the given key is found and removed.
15121608
15131609
This is functionally equivalent calling
@@ -1563,27 +1659,27 @@
15631659
path is a delimited string, where the delimiter is the given
15641660
separator character.
15651661
15661662
This function searches for the given path, starting at the given object
15671663
and traversing its properties as the path specifies. If a given part of the
1568
- path is not found, then this function fails with cson_rc.NotFoundError.
1664
+ path is not found, then this function fails with CSON_RC_NotFoundError.
15691665
15701666
If it finds the given path, it returns the value by assiging *tgt
15711667
to it. If tgt is NULL then this function has no side-effects but
15721668
will return 0 if the given path is found within the object, so it can be used
15731669
to test for existence without fetching it.
15741670
1575
- Returns 0 if it finds an entry, cson_rc.NotFoundError if it finds
1671
+ Returns 0 if it finds an entry, CSON_RC_NotFoundError if it finds
15761672
no item, and any other non-zero error code on a "real" error. Errors include:
15771673
1578
- - obj or path are NULL: cson_rc.ArgError
1674
+ - obj or path are NULL: CSON_RC_ArgError
15791675
15801676
- separator is 0, or path is an empty string or contains only
1581
- separator characters: cson_rc.RangeError
1677
+ separator characters: CSON_RC_RangeError
15821678
15831679
- There is an upper limit on how long a single path component may
1584
- be (some "reasonable" internal size), and cson_rc.RangeError is
1680
+ be (some "reasonable" internal size), and CSON_RC_RangeError is
15851681
returned if that length is violated.
15861682
15871683
15881684
Limitations:
15891685
@@ -1677,11 +1773,11 @@
16771773
either replaced or left as-is, depending on whether flags contains
16781774
he CSON_MERGE_REPLACE bit.
16791775
16801776
Returns 0 on success. The error conditions are:
16811777
1682
- - dest or src are NULL or (dest==src) returns cson_rc.ArgError.
1778
+ - dest or src are NULL or (dest==src) returns CSON_RC_ArgError.
16831779
16841780
- dest or src contain cyclic references - this will likely cause a
16851781
crash due to endless recursion.
16861782
16871783
Potential TODOs:
@@ -1724,11 +1820,11 @@
17241820
*/
17251821
extern const cson_object_iterator cson_object_iterator_empty;
17261822
17271823
/**
17281824
Initializes the given iterator to point at the start of obj's
1729
- properties. Returns 0 on success or cson_rc.ArgError if !obj
1825
+ properties. Returns 0 on success or CSON_RC_ArgError if !obj
17301826
or !iter.
17311827
17321828
obj must outlive iter, or results are undefined. Results are also
17331829
undefined if obj is modified while the iterator is active.
17341830
@@ -1891,13 +1987,13 @@
18911987
to be NULL-terminated. On error the buffer might contain partial
18921988
contents, and it should not be used except to free its contents.
18931989
18941990
On error non-zero is returned. Errors include:
18951991
1896
- - Invalid arguments: cson_rc.ArgError
1992
+ - Invalid arguments: CSON_RC_ArgError
18971993
1898
- - Buffer cannot be expanded (runs out of memory): cson_rc.AllocError
1994
+ - Buffer cannot be expanded (runs out of memory): CSON_RC_AllocError
18991995
19001996
Example usage:
19011997
19021998
@code
19031999
cson_buffer buf = cson_buffer_empty;
@@ -1999,13 +2095,13 @@
19992095
On error non-0 is returned and dest has almost certainly been
20002096
modified but its state must be considered incomplete.
20012097
20022098
Errors include:
20032099
2004
- - dest or src are NULL (cson_rc.ArgError)
2100
+ - dest or src are NULL (CSON_RC_ArgError)
20052101
2006
- - Allocation error (cson_rc.AllocError)
2102
+ - Allocation error (CSON_RC_AllocError)
20072103
20082104
- src() returns an error code
20092105
20102106
Whether or not the state parameter may be NULL depends on
20112107
the src implementation requirements.
@@ -2084,12 +2180,12 @@
20842180
will not be if there are still other live references to
20852181
it). cson_value_free() will not _actually_ destroy the value until
20862182
its reference count drops to 0.
20872183
20882184
Returns 0 on success. The only error conditions are if v is NULL
2089
- (cson_rc.ArgError) or if the reference increment would overflow
2090
- (cson_rc.RangeError). In theory a client would get allocation
2185
+ (CSON_RC_ArgError) or if the reference increment would overflow
2186
+ (CSON_RC_RangeError). In theory a client would get allocation
20912187
errors long before the reference count could overflow (assuming
20922188
those reference counts come from container insertions, as opposed
20932189
to via this function).
20942190
20952191
Insider notes which clients really need to know:
@@ -2238,11 +2334,11 @@
22382334
/**
22392335
Calculates the approximate in-memory-allocated size of v,
22402336
recursively if it is a container type, with the following caveats
22412337
and limitations:
22422338
2243
- If a given value is reference counted then it is only and multiple
2339
+ If a given value is reference counted and encountered multiple
22442340
times within a traversed container, each reference is counted at
22452341
full cost. We have no way of knowing if a given reference has been
22462342
visited already and whether it should or should not be counted, so
22472343
we pessimistically count them even though the _might_ not really
22482344
count for the given object tree (it depends on where the other open
@@ -2318,10 +2414,169 @@
23182414
it might contain partial results.
23192415
*/
23202416
int cson_parse_argv_flags( int argc, char const * const * argv,
23212417
cson_object ** tgt, unsigned int * count );
23222418
2419
+/**
2420
+ Return values for the cson_pack() and cson_unpack() interfaces.
2421
+*/
2422
+enum cson_pack_retval {
2423
+ /** Signals an out-of-memory error. */
2424
+ CSON_PACK_ALLOC_ERROR = -1,
2425
+ /** Signals a syntax error in the format string. */
2426
+ CSON_PACK_ARG_ERROR = -2,
2427
+ /**
2428
+ Signals an that an internal error has occurred.
2429
+ This indicates a bug in this library.
2430
+ */
2431
+ CSON_PACK_INTERNAL_ERROR = -3,
2432
+ /**
2433
+ Signals that the JSON document does not validate agains the format
2434
+ string passed to cson_unpack().
2435
+ */
2436
+ CSON_PACK_VALIDATION_ERROR = -4
2437
+};
2438
+
2439
+/**
2440
+ Construct arbitrarily complex JSON documents from native C types.
2441
+
2442
+ Create a new object or array and add or merge the passed values and
2443
+ properties to it according to the supplied format string.
2444
+
2445
+ fmt is a format string, it must at least contain an array or object
2446
+ specifier as its root value. Format specifiers start with a percent sign '\%'
2447
+ followed by one or more modifiers and a type character. Object properties
2448
+ are specified as key-value pairs where the key is specified as a string and
2449
+ passed as an argument of const char *. Any space, tab, carriage return, line
2450
+ feed, colon and comma characters between format specifiers are ignored.
2451
+
2452
+ | Type | Description |
2453
+ | :--: | :---------- |
2454
+ | s | creates either a property name or a string value, in case of the former the corresponding argument is a pointer to const char which is a sequence of bytes specifying the name of the property that is to be created, in case of the latter the corresponding argument is a pointer to const char |
2455
+ | d | creates an integer value, the corresponding argument is an int |
2456
+ | i | ^ |
2457
+ | f | creates a floating point value, the corresponding argument is a double |
2458
+ | b | creates a boolean value, the corresponding argument is an int |
2459
+ | N | creates a null value |
2460
+ | [...] | creates an array, the corresponding argument is a pointer to a cson_array |
2461
+ | {...} | creates an array, the corresponding argument is a pointer to a cson_object |
2462
+
2463
+ | Modifier | Description |
2464
+ | :------: | :---------- |
2465
+ | l | specifies that the following d or i specifier applies to an argument which is a pointer to long |
2466
+ | ll | specifies that the following d or i specifier applies to an argument which is a pointer to cson_int_t |
2467
+
2468
+ | Short Form | Expands to
2469
+ | :--------: | :--------- |
2470
+ | {...} | %*{...} |
2471
+ | [...] | %*[...] |
2472
+ | \%D | \%lld |
2473
+
2474
+
2475
+ Returns 0 on success. The error conditions are:
2476
+
2477
+ - CSON_PACK_ARG_ERROR: fmt contains a syntax error
2478
+
2479
+ - CSON_PACK_ALLOC_ERROR: a memory allocation failed
2480
+
2481
+ - CSON_PACK_INTERNAL_ERROR: an internal error has occurred, this is a bug in
2482
+ cson
2483
+
2484
+ Example:
2485
+ @code
2486
+ cson_value * root_value;
2487
+ cson_array * arr;
2488
+ ...
2489
+ rc = cson_pack( root_value, "{%s: %d, %s: %[]}", "foo", 42, "bar", arr );
2490
+ if( 0 != rc ) {
2491
+ ... error ...
2492
+ }
2493
+ @endcode
2494
+*/
2495
+int cson_pack( cson_value **root_valuep, const char *fmt, ... );
2496
+
2497
+/**
2498
+ Same as cson_pack() except that it takes a va_list instead of a variable
2499
+ number of arguments.
2500
+*/
2501
+int cson_vpack( cson_value **root_valuep, const char *fmt, va_list args );
2502
+
2503
+/**
2504
+ Iterate over the given object or array and convert an arbitrary number of
2505
+ JSON values into their native C types or validates them according to the
2506
+ given format string fmt.
2507
+
2508
+ fmt is a format string, it must at least contain an array or object
2509
+ specifier as its root value. Format specifiers start with a percent sign '\%'
2510
+ followed by one or more modifiers and a type character. Object properties
2511
+ are specified as key-value pairs where the key is specified as a string and
2512
+ passed as an argument of const char *. Any space, tab, carriage return, line
2513
+ feed, colon and comma characters between format specifiers are ignored.
2514
+
2515
+ | Type | Description |
2516
+ | :--: | :---------- |
2517
+ | s | matches a either a property name or a string value, in case of the former the corresponding argument is a pointer to const char which is a sequence of bytes specifying the name of the property that is to be matched, in case of the latter the corresponding argument is a pointer to a pointer to const char unless the 'm' modifier is specified where the the corresponding argument is a pointer to a pointer to char |
2518
+ | d | matches an integer value and must be used in with the "ll" modifier, the corresponding argument is a pointer to cson_int_t |
2519
+ | i | ^ |
2520
+ | f | matches a floating point value, the corresponding argument is a pointer to double |
2521
+ | b | matches a boolean value, the corresponding argument is a pointer to int |
2522
+ | N | matches a null value |
2523
+ | [...] | matches an array, the corresponding argument is a pointer to a pointer to a cson_array |
2524
+ | {...} | matches an array, the corresponding argument is a pointer to a pointer to a cson_object |
2525
+
2526
+ | Modifier | Description |
2527
+ | :------: | :---------- |
2528
+ | ? | specifies that the property reffered to by the given property name is optional |
2529
+ | * | suppresses assignment, only check for the presence and type of the specified value |
2530
+ | m | allocates a memory buffer for the extracted string |
2531
+ | ll | specifies that the following d or i specifier applies to an argument which is a pointer to cson_int_t |
2532
+
2533
+ | Short Form | Expands to
2534
+ | :--------: | :--------- |
2535
+ | {...} | %*{...} |
2536
+ | [...] | %*[...] |
2537
+ | \%D | \%lld |
2538
+
2539
+ Returns 0 on success. The error conditions are:
2540
+
2541
+ - CSON_PACK_ARG_ERROR: fmt contains a syntax error
2542
+
2543
+ - CSON_PACK_ALLOC_ERROR: a memory allocation failed
2544
+
2545
+ - CSON_PACK_VALIDATION_ERROR: validation failed, the JSON document structure
2546
+ differs from that described by the format string
2547
+
2548
+ - CSON_PACK_INTERNAL_ERROR: an internal error has occurred, this
2549
+ indicates a bug in this library.
2550
+
2551
+ Example:
2552
+ @code
2553
+ cson_value * root_value;
2554
+ cson_int_t x = 0;
2555
+ cson_array * arr = NULL;
2556
+ const char *str = NULL;
2557
+ ...
2558
+ rc = cson_unpack( root_value, "{%s: %d, %s: %[], %?s: %s}", "foo", &x, "bar", &arr, "baz", &str );
2559
+ if( rc < 3 && rc >= 0 ) {
2560
+ ... optional property is missing ...
2561
+ } else if ( CSON_PACK_ALLOC_ERROR == rc ) {
2562
+ ... out of memory error ...
2563
+ } else if ( CSON_PACK_VALIDATION_ERROR == rc ) {
2564
+ ... unexpected JSON document structure ...
2565
+ } else if ( rc ) {
2566
+ ... internal error ...
2567
+ }
2568
+ @endcode
2569
+
2570
+*/
2571
+int cson_unpack( cson_value *root_value, const char *fmt, ... );
2572
+
2573
+/**
2574
+ Same as cson_unpack() except that it takes a va_list instead of a variable
2575
+ number of arguments.
2576
+*/
2577
+int cson_vunpack( cson_value *root_value, const char *fmt, va_list args );
23232578
23242579
/* LICENSE
23252580
23262581
This software's source code, including accompanying documentation and
23272582
demonstration applications, are licensed under the following
23282583
--- extsrc/cson_amalgamation.h
+++ extsrc/cson_amalgamation.h
@@ -7,10 +7,12 @@
7 #if !defined(WANDERINGHORSE_NET_CSON_H_INCLUDED)
8 #define WANDERINGHORSE_NET_CSON_H_INCLUDED 1
9
10 /*#include <stdint.h> C99: fixed-size int types. */
11 #include <stdio.h> /* FILE decl */
 
 
12
13 /** @page page_cson cson JSON API
14
15 cson (pronounced "season") is an object-oriented C API for generating
16 and consuming JSON (http://www.json.org) data.
@@ -19,24 +21,22 @@
19 to, damned near anywhere. The i/o routines use a callback function to
20 fetch/emit JSON data, allowing clients to easily plug in their own
21 implementations. Implementations are provided for string- and
22 FILE-based i/o.
23
24 Project home page: http://fossil.wanderinghorse.net/repos/cson
25
26 Author: Stephan Beal (http://www.wanderinghorse.net/home/stephan/)
27
28 License: Dual Public Domain/MIT
29
30 The full license text is at the bottom of the main header file
31 (cson.h).
32
33 Examples of how to use the library are scattered throughout
34 the API documentation, in the test.c file in the source repo,
35 and in the wiki on the project's home page.
36
37
38 */
39
40 #if defined(__cplusplus)
41 extern "C" {
42 #endif
@@ -296,10 +296,14 @@
296 @see cson_value_type_id()
297 */
298
299 /** @var cson_rc
300
 
 
 
 
301 This object defines the error codes used by cson.
302
303 Library routines which return int values almost always return a
304 value from this structure. None of the members in this struct have
305 published values except for the OK member, which has the value 0.
@@ -315,14 +319,106 @@
315 if( 0 == rc ) {...success...}
316 else if( cson_rc.ArgError == rc ) { ... some argument was wrong ... }
317 else if( cson_rc.AllocError == rc ) { ... allocation error ... }
318 ...
319 @endcode
 
 
 
 
 
 
 
 
 
 
 
 
320
321 The entries named Parse_XXX are generally only returned by
322 cson_parse() and friends.
 
 
323 */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
324
325 /** @struct cson_rc_
326 See \ref cson_rc for details.
327 */
328 static const struct cson_rc_
@@ -397,30 +493,30 @@
397 Signifies that the parser expected to find a colon but
398 found none (e.g. between keys and values in an object).
399 */
400 const int Parse_EXPECTED_COLON;
401 } cson_rc = {
402 0/*OK*/,
403 1/*ArgError*/,
404 2/*RangeError*/,
405 3/*TypeError*/,
406 4/*IOError*/,
407 5/*AllocError*/,
408 6/*NYIError*/,
409 7/*InternalError*/,
410 8/*UnsupportedError*/,
411 9/*NotFoundError*/,
412 10/*UnknownError*/,
413 11/*Parse_INVALID_CHAR*/,
414 12/*Parse_INVALID_KEYWORD*/,
415 13/*Parse_INVALID_ESCAPE_SEQUENCE*/,
416 14/*Parse_INVALID_UNICODE_SEQUENCE*/,
417 15/*Parse_INVALID_NUMBER*/,
418 16/*Parse_NESTING_DEPTH_REACHED*/,
419 17/*Parse_UNBALANCED_COLLECTION*/,
420 18/*Parse_EXPECTED_KEY*/,
421 19/*Parse_EXPECTED_COLON*/
422 };
423
424 /**
425 Returns the string form of the cson_rc code corresponding to rc, or
426 some unspecified, non-NULL string if it is an unknown code.
@@ -671,12 +767,12 @@
671 so any output-destination-specific state can be stored there and accessed
672 via the src callback.
673
674 Non-parse error conditions include:
675
676 - (!tgt) or !src: cson_rc.ArgError
677 - cson_rc.AllocError can happen at any time during the input phase
678
679 Here's a complete example of using a custom input source:
680
681 @code
682 // Internal type to hold state for a JSON input string.
@@ -692,12 +788,12 @@
692 unsigned int * n )
693 {
694 StringSource * ss = (StringSource*) state;
695 unsigned int i;
696 unsigned char * tgt = (unsigned char *)dest;
697 if( ! ss || ! n || !dest ) return cson_rc.ArgError;
698 else if( !*n ) return cson_rc.RangeError;
699 for( i = 0;
700 (i < *n) && (ss->pos < ss->end);
701 ++i, ++ss->pos, ++tgt )
702 {
703 *tgt = *ss->pos;
@@ -748,11 +844,11 @@
748 cson_parse_opt const * opt, cson_parse_info * info );
749
750 /**
751 Convenience wrapper around cson_parse_FILE() which opens the given filename.
752
753 Returns cson_rc.IOError if the file cannot be opened.
754
755 @see cson_parse_FILE()
756 */
757 int cson_parse_filename( cson_value ** tgt, char const * src,
758 cson_parse_opt const * opt, cson_parse_info * info );
@@ -763,11 +859,11 @@
763
764 src must be a string containing JSON code, at least len bytes long,
765 and the parser will attempt to parse exactly len bytes from src.
766
767 If len is less than 2 (the minimum length of a legal top-node JSON
768 object) then cson_rc.RangeError is returned.
769 */
770 int cson_parse_string( cson_value ** tgt, char const * src, unsigned int len,
771 cson_parse_opt const * opt, cson_parse_info * info );
772
773
@@ -779,11 +875,11 @@
779
780 If opt is NULL then default options (the values defined in
781 cson_output_opt_empty) are used.
782
783 If opt->maxDepth is exceeded while traversing the value tree,
784 cson_rc.RangeError is returned.
785
786 The destState parameter is ignored by this function and is passed
787 on to the dest function.
788
789 Returns 0 on success. On error, any amount of output might have been
@@ -816,11 +912,11 @@
816 @see cson_output_filename()
817 */
818 int cson_output_FILE( cson_value const * src, FILE * dest, cson_output_opt const * opt );
819 /**
820 Convenience wrapper around cson_output_FILE() which writes to the given filename, destroying
821 any existing contents. Returns cson_rc.IOError if the file cannot be opened.
822
823 @see cson_output_FILE()
824 */
825 int cson_output_filename( cson_value const * src, char const * dest, cson_output_opt const * fmt );
826
@@ -947,11 +1043,11 @@
947 The conversion, if any, depends on the concrete type of val:
948
949 NULL, null, undefined: *v is set to 0 and 0 is returned.
950
951 string, object, array: *v is set to 0 and
952 cson_rc.TypeError is returned. The error may normally be safely
953 ignored, but it is provided for those wanted to know whether a direct
954 conversion was possible.
955
956 integer: *v is set to the int value and 0 is returned.
957
@@ -1178,19 +1274,19 @@
1178 changes its logical size, but may pre-allocate space in the
1179 array for storing new (as-yet-unassigned) values.
1180
1181 Returns 0 on success, or non-zero on error:
1182
1183 - If ar is NULL: cson_rc.ArgError
1184
1185 - If allocation fails: cson_rc.AllocError
1186 */
1187 int cson_array_reserve( cson_array * ar, unsigned int size );
1188
1189 /**
1190 If ar is not NULL, sets *v (if v is not NULL) to the length of the array
1191 and returns 0. Returns cson_rc.ArgError if ar is NULL.
1192 */
1193 int cson_array_length_fetch( cson_array const * ar, unsigned int * v );
1194
1195 /**
1196 Simplified form of cson_array_length_fetch() which returns 0 if ar
@@ -1243,16 +1339,16 @@
1243 implementation has slightly different array-preallocation policy
1244 (it grows more eagerly).
1245
1246 Returns 0 on success, non-zero on error. Error cases include:
1247
1248 - ar or v are NULL: cson_rc.ArgError
1249
1250 - Array cannot be expanded to hold enough elements: cson_rc.AllocError.
1251
1252 - Appending would cause a numeric overlow in the array's size:
1253 cson_rc.RangeError. (However, you'll get an AllocError long before
1254 that happens!)
1255
1256 On error ownership of v is NOT modified, and the caller may still
1257 need to clean it up. See cson_array_set() for the details.
1258
@@ -1449,13 +1545,13 @@
1449 show up later, e.g. during output.
1450
1451 Returns 0 on success, non-0 on error. It has the following error
1452 cases:
1453
1454 - cson_rc.ArgError: obj or key are NULL or strlen(key) is 0.
1455
1456 - cson_rc.AllocError: an out-of-memory error
1457
1458 On error ownership of v is NOT modified, and the caller may still
1459 need to clean it up. For example, the following code will introduce
1460 a leak if this function fails:
1461
@@ -1500,14 +1596,14 @@
1500
1501 /**
1502 Removes a property from an object.
1503
1504 If obj contains the given key, it is removed and 0 is returned. If
1505 it is not found, cson_rc.NotFoundError is returned (which can
1506 normally be ignored by client code).
1507
1508 cson_rc.ArgError is returned if obj or key are NULL or key has
1509 a length of 0.
1510
1511 Returns 0 if the given key is found and removed.
1512
1513 This is functionally equivalent calling
@@ -1563,27 +1659,27 @@
1563 path is a delimited string, where the delimiter is the given
1564 separator character.
1565
1566 This function searches for the given path, starting at the given object
1567 and traversing its properties as the path specifies. If a given part of the
1568 path is not found, then this function fails with cson_rc.NotFoundError.
1569
1570 If it finds the given path, it returns the value by assiging *tgt
1571 to it. If tgt is NULL then this function has no side-effects but
1572 will return 0 if the given path is found within the object, so it can be used
1573 to test for existence without fetching it.
1574
1575 Returns 0 if it finds an entry, cson_rc.NotFoundError if it finds
1576 no item, and any other non-zero error code on a "real" error. Errors include:
1577
1578 - obj or path are NULL: cson_rc.ArgError
1579
1580 - separator is 0, or path is an empty string or contains only
1581 separator characters: cson_rc.RangeError
1582
1583 - There is an upper limit on how long a single path component may
1584 be (some "reasonable" internal size), and cson_rc.RangeError is
1585 returned if that length is violated.
1586
1587
1588 Limitations:
1589
@@ -1677,11 +1773,11 @@
1677 either replaced or left as-is, depending on whether flags contains
1678 he CSON_MERGE_REPLACE bit.
1679
1680 Returns 0 on success. The error conditions are:
1681
1682 - dest or src are NULL or (dest==src) returns cson_rc.ArgError.
1683
1684 - dest or src contain cyclic references - this will likely cause a
1685 crash due to endless recursion.
1686
1687 Potential TODOs:
@@ -1724,11 +1820,11 @@
1724 */
1725 extern const cson_object_iterator cson_object_iterator_empty;
1726
1727 /**
1728 Initializes the given iterator to point at the start of obj's
1729 properties. Returns 0 on success or cson_rc.ArgError if !obj
1730 or !iter.
1731
1732 obj must outlive iter, or results are undefined. Results are also
1733 undefined if obj is modified while the iterator is active.
1734
@@ -1891,13 +1987,13 @@
1891 to be NULL-terminated. On error the buffer might contain partial
1892 contents, and it should not be used except to free its contents.
1893
1894 On error non-zero is returned. Errors include:
1895
1896 - Invalid arguments: cson_rc.ArgError
1897
1898 - Buffer cannot be expanded (runs out of memory): cson_rc.AllocError
1899
1900 Example usage:
1901
1902 @code
1903 cson_buffer buf = cson_buffer_empty;
@@ -1999,13 +2095,13 @@
1999 On error non-0 is returned and dest has almost certainly been
2000 modified but its state must be considered incomplete.
2001
2002 Errors include:
2003
2004 - dest or src are NULL (cson_rc.ArgError)
2005
2006 - Allocation error (cson_rc.AllocError)
2007
2008 - src() returns an error code
2009
2010 Whether or not the state parameter may be NULL depends on
2011 the src implementation requirements.
@@ -2084,12 +2180,12 @@
2084 will not be if there are still other live references to
2085 it). cson_value_free() will not _actually_ destroy the value until
2086 its reference count drops to 0.
2087
2088 Returns 0 on success. The only error conditions are if v is NULL
2089 (cson_rc.ArgError) or if the reference increment would overflow
2090 (cson_rc.RangeError). In theory a client would get allocation
2091 errors long before the reference count could overflow (assuming
2092 those reference counts come from container insertions, as opposed
2093 to via this function).
2094
2095 Insider notes which clients really need to know:
@@ -2238,11 +2334,11 @@
2238 /**
2239 Calculates the approximate in-memory-allocated size of v,
2240 recursively if it is a container type, with the following caveats
2241 and limitations:
2242
2243 If a given value is reference counted then it is only and multiple
2244 times within a traversed container, each reference is counted at
2245 full cost. We have no way of knowing if a given reference has been
2246 visited already and whether it should or should not be counted, so
2247 we pessimistically count them even though the _might_ not really
2248 count for the given object tree (it depends on where the other open
@@ -2318,10 +2414,169 @@
2318 it might contain partial results.
2319 */
2320 int cson_parse_argv_flags( int argc, char const * const * argv,
2321 cson_object ** tgt, unsigned int * count );
2322
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2323
2324 /* LICENSE
2325
2326 This software's source code, including accompanying documentation and
2327 demonstration applications, are licensed under the following
2328
--- extsrc/cson_amalgamation.h
+++ extsrc/cson_amalgamation.h
@@ -7,10 +7,12 @@
7 #if !defined(WANDERINGHORSE_NET_CSON_H_INCLUDED)
8 #define WANDERINGHORSE_NET_CSON_H_INCLUDED 1
9
10 /*#include <stdint.h> C99: fixed-size int types. */
11 #include <stdio.h> /* FILE decl */
12
13 #include <stdarg.h>
14
15 /** @page page_cson cson JSON API
16
17 cson (pronounced "season") is an object-oriented C API for generating
18 and consuming JSON (http://www.json.org) data.
@@ -19,24 +21,22 @@
21 to, damned near anywhere. The i/o routines use a callback function to
22 fetch/emit JSON data, allowing clients to easily plug in their own
23 implementations. Implementations are provided for string- and
24 FILE-based i/o.
25
26 Project home page: https://fossil.wanderinghorse.net/r/cson
27
28 Author: Stephan Beal (https://www.wanderinghorse.net/home/stephan/)
29
30 License: Dual Public Domain/MIT
31
32 The full license text is at the bottom of the main header file
33 (cson.h).
34
35 Examples of how to use the library are scattered throughout
36 the API documentation, in the test.c file in the source repo,
37 and in the wiki on the project's home page.
 
 
38 */
39
40 #if defined(__cplusplus)
41 extern "C" {
42 #endif
@@ -296,10 +296,14 @@
296 @see cson_value_type_id()
297 */
298
299 /** @var cson_rc
300
301 Deprecated: clients are encouraged to use the CSON_RC_xxx values
302 which correspond to cson_rc.xxx, as those are more efficient. Some
303 docs and code may still refer to cson_rc, though.
304
305 This object defines the error codes used by cson.
306
307 Library routines which return int values almost always return a
308 value from this structure. None of the members in this struct have
309 published values except for the OK member, which has the value 0.
@@ -315,14 +319,106 @@
319 if( 0 == rc ) {...success...}
320 else if( cson_rc.ArgError == rc ) { ... some argument was wrong ... }
321 else if( cson_rc.AllocError == rc ) { ... allocation error ... }
322 ...
323 @endcode
324
325 Or with the preferred/newer method:
326
327 @code
328 int rc = cson_some_func(...);
329 switch(rc){
330 case 0: ...success...;
331 case CSON_RC_ArgError: ... some argument was wrong ...
332 case CSON_RC_AllocError: ... allocation error ...
333 ...
334 }
335 @endcode
336
337 The entries named Parse_XXX are generally only returned by
338 cson_parse() and friends.
339
340 @deprecated
341 */
342
343 /**
344 The CSON_RC_xxx values are intended to replace the older
345 cson_rc.xxx values.
346 */
347 enum cson_rc_values {
348 /** The generic success value. Guaranteed to be 0. */
349 CSON_RC_OK = 0,
350 /** Signifies an error in one or more arguments (e.g. NULL where it is not allowed). */
351 CSON_RC_ArgError,
352 /** Signifies that some argument is not in a valid range. */
353 CSON_RC_RangeError,
354 /** Signifies that some argument is not of the correct logical cson type. */
355 CSON_RC_TypeError,
356 /** Signifies an input/ouput error. */
357 CSON_RC_IOError,
358 /** Signifies an out-of-memory error. */
359 CSON_RC_AllocError,
360 /** Signifies that the called code is "NYI" (Not Yet Implemented). */
361 CSON_RC_NYIError,
362 /** Signifies that an internal error was triggered. If it happens, please report this as a bug! */
363 CSON_RC_InternalError,
364 /** Signifies that the called operation is not supported in the
365 current environment. e.g. missing support from 3rd-party or
366 platform-specific code.
367 */
368 CSON_RC_UnsupportedError,
369 /**
370 Signifies that the request resource could not be found.
371 */
372 CSON_RC_NotFoundError,
373 /**
374 Signifies an unknown error, possibly because an underlying
375 3rd-party API produced an error and we have no other reasonable
376 error code to convert it to.
377 */
378 CSON_RC_UnknownError,
379 /**
380 Signifies that the parser found an unexpected character.
381 */
382 CSON_RC_Parse_INVALID_CHAR,
383 /**
384 Signifies that the parser found an invalid keyword (possibly
385 an unquoted string).
386 */
387 CSON_RC_Parse_INVALID_KEYWORD,
388 /**
389 Signifies that the parser found an invalid escape sequence.
390 */
391 CSON_RC_Parse_INVALID_ESCAPE_SEQUENCE,
392 /**
393 Signifies that the parser found an invalid Unicode character
394 sequence.
395 */
396 CSON_RC_Parse_INVALID_UNICODE_SEQUENCE,
397 /**
398 Signifies that the parser found an invalid numeric token.
399 */
400 CSON_RC_Parse_INVALID_NUMBER,
401 /**
402 Signifies that the parser reached its maximum defined
403 parsing depth before finishing the input.
404 */
405 CSON_RC_Parse_NESTING_DEPTH_REACHED,
406 /**
407 Signifies that the parser found an unclosed object or array.
408 */
409 CSON_RC_Parse_UNBALANCED_COLLECTION,
410 /**
411 Signifies that the parser found an key in an unexpected place.
412 */
413 CSON_RC_Parse_EXPECTED_KEY,
414 /**
415 Signifies that the parser expected to find a colon but
416 found none (e.g. between keys and values in an object).
417 */
418 CSON_RC_Parse_EXPECTED_COLON
419 };
420
421 /** @struct cson_rc_
422 See \ref cson_rc for details.
423 */
424 static const struct cson_rc_
@@ -397,30 +493,30 @@
493 Signifies that the parser expected to find a colon but
494 found none (e.g. between keys and values in an object).
495 */
496 const int Parse_EXPECTED_COLON;
497 } cson_rc = {
498 CSON_RC_OK,
499 CSON_RC_ArgError,
500 CSON_RC_RangeError,
501 CSON_RC_TypeError,
502 CSON_RC_IOError,
503 CSON_RC_AllocError,
504 CSON_RC_NYIError,
505 CSON_RC_InternalError,
506 CSON_RC_UnsupportedError,
507 CSON_RC_NotFoundError,
508 CSON_RC_UnknownError,
509 CSON_RC_Parse_INVALID_CHAR,
510 CSON_RC_Parse_INVALID_KEYWORD,
511 CSON_RC_Parse_INVALID_ESCAPE_SEQUENCE,
512 CSON_RC_Parse_INVALID_UNICODE_SEQUENCE,
513 CSON_RC_Parse_INVALID_NUMBER,
514 CSON_RC_Parse_NESTING_DEPTH_REACHED,
515 CSON_RC_Parse_UNBALANCED_COLLECTION,
516 CSON_RC_Parse_EXPECTED_KEY,
517 CSON_RC_Parse_EXPECTED_COLON
518 };
519
520 /**
521 Returns the string form of the cson_rc code corresponding to rc, or
522 some unspecified, non-NULL string if it is an unknown code.
@@ -671,12 +767,12 @@
767 so any output-destination-specific state can be stored there and accessed
768 via the src callback.
769
770 Non-parse error conditions include:
771
772 - (!tgt) or !src: CSON_RC_ArgError
773 - CSON_RC_AllocError can happen at any time during the input phase
774
775 Here's a complete example of using a custom input source:
776
777 @code
778 // Internal type to hold state for a JSON input string.
@@ -692,12 +788,12 @@
788 unsigned int * n )
789 {
790 StringSource * ss = (StringSource*) state;
791 unsigned int i;
792 unsigned char * tgt = (unsigned char *)dest;
793 if( ! ss || ! n || !dest ) return CSON_RC_ArgError;
794 else if( !*n ) return CSON_RC_RangeError;
795 for( i = 0;
796 (i < *n) && (ss->pos < ss->end);
797 ++i, ++ss->pos, ++tgt )
798 {
799 *tgt = *ss->pos;
@@ -748,11 +844,11 @@
844 cson_parse_opt const * opt, cson_parse_info * info );
845
846 /**
847 Convenience wrapper around cson_parse_FILE() which opens the given filename.
848
849 Returns CSON_RC_IOError if the file cannot be opened.
850
851 @see cson_parse_FILE()
852 */
853 int cson_parse_filename( cson_value ** tgt, char const * src,
854 cson_parse_opt const * opt, cson_parse_info * info );
@@ -763,11 +859,11 @@
859
860 src must be a string containing JSON code, at least len bytes long,
861 and the parser will attempt to parse exactly len bytes from src.
862
863 If len is less than 2 (the minimum length of a legal top-node JSON
864 object) then CSON_RC_RangeError is returned.
865 */
866 int cson_parse_string( cson_value ** tgt, char const * src, unsigned int len,
867 cson_parse_opt const * opt, cson_parse_info * info );
868
869
@@ -779,11 +875,11 @@
875
876 If opt is NULL then default options (the values defined in
877 cson_output_opt_empty) are used.
878
879 If opt->maxDepth is exceeded while traversing the value tree,
880 CSON_RC_RangeError is returned.
881
882 The destState parameter is ignored by this function and is passed
883 on to the dest function.
884
885 Returns 0 on success. On error, any amount of output might have been
@@ -816,11 +912,11 @@
912 @see cson_output_filename()
913 */
914 int cson_output_FILE( cson_value const * src, FILE * dest, cson_output_opt const * opt );
915 /**
916 Convenience wrapper around cson_output_FILE() which writes to the given filename, destroying
917 any existing contents. Returns CSON_RC_IOError if the file cannot be opened.
918
919 @see cson_output_FILE()
920 */
921 int cson_output_filename( cson_value const * src, char const * dest, cson_output_opt const * fmt );
922
@@ -947,11 +1043,11 @@
1043 The conversion, if any, depends on the concrete type of val:
1044
1045 NULL, null, undefined: *v is set to 0 and 0 is returned.
1046
1047 string, object, array: *v is set to 0 and
1048 CSON_RC_TypeError is returned. The error may normally be safely
1049 ignored, but it is provided for those wanted to know whether a direct
1050 conversion was possible.
1051
1052 integer: *v is set to the int value and 0 is returned.
1053
@@ -1178,19 +1274,19 @@
1274 changes its logical size, but may pre-allocate space in the
1275 array for storing new (as-yet-unassigned) values.
1276
1277 Returns 0 on success, or non-zero on error:
1278
1279 - If ar is NULL: CSON_RC_ArgError
1280
1281 - If allocation fails: CSON_RC_AllocError
1282 */
1283 int cson_array_reserve( cson_array * ar, unsigned int size );
1284
1285 /**
1286 If ar is not NULL, sets *v (if v is not NULL) to the length of the array
1287 and returns 0. Returns CSON_RC_ArgError if ar is NULL.
1288 */
1289 int cson_array_length_fetch( cson_array const * ar, unsigned int * v );
1290
1291 /**
1292 Simplified form of cson_array_length_fetch() which returns 0 if ar
@@ -1243,16 +1339,16 @@
1339 implementation has slightly different array-preallocation policy
1340 (it grows more eagerly).
1341
1342 Returns 0 on success, non-zero on error. Error cases include:
1343
1344 - ar or v are NULL: CSON_RC_ArgError
1345
1346 - Array cannot be expanded to hold enough elements: CSON_RC_AllocError.
1347
1348 - Appending would cause a numeric overlow in the array's size:
1349 CSON_RC_RangeError. (However, you'll get an AllocError long before
1350 that happens!)
1351
1352 On error ownership of v is NOT modified, and the caller may still
1353 need to clean it up. See cson_array_set() for the details.
1354
@@ -1449,13 +1545,13 @@
1545 show up later, e.g. during output.
1546
1547 Returns 0 on success, non-0 on error. It has the following error
1548 cases:
1549
1550 - CSON_RC_ArgError: obj or key are NULL or strlen(key) is 0.
1551
1552 - CSON_RC_AllocError: an out-of-memory error
1553
1554 On error ownership of v is NOT modified, and the caller may still
1555 need to clean it up. For example, the following code will introduce
1556 a leak if this function fails:
1557
@@ -1500,14 +1596,14 @@
1596
1597 /**
1598 Removes a property from an object.
1599
1600 If obj contains the given key, it is removed and 0 is returned. If
1601 it is not found, CSON_RC_NotFoundError is returned (which can
1602 normally be ignored by client code).
1603
1604 CSON_RC_ArgError is returned if obj or key are NULL or key has
1605 a length of 0.
1606
1607 Returns 0 if the given key is found and removed.
1608
1609 This is functionally equivalent calling
@@ -1563,27 +1659,27 @@
1659 path is a delimited string, where the delimiter is the given
1660 separator character.
1661
1662 This function searches for the given path, starting at the given object
1663 and traversing its properties as the path specifies. If a given part of the
1664 path is not found, then this function fails with CSON_RC_NotFoundError.
1665
1666 If it finds the given path, it returns the value by assiging *tgt
1667 to it. If tgt is NULL then this function has no side-effects but
1668 will return 0 if the given path is found within the object, so it can be used
1669 to test for existence without fetching it.
1670
1671 Returns 0 if it finds an entry, CSON_RC_NotFoundError if it finds
1672 no item, and any other non-zero error code on a "real" error. Errors include:
1673
1674 - obj or path are NULL: CSON_RC_ArgError
1675
1676 - separator is 0, or path is an empty string or contains only
1677 separator characters: CSON_RC_RangeError
1678
1679 - There is an upper limit on how long a single path component may
1680 be (some "reasonable" internal size), and CSON_RC_RangeError is
1681 returned if that length is violated.
1682
1683
1684 Limitations:
1685
@@ -1677,11 +1773,11 @@
1773 either replaced or left as-is, depending on whether flags contains
1774 he CSON_MERGE_REPLACE bit.
1775
1776 Returns 0 on success. The error conditions are:
1777
1778 - dest or src are NULL or (dest==src) returns CSON_RC_ArgError.
1779
1780 - dest or src contain cyclic references - this will likely cause a
1781 crash due to endless recursion.
1782
1783 Potential TODOs:
@@ -1724,11 +1820,11 @@
1820 */
1821 extern const cson_object_iterator cson_object_iterator_empty;
1822
1823 /**
1824 Initializes the given iterator to point at the start of obj's
1825 properties. Returns 0 on success or CSON_RC_ArgError if !obj
1826 or !iter.
1827
1828 obj must outlive iter, or results are undefined. Results are also
1829 undefined if obj is modified while the iterator is active.
1830
@@ -1891,13 +1987,13 @@
1987 to be NULL-terminated. On error the buffer might contain partial
1988 contents, and it should not be used except to free its contents.
1989
1990 On error non-zero is returned. Errors include:
1991
1992 - Invalid arguments: CSON_RC_ArgError
1993
1994 - Buffer cannot be expanded (runs out of memory): CSON_RC_AllocError
1995
1996 Example usage:
1997
1998 @code
1999 cson_buffer buf = cson_buffer_empty;
@@ -1999,13 +2095,13 @@
2095 On error non-0 is returned and dest has almost certainly been
2096 modified but its state must be considered incomplete.
2097
2098 Errors include:
2099
2100 - dest or src are NULL (CSON_RC_ArgError)
2101
2102 - Allocation error (CSON_RC_AllocError)
2103
2104 - src() returns an error code
2105
2106 Whether or not the state parameter may be NULL depends on
2107 the src implementation requirements.
@@ -2084,12 +2180,12 @@
2180 will not be if there are still other live references to
2181 it). cson_value_free() will not _actually_ destroy the value until
2182 its reference count drops to 0.
2183
2184 Returns 0 on success. The only error conditions are if v is NULL
2185 (CSON_RC_ArgError) or if the reference increment would overflow
2186 (CSON_RC_RangeError). In theory a client would get allocation
2187 errors long before the reference count could overflow (assuming
2188 those reference counts come from container insertions, as opposed
2189 to via this function).
2190
2191 Insider notes which clients really need to know:
@@ -2238,11 +2334,11 @@
2334 /**
2335 Calculates the approximate in-memory-allocated size of v,
2336 recursively if it is a container type, with the following caveats
2337 and limitations:
2338
2339 If a given value is reference counted and encountered multiple
2340 times within a traversed container, each reference is counted at
2341 full cost. We have no way of knowing if a given reference has been
2342 visited already and whether it should or should not be counted, so
2343 we pessimistically count them even though the _might_ not really
2344 count for the given object tree (it depends on where the other open
@@ -2318,10 +2414,169 @@
2414 it might contain partial results.
2415 */
2416 int cson_parse_argv_flags( int argc, char const * const * argv,
2417 cson_object ** tgt, unsigned int * count );
2418
2419 /**
2420 Return values for the cson_pack() and cson_unpack() interfaces.
2421 */
2422 enum cson_pack_retval {
2423 /** Signals an out-of-memory error. */
2424 CSON_PACK_ALLOC_ERROR = -1,
2425 /** Signals a syntax error in the format string. */
2426 CSON_PACK_ARG_ERROR = -2,
2427 /**
2428 Signals an that an internal error has occurred.
2429 This indicates a bug in this library.
2430 */
2431 CSON_PACK_INTERNAL_ERROR = -3,
2432 /**
2433 Signals that the JSON document does not validate agains the format
2434 string passed to cson_unpack().
2435 */
2436 CSON_PACK_VALIDATION_ERROR = -4
2437 };
2438
2439 /**
2440 Construct arbitrarily complex JSON documents from native C types.
2441
2442 Create a new object or array and add or merge the passed values and
2443 properties to it according to the supplied format string.
2444
2445 fmt is a format string, it must at least contain an array or object
2446 specifier as its root value. Format specifiers start with a percent sign '\%'
2447 followed by one or more modifiers and a type character. Object properties
2448 are specified as key-value pairs where the key is specified as a string and
2449 passed as an argument of const char *. Any space, tab, carriage return, line
2450 feed, colon and comma characters between format specifiers are ignored.
2451
2452 | Type | Description |
2453 | :--: | :---------- |
2454 | s | creates either a property name or a string value, in case of the former the corresponding argument is a pointer to const char which is a sequence of bytes specifying the name of the property that is to be created, in case of the latter the corresponding argument is a pointer to const char |
2455 | d | creates an integer value, the corresponding argument is an int |
2456 | i | ^ |
2457 | f | creates a floating point value, the corresponding argument is a double |
2458 | b | creates a boolean value, the corresponding argument is an int |
2459 | N | creates a null value |
2460 | [...] | creates an array, the corresponding argument is a pointer to a cson_array |
2461 | {...} | creates an array, the corresponding argument is a pointer to a cson_object |
2462
2463 | Modifier | Description |
2464 | :------: | :---------- |
2465 | l | specifies that the following d or i specifier applies to an argument which is a pointer to long |
2466 | ll | specifies that the following d or i specifier applies to an argument which is a pointer to cson_int_t |
2467
2468 | Short Form | Expands to
2469 | :--------: | :--------- |
2470 | {...} | %*{...} |
2471 | [...] | %*[...] |
2472 | \%D | \%lld |
2473
2474
2475 Returns 0 on success. The error conditions are:
2476
2477 - CSON_PACK_ARG_ERROR: fmt contains a syntax error
2478
2479 - CSON_PACK_ALLOC_ERROR: a memory allocation failed
2480
2481 - CSON_PACK_INTERNAL_ERROR: an internal error has occurred, this is a bug in
2482 cson
2483
2484 Example:
2485 @code
2486 cson_value * root_value;
2487 cson_array * arr;
2488 ...
2489 rc = cson_pack( root_value, "{%s: %d, %s: %[]}", "foo", 42, "bar", arr );
2490 if( 0 != rc ) {
2491 ... error ...
2492 }
2493 @endcode
2494 */
2495 int cson_pack( cson_value **root_valuep, const char *fmt, ... );
2496
2497 /**
2498 Same as cson_pack() except that it takes a va_list instead of a variable
2499 number of arguments.
2500 */
2501 int cson_vpack( cson_value **root_valuep, const char *fmt, va_list args );
2502
2503 /**
2504 Iterate over the given object or array and convert an arbitrary number of
2505 JSON values into their native C types or validates them according to the
2506 given format string fmt.
2507
2508 fmt is a format string, it must at least contain an array or object
2509 specifier as its root value. Format specifiers start with a percent sign '\%'
2510 followed by one or more modifiers and a type character. Object properties
2511 are specified as key-value pairs where the key is specified as a string and
2512 passed as an argument of const char *. Any space, tab, carriage return, line
2513 feed, colon and comma characters between format specifiers are ignored.
2514
2515 | Type | Description |
2516 | :--: | :---------- |
2517 | s | matches a either a property name or a string value, in case of the former the corresponding argument is a pointer to const char which is a sequence of bytes specifying the name of the property that is to be matched, in case of the latter the corresponding argument is a pointer to a pointer to const char unless the 'm' modifier is specified where the the corresponding argument is a pointer to a pointer to char |
2518 | d | matches an integer value and must be used in with the "ll" modifier, the corresponding argument is a pointer to cson_int_t |
2519 | i | ^ |
2520 | f | matches a floating point value, the corresponding argument is a pointer to double |
2521 | b | matches a boolean value, the corresponding argument is a pointer to int |
2522 | N | matches a null value |
2523 | [...] | matches an array, the corresponding argument is a pointer to a pointer to a cson_array |
2524 | {...} | matches an array, the corresponding argument is a pointer to a pointer to a cson_object |
2525
2526 | Modifier | Description |
2527 | :------: | :---------- |
2528 | ? | specifies that the property reffered to by the given property name is optional |
2529 | * | suppresses assignment, only check for the presence and type of the specified value |
2530 | m | allocates a memory buffer for the extracted string |
2531 | ll | specifies that the following d or i specifier applies to an argument which is a pointer to cson_int_t |
2532
2533 | Short Form | Expands to
2534 | :--------: | :--------- |
2535 | {...} | %*{...} |
2536 | [...] | %*[...] |
2537 | \%D | \%lld |
2538
2539 Returns 0 on success. The error conditions are:
2540
2541 - CSON_PACK_ARG_ERROR: fmt contains a syntax error
2542
2543 - CSON_PACK_ALLOC_ERROR: a memory allocation failed
2544
2545 - CSON_PACK_VALIDATION_ERROR: validation failed, the JSON document structure
2546 differs from that described by the format string
2547
2548 - CSON_PACK_INTERNAL_ERROR: an internal error has occurred, this
2549 indicates a bug in this library.
2550
2551 Example:
2552 @code
2553 cson_value * root_value;
2554 cson_int_t x = 0;
2555 cson_array * arr = NULL;
2556 const char *str = NULL;
2557 ...
2558 rc = cson_unpack( root_value, "{%s: %d, %s: %[], %?s: %s}", "foo", &x, "bar", &arr, "baz", &str );
2559 if( rc < 3 && rc >= 0 ) {
2560 ... optional property is missing ...
2561 } else if ( CSON_PACK_ALLOC_ERROR == rc ) {
2562 ... out of memory error ...
2563 } else if ( CSON_PACK_VALIDATION_ERROR == rc ) {
2564 ... unexpected JSON document structure ...
2565 } else if ( rc ) {
2566 ... internal error ...
2567 }
2568 @endcode
2569
2570 */
2571 int cson_unpack( cson_value *root_value, const char *fmt, ... );
2572
2573 /**
2574 Same as cson_unpack() except that it takes a va_list instead of a variable
2575 number of arguments.
2576 */
2577 int cson_vunpack( cson_value *root_value, const char *fmt, va_list args );
2578
2579 /* LICENSE
2580
2581 This software's source code, including accompanying documentation and
2582 demonstration applications, are licensed under the following
2583
+2 -2
--- src/json.c
+++ src/json.c
@@ -221,14 +221,14 @@
221221
** when constructing the JSON response envelope, so the static buffer
222222
** "shouldn't" be a problem.
223223
**
224224
*/
225225
char const * json_rc_cstr( int code ){
226
- enum { BufSize = 12 };
226
+ enum { BufSize = 13 };
227227
static char buf[BufSize] = {'F','O','S','S','I','L','-',0};
228228
assert((code >= 1000) && (code <= 9999) && "Invalid Fossil/JSON code.");
229
- sprintf(buf+7,"%04d", code);
229
+ sqlite3_snprintf((int)BufSize, buf+7,"%04d", code);
230230
return buf;
231231
}
232232
233233
/*
234234
** Adds v to the API-internal cleanup mechanism. key is ignored
235235
--- src/json.c
+++ src/json.c
@@ -221,14 +221,14 @@
221 ** when constructing the JSON response envelope, so the static buffer
222 ** "shouldn't" be a problem.
223 **
224 */
225 char const * json_rc_cstr( int code ){
226 enum { BufSize = 12 };
227 static char buf[BufSize] = {'F','O','S','S','I','L','-',0};
228 assert((code >= 1000) && (code <= 9999) && "Invalid Fossil/JSON code.");
229 sprintf(buf+7,"%04d", code);
230 return buf;
231 }
232
233 /*
234 ** Adds v to the API-internal cleanup mechanism. key is ignored
235
--- src/json.c
+++ src/json.c
@@ -221,14 +221,14 @@
221 ** when constructing the JSON response envelope, so the static buffer
222 ** "shouldn't" be a problem.
223 **
224 */
225 char const * json_rc_cstr( int code ){
226 enum { BufSize = 13 };
227 static char buf[BufSize] = {'F','O','S','S','I','L','-',0};
228 assert((code >= 1000) && (code <= 9999) && "Invalid Fossil/JSON code.");
229 sqlite3_snprintf((int)BufSize, buf+7,"%04d", code);
230 return buf;
231 }
232
233 /*
234 ** Adds v to the API-internal cleanup mechanism. key is ignored
235
--- src/json_login.c
+++ src/json_login.c
@@ -105,11 +105,12 @@
105105
jseed = json_getenv("cs") /* name used by HTML interface */;
106106
}
107107
}
108108
if(jseed){
109109
if( cson_value_is_number(jseed) ){
110
- sprintf(seedBuffer, "%"CSON_INT_T_PFMT, cson_value_get_integer(jseed));
110
+ sqlite3_snprintf((int)SeedBufLen, seedBuffer, "%"CSON_INT_T_PFMT,
111
+ cson_value_get_integer(jseed));
111112
anonSeed = seedBuffer;
112113
}else if( cson_value_is_string(jseed) ){
113114
anonSeed = cson_string_cstr(cson_value_get_string(jseed));
114115
}
115116
}
116117
--- src/json_login.c
+++ src/json_login.c
@@ -105,11 +105,12 @@
105 jseed = json_getenv("cs") /* name used by HTML interface */;
106 }
107 }
108 if(jseed){
109 if( cson_value_is_number(jseed) ){
110 sprintf(seedBuffer, "%"CSON_INT_T_PFMT, cson_value_get_integer(jseed));
 
111 anonSeed = seedBuffer;
112 }else if( cson_value_is_string(jseed) ){
113 anonSeed = cson_string_cstr(cson_value_get_string(jseed));
114 }
115 }
116
--- src/json_login.c
+++ src/json_login.c
@@ -105,11 +105,12 @@
105 jseed = json_getenv("cs") /* name used by HTML interface */;
106 }
107 }
108 if(jseed){
109 if( cson_value_is_number(jseed) ){
110 sqlite3_snprintf((int)SeedBufLen, seedBuffer, "%"CSON_INT_T_PFMT,
111 cson_value_get_integer(jseed));
112 anonSeed = seedBuffer;
113 }else if( cson_value_is_string(jseed) ){
114 anonSeed = cson_string_cstr(cson_value_get_string(jseed));
115 }
116 }
117

Keyboard Shortcuts

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