Fossil SCM

Another round of cson memory optimizations. Object keys can now be cson_strings, which can be refcounted/shared.

stephan 2011-10-07 10:20 json-multitag-test
Commit 3d252e87548f99713d93203d3ae00412497596a5
--- src/cson_amalgamation.c
+++ src/cson_amalgamation.c
@@ -1873,41 +1873,10 @@
18731873
return 0;
18741874
}
18751875
else return cv->refcount;
18761876
}
18771877
1878
-/**
1879
- Allocates a new cson_string object with enough space for
1880
- the given number of bytes. A byte for a NUL terminator
1881
- is added automatically. Use cson_string_str() to get
1882
- access to the string bytes, which will be len bytes long.
1883
-
1884
- len may be 0, in which case the internal string is "", as opposed
1885
- to null. This is because the string bytes and the cson_string are
1886
- allocated in a single chunk of memory, and the cson_string object
1887
- does not directly provide (or have) a pointer to the string bytes.
1888
-*/
1889
-static cson_string * cson_string_alloc(unsigned int len)
1890
-{
1891
- if( ! len ) return CSON_STR(&CSON_SPECIAL_VALUES[CSON_VAL_STR_EMPTY]);
1892
- else
1893
- {
1894
- cson_string * s = NULL;
1895
- const size_t msz = sizeof(cson_string) + len + 1 /*NUL*/;
1896
- unsigned char * mem = NULL;
1897
- if( msz < (sizeof(cson_string)+len) ) /*overflow*/ return NULL;
1898
- mem = (unsigned char *)cson_malloc( msz, "cson_string_alloc" );
1899
- if( mem )
1900
- {
1901
- memset( mem, 0, msz );
1902
- s = (cson_string *)mem;
1903
- s->length = len;
1904
- }
1905
- return s;
1906
- }
1907
-}
1908
-
19091878
unsigned int cson_string_length_bytes( cson_string const * str )
19101879
{
19111880
return str ? str->length : 0;
19121881
}
19131882
@@ -1974,33 +1943,10 @@
19741943
memset( rc, 0, n+1 );
19751944
rc[n] = 0;
19761945
return strncpy( rc, src, n );
19771946
}
19781947
#endif
1979
-
1980
-/**
1981
- Allocates a new cson_string() from the the first n bytes of src.
1982
- Returns NULL on allocation error, else the caller owns the returned
1983
- object and must eventually free() it.
1984
-*/
1985
-static cson_string * cson_string_strdup( char const * src, size_t n )
1986
-{
1987
- cson_string * cs = cson_string_alloc(n);
1988
- if( ! cs ) return NULL;
1989
- else if( &CSON_EMPTY_HOLDER.stringValue == cs ) return cs;
1990
- else
1991
- {
1992
- char * cstr = cson_string_str(cs);
1993
- assert( cs->length == n );
1994
- if( cstr && n )
1995
- {
1996
- strncpy( cstr, src, n );
1997
- }
1998
- return cs;
1999
- }
2000
-}
2001
-
20021948
20031949
int cson_string_cmp_cstr_n( cson_string const * str, char const * other, unsigned int otherLen )
20041950
{
20051951
if( ! other && !str ) return 0;
20061952
else if( other && !str ) return 1;
@@ -2045,14 +1991,11 @@
20451991
Each of these objects owns its key/value pointers, and they
20461992
are cleaned up by cson_kvp_clean().
20471993
*/
20481994
struct cson_kvp
20491995
{
2050
- /* FIXME: switch to cson_value keys. Calling cson_string_value()
2051
- on one of these guys will read invalid memory.
2052
- */
2053
- cson_string * key;
1996
+ cson_value * key;
20541997
cson_value * value;
20551998
};
20561999
#define cson_kvp_empty_m {NULL,NULL}
20572000
static const cson_kvp cson_kvp_empty = cson_kvp_empty_m;
20582001
@@ -2087,45 +2030,21 @@
20872030
*/
20882031
#define CSON_OBJECT_PROPS_SORT_USE_LENGTH 0
20892032
20902033
#if CSON_OBJECT_PROPS_SORT
20912034
2092
-#if 0
2093
-/* i would prefer case-insensitive sorting but keys need
2094
- to be case-sensitive for search purposes.
2095
-
2096
- TODO? write a comparitor which reverses the default
2097
- sort order of upper/lower-case. The current behaviour
2098
- is a bit non-intuitive, where 'Z' < 'a'.
2099
-*/
2100
-static int cson_kvp_strcmp( char const * l, char const * r )
2101
-{
2102
- char cl;
2103
- char cr;
2104
- for( ; *l && *r; ++l, ++r )
2105
- {
2106
- cl = tolower(*l);
2107
- cr = tolower(*r);
2108
- if( cl < cr ) return -1;
2109
- else if( cl > cr ) return 1;
2110
- }
2111
- if( !*l && !*r ) return 0;
2112
- else return (*l) ? 1 : -1;
2113
-}
2114
-#endif
2115
-
21162035
/**
21172036
cson_kvp comparator for use with qsort(). ALMOST compares with
21182037
strcmp() semantics, but it uses the strings' lengths as a quicker
21192038
approach. This might give non-intuitive results, but it's faster.
21202039
*/
21212040
static int cson_kvp_cmp( void const * lhs, void const * rhs )
21222041
{
21232042
cson_kvp const * lk = *((cson_kvp const * const*)lhs);
21242043
cson_kvp const * rk = *((cson_kvp const * const*)rhs);
2125
- cson_string const * l = lk->key;
2126
- cson_string const * r = rk->key;
2044
+ cson_string const * l = cson_string_value(lk->key);
2045
+ cson_string const * r = cson_string_value(rk->key);
21272046
#if CSON_OBJECT_PROPS_SORT_USE_LENGTH
21282047
if( l->length < r->length ) return -1;
21292048
else if( l->length > r->length ) return 1;
21302049
else return strcmp( cson_string_cstr( l ), cson_string_cstr( r ) );
21312050
#else
@@ -2135,10 +2054,11 @@
21352054
}
21362055
#endif /*CSON_OBJECT_PROPS_SORT*/
21372056
21382057
21392058
#if CSON_OBJECT_PROPS_SORT
2059
+#error "Need to rework this for cson_string-to-cson_value refactoring"
21402060
/**
21412061
A bsearch() comparison function which requires that lhs be a (char
21422062
const *) and rhs be-a (cson_kvp const * const *). It compares lhs
21432063
to rhs->key's value, using strcmp() semantics.
21442064
*/
@@ -2450,11 +2370,11 @@
24502370
{
24512371
if( kvp )
24522372
{
24532373
if(kvp->key)
24542374
{
2455
- cson_free(kvp->key,"cson_kvp::key");
2375
+ cson_value_free(kvp->key);
24562376
kvp->key = NULL;
24572377
}
24582378
if(kvp->value)
24592379
{
24602380
cson_value_free( kvp->value );
@@ -2463,11 +2383,11 @@
24632383
}
24642384
}
24652385
24662386
cson_string const * cson_kvp_key( cson_kvp const * kvp )
24672387
{
2468
- return kvp ? kvp->key : NULL;
2388
+ return kvp ? cson_value_get_string(kvp->key) : NULL;
24692389
}
24702390
cson_value * cson_kvp_value( cson_kvp const * kvp )
24712391
{
24722392
return kvp ? kvp->value : NULL;
24732393
}
@@ -2554,33 +2474,10 @@
25542474
cson_array_clean( ar, 1 );
25552475
*self = cson_value_undef;
25562476
}
25572477
}
25582478
2559
-
2560
-#if 0
2561
-static void cson_kvp_list_item_clean( void * kvp );
2562
-static void cson_value_list_item_clean( void * val );
2563
-void cson_value_list_item_clean( void * val_ )
2564
-{
2565
- cson_value * val = (cson_value*)val_;
2566
- if( val )
2567
- {
2568
- cson_value_clean(val);
2569
- }
2570
-}
2571
-void cson_kvp_list_item_clean( void * val )
2572
-{
2573
- cson_kvp * kvp = (cson_kvp *)val;
2574
- if( kvp )
2575
- {
2576
- cson_free(kvp->key,"cson_kvp::key");
2577
- cson_value_clean( &kvp->value );
2578
- }
2579
-}
2580
-#endif
2581
-
25822479
int cson_buffer_fill_from( cson_buffer * dest, cson_data_source_f src, void * state )
25832480
{
25842481
int rc;
25852482
enum { BufSize = 1024 * 4 };
25862483
char rbuf[BufSize];
@@ -2926,10 +2823,15 @@
29262823
29272824
cson_value * cson_value_null()
29282825
{
29292826
return &CSON_SPECIAL_VALUES[CSON_VAL_NULL];
29302827
}
2828
+
2829
+cson_value * cson_new_int( cson_int_t v )
2830
+{
2831
+ return cson_value_new_integer(v);
2832
+}
29312833
29322834
cson_value * cson_value_new_integer( cson_int_t v )
29332835
{
29342836
if( 0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_INT_0];
29352837
else
@@ -2941,10 +2843,15 @@
29412843
*CSON_INT(c) = v;
29422844
}
29432845
return c;
29442846
}
29452847
}
2848
+
2849
+cson_value * cson_new_double( cson_double_t v )
2850
+{
2851
+ return cson_value_new_double(v);
2852
+}
29462853
29472854
cson_value * cson_value_new_double( cson_double_t v )
29482855
{
29492856
if( 0.0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_DBL_0];
29502857
else
@@ -2956,11 +2863,11 @@
29562863
}
29572864
return c;
29582865
}
29592866
}
29602867
2961
-cson_string const * cson_new_string(char const * str, unsigned int len)
2868
+cson_string * cson_new_string(char const * str, unsigned int len)
29622869
{
29632870
if( !str || !*str || !len ) return &CSON_EMPTY_HOLDER.stringValue;
29642871
else
29652872
{
29662873
cson_value * c = cson_value_new(CSON_TYPE_STRING, len + 1/*NUL byte*/);
@@ -3100,14 +3007,17 @@
31003007
unsigned int i = 0;
31013008
cson_kvp * kvp;
31023009
const unsigned int klen = strlen(key);
31033010
for( ; i < li->count; ++i )
31043011
{
3012
+ cson_string const * sKey;
31053013
kvp = li->list[i];
31063014
assert( kvp && kvp->key );
3107
- if( kvp->key->length != klen ) continue;
3108
- else if(0==strcmp(key,cson_string_cstr(kvp->key)))
3015
+ sKey = cson_value_get_string(kvp->key);
3016
+ assert(sKey);
3017
+ if( sKey->length != klen ) continue;
3018
+ else if(0==strcmp(key,cson_string_cstr(sKey)))
31093019
{
31103020
if(ndx) *ndx = i;
31113021
return kvp;
31123022
}
31133023
}
@@ -3166,67 +3076,91 @@
31663076
#endif
31673077
return 0;
31683078
}
31693079
}
31703080
3081
+int cson_object_set_s( cson_object * obj, cson_string * key, cson_value * v )
3082
+{
3083
+ if( !obj || !key ) return cson_rc.ArgError;
3084
+ else if( NULL == v ) return cson_object_unset( obj, cson_string_cstr(key) );
3085
+ else
3086
+ {
3087
+ char const * cKey;
3088
+ cson_value * vKey;
3089
+ cson_kvp * kvp;
3090
+ vKey = cson_string_value(key);
3091
+ assert(vKey && (key==CSON_STR(vKey)));
3092
+ if( vKey == CSON_VCAST(obj) ){
3093
+ return cson_rc.ArgError;
3094
+ }
3095
+ cKey = cson_string_cstr(key);
3096
+ kvp = cson_object_search_impl( obj, cKey, NULL );
3097
+ if( kvp )
3098
+ { /* "I told 'em we've already got one!" */
3099
+ if( kvp->key != vKey ){
3100
+ cson_value_free( kvp->key );
3101
+ cson_refcount_incr(vKey);
3102
+ kvp->key = vKey;
3103
+ }
3104
+ if(kvp->value != v){
3105
+ cson_value_free( kvp->value );
3106
+ cson_refcount_incr( v );
3107
+ kvp->value = v;
3108
+ }
3109
+ return 0;
3110
+ }
3111
+ if( !obj->kvp.alloced || (obj->kvp.count == obj->kvp.alloced-1))
3112
+ {
3113
+ unsigned int const n = obj->kvp.count ? (obj->kvp.count*2) : 6;
3114
+ if( n > cson_kvp_list_reserve( &obj->kvp, n ) )
3115
+ {
3116
+ return cson_rc.AllocError;
3117
+ }
3118
+ }
3119
+ { /* insert new item... */
3120
+ int rc = 0;
3121
+ kvp = cson_kvp_alloc();
3122
+ if( ! kvp )
3123
+ {
3124
+ return cson_rc.AllocError;
3125
+ }
3126
+ rc = cson_kvp_list_append( &obj->kvp, kvp );
3127
+ if( 0 != rc )
3128
+ {
3129
+ cson_kvp_free(kvp);
3130
+ }
3131
+ else
3132
+ {
3133
+ cson_refcount_incr(vKey);
3134
+ cson_refcount_incr(v);
3135
+ kvp->key = vKey;
3136
+ kvp->value = v;
3137
+#if CSON_OBJECT_PROPS_SORT
3138
+ cson_object_sort_props( obj );
3139
+#endif
3140
+ }
3141
+ return rc;
3142
+ }
3143
+ }
3144
+
3145
+}
31713146
int cson_object_set( cson_object * obj, char const * key, cson_value * v )
31723147
{
31733148
if( ! obj || !key || !*key ) return cson_rc.ArgError;
31743149
else if( NULL == v )
31753150
{
31763151
return cson_object_unset( obj, key );
31773152
}
31783153
else
31793154
{
3180
- cson_kvp * kvp = cson_object_search_impl( obj, key, NULL );
3181
- if( kvp )
3182
- { /* "I told 'em we've already got one!" */
3183
- if( v == kvp->value ) return 0 /* actually a usage error */;
3184
- else
3185
- {
3186
- cson_value_free( kvp->value );
3187
- cson_refcount_incr( v );
3188
- kvp->value = v;
3189
- return 0;
3190
- }
3191
- }
3192
- if( !obj->kvp.alloced || (obj->kvp.count == obj->kvp.alloced-1))
3193
- {
3194
- unsigned int const n = obj->kvp.count ? (obj->kvp.count*2) : 7;
3195
- if( n > cson_kvp_list_reserve( &obj->kvp, n ) )
3196
- {
3197
- return cson_rc.AllocError;
3198
- }
3199
- }
3200
- { /* insert new item... */
3201
- int rc = 0;
3202
- cson_string * keycp = cson_string_strdup(key, strlen(key));
3203
- if( ! keycp )
3204
- {
3205
- return cson_rc.AllocError;
3206
- }
3207
- kvp = cson_kvp_alloc();
3208
- if( ! kvp )
3209
- {
3210
- cson_free(keycp,"cson_parser::key");
3211
- return cson_rc.AllocError;
3212
- }
3213
- kvp->key = keycp /* transfer ownership */;
3214
- rc = cson_kvp_list_append( &obj->kvp, kvp );
3215
- if( 0 != rc )
3216
- {
3217
- cson_kvp_free(kvp);
3218
- }
3219
- else
3220
- {
3221
- cson_refcount_incr( v );
3222
- kvp->value = v /* transfer ownership */;
3223
-#if CSON_OBJECT_PROPS_SORT
3224
- cson_object_sort_props( obj );
3225
-#endif
3226
- }
3227
- return 0;
3155
+ cson_string * cs = cson_new_string(key,strlen(key));
3156
+ if(!cs) return cson_rc.AllocError;
3157
+ else
3158
+ {
3159
+ int const rc = cson_object_set_s(obj, cs, v);
3160
+ if(rc) cson_value_free(cson_string_value(cs));
3161
+ return rc;
32283162
}
32293163
}
32303164
}
32313165
32323166
cson_value * cson_object_take( cson_object * obj, char const * key )
@@ -3311,11 +3245,11 @@
33113245
if( ! kvp )
33123246
{
33133247
cson_value_free(val);
33143248
return cson_rc.AllocError;
33153249
}
3316
- kvp->key = p->ckey/*transfer ownership*/;
3250
+ kvp->key = cson_string_value(p->ckey)/*transfer ownership*/;
33173251
p->ckey = NULL;
33183252
kvp->value = val;
33193253
cson_refcount_incr( val );
33203254
rc = cson_kvp_list_append( &obj->kvp, kvp );
33213255
if( 0 != rc )
@@ -3507,11 +3441,11 @@
35073441
rc = cson_parser_push_value( p, cson_value_false() );
35083442
break;
35093443
}
35103444
case JSON_T_KEY: {
35113445
assert(!p->ckey);
3512
- p->ckey = cson_string_strdup( value->vu.str.value, value->vu.str.length );
3446
+ p->ckey = cson_new_string( value->vu.str.value, value->vu.str.length );
35133447
if( ! p->ckey )
35143448
{
35153449
rc = cson_rc.AllocError;
35163450
break;
35173451
}
@@ -3580,11 +3514,13 @@
35803514
if( p->p )
35813515
{
35823516
delete_JSON_parser(p->p);
35833517
p->p = NULL;
35843518
}
3585
- cson_free( p->ckey, "cson_parser::key" );
3519
+ if( p->ckey ){
3520
+ cson_value_free(cson_string_value(p->ckey));
3521
+ }
35863522
cson_array_clean( &p->stack, 1 );
35873523
if( p->root )
35883524
{
35893525
cson_value_free( p->root );
35903526
}
@@ -4192,11 +4128,13 @@
41924128
for( i = 0; (i < obj->kvp.count) && (0 == rc); ++i )
41934129
{
41944130
kvp = obj->kvp.list[i];
41954131
if( kvp && kvp->key )
41964132
{
4197
- rc = cson_str_to_json(cson_string_cstr(kvp->key), kvp->key->length,
4133
+ cson_string const * sKey = cson_value_get_string(kvp->key);
4134
+ char const * cKey = cson_string_cstr(sKey);
4135
+ rc = cson_str_to_json(cKey, sKey->length,
41984136
fmt->escapeForwardSlashes, f, state);
41994137
if( 0 == rc )
42004138
{
42014139
rc = fmt->addSpaceAfterColon
42024140
? f(state, ": ", 2 )
@@ -4638,26 +4576,42 @@
46384576
cson_kvp const * kvp = NULL;
46394577
cson_object_iterator iter = cson_object_iterator_empty;
46404578
assert( orig && src );
46414579
if( 0 != cson_object_iter_init( src, &iter ) )
46424580
{
4643
- cson_value_free( destV );
46444581
return NULL;
46454582
}
46464583
destV = cson_value_new_object();
46474584
if( NULL == destV ) return NULL;
46484585
dest = cson_value_get_object( destV );
46494586
assert( dest );
4587
+ if( src->kvp.count > cson_kvp_list_reserve( &dest->kvp, src->kvp.count ) ){
4588
+ cson_value_free( destV );
4589
+ return NULL;
4590
+ }
46504591
while( (kvp = cson_object_iter_next( &iter )) )
46514592
{
4652
- cson_string const * key = cson_kvp_key( kvp );
4653
- cson_value const * val = cson_kvp_value( kvp );
4654
- if( 0 != cson_object_set( dest,
4655
- cson_string_cstr( key ),
4656
- cson_value_clone( val ) ) )
4593
+ /*
4594
+ FIXME: refcount the keys! We first need a setter which takes
4595
+ a cson_string or cson_value key type.
4596
+ */
4597
+ cson_value * key = NULL;
4598
+ cson_value * val = NULL;
4599
+ key = cson_value_clone(kvp->key);
4600
+ val = key ? cson_value_clone( kvp->value ) : NULL;
4601
+ if( ! key || !val ){
4602
+ cson_value_free(key);
4603
+ cson_value_free(val);
4604
+ cson_value_free(destV);
4605
+ return NULL;
4606
+ }
4607
+ assert( CSON_STR(key) );
4608
+ if( 0 != cson_object_set_s( dest, CSON_STR(key), val ) )
46574609
{
4658
- cson_value_free( destV );
4610
+ cson_value_free(key);
4611
+ cson_value_free(val);
4612
+ cson_value_free(destV);
46594613
return NULL;
46604614
}
46614615
}
46624616
return destV;
46634617
}
@@ -4719,10 +4673,27 @@
47194673
return s
47204674
? CSON_VCAST(s)
47214675
: NULL;
47224676
}
47234677
4678
+void cson_free_object(cson_object *x)
4679
+{
4680
+ if(x) cson_value_free(cson_object_value(x));
4681
+}
4682
+void cson_free_array(cson_array *x)
4683
+{
4684
+ if(x) cson_value_free(cson_array_value(x));
4685
+}
4686
+
4687
+void cson_free_string(cson_string const *x)
4688
+{
4689
+ if(x) cson_value_free(cson_string_value(x));
4690
+}
4691
+void cson_free_value(cson_value *x)
4692
+{
4693
+ cson_value_free(x);
4694
+}
47244695
47254696
47264697
#if 0
47274698
/* i'm not happy with this... */
47284699
char * cson_pod_to_string( cson_value const * orig )
@@ -4826,10 +4797,74 @@
48264797
}
48274798
return v;
48284799
}
48294800
}
48304801
#endif
4802
+
4803
+unsigned int cson_value_msize(cson_value const * v)
4804
+{
4805
+ if(!v) return 0;
4806
+ else if( cson_value_is_builtin(v) ) return 0;
4807
+ else {
4808
+ unsigned int rc = sizeof(cson_value);
4809
+ assert(NULL != v->api);
4810
+ switch(v->api->typeID){
4811
+ case CSON_TYPE_INTEGER:
4812
+ assert( v != &CSON_SPECIAL_VALUES[CSON_VAL_INT_0]);
4813
+ rc += sizeof(cson_int_t);
4814
+ break;
4815
+ case CSON_TYPE_DOUBLE:
4816
+ assert( v != &CSON_SPECIAL_VALUES[CSON_VAL_DBL_0]);
4817
+ rc += sizeof(cson_double_t);
4818
+ break;
4819
+ case CSON_TYPE_STRING:
4820
+ rc += sizeof(cson_string)
4821
+ + CSON_STR(v)->length + 1/*NUL*/;
4822
+ break;
4823
+ case CSON_TYPE_ARRAY:{
4824
+ cson_array const * ar = CSON_ARRAY(v);
4825
+ cson_value_list const * li;
4826
+ unsigned int i = 0;
4827
+ assert( NULL != ar );
4828
+ li = &ar->list;
4829
+ rc += sizeof(cson_array)
4830
+ + (li->alloced * sizeof(cson_value *));
4831
+ for( ; i < li->count; ++i ){
4832
+ cson_value const * e = ar->list.list[i];
4833
+ if( e ) rc += cson_value_msize( e );
4834
+ }
4835
+ break;
4836
+ }
4837
+ case CSON_TYPE_OBJECT:{
4838
+ cson_object const * obj = CSON_OBJ(v);
4839
+ unsigned int i = 0;
4840
+ cson_kvp_list const * kl;
4841
+ assert(NULL != obj);
4842
+ kl = &obj->kvp;
4843
+ rc += sizeof(cson_object)
4844
+ + (kl->alloced * sizeof(cson_kvp*));
4845
+ for( ; i < kl->count; ++i ){
4846
+ cson_kvp const * kvp = kl->list[i];
4847
+ assert(NULL != kvp);
4848
+ rc += cson_value_msize(kvp->key);
4849
+ rc += cson_value_msize(kvp->value);
4850
+ }
4851
+ break;
4852
+ }
4853
+ case CSON_TYPE_UNDEF:
4854
+ case CSON_TYPE_NULL:
4855
+ case CSON_TYPE_BOOL:
4856
+ assert( 0 && "Should have been caught by is-builtin check!" );
4857
+ break;
4858
+ default:
4859
+ assert(0 && "Invalid typeID!");
4860
+ return 0;
4861
+
4862
+ }
4863
+ return rc;
4864
+ }
4865
+}
48314866
48324867
#if defined(__cplusplus)
48334868
} /*extern "C"*/
48344869
#endif
48354870
48364871
--- src/cson_amalgamation.c
+++ src/cson_amalgamation.c
@@ -1873,41 +1873,10 @@
1873 return 0;
1874 }
1875 else return cv->refcount;
1876 }
1877
1878 /**
1879 Allocates a new cson_string object with enough space for
1880 the given number of bytes. A byte for a NUL terminator
1881 is added automatically. Use cson_string_str() to get
1882 access to the string bytes, which will be len bytes long.
1883
1884 len may be 0, in which case the internal string is "", as opposed
1885 to null. This is because the string bytes and the cson_string are
1886 allocated in a single chunk of memory, and the cson_string object
1887 does not directly provide (or have) a pointer to the string bytes.
1888 */
1889 static cson_string * cson_string_alloc(unsigned int len)
1890 {
1891 if( ! len ) return CSON_STR(&CSON_SPECIAL_VALUES[CSON_VAL_STR_EMPTY]);
1892 else
1893 {
1894 cson_string * s = NULL;
1895 const size_t msz = sizeof(cson_string) + len + 1 /*NUL*/;
1896 unsigned char * mem = NULL;
1897 if( msz < (sizeof(cson_string)+len) ) /*overflow*/ return NULL;
1898 mem = (unsigned char *)cson_malloc( msz, "cson_string_alloc" );
1899 if( mem )
1900 {
1901 memset( mem, 0, msz );
1902 s = (cson_string *)mem;
1903 s->length = len;
1904 }
1905 return s;
1906 }
1907 }
1908
1909 unsigned int cson_string_length_bytes( cson_string const * str )
1910 {
1911 return str ? str->length : 0;
1912 }
1913
@@ -1974,33 +1943,10 @@
1974 memset( rc, 0, n+1 );
1975 rc[n] = 0;
1976 return strncpy( rc, src, n );
1977 }
1978 #endif
1979
1980 /**
1981 Allocates a new cson_string() from the the first n bytes of src.
1982 Returns NULL on allocation error, else the caller owns the returned
1983 object and must eventually free() it.
1984 */
1985 static cson_string * cson_string_strdup( char const * src, size_t n )
1986 {
1987 cson_string * cs = cson_string_alloc(n);
1988 if( ! cs ) return NULL;
1989 else if( &CSON_EMPTY_HOLDER.stringValue == cs ) return cs;
1990 else
1991 {
1992 char * cstr = cson_string_str(cs);
1993 assert( cs->length == n );
1994 if( cstr && n )
1995 {
1996 strncpy( cstr, src, n );
1997 }
1998 return cs;
1999 }
2000 }
2001
2002
2003 int cson_string_cmp_cstr_n( cson_string const * str, char const * other, unsigned int otherLen )
2004 {
2005 if( ! other && !str ) return 0;
2006 else if( other && !str ) return 1;
@@ -2045,14 +1991,11 @@
2045 Each of these objects owns its key/value pointers, and they
2046 are cleaned up by cson_kvp_clean().
2047 */
2048 struct cson_kvp
2049 {
2050 /* FIXME: switch to cson_value keys. Calling cson_string_value()
2051 on one of these guys will read invalid memory.
2052 */
2053 cson_string * key;
2054 cson_value * value;
2055 };
2056 #define cson_kvp_empty_m {NULL,NULL}
2057 static const cson_kvp cson_kvp_empty = cson_kvp_empty_m;
2058
@@ -2087,45 +2030,21 @@
2087 */
2088 #define CSON_OBJECT_PROPS_SORT_USE_LENGTH 0
2089
2090 #if CSON_OBJECT_PROPS_SORT
2091
2092 #if 0
2093 /* i would prefer case-insensitive sorting but keys need
2094 to be case-sensitive for search purposes.
2095
2096 TODO? write a comparitor which reverses the default
2097 sort order of upper/lower-case. The current behaviour
2098 is a bit non-intuitive, where 'Z' < 'a'.
2099 */
2100 static int cson_kvp_strcmp( char const * l, char const * r )
2101 {
2102 char cl;
2103 char cr;
2104 for( ; *l && *r; ++l, ++r )
2105 {
2106 cl = tolower(*l);
2107 cr = tolower(*r);
2108 if( cl < cr ) return -1;
2109 else if( cl > cr ) return 1;
2110 }
2111 if( !*l && !*r ) return 0;
2112 else return (*l) ? 1 : -1;
2113 }
2114 #endif
2115
2116 /**
2117 cson_kvp comparator for use with qsort(). ALMOST compares with
2118 strcmp() semantics, but it uses the strings' lengths as a quicker
2119 approach. This might give non-intuitive results, but it's faster.
2120 */
2121 static int cson_kvp_cmp( void const * lhs, void const * rhs )
2122 {
2123 cson_kvp const * lk = *((cson_kvp const * const*)lhs);
2124 cson_kvp const * rk = *((cson_kvp const * const*)rhs);
2125 cson_string const * l = lk->key;
2126 cson_string const * r = rk->key;
2127 #if CSON_OBJECT_PROPS_SORT_USE_LENGTH
2128 if( l->length < r->length ) return -1;
2129 else if( l->length > r->length ) return 1;
2130 else return strcmp( cson_string_cstr( l ), cson_string_cstr( r ) );
2131 #else
@@ -2135,10 +2054,11 @@
2135 }
2136 #endif /*CSON_OBJECT_PROPS_SORT*/
2137
2138
2139 #if CSON_OBJECT_PROPS_SORT
 
2140 /**
2141 A bsearch() comparison function which requires that lhs be a (char
2142 const *) and rhs be-a (cson_kvp const * const *). It compares lhs
2143 to rhs->key's value, using strcmp() semantics.
2144 */
@@ -2450,11 +2370,11 @@
2450 {
2451 if( kvp )
2452 {
2453 if(kvp->key)
2454 {
2455 cson_free(kvp->key,"cson_kvp::key");
2456 kvp->key = NULL;
2457 }
2458 if(kvp->value)
2459 {
2460 cson_value_free( kvp->value );
@@ -2463,11 +2383,11 @@
2463 }
2464 }
2465
2466 cson_string const * cson_kvp_key( cson_kvp const * kvp )
2467 {
2468 return kvp ? kvp->key : NULL;
2469 }
2470 cson_value * cson_kvp_value( cson_kvp const * kvp )
2471 {
2472 return kvp ? kvp->value : NULL;
2473 }
@@ -2554,33 +2474,10 @@
2554 cson_array_clean( ar, 1 );
2555 *self = cson_value_undef;
2556 }
2557 }
2558
2559
2560 #if 0
2561 static void cson_kvp_list_item_clean( void * kvp );
2562 static void cson_value_list_item_clean( void * val );
2563 void cson_value_list_item_clean( void * val_ )
2564 {
2565 cson_value * val = (cson_value*)val_;
2566 if( val )
2567 {
2568 cson_value_clean(val);
2569 }
2570 }
2571 void cson_kvp_list_item_clean( void * val )
2572 {
2573 cson_kvp * kvp = (cson_kvp *)val;
2574 if( kvp )
2575 {
2576 cson_free(kvp->key,"cson_kvp::key");
2577 cson_value_clean( &kvp->value );
2578 }
2579 }
2580 #endif
2581
2582 int cson_buffer_fill_from( cson_buffer * dest, cson_data_source_f src, void * state )
2583 {
2584 int rc;
2585 enum { BufSize = 1024 * 4 };
2586 char rbuf[BufSize];
@@ -2926,10 +2823,15 @@
2926
2927 cson_value * cson_value_null()
2928 {
2929 return &CSON_SPECIAL_VALUES[CSON_VAL_NULL];
2930 }
 
 
 
 
 
2931
2932 cson_value * cson_value_new_integer( cson_int_t v )
2933 {
2934 if( 0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_INT_0];
2935 else
@@ -2941,10 +2843,15 @@
2941 *CSON_INT(c) = v;
2942 }
2943 return c;
2944 }
2945 }
 
 
 
 
 
2946
2947 cson_value * cson_value_new_double( cson_double_t v )
2948 {
2949 if( 0.0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_DBL_0];
2950 else
@@ -2956,11 +2863,11 @@
2956 }
2957 return c;
2958 }
2959 }
2960
2961 cson_string const * cson_new_string(char const * str, unsigned int len)
2962 {
2963 if( !str || !*str || !len ) return &CSON_EMPTY_HOLDER.stringValue;
2964 else
2965 {
2966 cson_value * c = cson_value_new(CSON_TYPE_STRING, len + 1/*NUL byte*/);
@@ -3100,14 +3007,17 @@
3100 unsigned int i = 0;
3101 cson_kvp * kvp;
3102 const unsigned int klen = strlen(key);
3103 for( ; i < li->count; ++i )
3104 {
 
3105 kvp = li->list[i];
3106 assert( kvp && kvp->key );
3107 if( kvp->key->length != klen ) continue;
3108 else if(0==strcmp(key,cson_string_cstr(kvp->key)))
 
 
3109 {
3110 if(ndx) *ndx = i;
3111 return kvp;
3112 }
3113 }
@@ -3166,67 +3076,91 @@
3166 #endif
3167 return 0;
3168 }
3169 }
3170
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3171 int cson_object_set( cson_object * obj, char const * key, cson_value * v )
3172 {
3173 if( ! obj || !key || !*key ) return cson_rc.ArgError;
3174 else if( NULL == v )
3175 {
3176 return cson_object_unset( obj, key );
3177 }
3178 else
3179 {
3180 cson_kvp * kvp = cson_object_search_impl( obj, key, NULL );
3181 if( kvp )
3182 { /* "I told 'em we've already got one!" */
3183 if( v == kvp->value ) return 0 /* actually a usage error */;
3184 else
3185 {
3186 cson_value_free( kvp->value );
3187 cson_refcount_incr( v );
3188 kvp->value = v;
3189 return 0;
3190 }
3191 }
3192 if( !obj->kvp.alloced || (obj->kvp.count == obj->kvp.alloced-1))
3193 {
3194 unsigned int const n = obj->kvp.count ? (obj->kvp.count*2) : 7;
3195 if( n > cson_kvp_list_reserve( &obj->kvp, n ) )
3196 {
3197 return cson_rc.AllocError;
3198 }
3199 }
3200 { /* insert new item... */
3201 int rc = 0;
3202 cson_string * keycp = cson_string_strdup(key, strlen(key));
3203 if( ! keycp )
3204 {
3205 return cson_rc.AllocError;
3206 }
3207 kvp = cson_kvp_alloc();
3208 if( ! kvp )
3209 {
3210 cson_free(keycp,"cson_parser::key");
3211 return cson_rc.AllocError;
3212 }
3213 kvp->key = keycp /* transfer ownership */;
3214 rc = cson_kvp_list_append( &obj->kvp, kvp );
3215 if( 0 != rc )
3216 {
3217 cson_kvp_free(kvp);
3218 }
3219 else
3220 {
3221 cson_refcount_incr( v );
3222 kvp->value = v /* transfer ownership */;
3223 #if CSON_OBJECT_PROPS_SORT
3224 cson_object_sort_props( obj );
3225 #endif
3226 }
3227 return 0;
3228 }
3229 }
3230 }
3231
3232 cson_value * cson_object_take( cson_object * obj, char const * key )
@@ -3311,11 +3245,11 @@
3311 if( ! kvp )
3312 {
3313 cson_value_free(val);
3314 return cson_rc.AllocError;
3315 }
3316 kvp->key = p->ckey/*transfer ownership*/;
3317 p->ckey = NULL;
3318 kvp->value = val;
3319 cson_refcount_incr( val );
3320 rc = cson_kvp_list_append( &obj->kvp, kvp );
3321 if( 0 != rc )
@@ -3507,11 +3441,11 @@
3507 rc = cson_parser_push_value( p, cson_value_false() );
3508 break;
3509 }
3510 case JSON_T_KEY: {
3511 assert(!p->ckey);
3512 p->ckey = cson_string_strdup( value->vu.str.value, value->vu.str.length );
3513 if( ! p->ckey )
3514 {
3515 rc = cson_rc.AllocError;
3516 break;
3517 }
@@ -3580,11 +3514,13 @@
3580 if( p->p )
3581 {
3582 delete_JSON_parser(p->p);
3583 p->p = NULL;
3584 }
3585 cson_free( p->ckey, "cson_parser::key" );
 
 
3586 cson_array_clean( &p->stack, 1 );
3587 if( p->root )
3588 {
3589 cson_value_free( p->root );
3590 }
@@ -4192,11 +4128,13 @@
4192 for( i = 0; (i < obj->kvp.count) && (0 == rc); ++i )
4193 {
4194 kvp = obj->kvp.list[i];
4195 if( kvp && kvp->key )
4196 {
4197 rc = cson_str_to_json(cson_string_cstr(kvp->key), kvp->key->length,
 
 
4198 fmt->escapeForwardSlashes, f, state);
4199 if( 0 == rc )
4200 {
4201 rc = fmt->addSpaceAfterColon
4202 ? f(state, ": ", 2 )
@@ -4638,26 +4576,42 @@
4638 cson_kvp const * kvp = NULL;
4639 cson_object_iterator iter = cson_object_iterator_empty;
4640 assert( orig && src );
4641 if( 0 != cson_object_iter_init( src, &iter ) )
4642 {
4643 cson_value_free( destV );
4644 return NULL;
4645 }
4646 destV = cson_value_new_object();
4647 if( NULL == destV ) return NULL;
4648 dest = cson_value_get_object( destV );
4649 assert( dest );
 
 
 
 
4650 while( (kvp = cson_object_iter_next( &iter )) )
4651 {
4652 cson_string const * key = cson_kvp_key( kvp );
4653 cson_value const * val = cson_kvp_value( kvp );
4654 if( 0 != cson_object_set( dest,
4655 cson_string_cstr( key ),
4656 cson_value_clone( val ) ) )
 
 
 
 
 
 
 
 
 
 
 
4657 {
4658 cson_value_free( destV );
 
 
4659 return NULL;
4660 }
4661 }
4662 return destV;
4663 }
@@ -4719,10 +4673,27 @@
4719 return s
4720 ? CSON_VCAST(s)
4721 : NULL;
4722 }
4723
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4724
4725
4726 #if 0
4727 /* i'm not happy with this... */
4728 char * cson_pod_to_string( cson_value const * orig )
@@ -4826,10 +4797,74 @@
4826 }
4827 return v;
4828 }
4829 }
4830 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4831
4832 #if defined(__cplusplus)
4833 } /*extern "C"*/
4834 #endif
4835
4836
--- src/cson_amalgamation.c
+++ src/cson_amalgamation.c
@@ -1873,41 +1873,10 @@
1873 return 0;
1874 }
1875 else return cv->refcount;
1876 }
1877
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1878 unsigned int cson_string_length_bytes( cson_string const * str )
1879 {
1880 return str ? str->length : 0;
1881 }
1882
@@ -1974,33 +1943,10 @@
1943 memset( rc, 0, n+1 );
1944 rc[n] = 0;
1945 return strncpy( rc, src, n );
1946 }
1947 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1948
1949 int cson_string_cmp_cstr_n( cson_string const * str, char const * other, unsigned int otherLen )
1950 {
1951 if( ! other && !str ) return 0;
1952 else if( other && !str ) return 1;
@@ -2045,14 +1991,11 @@
1991 Each of these objects owns its key/value pointers, and they
1992 are cleaned up by cson_kvp_clean().
1993 */
1994 struct cson_kvp
1995 {
1996 cson_value * key;
 
 
 
1997 cson_value * value;
1998 };
1999 #define cson_kvp_empty_m {NULL,NULL}
2000 static const cson_kvp cson_kvp_empty = cson_kvp_empty_m;
2001
@@ -2087,45 +2030,21 @@
2030 */
2031 #define CSON_OBJECT_PROPS_SORT_USE_LENGTH 0
2032
2033 #if CSON_OBJECT_PROPS_SORT
2034
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2035 /**
2036 cson_kvp comparator for use with qsort(). ALMOST compares with
2037 strcmp() semantics, but it uses the strings' lengths as a quicker
2038 approach. This might give non-intuitive results, but it's faster.
2039 */
2040 static int cson_kvp_cmp( void const * lhs, void const * rhs )
2041 {
2042 cson_kvp const * lk = *((cson_kvp const * const*)lhs);
2043 cson_kvp const * rk = *((cson_kvp const * const*)rhs);
2044 cson_string const * l = cson_string_value(lk->key);
2045 cson_string const * r = cson_string_value(rk->key);
2046 #if CSON_OBJECT_PROPS_SORT_USE_LENGTH
2047 if( l->length < r->length ) return -1;
2048 else if( l->length > r->length ) return 1;
2049 else return strcmp( cson_string_cstr( l ), cson_string_cstr( r ) );
2050 #else
@@ -2135,10 +2054,11 @@
2054 }
2055 #endif /*CSON_OBJECT_PROPS_SORT*/
2056
2057
2058 #if CSON_OBJECT_PROPS_SORT
2059 #error "Need to rework this for cson_string-to-cson_value refactoring"
2060 /**
2061 A bsearch() comparison function which requires that lhs be a (char
2062 const *) and rhs be-a (cson_kvp const * const *). It compares lhs
2063 to rhs->key's value, using strcmp() semantics.
2064 */
@@ -2450,11 +2370,11 @@
2370 {
2371 if( kvp )
2372 {
2373 if(kvp->key)
2374 {
2375 cson_value_free(kvp->key);
2376 kvp->key = NULL;
2377 }
2378 if(kvp->value)
2379 {
2380 cson_value_free( kvp->value );
@@ -2463,11 +2383,11 @@
2383 }
2384 }
2385
2386 cson_string const * cson_kvp_key( cson_kvp const * kvp )
2387 {
2388 return kvp ? cson_value_get_string(kvp->key) : NULL;
2389 }
2390 cson_value * cson_kvp_value( cson_kvp const * kvp )
2391 {
2392 return kvp ? kvp->value : NULL;
2393 }
@@ -2554,33 +2474,10 @@
2474 cson_array_clean( ar, 1 );
2475 *self = cson_value_undef;
2476 }
2477 }
2478
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2479 int cson_buffer_fill_from( cson_buffer * dest, cson_data_source_f src, void * state )
2480 {
2481 int rc;
2482 enum { BufSize = 1024 * 4 };
2483 char rbuf[BufSize];
@@ -2926,10 +2823,15 @@
2823
2824 cson_value * cson_value_null()
2825 {
2826 return &CSON_SPECIAL_VALUES[CSON_VAL_NULL];
2827 }
2828
2829 cson_value * cson_new_int( cson_int_t v )
2830 {
2831 return cson_value_new_integer(v);
2832 }
2833
2834 cson_value * cson_value_new_integer( cson_int_t v )
2835 {
2836 if( 0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_INT_0];
2837 else
@@ -2941,10 +2843,15 @@
2843 *CSON_INT(c) = v;
2844 }
2845 return c;
2846 }
2847 }
2848
2849 cson_value * cson_new_double( cson_double_t v )
2850 {
2851 return cson_value_new_double(v);
2852 }
2853
2854 cson_value * cson_value_new_double( cson_double_t v )
2855 {
2856 if( 0.0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_DBL_0];
2857 else
@@ -2956,11 +2863,11 @@
2863 }
2864 return c;
2865 }
2866 }
2867
2868 cson_string * cson_new_string(char const * str, unsigned int len)
2869 {
2870 if( !str || !*str || !len ) return &CSON_EMPTY_HOLDER.stringValue;
2871 else
2872 {
2873 cson_value * c = cson_value_new(CSON_TYPE_STRING, len + 1/*NUL byte*/);
@@ -3100,14 +3007,17 @@
3007 unsigned int i = 0;
3008 cson_kvp * kvp;
3009 const unsigned int klen = strlen(key);
3010 for( ; i < li->count; ++i )
3011 {
3012 cson_string const * sKey;
3013 kvp = li->list[i];
3014 assert( kvp && kvp->key );
3015 sKey = cson_value_get_string(kvp->key);
3016 assert(sKey);
3017 if( sKey->length != klen ) continue;
3018 else if(0==strcmp(key,cson_string_cstr(sKey)))
3019 {
3020 if(ndx) *ndx = i;
3021 return kvp;
3022 }
3023 }
@@ -3166,67 +3076,91 @@
3076 #endif
3077 return 0;
3078 }
3079 }
3080
3081 int cson_object_set_s( cson_object * obj, cson_string * key, cson_value * v )
3082 {
3083 if( !obj || !key ) return cson_rc.ArgError;
3084 else if( NULL == v ) return cson_object_unset( obj, cson_string_cstr(key) );
3085 else
3086 {
3087 char const * cKey;
3088 cson_value * vKey;
3089 cson_kvp * kvp;
3090 vKey = cson_string_value(key);
3091 assert(vKey && (key==CSON_STR(vKey)));
3092 if( vKey == CSON_VCAST(obj) ){
3093 return cson_rc.ArgError;
3094 }
3095 cKey = cson_string_cstr(key);
3096 kvp = cson_object_search_impl( obj, cKey, NULL );
3097 if( kvp )
3098 { /* "I told 'em we've already got one!" */
3099 if( kvp->key != vKey ){
3100 cson_value_free( kvp->key );
3101 cson_refcount_incr(vKey);
3102 kvp->key = vKey;
3103 }
3104 if(kvp->value != v){
3105 cson_value_free( kvp->value );
3106 cson_refcount_incr( v );
3107 kvp->value = v;
3108 }
3109 return 0;
3110 }
3111 if( !obj->kvp.alloced || (obj->kvp.count == obj->kvp.alloced-1))
3112 {
3113 unsigned int const n = obj->kvp.count ? (obj->kvp.count*2) : 6;
3114 if( n > cson_kvp_list_reserve( &obj->kvp, n ) )
3115 {
3116 return cson_rc.AllocError;
3117 }
3118 }
3119 { /* insert new item... */
3120 int rc = 0;
3121 kvp = cson_kvp_alloc();
3122 if( ! kvp )
3123 {
3124 return cson_rc.AllocError;
3125 }
3126 rc = cson_kvp_list_append( &obj->kvp, kvp );
3127 if( 0 != rc )
3128 {
3129 cson_kvp_free(kvp);
3130 }
3131 else
3132 {
3133 cson_refcount_incr(vKey);
3134 cson_refcount_incr(v);
3135 kvp->key = vKey;
3136 kvp->value = v;
3137 #if CSON_OBJECT_PROPS_SORT
3138 cson_object_sort_props( obj );
3139 #endif
3140 }
3141 return rc;
3142 }
3143 }
3144
3145 }
3146 int cson_object_set( cson_object * obj, char const * key, cson_value * v )
3147 {
3148 if( ! obj || !key || !*key ) return cson_rc.ArgError;
3149 else if( NULL == v )
3150 {
3151 return cson_object_unset( obj, key );
3152 }
3153 else
3154 {
3155 cson_string * cs = cson_new_string(key,strlen(key));
3156 if(!cs) return cson_rc.AllocError;
3157 else
3158 {
3159 int const rc = cson_object_set_s(obj, cs, v);
3160 if(rc) cson_value_free(cson_string_value(cs));
3161 return rc;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3162 }
3163 }
3164 }
3165
3166 cson_value * cson_object_take( cson_object * obj, char const * key )
@@ -3311,11 +3245,11 @@
3245 if( ! kvp )
3246 {
3247 cson_value_free(val);
3248 return cson_rc.AllocError;
3249 }
3250 kvp->key = cson_string_value(p->ckey)/*transfer ownership*/;
3251 p->ckey = NULL;
3252 kvp->value = val;
3253 cson_refcount_incr( val );
3254 rc = cson_kvp_list_append( &obj->kvp, kvp );
3255 if( 0 != rc )
@@ -3507,11 +3441,11 @@
3441 rc = cson_parser_push_value( p, cson_value_false() );
3442 break;
3443 }
3444 case JSON_T_KEY: {
3445 assert(!p->ckey);
3446 p->ckey = cson_new_string( value->vu.str.value, value->vu.str.length );
3447 if( ! p->ckey )
3448 {
3449 rc = cson_rc.AllocError;
3450 break;
3451 }
@@ -3580,11 +3514,13 @@
3514 if( p->p )
3515 {
3516 delete_JSON_parser(p->p);
3517 p->p = NULL;
3518 }
3519 if( p->ckey ){
3520 cson_value_free(cson_string_value(p->ckey));
3521 }
3522 cson_array_clean( &p->stack, 1 );
3523 if( p->root )
3524 {
3525 cson_value_free( p->root );
3526 }
@@ -4192,11 +4128,13 @@
4128 for( i = 0; (i < obj->kvp.count) && (0 == rc); ++i )
4129 {
4130 kvp = obj->kvp.list[i];
4131 if( kvp && kvp->key )
4132 {
4133 cson_string const * sKey = cson_value_get_string(kvp->key);
4134 char const * cKey = cson_string_cstr(sKey);
4135 rc = cson_str_to_json(cKey, sKey->length,
4136 fmt->escapeForwardSlashes, f, state);
4137 if( 0 == rc )
4138 {
4139 rc = fmt->addSpaceAfterColon
4140 ? f(state, ": ", 2 )
@@ -4638,26 +4576,42 @@
4576 cson_kvp const * kvp = NULL;
4577 cson_object_iterator iter = cson_object_iterator_empty;
4578 assert( orig && src );
4579 if( 0 != cson_object_iter_init( src, &iter ) )
4580 {
 
4581 return NULL;
4582 }
4583 destV = cson_value_new_object();
4584 if( NULL == destV ) return NULL;
4585 dest = cson_value_get_object( destV );
4586 assert( dest );
4587 if( src->kvp.count > cson_kvp_list_reserve( &dest->kvp, src->kvp.count ) ){
4588 cson_value_free( destV );
4589 return NULL;
4590 }
4591 while( (kvp = cson_object_iter_next( &iter )) )
4592 {
4593 /*
4594 FIXME: refcount the keys! We first need a setter which takes
4595 a cson_string or cson_value key type.
4596 */
4597 cson_value * key = NULL;
4598 cson_value * val = NULL;
4599 key = cson_value_clone(kvp->key);
4600 val = key ? cson_value_clone( kvp->value ) : NULL;
4601 if( ! key || !val ){
4602 cson_value_free(key);
4603 cson_value_free(val);
4604 cson_value_free(destV);
4605 return NULL;
4606 }
4607 assert( CSON_STR(key) );
4608 if( 0 != cson_object_set_s( dest, CSON_STR(key), val ) )
4609 {
4610 cson_value_free(key);
4611 cson_value_free(val);
4612 cson_value_free(destV);
4613 return NULL;
4614 }
4615 }
4616 return destV;
4617 }
@@ -4719,10 +4673,27 @@
4673 return s
4674 ? CSON_VCAST(s)
4675 : NULL;
4676 }
4677
4678 void cson_free_object(cson_object *x)
4679 {
4680 if(x) cson_value_free(cson_object_value(x));
4681 }
4682 void cson_free_array(cson_array *x)
4683 {
4684 if(x) cson_value_free(cson_array_value(x));
4685 }
4686
4687 void cson_free_string(cson_string const *x)
4688 {
4689 if(x) cson_value_free(cson_string_value(x));
4690 }
4691 void cson_free_value(cson_value *x)
4692 {
4693 cson_value_free(x);
4694 }
4695
4696
4697 #if 0
4698 /* i'm not happy with this... */
4699 char * cson_pod_to_string( cson_value const * orig )
@@ -4826,10 +4797,74 @@
4797 }
4798 return v;
4799 }
4800 }
4801 #endif
4802
4803 unsigned int cson_value_msize(cson_value const * v)
4804 {
4805 if(!v) return 0;
4806 else if( cson_value_is_builtin(v) ) return 0;
4807 else {
4808 unsigned int rc = sizeof(cson_value);
4809 assert(NULL != v->api);
4810 switch(v->api->typeID){
4811 case CSON_TYPE_INTEGER:
4812 assert( v != &CSON_SPECIAL_VALUES[CSON_VAL_INT_0]);
4813 rc += sizeof(cson_int_t);
4814 break;
4815 case CSON_TYPE_DOUBLE:
4816 assert( v != &CSON_SPECIAL_VALUES[CSON_VAL_DBL_0]);
4817 rc += sizeof(cson_double_t);
4818 break;
4819 case CSON_TYPE_STRING:
4820 rc += sizeof(cson_string)
4821 + CSON_STR(v)->length + 1/*NUL*/;
4822 break;
4823 case CSON_TYPE_ARRAY:{
4824 cson_array const * ar = CSON_ARRAY(v);
4825 cson_value_list const * li;
4826 unsigned int i = 0;
4827 assert( NULL != ar );
4828 li = &ar->list;
4829 rc += sizeof(cson_array)
4830 + (li->alloced * sizeof(cson_value *));
4831 for( ; i < li->count; ++i ){
4832 cson_value const * e = ar->list.list[i];
4833 if( e ) rc += cson_value_msize( e );
4834 }
4835 break;
4836 }
4837 case CSON_TYPE_OBJECT:{
4838 cson_object const * obj = CSON_OBJ(v);
4839 unsigned int i = 0;
4840 cson_kvp_list const * kl;
4841 assert(NULL != obj);
4842 kl = &obj->kvp;
4843 rc += sizeof(cson_object)
4844 + (kl->alloced * sizeof(cson_kvp*));
4845 for( ; i < kl->count; ++i ){
4846 cson_kvp const * kvp = kl->list[i];
4847 assert(NULL != kvp);
4848 rc += cson_value_msize(kvp->key);
4849 rc += cson_value_msize(kvp->value);
4850 }
4851 break;
4852 }
4853 case CSON_TYPE_UNDEF:
4854 case CSON_TYPE_NULL:
4855 case CSON_TYPE_BOOL:
4856 assert( 0 && "Should have been caught by is-builtin check!" );
4857 break;
4858 default:
4859 assert(0 && "Invalid typeID!");
4860 return 0;
4861
4862 }
4863 return rc;
4864 }
4865 }
4866
4867 #if defined(__cplusplus)
4868 } /*extern "C"*/
4869 #endif
4870
4871
--- src/cson_amalgamation.h
+++ src/cson_amalgamation.h
@@ -1147,10 +1147,15 @@
11471147
Returns NULL on allocation error.
11481148
*/
11491149
cson_value * cson_value_new_bool( char v );
11501150
11511151
1152
+/**
1153
+ Alias for cson_value_new_bool(v).
1154
+*/
1155
+cson_value * cson_new_bool(char v);
1156
+
11521157
/**
11531158
Returns the special JSON "null" value. When outputing JSON,
11541159
its string representation is "null" (without the quotes).
11551160
11561161
See cson_value_new_bool() for notes regarding the returned
@@ -1171,15 +1176,25 @@
11711176
/**
11721177
Semantically the same as cson_value_new_bool(), but for integers.
11731178
*/
11741179
cson_value * cson_value_new_integer( cson_int_t v );
11751180
1181
+/**
1182
+ Alias for cson_value_new_integer(v).
1183
+*/
1184
+cson_value * cson_new_int(cson_int_t v);
1185
+
11761186
/**
11771187
Semantically the same as cson_value_new_bool(), but for doubles.
11781188
*/
11791189
cson_value * cson_value_new_double( cson_double_t v );
11801190
1191
+/**
1192
+ Alias for cson_value_new_double(v).
1193
+*/
1194
+cson_value * cson_new_double(cson_double_t v);
1195
+
11811196
/**
11821197
Semantically the same as cson_value_new_bool(), but for strings.
11831198
This creates a JSON value which copies the first n bytes of str.
11841199
The string will automatically be NUL-terminated.
11851200
@@ -1229,17 +1244,28 @@
12291244
cson_array * cson_new_array();
12301245
12311246
/**
12321247
Identical to cson_new_object() except that it creates
12331248
a String.
1249
+*/
1250
+cson_string * cson_new_string(char const * val, unsigned int len);
12341251
1235
- ACHTUNG: this function returns a const pointer but the ownership of
1236
- the memory belongs to the caller! Use cson_string_value() to fetch
1237
- the Value handle, and then cson_value_free() that handle or insert
1238
- it into a container to transfer ownership.
1252
+/**
1253
+ Equivalent to cson_value_free(cson_object_value(x)).
1254
+*/
1255
+void cson_free_object(cson_object *x);
1256
+
1257
+/**
1258
+ Equivalent to cson_value_free(cson_array_value(x)).
1259
+*/
1260
+void cson_free_array(cson_array *x);
1261
+
1262
+/**
1263
+ Equivalent to cson_value_free(cson_string_value(x)).
12391264
*/
1240
-cson_string const * cson_new_string(char const * val, unsigned int len);
1265
+void cson_free_string(cson_string const *x);
1266
+
12411267
12421268
/**
12431269
Allocates a new "array" value and transfers ownership of it to the
12441270
caller. It must eventually be destroyed, by the caller or its
12451271
owning container, by passing it to cson_value_free().
@@ -1271,10 +1297,16 @@
12711297
@see cson_value_new_object()
12721298
@see cson_value_new_array()
12731299
@see cson_value_add_reference()
12741300
*/
12751301
void cson_value_free(cson_value * v);
1302
+
1303
+/**
1304
+ Alias for cson_value_free().
1305
+*/
1306
+void cson_free_value(cson_value * v);
1307
+
12761308
12771309
/**
12781310
Functionally similar to cson_array_set(), but uses a string key
12791311
as an index. Like arrays, if a value already exists for the given key,
12801312
it is destroyed by this function before inserting the new value.
@@ -1322,10 +1354,24 @@
13221354
value types to strings. We could simply to-JSON them and use those
13231355
as keys.
13241356
*/
13251357
int cson_object_set( cson_object * obj, char const * key, cson_value * v );
13261358
1359
+/**
1360
+ Functionaly equivalent to cson_object_set(), but takes a
1361
+ cson_string() as its KEY type. The string will be reference-counted
1362
+ like any other values, and the key may legally be used within this
1363
+ same container (as a value) or others (as a key or value) at the
1364
+ same time.
1365
+
1366
+ Returns 0 on success. On error, ownership (i.e. refcounts) of key
1367
+ and value are not modified. On success key and value will get
1368
+ increased refcounts unless they are replacing themselves (which is
1369
+ a harmless no-op).
1370
+*/
1371
+int cson_object_set_s( cson_object * obj, cson_string * key, cson_value * v );
1372
+
13271373
/**
13281374
Removes a property from an object.
13291375
13301376
If obj contains the given key, it is removed and 0 is returned. If
13311377
it is not found, cson_rc.NotFoundError is returned (which can
@@ -1965,10 +2011,41 @@
19652011
for full details.
19662012
*/
19672013
cson_value * cson_array_value(cson_array const * s);
19682014
19692015
2016
+/**
2017
+ Calculates the in-memory-allocated size of v, recursively if it is
2018
+ a container type, with the following caveats and limitations:
2019
+
2020
+ If a given value is reference counted and multiple times within a
2021
+ traversed container, each reference is counted at full cost. We
2022
+ have no what of knowing if a given reference has been visited
2023
+ already and whether it should or should not be counted, so we
2024
+ pessimistically count them even though the _might_ not really count
2025
+ for the given object tree (it depends on where the other open
2026
+ references live).
2027
+
2028
+ This function returns 0 if any of the following are true:
2029
+
2030
+ - v is NULL
2031
+
2032
+ - v is one of the special singleton values (null, bools, empty
2033
+ string, int 0, double 0.0)
2034
+
2035
+ All other values require an allocation, and this will return their
2036
+ total memory cost, including the cson-specific internals and the
2037
+ native value(s).
2038
+
2039
+ Note that because arrays and objects might have more internal slots
2040
+ allocated than used, the alloced size of a container does not
2041
+ necessarily increase when a new item is inserted into it. An interesting
2042
+ side-effect of this is that when cson_clone()ing an array or object, the
2043
+ size of the clone can actually be less than the original.
2044
+*/
2045
+unsigned int cson_value_msize(cson_value const * v);
2046
+
19702047
/* LICENSE
19712048
19722049
This software's source code, including accompanying documentation and
19732050
demonstration applications, are licensed under the following
19742051
conditions...
19752052
--- src/cson_amalgamation.h
+++ src/cson_amalgamation.h
@@ -1147,10 +1147,15 @@
1147 Returns NULL on allocation error.
1148 */
1149 cson_value * cson_value_new_bool( char v );
1150
1151
 
 
 
 
 
1152 /**
1153 Returns the special JSON "null" value. When outputing JSON,
1154 its string representation is "null" (without the quotes).
1155
1156 See cson_value_new_bool() for notes regarding the returned
@@ -1171,15 +1176,25 @@
1171 /**
1172 Semantically the same as cson_value_new_bool(), but for integers.
1173 */
1174 cson_value * cson_value_new_integer( cson_int_t v );
1175
 
 
 
 
 
1176 /**
1177 Semantically the same as cson_value_new_bool(), but for doubles.
1178 */
1179 cson_value * cson_value_new_double( cson_double_t v );
1180
 
 
 
 
 
1181 /**
1182 Semantically the same as cson_value_new_bool(), but for strings.
1183 This creates a JSON value which copies the first n bytes of str.
1184 The string will automatically be NUL-terminated.
1185
@@ -1229,17 +1244,28 @@
1229 cson_array * cson_new_array();
1230
1231 /**
1232 Identical to cson_new_object() except that it creates
1233 a String.
 
 
1234
1235 ACHTUNG: this function returns a const pointer but the ownership of
1236 the memory belongs to the caller! Use cson_string_value() to fetch
1237 the Value handle, and then cson_value_free() that handle or insert
1238 it into a container to transfer ownership.
 
 
 
 
 
 
 
 
1239 */
1240 cson_string const * cson_new_string(char const * val, unsigned int len);
 
1241
1242 /**
1243 Allocates a new "array" value and transfers ownership of it to the
1244 caller. It must eventually be destroyed, by the caller or its
1245 owning container, by passing it to cson_value_free().
@@ -1271,10 +1297,16 @@
1271 @see cson_value_new_object()
1272 @see cson_value_new_array()
1273 @see cson_value_add_reference()
1274 */
1275 void cson_value_free(cson_value * v);
 
 
 
 
 
 
1276
1277 /**
1278 Functionally similar to cson_array_set(), but uses a string key
1279 as an index. Like arrays, if a value already exists for the given key,
1280 it is destroyed by this function before inserting the new value.
@@ -1322,10 +1354,24 @@
1322 value types to strings. We could simply to-JSON them and use those
1323 as keys.
1324 */
1325 int cson_object_set( cson_object * obj, char const * key, cson_value * v );
1326
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1327 /**
1328 Removes a property from an object.
1329
1330 If obj contains the given key, it is removed and 0 is returned. If
1331 it is not found, cson_rc.NotFoundError is returned (which can
@@ -1965,10 +2011,41 @@
1965 for full details.
1966 */
1967 cson_value * cson_array_value(cson_array const * s);
1968
1969
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1970 /* LICENSE
1971
1972 This software's source code, including accompanying documentation and
1973 demonstration applications, are licensed under the following
1974 conditions...
1975
--- src/cson_amalgamation.h
+++ src/cson_amalgamation.h
@@ -1147,10 +1147,15 @@
1147 Returns NULL on allocation error.
1148 */
1149 cson_value * cson_value_new_bool( char v );
1150
1151
1152 /**
1153 Alias for cson_value_new_bool(v).
1154 */
1155 cson_value * cson_new_bool(char v);
1156
1157 /**
1158 Returns the special JSON "null" value. When outputing JSON,
1159 its string representation is "null" (without the quotes).
1160
1161 See cson_value_new_bool() for notes regarding the returned
@@ -1171,15 +1176,25 @@
1176 /**
1177 Semantically the same as cson_value_new_bool(), but for integers.
1178 */
1179 cson_value * cson_value_new_integer( cson_int_t v );
1180
1181 /**
1182 Alias for cson_value_new_integer(v).
1183 */
1184 cson_value * cson_new_int(cson_int_t v);
1185
1186 /**
1187 Semantically the same as cson_value_new_bool(), but for doubles.
1188 */
1189 cson_value * cson_value_new_double( cson_double_t v );
1190
1191 /**
1192 Alias for cson_value_new_double(v).
1193 */
1194 cson_value * cson_new_double(cson_double_t v);
1195
1196 /**
1197 Semantically the same as cson_value_new_bool(), but for strings.
1198 This creates a JSON value which copies the first n bytes of str.
1199 The string will automatically be NUL-terminated.
1200
@@ -1229,17 +1244,28 @@
1244 cson_array * cson_new_array();
1245
1246 /**
1247 Identical to cson_new_object() except that it creates
1248 a String.
1249 */
1250 cson_string * cson_new_string(char const * val, unsigned int len);
1251
1252 /**
1253 Equivalent to cson_value_free(cson_object_value(x)).
1254 */
1255 void cson_free_object(cson_object *x);
1256
1257 /**
1258 Equivalent to cson_value_free(cson_array_value(x)).
1259 */
1260 void cson_free_array(cson_array *x);
1261
1262 /**
1263 Equivalent to cson_value_free(cson_string_value(x)).
1264 */
1265 void cson_free_string(cson_string const *x);
1266
1267
1268 /**
1269 Allocates a new "array" value and transfers ownership of it to the
1270 caller. It must eventually be destroyed, by the caller or its
1271 owning container, by passing it to cson_value_free().
@@ -1271,10 +1297,16 @@
1297 @see cson_value_new_object()
1298 @see cson_value_new_array()
1299 @see cson_value_add_reference()
1300 */
1301 void cson_value_free(cson_value * v);
1302
1303 /**
1304 Alias for cson_value_free().
1305 */
1306 void cson_free_value(cson_value * v);
1307
1308
1309 /**
1310 Functionally similar to cson_array_set(), but uses a string key
1311 as an index. Like arrays, if a value already exists for the given key,
1312 it is destroyed by this function before inserting the new value.
@@ -1322,10 +1354,24 @@
1354 value types to strings. We could simply to-JSON them and use those
1355 as keys.
1356 */
1357 int cson_object_set( cson_object * obj, char const * key, cson_value * v );
1358
1359 /**
1360 Functionaly equivalent to cson_object_set(), but takes a
1361 cson_string() as its KEY type. The string will be reference-counted
1362 like any other values, and the key may legally be used within this
1363 same container (as a value) or others (as a key or value) at the
1364 same time.
1365
1366 Returns 0 on success. On error, ownership (i.e. refcounts) of key
1367 and value are not modified. On success key and value will get
1368 increased refcounts unless they are replacing themselves (which is
1369 a harmless no-op).
1370 */
1371 int cson_object_set_s( cson_object * obj, cson_string * key, cson_value * v );
1372
1373 /**
1374 Removes a property from an object.
1375
1376 If obj contains the given key, it is removed and 0 is returned. If
1377 it is not found, cson_rc.NotFoundError is returned (which can
@@ -1965,10 +2011,41 @@
2011 for full details.
2012 */
2013 cson_value * cson_array_value(cson_array const * s);
2014
2015
2016 /**
2017 Calculates the in-memory-allocated size of v, recursively if it is
2018 a container type, with the following caveats and limitations:
2019
2020 If a given value is reference counted and multiple times within a
2021 traversed container, each reference is counted at full cost. We
2022 have no what of knowing if a given reference has been visited
2023 already and whether it should or should not be counted, so we
2024 pessimistically count them even though the _might_ not really count
2025 for the given object tree (it depends on where the other open
2026 references live).
2027
2028 This function returns 0 if any of the following are true:
2029
2030 - v is NULL
2031
2032 - v is one of the special singleton values (null, bools, empty
2033 string, int 0, double 0.0)
2034
2035 All other values require an allocation, and this will return their
2036 total memory cost, including the cson-specific internals and the
2037 native value(s).
2038
2039 Note that because arrays and objects might have more internal slots
2040 allocated than used, the alloced size of a container does not
2041 necessarily increase when a new item is inserted into it. An interesting
2042 side-effect of this is that when cson_clone()ing an array or object, the
2043 size of the clone can actually be less than the original.
2044 */
2045 unsigned int cson_value_msize(cson_value const * v);
2046
2047 /* LICENSE
2048
2049 This software's source code, including accompanying documentation and
2050 demonstration applications, are licensed under the following
2051 conditions...
2052

Keyboard Shortcuts

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