Fossil SCM
pulled in tonight's libcson changes, which halve the number of allocations needed for creating new JSON values.
Commit
130cc65cb575071eb815a57691d15ece631aa245
Parent
be41009046fb078…
2 files changed
+149
-286
+28
-36
+149
-286
| --- src/cson_amalgamation.c | ||
| +++ src/cson_amalgamation.c | ||
| @@ -1570,35 +1570,28 @@ | ||
| 1570 | 1570 | const cson_object_iterator cson_object_iterator_empty = cson_object_iterator_empty_m; |
| 1571 | 1571 | const cson_buffer cson_buffer_empty = cson_buffer_empty_m; |
| 1572 | 1572 | const cson_parse_info cson_parse_info_empty = cson_parse_info_empty_m; |
| 1573 | 1573 | |
| 1574 | 1574 | static void cson_value_destroy_zero_it( cson_value * self ); |
| 1575 | -static void cson_value_destroy_free( cson_value * self ); | |
| 1576 | 1575 | static void cson_value_destroy_object( cson_value * self ); |
| 1577 | -static void cson_value_destroy_integer( cson_value * self ); | |
| 1578 | 1576 | /** |
| 1579 | 1577 | If self is-a array then this function destroys its contents, |
| 1580 | 1578 | else this function does nothing. |
| 1581 | 1579 | */ |
| 1582 | 1580 | static void cson_value_destroy_array( cson_value * self ); |
| 1583 | 1581 | |
| 1584 | -/** | |
| 1585 | - If self is-a string then this function destroys its contents, | |
| 1586 | - else this function does nothing. | |
| 1587 | -*/ | |
| 1588 | -static void cson_value_destroy_string( cson_value * self ); | |
| 1589 | - | |
| 1590 | 1582 | static const cson_value_api cson_value_api_null = { CSON_TYPE_NULL, cson_value_destroy_zero_it }; |
| 1591 | 1583 | static const cson_value_api cson_value_api_undef = { CSON_TYPE_UNDEF, cson_value_destroy_zero_it }; |
| 1592 | 1584 | static const cson_value_api cson_value_api_bool = { CSON_TYPE_BOOL, cson_value_destroy_zero_it }; |
| 1593 | -static const cson_value_api cson_value_api_integer = { CSON_TYPE_INTEGER, cson_value_destroy_integer }; | |
| 1594 | -static const cson_value_api cson_value_api_double = { CSON_TYPE_DOUBLE, cson_value_destroy_free }; | |
| 1595 | -static const cson_value_api cson_value_api_string = { CSON_TYPE_STRING, cson_value_destroy_string }; | |
| 1585 | +static const cson_value_api cson_value_api_integer = { CSON_TYPE_INTEGER, cson_value_destroy_zero_it }; | |
| 1586 | +static const cson_value_api cson_value_api_double = { CSON_TYPE_DOUBLE, cson_value_destroy_zero_it }; | |
| 1587 | +static const cson_value_api cson_value_api_string = { CSON_TYPE_STRING, cson_value_destroy_zero_it }; | |
| 1596 | 1588 | static const cson_value_api cson_value_api_array = { CSON_TYPE_ARRAY, cson_value_destroy_array }; |
| 1597 | 1589 | static const cson_value_api cson_value_api_object = { CSON_TYPE_OBJECT, cson_value_destroy_object }; |
| 1598 | 1590 | |
| 1599 | 1591 | static const cson_value cson_value_undef = { &cson_value_api_undef, NULL, 0 }; |
| 1592 | +static const cson_value cson_value_null_empty = { &cson_value_api_null, NULL, 0 }; | |
| 1600 | 1593 | static const cson_value cson_value_bool_empty = { &cson_value_api_bool, NULL, 0 }; |
| 1601 | 1594 | static const cson_value cson_value_integer_empty = { &cson_value_api_integer, NULL, 0 }; |
| 1602 | 1595 | static const cson_value cson_value_double_empty = { &cson_value_api_double, NULL, 0 }; |
| 1603 | 1596 | static const cson_value cson_value_string_empty = { &cson_value_api_string, NULL, 0 }; |
| 1604 | 1597 | static const cson_value cson_value_array_empty = { &cson_value_api_array, NULL, 0 }; |
| @@ -1608,11 +1601,11 @@ | ||
| 1608 | 1601 | struct cson_string |
| 1609 | 1602 | { |
| 1610 | 1603 | unsigned int length; |
| 1611 | 1604 | }; |
| 1612 | 1605 | #define cson_string_empty_m {0/*length*/} |
| 1613 | - | |
| 1606 | +static const cson_string cson_string_empty = cson_string_empty_m; | |
| 1614 | 1607 | /** |
| 1615 | 1608 | |
| 1616 | 1609 | Holds special shared "constant" (though they are non-const) |
| 1617 | 1610 | values. |
| 1618 | 1611 | |
| @@ -2033,37 +2026,22 @@ | ||
| 2033 | 2026 | if( self ) |
| 2034 | 2027 | { |
| 2035 | 2028 | *self = cson_value_undef; |
| 2036 | 2029 | } |
| 2037 | 2030 | } |
| 2038 | - | |
| 2039 | -/** | |
| 2040 | - If self is not null, free(self->value) is called. *self is then | |
| 2041 | - overwritten to have the undefined type. self is not freed. | |
| 2042 | - | |
| 2043 | -*/ | |
| 2044 | -void cson_value_destroy_free( cson_value * self ) | |
| 2045 | -{ | |
| 2046 | - if(self) { | |
| 2047 | - if( self->value ) | |
| 2048 | - { | |
| 2049 | - cson_free(self->value,"cson_value_destroy_free()"); | |
| 2050 | - } | |
| 2051 | - *self = cson_value_undef; | |
| 2052 | - } | |
| 2053 | -} | |
| 2054 | - | |
| 2055 | - | |
| 2056 | 2031 | |
| 2057 | 2032 | /** |
| 2058 | 2033 | A key/value pair collection. |
| 2059 | 2034 | |
| 2060 | 2035 | Each of these objects owns its key/value pointers, and they |
| 2061 | 2036 | are cleaned up by cson_kvp_clean(). |
| 2062 | 2037 | */ |
| 2063 | 2038 | struct cson_kvp |
| 2064 | 2039 | { |
| 2040 | + /* FIXME: switch to cson_value keys. Calling cson_string_value() | |
| 2041 | + on one of these guys will read invalid memory. | |
| 2042 | + */ | |
| 2065 | 2043 | cson_string * key; |
| 2066 | 2044 | cson_value * value; |
| 2067 | 2045 | }; |
| 2068 | 2046 | #define cson_kvp_empty_m {NULL,NULL} |
| 2069 | 2047 | static const cson_kvp cson_kvp_empty = cson_kvp_empty_m; |
| @@ -2261,32 +2239,23 @@ | ||
| 2261 | 2239 | # define VALUE_T cson_kvp * |
| 2262 | 2240 | # define VALUE_T_IS_PTR 1 |
| 2263 | 2241 | #else |
| 2264 | 2242 | #endif |
| 2265 | 2243 | |
| 2266 | -/* | |
| 2267 | - Reminders to self: | |
| 2268 | - | |
| 2269 | - - 20110126: moved cson_value_new() and cson_value_set_xxx() out of the | |
| 2270 | - public API because: | |
| 2271 | - | |
| 2272 | - a) They can be easily mis-used to cause memory leaks, even when used in | |
| 2273 | - a manner which seems relatively intuitive. | |
| 2274 | - | |
| 2275 | - b) Having them in the API prohibits us from eventually doing certain | |
| 2276 | - allocation optimizations like not allocating Booleans, | |
| 2277 | - Integer/Doubles with the value 0, or empty Strings. The main problem | |
| 2278 | - is that cson_value_set_xxx() cannot be implemented properly if we | |
| 2279 | - add that type of optimization. | |
| 2280 | -*/ | |
| 2281 | - | |
| 2282 | 2244 | /** |
| 2283 | - Allocates a new value with the "undefined" value and transfers | |
| 2284 | - ownership of it to the caller. Use The cson_value_set_xxx() family | |
| 2285 | - of functions to assign a typed value to it. It must eventually be | |
| 2286 | - destroyed, by the caller or its owning container, by passing it to | |
| 2287 | - cson_value_free(). | |
| 2245 | + Allocates a new value of the specified type ownership of it to the | |
| 2246 | + caller. It must eventually be destroyed, by the caller or its | |
| 2247 | + owning container, by passing it to cson_value_free() or transfering | |
| 2248 | + ownership to a container. | |
| 2249 | + | |
| 2250 | + extra is only valid for type CSON_TYPE_STRING, and must be the length | |
| 2251 | + of the string to allocate + 1 byte (for the NUL). | |
| 2252 | + | |
| 2253 | + The returned value->api member will be set appropriately and | |
| 2254 | + val->value will be set to point to the memory allocated to hold the | |
| 2255 | + native value type. Use the internal CSON_CAST() family of macros to | |
| 2256 | + convert them. | |
| 2288 | 2257 | |
| 2289 | 2258 | Returns NULL on allocation error. |
| 2290 | 2259 | |
| 2291 | 2260 | @see cson_value_new_array() |
| 2292 | 2261 | @see cson_value_new_object() |
| @@ -2294,65 +2263,73 @@ | ||
| 2294 | 2263 | @see cson_value_new_integer() |
| 2295 | 2264 | @see cson_value_new_double() |
| 2296 | 2265 | @see cson_value_new_bool() |
| 2297 | 2266 | @see cson_value_free() |
| 2298 | 2267 | */ |
| 2299 | -static cson_value * cson_value_new(); | |
| 2300 | -/** | |
| 2301 | - Cleans any existing contents of val and sets its new value | |
| 2302 | - to the special NULL value. | |
| 2303 | - | |
| 2304 | - Returns 0 on success. | |
| 2305 | - | |
| 2306 | -*/ | |
| 2307 | -#if 0 | |
| 2308 | -static int cson_value_set_null( cson_value * val ); | |
| 2309 | -#endif | |
| 2310 | -/** | |
| 2311 | - Cleans any existing contents of val and sets its new value | |
| 2312 | - to v. | |
| 2313 | - | |
| 2314 | - Returns 0 on success. | |
| 2315 | - | |
| 2316 | -*/ | |
| 2317 | -#if 0 | |
| 2318 | -static int cson_value_set_bool( cson_value * val, char v ); | |
| 2319 | -#endif | |
| 2320 | -/** | |
| 2321 | - Cleans any existing contents of val and sets its new value | |
| 2322 | - to v. | |
| 2323 | - | |
| 2324 | - Returns 0 on success. | |
| 2325 | - | |
| 2326 | -*/ | |
| 2327 | -static int cson_value_set_integer( cson_value * val, cson_int_t v ); | |
| 2328 | -/** | |
| 2329 | - Cleans any existing contents of val and sets its new value | |
| 2330 | - to v. | |
| 2331 | - | |
| 2332 | - Returns 0 on success. | |
| 2333 | -*/ | |
| 2334 | -static int cson_value_set_double( cson_value * val, cson_double_t v ); | |
| 2335 | - | |
| 2336 | -/** | |
| 2337 | - Cleans any existing contents of val and sets its new value to | |
| 2338 | - str. On success, ownership of str is passed on to val. On error | |
| 2339 | - ownership is not changed. | |
| 2340 | - | |
| 2341 | - Returns 0 on success. | |
| 2342 | - | |
| 2343 | - If str is NULL, (!*str), or (!len) then this function does not | |
| 2344 | - allocate any memory for a new string, and cson_value_fetch_string() | |
| 2345 | - will return an empty string as opposed to a NULL string. | |
| 2346 | -*/ | |
| 2347 | -static int cson_value_set_string( cson_value * val, char const * str, unsigned int len ); | |
| 2348 | - | |
| 2349 | - | |
| 2350 | -cson_value * cson_value_new() | |
| 2351 | -{ | |
| 2352 | - cson_value * v = (cson_value *)cson_malloc(sizeof(cson_value),"cson_value_new"); | |
| 2353 | - if( v ) *v = cson_value_undef; | |
| 2268 | +static cson_value * cson_value_new(cson_type_id t, size_t extra); | |
| 2269 | + | |
| 2270 | +#define CSON_CAST(T,V) ((T*)((V)->value)) | |
| 2271 | +#define CSON_VCAST(V) ((cson_value *)(((unsigned char *)(V))-sizeof(cson_value))) | |
| 2272 | +#define CSON_INT(V) ((cson_int_t*)(V)->value) | |
| 2273 | +#define CSON_DBL(V) CSON_CAST(cson_double_t,(V)) | |
| 2274 | +#define CSON_STR(V) CSON_CAST(cson_string,(V)) | |
| 2275 | +#define CSON_OBJ(V) CSON_CAST(cson_object,(V)) | |
| 2276 | +#define CSON_ARRAY(V) CSON_CAST(cson_array,(V)) | |
| 2277 | + | |
| 2278 | +cson_value * cson_value_new(cson_type_id t, size_t extra) | |
| 2279 | +{ | |
| 2280 | + static const size_t vsz = sizeof(cson_value); | |
| 2281 | + const size_t sz = vsz + extra; | |
| 2282 | + size_t tx = 0; | |
| 2283 | + cson_value def = cson_value_undef; | |
| 2284 | + cson_value * v = NULL; | |
| 2285 | + char const * reason = "cson_value_new"; | |
| 2286 | + switch(t) | |
| 2287 | + { | |
| 2288 | + case CSON_TYPE_ARRAY: | |
| 2289 | + assert( 0 == extra ); | |
| 2290 | + def = cson_value_array_empty; | |
| 2291 | + tx = sizeof(cson_array); | |
| 2292 | + reason = "cson_value:array"; | |
| 2293 | + break; | |
| 2294 | + case CSON_TYPE_DOUBLE: | |
| 2295 | + assert( 0 == extra ); | |
| 2296 | + def = cson_value_double_empty; | |
| 2297 | + tx = sizeof(cson_double_t); | |
| 2298 | + reason = "cson_value:double"; | |
| 2299 | + break; | |
| 2300 | + case CSON_TYPE_INTEGER: | |
| 2301 | + assert( 0 == extra ); | |
| 2302 | + def = cson_value_integer_empty; | |
| 2303 | + tx = sizeof(cson_int_t); | |
| 2304 | + reason = "cson_value:int"; | |
| 2305 | + break; | |
| 2306 | + case CSON_TYPE_STRING: | |
| 2307 | + assert( 0 != extra ); | |
| 2308 | + def = cson_value_string_empty; | |
| 2309 | + tx = sizeof(cson_string); | |
| 2310 | + reason = "cson_value:string"; | |
| 2311 | + break; | |
| 2312 | + case CSON_TYPE_OBJECT: | |
| 2313 | + assert( 0 == extra ); | |
| 2314 | + def = cson_value_object_empty; | |
| 2315 | + tx = sizeof(cson_object); | |
| 2316 | + reason = "cson_value:object"; | |
| 2317 | + break; | |
| 2318 | + default: | |
| 2319 | + assert(0 && "Unhandled type in cson_value_new()!"); | |
| 2320 | + return NULL; | |
| 2321 | + } | |
| 2322 | + assert( def.api->typeID != CSON_TYPE_UNDEF ); | |
| 2323 | + v = (cson_value *)cson_malloc(sz+tx, reason); | |
| 2324 | + if( v ) { | |
| 2325 | + *v = def; | |
| 2326 | + if(tx || extra){ | |
| 2327 | + memset(v+1, 0, tx + extra); | |
| 2328 | + v->value = (void *)(v+1); | |
| 2329 | + } | |
| 2330 | + } | |
| 2354 | 2331 | return v; |
| 2355 | 2332 | } |
| 2356 | 2333 | |
| 2357 | 2334 | |
| 2358 | 2335 | void cson_value_free(cson_value *v) |
| @@ -2414,151 +2391,31 @@ | ||
| 2414 | 2391 | *val = cson_value_undef; |
| 2415 | 2392 | val->refcount = rc; |
| 2416 | 2393 | } |
| 2417 | 2394 | } |
| 2418 | 2395 | } |
| 2419 | - | |
| 2420 | -static void cson_value_destroy_integer( cson_value * self ) | |
| 2421 | -{ | |
| 2422 | - if( self ) | |
| 2423 | - { | |
| 2424 | -#if !CSON_VOID_PTR_IS_BIG | |
| 2425 | - cson_free(self->value,"cson_int_t"); | |
| 2426 | -#endif | |
| 2427 | - *self = cson_value_empty; | |
| 2428 | - } | |
| 2429 | -} | |
| 2430 | -static int cson_value_set_integer( cson_value * val, cson_int_t v ) | |
| 2431 | -{ | |
| 2432 | - if( ! val ) return cson_rc.ArgError; | |
| 2433 | - else | |
| 2434 | - { | |
| 2435 | -#if CSON_VOID_PTR_IS_BIG | |
| 2436 | - cson_value_clean( val ); | |
| 2437 | - val->value = (void *)v; | |
| 2438 | -#else | |
| 2439 | - cson_int_t * iv = NULL; | |
| 2440 | - iv = (cson_int_t*)cson_malloc(sizeof(cson_int_t), "cson_int_t"); | |
| 2441 | - if( ! iv ) return cson_rc.AllocError; | |
| 2442 | - cson_value_clean( val ); | |
| 2443 | - *iv = v; | |
| 2444 | - val->value = iv; | |
| 2445 | -#endif | |
| 2446 | - val->api = &cson_value_api_integer; | |
| 2447 | - return 0; | |
| 2448 | - } | |
| 2449 | -} | |
| 2450 | - | |
| 2451 | -static int cson_value_set_double( cson_value * val, cson_double_t v ) | |
| 2452 | -{ | |
| 2453 | - if( ! val ) return cson_rc.ArgError; | |
| 2454 | - else | |
| 2455 | - { | |
| 2456 | - cson_double_t * rv = NULL; | |
| 2457 | - cson_value_clean( val ); | |
| 2458 | - val->api = &cson_value_api_double; | |
| 2459 | - if( 0.0 != v ) | |
| 2460 | - { | |
| 2461 | - /* | |
| 2462 | - Reminder: we can't re-use val if it alreay is-a double | |
| 2463 | - because we have no reference counting. | |
| 2464 | - */ | |
| 2465 | - rv = (cson_double_t*)cson_malloc(sizeof(cson_double_t),"double"); | |
| 2466 | - if( ! rv ) return cson_rc.AllocError; | |
| 2467 | - } | |
| 2468 | - if(NULL != rv) *rv = v; | |
| 2469 | - val->value = rv; | |
| 2470 | - return 0; | |
| 2471 | - } | |
| 2472 | -} | |
| 2473 | - | |
| 2474 | -static cson_string * cson_string_shared_empty() | |
| 2475 | -{ | |
| 2476 | - /** | |
| 2477 | - We have code in place elsewhere to avoid that | |
| 2478 | - cson_string_cstr(&bob) and cson_string_str(&bob) will misbehave | |
| 2479 | - by accessing the bytes directly after bob (which are undefined | |
| 2480 | - in this case). | |
| 2481 | - */ | |
| 2482 | -#if 0 | |
| 2483 | - static cson_string bob[2] = {cson_string_empty_m, | |
| 2484 | - cson_string_empty_m/*trick to 0-init bob[0]'s tail*/}; | |
| 2485 | - return &bob[0]; | |
| 2486 | -#else | |
| 2487 | - static cson_string bob = cson_string_empty_m; | |
| 2488 | - return &bob; | |
| 2489 | -#endif | |
| 2490 | -} | |
| 2491 | - | |
| 2492 | -static int cson_value_set_string( cson_value * val, char const * str, unsigned int len ) | |
| 2493 | -{ | |
| 2494 | - cson_string * jstr = NULL; | |
| 2495 | - if( ! val ) return cson_rc.ArgError; | |
| 2496 | - cson_value_clean( val ); | |
| 2497 | - val->api = &cson_value_api_string; | |
| 2498 | - if( !str || !*str || !len ) | |
| 2499 | - { | |
| 2500 | - val->value = cson_string_shared_empty(); | |
| 2501 | - return 0; | |
| 2502 | - } | |
| 2503 | - else | |
| 2504 | - { | |
| 2505 | - jstr = cson_string_alloc( len ); | |
| 2506 | - if( NULL == jstr ) return cson_rc.AllocError; | |
| 2507 | - else | |
| 2508 | - { | |
| 2509 | - if( len ) | |
| 2510 | - { | |
| 2511 | - char * dest = cson_string_str( jstr ); | |
| 2512 | - val->value = jstr; | |
| 2513 | - strncpy( dest, str, len ); | |
| 2514 | - } | |
| 2515 | - /* else it's the empty string special value */ | |
| 2516 | - return 0; | |
| 2517 | - } | |
| 2518 | - } | |
| 2519 | -} | |
| 2520 | - | |
| 2521 | 2396 | |
| 2522 | 2397 | static cson_value * cson_value_array_alloc() |
| 2523 | 2398 | { |
| 2524 | - cson_value * v = (cson_value*)cson_malloc(sizeof(cson_value),"cson_value_array"); | |
| 2399 | + cson_value * v = cson_value_new(CSON_TYPE_ARRAY,0); | |
| 2525 | 2400 | if( NULL != v ) |
| 2526 | 2401 | { |
| 2527 | - cson_array * ar = (cson_array *)cson_malloc(sizeof(cson_array),"cson_array"); | |
| 2528 | - if( ! ar ) | |
| 2529 | - { | |
| 2530 | - cson_free(v,"cson_array"); | |
| 2531 | - v = NULL; | |
| 2532 | - } | |
| 2533 | - else | |
| 2534 | - { | |
| 2535 | - *ar = cson_array_empty; | |
| 2536 | - *v = cson_value_array_empty; | |
| 2537 | - v->value = ar; | |
| 2538 | - } | |
| 2402 | + cson_array * ar = CSON_ARRAY(v); | |
| 2403 | + assert(NULL != ar); | |
| 2404 | + *ar = cson_array_empty; | |
| 2539 | 2405 | } |
| 2540 | 2406 | return v; |
| 2541 | 2407 | } |
| 2542 | 2408 | |
| 2543 | 2409 | static cson_value * cson_value_object_alloc() |
| 2544 | 2410 | { |
| 2545 | - cson_value * v = (cson_value*)cson_malloc(sizeof(cson_value),"cson_value_object"); | |
| 2411 | + cson_value * v = cson_value_new(CSON_TYPE_OBJECT,0); | |
| 2546 | 2412 | if( NULL != v ) |
| 2547 | 2413 | { |
| 2548 | - cson_object * obj = (cson_object*)cson_malloc(sizeof(cson_object),"cson_value"); | |
| 2549 | - if( ! obj ) | |
| 2550 | - { | |
| 2551 | - cson_free(v,"cson_value_object"); | |
| 2552 | - v = NULL; | |
| 2553 | - } | |
| 2554 | - else | |
| 2555 | - { | |
| 2556 | - *obj = cson_object_empty; | |
| 2557 | - *v = cson_value_object_empty; | |
| 2558 | - v->value = obj; | |
| 2559 | - } | |
| 2414 | + cson_object * obj = CSON_OBJ(v); | |
| 2415 | + assert(NULL != obj); | |
| 2416 | + *obj = cson_object_empty; | |
| 2560 | 2417 | } |
| 2561 | 2418 | return v; |
| 2562 | 2419 | } |
| 2563 | 2420 | |
| 2564 | 2421 | cson_value * cson_value_new_object() |
| @@ -2612,31 +2469,10 @@ | ||
| 2612 | 2469 | cson_kvp_clean(kvp); |
| 2613 | 2470 | cson_free(kvp,"cson_kvp"); |
| 2614 | 2471 | } |
| 2615 | 2472 | } |
| 2616 | 2473 | |
| 2617 | -/** | |
| 2618 | - cson_value_api::destroy_value() impl for Object | |
| 2619 | - values. Cleans up self-owned memory and overwrites | |
| 2620 | - self to have the undefined value, but does not | |
| 2621 | - free self. | |
| 2622 | - | |
| 2623 | - If self->value == cson_string_shared_empty() | |
| 2624 | - then this function does not actually free it. | |
| 2625 | -*/ | |
| 2626 | -static void cson_value_destroy_string( cson_value * self ) | |
| 2627 | -{ | |
| 2628 | - if(self && self->value) { | |
| 2629 | - cson_string * obj = (cson_string *)self->value; | |
| 2630 | - if( obj != cson_string_shared_empty() ) | |
| 2631 | - { | |
| 2632 | - cson_free(self->value,"cson_string"); | |
| 2633 | - } | |
| 2634 | - *self = cson_value_undef; | |
| 2635 | - } | |
| 2636 | -} | |
| 2637 | - | |
| 2638 | 2474 | |
| 2639 | 2475 | /** |
| 2640 | 2476 | cson_value_api::destroy_value() impl for Object |
| 2641 | 2477 | values. Cleans up self-owned memory and overwrites |
| 2642 | 2478 | self to have the undefined value, but does not |
| @@ -2646,11 +2482,10 @@ | ||
| 2646 | 2482 | { |
| 2647 | 2483 | if(self && self->value) { |
| 2648 | 2484 | cson_object * obj = (cson_object *)self->value; |
| 2649 | 2485 | assert( self->value == obj ); |
| 2650 | 2486 | cson_kvp_list_clean( &obj->kvp, cson_kvp_free ); |
| 2651 | - cson_free(self->value,"cson_object"); | |
| 2652 | 2487 | *self = cson_value_undef; |
| 2653 | 2488 | } |
| 2654 | 2489 | } |
| 2655 | 2490 | |
| 2656 | 2491 | /** |
| @@ -2701,11 +2536,10 @@ | ||
| 2701 | 2536 | { |
| 2702 | 2537 | cson_array * ar = cson_value_get_array(self); |
| 2703 | 2538 | if(ar) { |
| 2704 | 2539 | assert( self->value == ar ); |
| 2705 | 2540 | cson_array_clean( ar, 1 ); |
| 2706 | - cson_free(ar,"cson_array"); | |
| 2707 | 2541 | *self = cson_value_undef; |
| 2708 | 2542 | } |
| 2709 | 2543 | } |
| 2710 | 2544 | |
| 2711 | 2545 | |
| @@ -2857,16 +2691,16 @@ | ||
| 2857 | 2691 | cson_value_fetch_bool( val, &b ); |
| 2858 | 2692 | i = b; |
| 2859 | 2693 | break; |
| 2860 | 2694 | } |
| 2861 | 2695 | case CSON_TYPE_INTEGER: { |
| 2862 | -#if CSON_VOID_PTR_IS_BIG | |
| 2863 | - i = (cson_int_t)val->value; | |
| 2864 | -#else | |
| 2865 | - cson_int_t const * x = (cson_int_t const *)val->value; | |
| 2696 | + cson_int_t const * x = CSON_INT(val); | |
| 2697 | + if(!x) | |
| 2698 | + { | |
| 2699 | + assert( val == &CSON_SPECIAL_VALUES[CSON_VAL_INT_0] ); | |
| 2700 | + } | |
| 2866 | 2701 | i = x ? *x : 0; |
| 2867 | -#endif | |
| 2868 | 2702 | break; |
| 2869 | 2703 | } |
| 2870 | 2704 | case CSON_TYPE_DOUBLE: { |
| 2871 | 2705 | cson_double_t d = 0.0; |
| 2872 | 2706 | cson_value_fetch_double( val, &d ); |
| @@ -2915,11 +2749,11 @@ | ||
| 2915 | 2749 | cson_value_fetch_integer( val, &i ); |
| 2916 | 2750 | d = i; |
| 2917 | 2751 | break; |
| 2918 | 2752 | } |
| 2919 | 2753 | case CSON_TYPE_DOUBLE: { |
| 2920 | - cson_double_t const* dv = (cson_double_t const *)val->value; | |
| 2754 | + cson_double_t const* dv = CSON_DBL(val); | |
| 2921 | 2755 | d = dv ? *dv : 0.0; |
| 2922 | 2756 | break; |
| 2923 | 2757 | } |
| 2924 | 2758 | default: |
| 2925 | 2759 | rc = cson_rc.TypeError; |
| @@ -2964,11 +2798,11 @@ | ||
| 2964 | 2798 | { |
| 2965 | 2799 | if( ! val ) return cson_rc.ArgError; |
| 2966 | 2800 | else if( ! cson_value_is_object(val) ) return cson_rc.TypeError; |
| 2967 | 2801 | else |
| 2968 | 2802 | { |
| 2969 | - if(obj) *obj = (cson_object*)val->value; | |
| 2803 | + if(obj) *obj = CSON_OBJ(val); | |
| 2970 | 2804 | return 0; |
| 2971 | 2805 | } |
| 2972 | 2806 | } |
| 2973 | 2807 | cson_object * cson_value_get_object( cson_value const * v ) |
| 2974 | 2808 | { |
| @@ -2978,14 +2812,14 @@ | ||
| 2978 | 2812 | } |
| 2979 | 2813 | |
| 2980 | 2814 | int cson_value_fetch_array( cson_value const * val, cson_array ** ar) |
| 2981 | 2815 | { |
| 2982 | 2816 | if( ! val ) return cson_rc.ArgError; |
| 2983 | - else if( ! cson_value_is_array(val) ) return cson_rc.TypeError; | |
| 2817 | + else if( !cson_value_is_array(val) ) return cson_rc.TypeError; | |
| 2984 | 2818 | else |
| 2985 | 2819 | { |
| 2986 | - if(ar) *ar = (cson_array*)val->value; | |
| 2820 | + if(ar) *ar = CSON_ARRAY(val); | |
| 2987 | 2821 | return 0; |
| 2988 | 2822 | } |
| 2989 | 2823 | } |
| 2990 | 2824 | |
| 2991 | 2825 | cson_array * cson_value_get_array( cson_value const * v ) |
| @@ -3084,18 +2918,15 @@ | ||
| 3084 | 2918 | cson_value * cson_value_new_integer( cson_int_t v ) |
| 3085 | 2919 | { |
| 3086 | 2920 | if( 0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_INT_0]; |
| 3087 | 2921 | else |
| 3088 | 2922 | { |
| 3089 | - cson_value * c = cson_value_new(); | |
| 2923 | + cson_value * c = cson_value_new(CSON_TYPE_INTEGER,0); | |
| 2924 | + | |
| 3090 | 2925 | if( c ) |
| 3091 | 2926 | { |
| 3092 | - if( 0 != cson_value_set_integer( c, v ) ) | |
| 3093 | - { | |
| 3094 | - cson_value_free(c); | |
| 3095 | - c = NULL; | |
| 3096 | - } | |
| 2927 | + *CSON_INT(c) = v; | |
| 3097 | 2928 | } |
| 3098 | 2929 | return c; |
| 3099 | 2930 | } |
| 3100 | 2931 | } |
| 3101 | 2932 | |
| @@ -3102,35 +2933,35 @@ | ||
| 3102 | 2933 | cson_value * cson_value_new_double( cson_double_t v ) |
| 3103 | 2934 | { |
| 3104 | 2935 | if( 0.0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_DBL_0]; |
| 3105 | 2936 | else |
| 3106 | 2937 | { |
| 3107 | - cson_value * c = cson_value_new(); | |
| 2938 | + cson_value * c = cson_value_new(CSON_TYPE_DOUBLE,0); | |
| 3108 | 2939 | if( c ) |
| 3109 | 2940 | { |
| 3110 | - if( 0 != cson_value_set_double( c, v ) ) | |
| 3111 | - { | |
| 3112 | - cson_value_free(c); | |
| 3113 | - c = NULL; | |
| 3114 | - } | |
| 2941 | + *CSON_DBL(c) = v; | |
| 3115 | 2942 | } |
| 3116 | 2943 | return c; |
| 3117 | 2944 | } |
| 3118 | 2945 | } |
| 3119 | 2946 | cson_value * cson_value_new_string( char const * str, unsigned int len ) |
| 3120 | 2947 | { |
| 3121 | - if( !str || !len ) return &CSON_SPECIAL_VALUES[CSON_VAL_STR_EMPTY]; | |
| 2948 | + if( !str || !*str || !len ) return &CSON_SPECIAL_VALUES[CSON_VAL_STR_EMPTY]; | |
| 3122 | 2949 | else |
| 3123 | 2950 | { |
| 3124 | - cson_value * c = cson_value_new(); | |
| 2951 | + cson_value * c = cson_value_new(CSON_TYPE_STRING, len + 1/*NUL byte*/); | |
| 3125 | 2952 | if( c ) |
| 3126 | 2953 | { |
| 3127 | - if( 0 != cson_value_set_string( c, str, len ) ) | |
| 3128 | - { | |
| 3129 | - cson_value_free(c); | |
| 3130 | - c = NULL; | |
| 3131 | - } | |
| 2954 | + char * dest = NULL; | |
| 2955 | + cson_string * s = CSON_STR(c); | |
| 2956 | + *s = cson_string_empty; | |
| 2957 | + assert( NULL != s ); | |
| 2958 | + s->length = len; | |
| 2959 | + dest = cson_string_str(s); | |
| 2960 | + assert( NULL != dest ); | |
| 2961 | + memcpy( dest, str, len ); | |
| 2962 | + dest[len] = 0; | |
| 3132 | 2963 | } |
| 3133 | 2964 | return c; |
| 3134 | 2965 | } |
| 3135 | 2966 | } |
| 3136 | 2967 | |
| @@ -4816,11 +4647,12 @@ | ||
| 4816 | 4647 | else |
| 4817 | 4648 | { |
| 4818 | 4649 | switch( orig->api->typeID ) |
| 4819 | 4650 | { |
| 4820 | 4651 | case CSON_TYPE_UNDEF: |
| 4821 | - return cson_value_new(); | |
| 4652 | + assert(0 && "This should never happen."); | |
| 4653 | + return NULL; | |
| 4822 | 4654 | case CSON_TYPE_NULL: |
| 4823 | 4655 | return cson_value_null(); |
| 4824 | 4656 | case CSON_TYPE_BOOL: |
| 4825 | 4657 | return cson_value_new_bool( cson_value_get_bool( orig ) ); |
| 4826 | 4658 | case CSON_TYPE_INTEGER: |
| @@ -4841,10 +4673,34 @@ | ||
| 4841 | 4673 | } |
| 4842 | 4674 | assert( 0 && "We can't get this far." ); |
| 4843 | 4675 | return NULL; |
| 4844 | 4676 | } |
| 4845 | 4677 | } |
| 4678 | + | |
| 4679 | +cson_value * cson_string_value(cson_string const * s) | |
| 4680 | +{ | |
| 4681 | + return s | |
| 4682 | + ? CSON_VCAST(s) | |
| 4683 | + : NULL; | |
| 4684 | +} | |
| 4685 | + | |
| 4686 | +cson_value * cson_object_value(cson_object const * s) | |
| 4687 | +{ | |
| 4688 | + return s | |
| 4689 | + ? CSON_VCAST(s) | |
| 4690 | + : NULL; | |
| 4691 | +} | |
| 4692 | + | |
| 4693 | + | |
| 4694 | +cson_value * cson_array_value(cson_array const * s) | |
| 4695 | +{ | |
| 4696 | + return s | |
| 4697 | + ? CSON_VCAST(s) | |
| 4698 | + : NULL; | |
| 4699 | +} | |
| 4700 | + | |
| 4701 | + | |
| 4846 | 4702 | |
| 4847 | 4703 | #if 0 |
| 4848 | 4704 | /* i'm not happy with this... */ |
| 4849 | 4705 | char * cson_pod_to_string( cson_value const * orig ) |
| 4850 | 4706 | { |
| @@ -4955,10 +4811,17 @@ | ||
| 4955 | 4811 | #endif |
| 4956 | 4812 | |
| 4957 | 4813 | #undef MARKER |
| 4958 | 4814 | #undef CSON_OBJECT_PROPS_SORT |
| 4959 | 4815 | #undef CSON_OBJECT_PROPS_SORT_USE_LENGTH |
| 4816 | +#undef CSON_CAST | |
| 4817 | +#undef CSON_INT | |
| 4818 | +#undef CSON_DBL | |
| 4819 | +#undef CSON_STR | |
| 4820 | +#undef CSON_OBJ | |
| 4821 | +#undef CSON_ARRAY | |
| 4822 | +#undef CSON_VCAST | |
| 4960 | 4823 | /* end file ./cson.c */ |
| 4961 | 4824 | /* begin file ./cson_lists.h */ |
| 4962 | 4825 | /* Auto-generated from cson_list.h. Edit at your own risk! */ |
| 4963 | 4826 | unsigned int cson_value_list_reserve( cson_value_list * self, unsigned int n ) |
| 4964 | 4827 | { |
| 4965 | 4828 |
| --- src/cson_amalgamation.c | |
| +++ src/cson_amalgamation.c | |
| @@ -1570,35 +1570,28 @@ | |
| 1570 | const cson_object_iterator cson_object_iterator_empty = cson_object_iterator_empty_m; |
| 1571 | const cson_buffer cson_buffer_empty = cson_buffer_empty_m; |
| 1572 | const cson_parse_info cson_parse_info_empty = cson_parse_info_empty_m; |
| 1573 | |
| 1574 | static void cson_value_destroy_zero_it( cson_value * self ); |
| 1575 | static void cson_value_destroy_free( cson_value * self ); |
| 1576 | static void cson_value_destroy_object( cson_value * self ); |
| 1577 | static void cson_value_destroy_integer( cson_value * self ); |
| 1578 | /** |
| 1579 | If self is-a array then this function destroys its contents, |
| 1580 | else this function does nothing. |
| 1581 | */ |
| 1582 | static void cson_value_destroy_array( cson_value * self ); |
| 1583 | |
| 1584 | /** |
| 1585 | If self is-a string then this function destroys its contents, |
| 1586 | else this function does nothing. |
| 1587 | */ |
| 1588 | static void cson_value_destroy_string( cson_value * self ); |
| 1589 | |
| 1590 | static const cson_value_api cson_value_api_null = { CSON_TYPE_NULL, cson_value_destroy_zero_it }; |
| 1591 | static const cson_value_api cson_value_api_undef = { CSON_TYPE_UNDEF, cson_value_destroy_zero_it }; |
| 1592 | static const cson_value_api cson_value_api_bool = { CSON_TYPE_BOOL, cson_value_destroy_zero_it }; |
| 1593 | static const cson_value_api cson_value_api_integer = { CSON_TYPE_INTEGER, cson_value_destroy_integer }; |
| 1594 | static const cson_value_api cson_value_api_double = { CSON_TYPE_DOUBLE, cson_value_destroy_free }; |
| 1595 | static const cson_value_api cson_value_api_string = { CSON_TYPE_STRING, cson_value_destroy_string }; |
| 1596 | static const cson_value_api cson_value_api_array = { CSON_TYPE_ARRAY, cson_value_destroy_array }; |
| 1597 | static const cson_value_api cson_value_api_object = { CSON_TYPE_OBJECT, cson_value_destroy_object }; |
| 1598 | |
| 1599 | static const cson_value cson_value_undef = { &cson_value_api_undef, NULL, 0 }; |
| 1600 | static const cson_value cson_value_bool_empty = { &cson_value_api_bool, NULL, 0 }; |
| 1601 | static const cson_value cson_value_integer_empty = { &cson_value_api_integer, NULL, 0 }; |
| 1602 | static const cson_value cson_value_double_empty = { &cson_value_api_double, NULL, 0 }; |
| 1603 | static const cson_value cson_value_string_empty = { &cson_value_api_string, NULL, 0 }; |
| 1604 | static const cson_value cson_value_array_empty = { &cson_value_api_array, NULL, 0 }; |
| @@ -1608,11 +1601,11 @@ | |
| 1608 | struct cson_string |
| 1609 | { |
| 1610 | unsigned int length; |
| 1611 | }; |
| 1612 | #define cson_string_empty_m {0/*length*/} |
| 1613 | |
| 1614 | /** |
| 1615 | |
| 1616 | Holds special shared "constant" (though they are non-const) |
| 1617 | values. |
| 1618 | |
| @@ -2033,37 +2026,22 @@ | |
| 2033 | if( self ) |
| 2034 | { |
| 2035 | *self = cson_value_undef; |
| 2036 | } |
| 2037 | } |
| 2038 | |
| 2039 | /** |
| 2040 | If self is not null, free(self->value) is called. *self is then |
| 2041 | overwritten to have the undefined type. self is not freed. |
| 2042 | |
| 2043 | */ |
| 2044 | void cson_value_destroy_free( cson_value * self ) |
| 2045 | { |
| 2046 | if(self) { |
| 2047 | if( self->value ) |
| 2048 | { |
| 2049 | cson_free(self->value,"cson_value_destroy_free()"); |
| 2050 | } |
| 2051 | *self = cson_value_undef; |
| 2052 | } |
| 2053 | } |
| 2054 | |
| 2055 | |
| 2056 | |
| 2057 | /** |
| 2058 | A key/value pair collection. |
| 2059 | |
| 2060 | Each of these objects owns its key/value pointers, and they |
| 2061 | are cleaned up by cson_kvp_clean(). |
| 2062 | */ |
| 2063 | struct cson_kvp |
| 2064 | { |
| 2065 | cson_string * key; |
| 2066 | cson_value * value; |
| 2067 | }; |
| 2068 | #define cson_kvp_empty_m {NULL,NULL} |
| 2069 | static const cson_kvp cson_kvp_empty = cson_kvp_empty_m; |
| @@ -2261,32 +2239,23 @@ | |
| 2261 | # define VALUE_T cson_kvp * |
| 2262 | # define VALUE_T_IS_PTR 1 |
| 2263 | #else |
| 2264 | #endif |
| 2265 | |
| 2266 | /* |
| 2267 | Reminders to self: |
| 2268 | |
| 2269 | - 20110126: moved cson_value_new() and cson_value_set_xxx() out of the |
| 2270 | public API because: |
| 2271 | |
| 2272 | a) They can be easily mis-used to cause memory leaks, even when used in |
| 2273 | a manner which seems relatively intuitive. |
| 2274 | |
| 2275 | b) Having them in the API prohibits us from eventually doing certain |
| 2276 | allocation optimizations like not allocating Booleans, |
| 2277 | Integer/Doubles with the value 0, or empty Strings. The main problem |
| 2278 | is that cson_value_set_xxx() cannot be implemented properly if we |
| 2279 | add that type of optimization. |
| 2280 | */ |
| 2281 | |
| 2282 | /** |
| 2283 | Allocates a new value with the "undefined" value and transfers |
| 2284 | ownership of it to the caller. Use The cson_value_set_xxx() family |
| 2285 | of functions to assign a typed value to it. It must eventually be |
| 2286 | destroyed, by the caller or its owning container, by passing it to |
| 2287 | cson_value_free(). |
| 2288 | |
| 2289 | Returns NULL on allocation error. |
| 2290 | |
| 2291 | @see cson_value_new_array() |
| 2292 | @see cson_value_new_object() |
| @@ -2294,65 +2263,73 @@ | |
| 2294 | @see cson_value_new_integer() |
| 2295 | @see cson_value_new_double() |
| 2296 | @see cson_value_new_bool() |
| 2297 | @see cson_value_free() |
| 2298 | */ |
| 2299 | static cson_value * cson_value_new(); |
| 2300 | /** |
| 2301 | Cleans any existing contents of val and sets its new value |
| 2302 | to the special NULL value. |
| 2303 | |
| 2304 | Returns 0 on success. |
| 2305 | |
| 2306 | */ |
| 2307 | #if 0 |
| 2308 | static int cson_value_set_null( cson_value * val ); |
| 2309 | #endif |
| 2310 | /** |
| 2311 | Cleans any existing contents of val and sets its new value |
| 2312 | to v. |
| 2313 | |
| 2314 | Returns 0 on success. |
| 2315 | |
| 2316 | */ |
| 2317 | #if 0 |
| 2318 | static int cson_value_set_bool( cson_value * val, char v ); |
| 2319 | #endif |
| 2320 | /** |
| 2321 | Cleans any existing contents of val and sets its new value |
| 2322 | to v. |
| 2323 | |
| 2324 | Returns 0 on success. |
| 2325 | |
| 2326 | */ |
| 2327 | static int cson_value_set_integer( cson_value * val, cson_int_t v ); |
| 2328 | /** |
| 2329 | Cleans any existing contents of val and sets its new value |
| 2330 | to v. |
| 2331 | |
| 2332 | Returns 0 on success. |
| 2333 | */ |
| 2334 | static int cson_value_set_double( cson_value * val, cson_double_t v ); |
| 2335 | |
| 2336 | /** |
| 2337 | Cleans any existing contents of val and sets its new value to |
| 2338 | str. On success, ownership of str is passed on to val. On error |
| 2339 | ownership is not changed. |
| 2340 | |
| 2341 | Returns 0 on success. |
| 2342 | |
| 2343 | If str is NULL, (!*str), or (!len) then this function does not |
| 2344 | allocate any memory for a new string, and cson_value_fetch_string() |
| 2345 | will return an empty string as opposed to a NULL string. |
| 2346 | */ |
| 2347 | static int cson_value_set_string( cson_value * val, char const * str, unsigned int len ); |
| 2348 | |
| 2349 | |
| 2350 | cson_value * cson_value_new() |
| 2351 | { |
| 2352 | cson_value * v = (cson_value *)cson_malloc(sizeof(cson_value),"cson_value_new"); |
| 2353 | if( v ) *v = cson_value_undef; |
| 2354 | return v; |
| 2355 | } |
| 2356 | |
| 2357 | |
| 2358 | void cson_value_free(cson_value *v) |
| @@ -2414,151 +2391,31 @@ | |
| 2414 | *val = cson_value_undef; |
| 2415 | val->refcount = rc; |
| 2416 | } |
| 2417 | } |
| 2418 | } |
| 2419 | |
| 2420 | static void cson_value_destroy_integer( cson_value * self ) |
| 2421 | { |
| 2422 | if( self ) |
| 2423 | { |
| 2424 | #if !CSON_VOID_PTR_IS_BIG |
| 2425 | cson_free(self->value,"cson_int_t"); |
| 2426 | #endif |
| 2427 | *self = cson_value_empty; |
| 2428 | } |
| 2429 | } |
| 2430 | static int cson_value_set_integer( cson_value * val, cson_int_t v ) |
| 2431 | { |
| 2432 | if( ! val ) return cson_rc.ArgError; |
| 2433 | else |
| 2434 | { |
| 2435 | #if CSON_VOID_PTR_IS_BIG |
| 2436 | cson_value_clean( val ); |
| 2437 | val->value = (void *)v; |
| 2438 | #else |
| 2439 | cson_int_t * iv = NULL; |
| 2440 | iv = (cson_int_t*)cson_malloc(sizeof(cson_int_t), "cson_int_t"); |
| 2441 | if( ! iv ) return cson_rc.AllocError; |
| 2442 | cson_value_clean( val ); |
| 2443 | *iv = v; |
| 2444 | val->value = iv; |
| 2445 | #endif |
| 2446 | val->api = &cson_value_api_integer; |
| 2447 | return 0; |
| 2448 | } |
| 2449 | } |
| 2450 | |
| 2451 | static int cson_value_set_double( cson_value * val, cson_double_t v ) |
| 2452 | { |
| 2453 | if( ! val ) return cson_rc.ArgError; |
| 2454 | else |
| 2455 | { |
| 2456 | cson_double_t * rv = NULL; |
| 2457 | cson_value_clean( val ); |
| 2458 | val->api = &cson_value_api_double; |
| 2459 | if( 0.0 != v ) |
| 2460 | { |
| 2461 | /* |
| 2462 | Reminder: we can't re-use val if it alreay is-a double |
| 2463 | because we have no reference counting. |
| 2464 | */ |
| 2465 | rv = (cson_double_t*)cson_malloc(sizeof(cson_double_t),"double"); |
| 2466 | if( ! rv ) return cson_rc.AllocError; |
| 2467 | } |
| 2468 | if(NULL != rv) *rv = v; |
| 2469 | val->value = rv; |
| 2470 | return 0; |
| 2471 | } |
| 2472 | } |
| 2473 | |
| 2474 | static cson_string * cson_string_shared_empty() |
| 2475 | { |
| 2476 | /** |
| 2477 | We have code in place elsewhere to avoid that |
| 2478 | cson_string_cstr(&bob) and cson_string_str(&bob) will misbehave |
| 2479 | by accessing the bytes directly after bob (which are undefined |
| 2480 | in this case). |
| 2481 | */ |
| 2482 | #if 0 |
| 2483 | static cson_string bob[2] = {cson_string_empty_m, |
| 2484 | cson_string_empty_m/*trick to 0-init bob[0]'s tail*/}; |
| 2485 | return &bob[0]; |
| 2486 | #else |
| 2487 | static cson_string bob = cson_string_empty_m; |
| 2488 | return &bob; |
| 2489 | #endif |
| 2490 | } |
| 2491 | |
| 2492 | static int cson_value_set_string( cson_value * val, char const * str, unsigned int len ) |
| 2493 | { |
| 2494 | cson_string * jstr = NULL; |
| 2495 | if( ! val ) return cson_rc.ArgError; |
| 2496 | cson_value_clean( val ); |
| 2497 | val->api = &cson_value_api_string; |
| 2498 | if( !str || !*str || !len ) |
| 2499 | { |
| 2500 | val->value = cson_string_shared_empty(); |
| 2501 | return 0; |
| 2502 | } |
| 2503 | else |
| 2504 | { |
| 2505 | jstr = cson_string_alloc( len ); |
| 2506 | if( NULL == jstr ) return cson_rc.AllocError; |
| 2507 | else |
| 2508 | { |
| 2509 | if( len ) |
| 2510 | { |
| 2511 | char * dest = cson_string_str( jstr ); |
| 2512 | val->value = jstr; |
| 2513 | strncpy( dest, str, len ); |
| 2514 | } |
| 2515 | /* else it's the empty string special value */ |
| 2516 | return 0; |
| 2517 | } |
| 2518 | } |
| 2519 | } |
| 2520 | |
| 2521 | |
| 2522 | static cson_value * cson_value_array_alloc() |
| 2523 | { |
| 2524 | cson_value * v = (cson_value*)cson_malloc(sizeof(cson_value),"cson_value_array"); |
| 2525 | if( NULL != v ) |
| 2526 | { |
| 2527 | cson_array * ar = (cson_array *)cson_malloc(sizeof(cson_array),"cson_array"); |
| 2528 | if( ! ar ) |
| 2529 | { |
| 2530 | cson_free(v,"cson_array"); |
| 2531 | v = NULL; |
| 2532 | } |
| 2533 | else |
| 2534 | { |
| 2535 | *ar = cson_array_empty; |
| 2536 | *v = cson_value_array_empty; |
| 2537 | v->value = ar; |
| 2538 | } |
| 2539 | } |
| 2540 | return v; |
| 2541 | } |
| 2542 | |
| 2543 | static cson_value * cson_value_object_alloc() |
| 2544 | { |
| 2545 | cson_value * v = (cson_value*)cson_malloc(sizeof(cson_value),"cson_value_object"); |
| 2546 | if( NULL != v ) |
| 2547 | { |
| 2548 | cson_object * obj = (cson_object*)cson_malloc(sizeof(cson_object),"cson_value"); |
| 2549 | if( ! obj ) |
| 2550 | { |
| 2551 | cson_free(v,"cson_value_object"); |
| 2552 | v = NULL; |
| 2553 | } |
| 2554 | else |
| 2555 | { |
| 2556 | *obj = cson_object_empty; |
| 2557 | *v = cson_value_object_empty; |
| 2558 | v->value = obj; |
| 2559 | } |
| 2560 | } |
| 2561 | return v; |
| 2562 | } |
| 2563 | |
| 2564 | cson_value * cson_value_new_object() |
| @@ -2612,31 +2469,10 @@ | |
| 2612 | cson_kvp_clean(kvp); |
| 2613 | cson_free(kvp,"cson_kvp"); |
| 2614 | } |
| 2615 | } |
| 2616 | |
| 2617 | /** |
| 2618 | cson_value_api::destroy_value() impl for Object |
| 2619 | values. Cleans up self-owned memory and overwrites |
| 2620 | self to have the undefined value, but does not |
| 2621 | free self. |
| 2622 | |
| 2623 | If self->value == cson_string_shared_empty() |
| 2624 | then this function does not actually free it. |
| 2625 | */ |
| 2626 | static void cson_value_destroy_string( cson_value * self ) |
| 2627 | { |
| 2628 | if(self && self->value) { |
| 2629 | cson_string * obj = (cson_string *)self->value; |
| 2630 | if( obj != cson_string_shared_empty() ) |
| 2631 | { |
| 2632 | cson_free(self->value,"cson_string"); |
| 2633 | } |
| 2634 | *self = cson_value_undef; |
| 2635 | } |
| 2636 | } |
| 2637 | |
| 2638 | |
| 2639 | /** |
| 2640 | cson_value_api::destroy_value() impl for Object |
| 2641 | values. Cleans up self-owned memory and overwrites |
| 2642 | self to have the undefined value, but does not |
| @@ -2646,11 +2482,10 @@ | |
| 2646 | { |
| 2647 | if(self && self->value) { |
| 2648 | cson_object * obj = (cson_object *)self->value; |
| 2649 | assert( self->value == obj ); |
| 2650 | cson_kvp_list_clean( &obj->kvp, cson_kvp_free ); |
| 2651 | cson_free(self->value,"cson_object"); |
| 2652 | *self = cson_value_undef; |
| 2653 | } |
| 2654 | } |
| 2655 | |
| 2656 | /** |
| @@ -2701,11 +2536,10 @@ | |
| 2701 | { |
| 2702 | cson_array * ar = cson_value_get_array(self); |
| 2703 | if(ar) { |
| 2704 | assert( self->value == ar ); |
| 2705 | cson_array_clean( ar, 1 ); |
| 2706 | cson_free(ar,"cson_array"); |
| 2707 | *self = cson_value_undef; |
| 2708 | } |
| 2709 | } |
| 2710 | |
| 2711 | |
| @@ -2857,16 +2691,16 @@ | |
| 2857 | cson_value_fetch_bool( val, &b ); |
| 2858 | i = b; |
| 2859 | break; |
| 2860 | } |
| 2861 | case CSON_TYPE_INTEGER: { |
| 2862 | #if CSON_VOID_PTR_IS_BIG |
| 2863 | i = (cson_int_t)val->value; |
| 2864 | #else |
| 2865 | cson_int_t const * x = (cson_int_t const *)val->value; |
| 2866 | i = x ? *x : 0; |
| 2867 | #endif |
| 2868 | break; |
| 2869 | } |
| 2870 | case CSON_TYPE_DOUBLE: { |
| 2871 | cson_double_t d = 0.0; |
| 2872 | cson_value_fetch_double( val, &d ); |
| @@ -2915,11 +2749,11 @@ | |
| 2915 | cson_value_fetch_integer( val, &i ); |
| 2916 | d = i; |
| 2917 | break; |
| 2918 | } |
| 2919 | case CSON_TYPE_DOUBLE: { |
| 2920 | cson_double_t const* dv = (cson_double_t const *)val->value; |
| 2921 | d = dv ? *dv : 0.0; |
| 2922 | break; |
| 2923 | } |
| 2924 | default: |
| 2925 | rc = cson_rc.TypeError; |
| @@ -2964,11 +2798,11 @@ | |
| 2964 | { |
| 2965 | if( ! val ) return cson_rc.ArgError; |
| 2966 | else if( ! cson_value_is_object(val) ) return cson_rc.TypeError; |
| 2967 | else |
| 2968 | { |
| 2969 | if(obj) *obj = (cson_object*)val->value; |
| 2970 | return 0; |
| 2971 | } |
| 2972 | } |
| 2973 | cson_object * cson_value_get_object( cson_value const * v ) |
| 2974 | { |
| @@ -2978,14 +2812,14 @@ | |
| 2978 | } |
| 2979 | |
| 2980 | int cson_value_fetch_array( cson_value const * val, cson_array ** ar) |
| 2981 | { |
| 2982 | if( ! val ) return cson_rc.ArgError; |
| 2983 | else if( ! cson_value_is_array(val) ) return cson_rc.TypeError; |
| 2984 | else |
| 2985 | { |
| 2986 | if(ar) *ar = (cson_array*)val->value; |
| 2987 | return 0; |
| 2988 | } |
| 2989 | } |
| 2990 | |
| 2991 | cson_array * cson_value_get_array( cson_value const * v ) |
| @@ -3084,18 +2918,15 @@ | |
| 3084 | cson_value * cson_value_new_integer( cson_int_t v ) |
| 3085 | { |
| 3086 | if( 0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_INT_0]; |
| 3087 | else |
| 3088 | { |
| 3089 | cson_value * c = cson_value_new(); |
| 3090 | if( c ) |
| 3091 | { |
| 3092 | if( 0 != cson_value_set_integer( c, v ) ) |
| 3093 | { |
| 3094 | cson_value_free(c); |
| 3095 | c = NULL; |
| 3096 | } |
| 3097 | } |
| 3098 | return c; |
| 3099 | } |
| 3100 | } |
| 3101 | |
| @@ -3102,35 +2933,35 @@ | |
| 3102 | cson_value * cson_value_new_double( cson_double_t v ) |
| 3103 | { |
| 3104 | if( 0.0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_DBL_0]; |
| 3105 | else |
| 3106 | { |
| 3107 | cson_value * c = cson_value_new(); |
| 3108 | if( c ) |
| 3109 | { |
| 3110 | if( 0 != cson_value_set_double( c, v ) ) |
| 3111 | { |
| 3112 | cson_value_free(c); |
| 3113 | c = NULL; |
| 3114 | } |
| 3115 | } |
| 3116 | return c; |
| 3117 | } |
| 3118 | } |
| 3119 | cson_value * cson_value_new_string( char const * str, unsigned int len ) |
| 3120 | { |
| 3121 | if( !str || !len ) return &CSON_SPECIAL_VALUES[CSON_VAL_STR_EMPTY]; |
| 3122 | else |
| 3123 | { |
| 3124 | cson_value * c = cson_value_new(); |
| 3125 | if( c ) |
| 3126 | { |
| 3127 | if( 0 != cson_value_set_string( c, str, len ) ) |
| 3128 | { |
| 3129 | cson_value_free(c); |
| 3130 | c = NULL; |
| 3131 | } |
| 3132 | } |
| 3133 | return c; |
| 3134 | } |
| 3135 | } |
| 3136 | |
| @@ -4816,11 +4647,12 @@ | |
| 4816 | else |
| 4817 | { |
| 4818 | switch( orig->api->typeID ) |
| 4819 | { |
| 4820 | case CSON_TYPE_UNDEF: |
| 4821 | return cson_value_new(); |
| 4822 | case CSON_TYPE_NULL: |
| 4823 | return cson_value_null(); |
| 4824 | case CSON_TYPE_BOOL: |
| 4825 | return cson_value_new_bool( cson_value_get_bool( orig ) ); |
| 4826 | case CSON_TYPE_INTEGER: |
| @@ -4841,10 +4673,34 @@ | |
| 4841 | } |
| 4842 | assert( 0 && "We can't get this far." ); |
| 4843 | return NULL; |
| 4844 | } |
| 4845 | } |
| 4846 | |
| 4847 | #if 0 |
| 4848 | /* i'm not happy with this... */ |
| 4849 | char * cson_pod_to_string( cson_value const * orig ) |
| 4850 | { |
| @@ -4955,10 +4811,17 @@ | |
| 4955 | #endif |
| 4956 | |
| 4957 | #undef MARKER |
| 4958 | #undef CSON_OBJECT_PROPS_SORT |
| 4959 | #undef CSON_OBJECT_PROPS_SORT_USE_LENGTH |
| 4960 | /* end file ./cson.c */ |
| 4961 | /* begin file ./cson_lists.h */ |
| 4962 | /* Auto-generated from cson_list.h. Edit at your own risk! */ |
| 4963 | unsigned int cson_value_list_reserve( cson_value_list * self, unsigned int n ) |
| 4964 | { |
| 4965 |
| --- src/cson_amalgamation.c | |
| +++ src/cson_amalgamation.c | |
| @@ -1570,35 +1570,28 @@ | |
| 1570 | const cson_object_iterator cson_object_iterator_empty = cson_object_iterator_empty_m; |
| 1571 | const cson_buffer cson_buffer_empty = cson_buffer_empty_m; |
| 1572 | const cson_parse_info cson_parse_info_empty = cson_parse_info_empty_m; |
| 1573 | |
| 1574 | static void cson_value_destroy_zero_it( cson_value * self ); |
| 1575 | static void cson_value_destroy_object( cson_value * self ); |
| 1576 | /** |
| 1577 | If self is-a array then this function destroys its contents, |
| 1578 | else this function does nothing. |
| 1579 | */ |
| 1580 | static void cson_value_destroy_array( cson_value * self ); |
| 1581 | |
| 1582 | static const cson_value_api cson_value_api_null = { CSON_TYPE_NULL, cson_value_destroy_zero_it }; |
| 1583 | static const cson_value_api cson_value_api_undef = { CSON_TYPE_UNDEF, cson_value_destroy_zero_it }; |
| 1584 | static const cson_value_api cson_value_api_bool = { CSON_TYPE_BOOL, cson_value_destroy_zero_it }; |
| 1585 | static const cson_value_api cson_value_api_integer = { CSON_TYPE_INTEGER, cson_value_destroy_zero_it }; |
| 1586 | static const cson_value_api cson_value_api_double = { CSON_TYPE_DOUBLE, cson_value_destroy_zero_it }; |
| 1587 | static const cson_value_api cson_value_api_string = { CSON_TYPE_STRING, cson_value_destroy_zero_it }; |
| 1588 | static const cson_value_api cson_value_api_array = { CSON_TYPE_ARRAY, cson_value_destroy_array }; |
| 1589 | static const cson_value_api cson_value_api_object = { CSON_TYPE_OBJECT, cson_value_destroy_object }; |
| 1590 | |
| 1591 | static const cson_value cson_value_undef = { &cson_value_api_undef, NULL, 0 }; |
| 1592 | static const cson_value cson_value_null_empty = { &cson_value_api_null, NULL, 0 }; |
| 1593 | static const cson_value cson_value_bool_empty = { &cson_value_api_bool, NULL, 0 }; |
| 1594 | static const cson_value cson_value_integer_empty = { &cson_value_api_integer, NULL, 0 }; |
| 1595 | static const cson_value cson_value_double_empty = { &cson_value_api_double, NULL, 0 }; |
| 1596 | static const cson_value cson_value_string_empty = { &cson_value_api_string, NULL, 0 }; |
| 1597 | static const cson_value cson_value_array_empty = { &cson_value_api_array, NULL, 0 }; |
| @@ -1608,11 +1601,11 @@ | |
| 1601 | struct cson_string |
| 1602 | { |
| 1603 | unsigned int length; |
| 1604 | }; |
| 1605 | #define cson_string_empty_m {0/*length*/} |
| 1606 | static const cson_string cson_string_empty = cson_string_empty_m; |
| 1607 | /** |
| 1608 | |
| 1609 | Holds special shared "constant" (though they are non-const) |
| 1610 | values. |
| 1611 | |
| @@ -2033,37 +2026,22 @@ | |
| 2026 | if( self ) |
| 2027 | { |
| 2028 | *self = cson_value_undef; |
| 2029 | } |
| 2030 | } |
| 2031 | |
| 2032 | /** |
| 2033 | A key/value pair collection. |
| 2034 | |
| 2035 | Each of these objects owns its key/value pointers, and they |
| 2036 | are cleaned up by cson_kvp_clean(). |
| 2037 | */ |
| 2038 | struct cson_kvp |
| 2039 | { |
| 2040 | /* FIXME: switch to cson_value keys. Calling cson_string_value() |
| 2041 | on one of these guys will read invalid memory. |
| 2042 | */ |
| 2043 | cson_string * key; |
| 2044 | cson_value * value; |
| 2045 | }; |
| 2046 | #define cson_kvp_empty_m {NULL,NULL} |
| 2047 | static const cson_kvp cson_kvp_empty = cson_kvp_empty_m; |
| @@ -2261,32 +2239,23 @@ | |
| 2239 | # define VALUE_T cson_kvp * |
| 2240 | # define VALUE_T_IS_PTR 1 |
| 2241 | #else |
| 2242 | #endif |
| 2243 | |
| 2244 | /** |
| 2245 | Allocates a new value of the specified type ownership of it to the |
| 2246 | caller. It must eventually be destroyed, by the caller or its |
| 2247 | owning container, by passing it to cson_value_free() or transfering |
| 2248 | ownership to a container. |
| 2249 | |
| 2250 | extra is only valid for type CSON_TYPE_STRING, and must be the length |
| 2251 | of the string to allocate + 1 byte (for the NUL). |
| 2252 | |
| 2253 | The returned value->api member will be set appropriately and |
| 2254 | val->value will be set to point to the memory allocated to hold the |
| 2255 | native value type. Use the internal CSON_CAST() family of macros to |
| 2256 | convert them. |
| 2257 | |
| 2258 | Returns NULL on allocation error. |
| 2259 | |
| 2260 | @see cson_value_new_array() |
| 2261 | @see cson_value_new_object() |
| @@ -2294,65 +2263,73 @@ | |
| 2263 | @see cson_value_new_integer() |
| 2264 | @see cson_value_new_double() |
| 2265 | @see cson_value_new_bool() |
| 2266 | @see cson_value_free() |
| 2267 | */ |
| 2268 | static cson_value * cson_value_new(cson_type_id t, size_t extra); |
| 2269 | |
| 2270 | #define CSON_CAST(T,V) ((T*)((V)->value)) |
| 2271 | #define CSON_VCAST(V) ((cson_value *)(((unsigned char *)(V))-sizeof(cson_value))) |
| 2272 | #define CSON_INT(V) ((cson_int_t*)(V)->value) |
| 2273 | #define CSON_DBL(V) CSON_CAST(cson_double_t,(V)) |
| 2274 | #define CSON_STR(V) CSON_CAST(cson_string,(V)) |
| 2275 | #define CSON_OBJ(V) CSON_CAST(cson_object,(V)) |
| 2276 | #define CSON_ARRAY(V) CSON_CAST(cson_array,(V)) |
| 2277 | |
| 2278 | cson_value * cson_value_new(cson_type_id t, size_t extra) |
| 2279 | { |
| 2280 | static const size_t vsz = sizeof(cson_value); |
| 2281 | const size_t sz = vsz + extra; |
| 2282 | size_t tx = 0; |
| 2283 | cson_value def = cson_value_undef; |
| 2284 | cson_value * v = NULL; |
| 2285 | char const * reason = "cson_value_new"; |
| 2286 | switch(t) |
| 2287 | { |
| 2288 | case CSON_TYPE_ARRAY: |
| 2289 | assert( 0 == extra ); |
| 2290 | def = cson_value_array_empty; |
| 2291 | tx = sizeof(cson_array); |
| 2292 | reason = "cson_value:array"; |
| 2293 | break; |
| 2294 | case CSON_TYPE_DOUBLE: |
| 2295 | assert( 0 == extra ); |
| 2296 | def = cson_value_double_empty; |
| 2297 | tx = sizeof(cson_double_t); |
| 2298 | reason = "cson_value:double"; |
| 2299 | break; |
| 2300 | case CSON_TYPE_INTEGER: |
| 2301 | assert( 0 == extra ); |
| 2302 | def = cson_value_integer_empty; |
| 2303 | tx = sizeof(cson_int_t); |
| 2304 | reason = "cson_value:int"; |
| 2305 | break; |
| 2306 | case CSON_TYPE_STRING: |
| 2307 | assert( 0 != extra ); |
| 2308 | def = cson_value_string_empty; |
| 2309 | tx = sizeof(cson_string); |
| 2310 | reason = "cson_value:string"; |
| 2311 | break; |
| 2312 | case CSON_TYPE_OBJECT: |
| 2313 | assert( 0 == extra ); |
| 2314 | def = cson_value_object_empty; |
| 2315 | tx = sizeof(cson_object); |
| 2316 | reason = "cson_value:object"; |
| 2317 | break; |
| 2318 | default: |
| 2319 | assert(0 && "Unhandled type in cson_value_new()!"); |
| 2320 | return NULL; |
| 2321 | } |
| 2322 | assert( def.api->typeID != CSON_TYPE_UNDEF ); |
| 2323 | v = (cson_value *)cson_malloc(sz+tx, reason); |
| 2324 | if( v ) { |
| 2325 | *v = def; |
| 2326 | if(tx || extra){ |
| 2327 | memset(v+1, 0, tx + extra); |
| 2328 | v->value = (void *)(v+1); |
| 2329 | } |
| 2330 | } |
| 2331 | return v; |
| 2332 | } |
| 2333 | |
| 2334 | |
| 2335 | void cson_value_free(cson_value *v) |
| @@ -2414,151 +2391,31 @@ | |
| 2391 | *val = cson_value_undef; |
| 2392 | val->refcount = rc; |
| 2393 | } |
| 2394 | } |
| 2395 | } |
| 2396 | |
| 2397 | static cson_value * cson_value_array_alloc() |
| 2398 | { |
| 2399 | cson_value * v = cson_value_new(CSON_TYPE_ARRAY,0); |
| 2400 | if( NULL != v ) |
| 2401 | { |
| 2402 | cson_array * ar = CSON_ARRAY(v); |
| 2403 | assert(NULL != ar); |
| 2404 | *ar = cson_array_empty; |
| 2405 | } |
| 2406 | return v; |
| 2407 | } |
| 2408 | |
| 2409 | static cson_value * cson_value_object_alloc() |
| 2410 | { |
| 2411 | cson_value * v = cson_value_new(CSON_TYPE_OBJECT,0); |
| 2412 | if( NULL != v ) |
| 2413 | { |
| 2414 | cson_object * obj = CSON_OBJ(v); |
| 2415 | assert(NULL != obj); |
| 2416 | *obj = cson_object_empty; |
| 2417 | } |
| 2418 | return v; |
| 2419 | } |
| 2420 | |
| 2421 | cson_value * cson_value_new_object() |
| @@ -2612,31 +2469,10 @@ | |
| 2469 | cson_kvp_clean(kvp); |
| 2470 | cson_free(kvp,"cson_kvp"); |
| 2471 | } |
| 2472 | } |
| 2473 | |
| 2474 | |
| 2475 | /** |
| 2476 | cson_value_api::destroy_value() impl for Object |
| 2477 | values. Cleans up self-owned memory and overwrites |
| 2478 | self to have the undefined value, but does not |
| @@ -2646,11 +2482,10 @@ | |
| 2482 | { |
| 2483 | if(self && self->value) { |
| 2484 | cson_object * obj = (cson_object *)self->value; |
| 2485 | assert( self->value == obj ); |
| 2486 | cson_kvp_list_clean( &obj->kvp, cson_kvp_free ); |
| 2487 | *self = cson_value_undef; |
| 2488 | } |
| 2489 | } |
| 2490 | |
| 2491 | /** |
| @@ -2701,11 +2536,10 @@ | |
| 2536 | { |
| 2537 | cson_array * ar = cson_value_get_array(self); |
| 2538 | if(ar) { |
| 2539 | assert( self->value == ar ); |
| 2540 | cson_array_clean( ar, 1 ); |
| 2541 | *self = cson_value_undef; |
| 2542 | } |
| 2543 | } |
| 2544 | |
| 2545 | |
| @@ -2857,16 +2691,16 @@ | |
| 2691 | cson_value_fetch_bool( val, &b ); |
| 2692 | i = b; |
| 2693 | break; |
| 2694 | } |
| 2695 | case CSON_TYPE_INTEGER: { |
| 2696 | cson_int_t const * x = CSON_INT(val); |
| 2697 | if(!x) |
| 2698 | { |
| 2699 | assert( val == &CSON_SPECIAL_VALUES[CSON_VAL_INT_0] ); |
| 2700 | } |
| 2701 | i = x ? *x : 0; |
| 2702 | break; |
| 2703 | } |
| 2704 | case CSON_TYPE_DOUBLE: { |
| 2705 | cson_double_t d = 0.0; |
| 2706 | cson_value_fetch_double( val, &d ); |
| @@ -2915,11 +2749,11 @@ | |
| 2749 | cson_value_fetch_integer( val, &i ); |
| 2750 | d = i; |
| 2751 | break; |
| 2752 | } |
| 2753 | case CSON_TYPE_DOUBLE: { |
| 2754 | cson_double_t const* dv = CSON_DBL(val); |
| 2755 | d = dv ? *dv : 0.0; |
| 2756 | break; |
| 2757 | } |
| 2758 | default: |
| 2759 | rc = cson_rc.TypeError; |
| @@ -2964,11 +2798,11 @@ | |
| 2798 | { |
| 2799 | if( ! val ) return cson_rc.ArgError; |
| 2800 | else if( ! cson_value_is_object(val) ) return cson_rc.TypeError; |
| 2801 | else |
| 2802 | { |
| 2803 | if(obj) *obj = CSON_OBJ(val); |
| 2804 | return 0; |
| 2805 | } |
| 2806 | } |
| 2807 | cson_object * cson_value_get_object( cson_value const * v ) |
| 2808 | { |
| @@ -2978,14 +2812,14 @@ | |
| 2812 | } |
| 2813 | |
| 2814 | int cson_value_fetch_array( cson_value const * val, cson_array ** ar) |
| 2815 | { |
| 2816 | if( ! val ) return cson_rc.ArgError; |
| 2817 | else if( !cson_value_is_array(val) ) return cson_rc.TypeError; |
| 2818 | else |
| 2819 | { |
| 2820 | if(ar) *ar = CSON_ARRAY(val); |
| 2821 | return 0; |
| 2822 | } |
| 2823 | } |
| 2824 | |
| 2825 | cson_array * cson_value_get_array( cson_value const * v ) |
| @@ -3084,18 +2918,15 @@ | |
| 2918 | cson_value * cson_value_new_integer( cson_int_t v ) |
| 2919 | { |
| 2920 | if( 0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_INT_0]; |
| 2921 | else |
| 2922 | { |
| 2923 | cson_value * c = cson_value_new(CSON_TYPE_INTEGER,0); |
| 2924 | |
| 2925 | if( c ) |
| 2926 | { |
| 2927 | *CSON_INT(c) = v; |
| 2928 | } |
| 2929 | return c; |
| 2930 | } |
| 2931 | } |
| 2932 | |
| @@ -3102,35 +2933,35 @@ | |
| 2933 | cson_value * cson_value_new_double( cson_double_t v ) |
| 2934 | { |
| 2935 | if( 0.0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_DBL_0]; |
| 2936 | else |
| 2937 | { |
| 2938 | cson_value * c = cson_value_new(CSON_TYPE_DOUBLE,0); |
| 2939 | if( c ) |
| 2940 | { |
| 2941 | *CSON_DBL(c) = v; |
| 2942 | } |
| 2943 | return c; |
| 2944 | } |
| 2945 | } |
| 2946 | cson_value * cson_value_new_string( char const * str, unsigned int len ) |
| 2947 | { |
| 2948 | if( !str || !*str || !len ) return &CSON_SPECIAL_VALUES[CSON_VAL_STR_EMPTY]; |
| 2949 | else |
| 2950 | { |
| 2951 | cson_value * c = cson_value_new(CSON_TYPE_STRING, len + 1/*NUL byte*/); |
| 2952 | if( c ) |
| 2953 | { |
| 2954 | char * dest = NULL; |
| 2955 | cson_string * s = CSON_STR(c); |
| 2956 | *s = cson_string_empty; |
| 2957 | assert( NULL != s ); |
| 2958 | s->length = len; |
| 2959 | dest = cson_string_str(s); |
| 2960 | assert( NULL != dest ); |
| 2961 | memcpy( dest, str, len ); |
| 2962 | dest[len] = 0; |
| 2963 | } |
| 2964 | return c; |
| 2965 | } |
| 2966 | } |
| 2967 | |
| @@ -4816,11 +4647,12 @@ | |
| 4647 | else |
| 4648 | { |
| 4649 | switch( orig->api->typeID ) |
| 4650 | { |
| 4651 | case CSON_TYPE_UNDEF: |
| 4652 | assert(0 && "This should never happen."); |
| 4653 | return NULL; |
| 4654 | case CSON_TYPE_NULL: |
| 4655 | return cson_value_null(); |
| 4656 | case CSON_TYPE_BOOL: |
| 4657 | return cson_value_new_bool( cson_value_get_bool( orig ) ); |
| 4658 | case CSON_TYPE_INTEGER: |
| @@ -4841,10 +4673,34 @@ | |
| 4673 | } |
| 4674 | assert( 0 && "We can't get this far." ); |
| 4675 | return NULL; |
| 4676 | } |
| 4677 | } |
| 4678 | |
| 4679 | cson_value * cson_string_value(cson_string const * s) |
| 4680 | { |
| 4681 | return s |
| 4682 | ? CSON_VCAST(s) |
| 4683 | : NULL; |
| 4684 | } |
| 4685 | |
| 4686 | cson_value * cson_object_value(cson_object const * s) |
| 4687 | { |
| 4688 | return s |
| 4689 | ? CSON_VCAST(s) |
| 4690 | : NULL; |
| 4691 | } |
| 4692 | |
| 4693 | |
| 4694 | cson_value * cson_array_value(cson_array const * s) |
| 4695 | { |
| 4696 | return s |
| 4697 | ? CSON_VCAST(s) |
| 4698 | : NULL; |
| 4699 | } |
| 4700 | |
| 4701 | |
| 4702 | |
| 4703 | #if 0 |
| 4704 | /* i'm not happy with this... */ |
| 4705 | char * cson_pod_to_string( cson_value const * orig ) |
| 4706 | { |
| @@ -4955,10 +4811,17 @@ | |
| 4811 | #endif |
| 4812 | |
| 4813 | #undef MARKER |
| 4814 | #undef CSON_OBJECT_PROPS_SORT |
| 4815 | #undef CSON_OBJECT_PROPS_SORT_USE_LENGTH |
| 4816 | #undef CSON_CAST |
| 4817 | #undef CSON_INT |
| 4818 | #undef CSON_DBL |
| 4819 | #undef CSON_STR |
| 4820 | #undef CSON_OBJ |
| 4821 | #undef CSON_ARRAY |
| 4822 | #undef CSON_VCAST |
| 4823 | /* end file ./cson.c */ |
| 4824 | /* begin file ./cson_lists.h */ |
| 4825 | /* Auto-generated from cson_list.h. Edit at your own risk! */ |
| 4826 | unsigned int cson_value_list_reserve( cson_value_list * self, unsigned int n ) |
| 4827 | { |
| 4828 |
+28
-36
| --- src/cson_amalgamation.h | ||
| +++ src/cson_amalgamation.h | ||
| @@ -57,46 +57,10 @@ | ||
| 57 | 57 | typedef long cson_int_t; |
| 58 | 58 | #define CSON_INT_T_SFMT "ld" |
| 59 | 59 | #define CSON_INT_T_PFMT "ld" |
| 60 | 60 | #endif |
| 61 | 61 | |
| 62 | -/** @def CSON_VOID_PTR_IS_BIG | |
| 63 | - | |
| 64 | -ONLY define this to a true value if you know that | |
| 65 | - | |
| 66 | -(sizeof(cson_int_t) <= sizeof(void*)) | |
| 67 | - | |
| 68 | -If that is the case, cson does not need to dynamically | |
| 69 | -allocate integers. However, enabling this may cause | |
| 70 | -compilation warnings in 32-bit builds even though the code | |
| 71 | -being warned about cannot ever be called. To get around such | |
| 72 | -warnings, when building on a 64-bit environment you can define | |
| 73 | -this to 1 to get "big" integer support. HOWEVER, all clients must | |
| 74 | -also use the same value for this macro. If i knew a halfway reliable | |
| 75 | -way to determine this automatically at preprocessor-time, i would | |
| 76 | -automate this. We might be able to do halfway reliably by looking | |
| 77 | -for a large INT_MAX value? | |
| 78 | -*/ | |
| 79 | -#if !defined(CSON_VOID_PTR_IS_BIG) | |
| 80 | - | |
| 81 | -/* Largely taken from http://predef.sourceforge.net/prearch.html | |
| 82 | - | |
| 83 | -See also: http://poshlib.hookatooka.com/poshlib/trac.cgi/browser/posh.h | |
| 84 | -*/ | |
| 85 | -# if defined(_WIN64) || defined(__LP64__)/*gcc*/ \ | |
| 86 | - || defined(_M_X64) || defined(__amd64__) || defined(__amd64) \ | |
| 87 | - || defined(__x86_64__) || defined(__x86_64) \ | |
| 88 | - || defined(__ia64__) || defined(__ia64) || defined(_IA64) || defined(__IA64__) \ | |
| 89 | - || defined(_M_IA64) \ | |
| 90 | - || defined(__sparc_v9__) || defined(__sparcv9) || defined(_ADDR64) \ | |
| 91 | - || defined(__64BIT__) | |
| 92 | -# define CSON_VOID_PTR_IS_BIG 1 | |
| 93 | -# else | |
| 94 | -# define CSON_VOID_PTR_IS_BIG 0 | |
| 95 | -# endif | |
| 96 | -#endif | |
| 97 | - | |
| 98 | 62 | /** @typedef double_or_long_double cson_double_t |
| 99 | 63 | |
| 100 | 64 | This is the type of double value used by the library. |
| 101 | 65 | It is only lightly tested with long double, and when using |
| 102 | 66 | long double the memory requirements for such values goes |
| @@ -843,15 +807,18 @@ | ||
| 843 | 807 | boolean: same |
| 844 | 808 | |
| 845 | 809 | integer, double: 0 or 0.0 == false, else true |
| 846 | 810 | |
| 847 | 811 | object, array: true |
| 812 | + | |
| 813 | + string: length-0 string is false, else true. | |
| 848 | 814 | |
| 849 | 815 | Returns 0 on success and assigns *v (if v is not NULL) to either 0 or 1. |
| 850 | 816 | On error (val is NULL) then v is not modified. |
| 851 | 817 | */ |
| 852 | 818 | int cson_value_fetch_bool( cson_value const * val, char * v ); |
| 819 | + | |
| 853 | 820 | /** |
| 854 | 821 | Similar to cson_value_fetch_bool(), but fetches an integer value. |
| 855 | 822 | |
| 856 | 823 | The conversion, if any, depends on the concrete type of val: |
| 857 | 824 | |
| @@ -865,10 +832,11 @@ | ||
| 865 | 832 | integer: *v is set to the int value and 0 is returned. |
| 866 | 833 | |
| 867 | 834 | double: *v is set to the value truncated to int and 0 is returned. |
| 868 | 835 | */ |
| 869 | 836 | int cson_value_fetch_integer( cson_value const * val, cson_int_t * v ); |
| 837 | + | |
| 870 | 838 | /** |
| 871 | 839 | The same conversions and return values as |
| 872 | 840 | cson_value_fetch_integer(), except that the roles of int/double are |
| 873 | 841 | swapped. |
| 874 | 842 | */ |
| @@ -1940,10 +1908,34 @@ | ||
| 1940 | 1908 | allocation fails while constructing the clone. In other words, if |
| 1941 | 1909 | cloning fails due to something other than an allocation error then |
| 1942 | 1910 | either orig is in an invalid state or there is a bug. |
| 1943 | 1911 | */ |
| 1944 | 1912 | cson_value * cson_value_clone( cson_value const * orig ); |
| 1913 | + | |
| 1914 | +/** | |
| 1915 | + Returns the value handle associated with s. The handle itself owns | |
| 1916 | + s, and ownership of the handle is not changed by calling this | |
| 1917 | + function. If the returned handle is part of a container, calling | |
| 1918 | + cson_value_free() on the returned handle invoked undefined | |
| 1919 | + behaviour (quite possibly downstream when the container tries to | |
| 1920 | + use it). | |
| 1921 | + | |
| 1922 | + This function only returns NULL if s. is NULL. | |
| 1923 | +*/ | |
| 1924 | +cson_value * cson_string_value(cson_string const * s); | |
| 1925 | +/** | |
| 1926 | + The Object form of cson_string_value(). See that function | |
| 1927 | + for full details. | |
| 1928 | +*/ | |
| 1929 | +cson_value * cson_object_value(cson_object const * s); | |
| 1930 | + | |
| 1931 | +/** | |
| 1932 | + The Array form of cson_string_value(). See that function | |
| 1933 | + for full details. | |
| 1934 | +*/ | |
| 1935 | +cson_value * cson_array_value(cson_array const * s); | |
| 1936 | + | |
| 1945 | 1937 | |
| 1946 | 1938 | /* LICENSE |
| 1947 | 1939 | |
| 1948 | 1940 | This software's source code, including accompanying documentation and |
| 1949 | 1941 | demonstration applications, are licensed under the following |
| 1950 | 1942 |
| --- src/cson_amalgamation.h | |
| +++ src/cson_amalgamation.h | |
| @@ -57,46 +57,10 @@ | |
| 57 | typedef long cson_int_t; |
| 58 | #define CSON_INT_T_SFMT "ld" |
| 59 | #define CSON_INT_T_PFMT "ld" |
| 60 | #endif |
| 61 | |
| 62 | /** @def CSON_VOID_PTR_IS_BIG |
| 63 | |
| 64 | ONLY define this to a true value if you know that |
| 65 | |
| 66 | (sizeof(cson_int_t) <= sizeof(void*)) |
| 67 | |
| 68 | If that is the case, cson does not need to dynamically |
| 69 | allocate integers. However, enabling this may cause |
| 70 | compilation warnings in 32-bit builds even though the code |
| 71 | being warned about cannot ever be called. To get around such |
| 72 | warnings, when building on a 64-bit environment you can define |
| 73 | this to 1 to get "big" integer support. HOWEVER, all clients must |
| 74 | also use the same value for this macro. If i knew a halfway reliable |
| 75 | way to determine this automatically at preprocessor-time, i would |
| 76 | automate this. We might be able to do halfway reliably by looking |
| 77 | for a large INT_MAX value? |
| 78 | */ |
| 79 | #if !defined(CSON_VOID_PTR_IS_BIG) |
| 80 | |
| 81 | /* Largely taken from http://predef.sourceforge.net/prearch.html |
| 82 | |
| 83 | See also: http://poshlib.hookatooka.com/poshlib/trac.cgi/browser/posh.h |
| 84 | */ |
| 85 | # if defined(_WIN64) || defined(__LP64__)/*gcc*/ \ |
| 86 | || defined(_M_X64) || defined(__amd64__) || defined(__amd64) \ |
| 87 | || defined(__x86_64__) || defined(__x86_64) \ |
| 88 | || defined(__ia64__) || defined(__ia64) || defined(_IA64) || defined(__IA64__) \ |
| 89 | || defined(_M_IA64) \ |
| 90 | || defined(__sparc_v9__) || defined(__sparcv9) || defined(_ADDR64) \ |
| 91 | || defined(__64BIT__) |
| 92 | # define CSON_VOID_PTR_IS_BIG 1 |
| 93 | # else |
| 94 | # define CSON_VOID_PTR_IS_BIG 0 |
| 95 | # endif |
| 96 | #endif |
| 97 | |
| 98 | /** @typedef double_or_long_double cson_double_t |
| 99 | |
| 100 | This is the type of double value used by the library. |
| 101 | It is only lightly tested with long double, and when using |
| 102 | long double the memory requirements for such values goes |
| @@ -843,15 +807,18 @@ | |
| 843 | boolean: same |
| 844 | |
| 845 | integer, double: 0 or 0.0 == false, else true |
| 846 | |
| 847 | object, array: true |
| 848 | |
| 849 | Returns 0 on success and assigns *v (if v is not NULL) to either 0 or 1. |
| 850 | On error (val is NULL) then v is not modified. |
| 851 | */ |
| 852 | int cson_value_fetch_bool( cson_value const * val, char * v ); |
| 853 | /** |
| 854 | Similar to cson_value_fetch_bool(), but fetches an integer value. |
| 855 | |
| 856 | The conversion, if any, depends on the concrete type of val: |
| 857 | |
| @@ -865,10 +832,11 @@ | |
| 865 | integer: *v is set to the int value and 0 is returned. |
| 866 | |
| 867 | double: *v is set to the value truncated to int and 0 is returned. |
| 868 | */ |
| 869 | int cson_value_fetch_integer( cson_value const * val, cson_int_t * v ); |
| 870 | /** |
| 871 | The same conversions and return values as |
| 872 | cson_value_fetch_integer(), except that the roles of int/double are |
| 873 | swapped. |
| 874 | */ |
| @@ -1940,10 +1908,34 @@ | |
| 1940 | allocation fails while constructing the clone. In other words, if |
| 1941 | cloning fails due to something other than an allocation error then |
| 1942 | either orig is in an invalid state or there is a bug. |
| 1943 | */ |
| 1944 | cson_value * cson_value_clone( cson_value const * orig ); |
| 1945 | |
| 1946 | /* LICENSE |
| 1947 | |
| 1948 | This software's source code, including accompanying documentation and |
| 1949 | demonstration applications, are licensed under the following |
| 1950 |
| --- src/cson_amalgamation.h | |
| +++ src/cson_amalgamation.h | |
| @@ -57,46 +57,10 @@ | |
| 57 | typedef long cson_int_t; |
| 58 | #define CSON_INT_T_SFMT "ld" |
| 59 | #define CSON_INT_T_PFMT "ld" |
| 60 | #endif |
| 61 | |
| 62 | /** @typedef double_or_long_double cson_double_t |
| 63 | |
| 64 | This is the type of double value used by the library. |
| 65 | It is only lightly tested with long double, and when using |
| 66 | long double the memory requirements for such values goes |
| @@ -843,15 +807,18 @@ | |
| 807 | boolean: same |
| 808 | |
| 809 | integer, double: 0 or 0.0 == false, else true |
| 810 | |
| 811 | object, array: true |
| 812 | |
| 813 | string: length-0 string is false, else true. |
| 814 | |
| 815 | Returns 0 on success and assigns *v (if v is not NULL) to either 0 or 1. |
| 816 | On error (val is NULL) then v is not modified. |
| 817 | */ |
| 818 | int cson_value_fetch_bool( cson_value const * val, char * v ); |
| 819 | |
| 820 | /** |
| 821 | Similar to cson_value_fetch_bool(), but fetches an integer value. |
| 822 | |
| 823 | The conversion, if any, depends on the concrete type of val: |
| 824 | |
| @@ -865,10 +832,11 @@ | |
| 832 | integer: *v is set to the int value and 0 is returned. |
| 833 | |
| 834 | double: *v is set to the value truncated to int and 0 is returned. |
| 835 | */ |
| 836 | int cson_value_fetch_integer( cson_value const * val, cson_int_t * v ); |
| 837 | |
| 838 | /** |
| 839 | The same conversions and return values as |
| 840 | cson_value_fetch_integer(), except that the roles of int/double are |
| 841 | swapped. |
| 842 | */ |
| @@ -1940,10 +1908,34 @@ | |
| 1908 | allocation fails while constructing the clone. In other words, if |
| 1909 | cloning fails due to something other than an allocation error then |
| 1910 | either orig is in an invalid state or there is a bug. |
| 1911 | */ |
| 1912 | cson_value * cson_value_clone( cson_value const * orig ); |
| 1913 | |
| 1914 | /** |
| 1915 | Returns the value handle associated with s. The handle itself owns |
| 1916 | s, and ownership of the handle is not changed by calling this |
| 1917 | function. If the returned handle is part of a container, calling |
| 1918 | cson_value_free() on the returned handle invoked undefined |
| 1919 | behaviour (quite possibly downstream when the container tries to |
| 1920 | use it). |
| 1921 | |
| 1922 | This function only returns NULL if s. is NULL. |
| 1923 | */ |
| 1924 | cson_value * cson_string_value(cson_string const * s); |
| 1925 | /** |
| 1926 | The Object form of cson_string_value(). See that function |
| 1927 | for full details. |
| 1928 | */ |
| 1929 | cson_value * cson_object_value(cson_object const * s); |
| 1930 | |
| 1931 | /** |
| 1932 | The Array form of cson_string_value(). See that function |
| 1933 | for full details. |
| 1934 | */ |
| 1935 | cson_value * cson_array_value(cson_array const * s); |
| 1936 | |
| 1937 | |
| 1938 | /* LICENSE |
| 1939 | |
| 1940 | This software's source code, including accompanying documentation and |
| 1941 | demonstration applications, are licensed under the following |
| 1942 |