Fossil SCM
latest cson amalgamation - malloc() reduction optimization for integer values on 64-bit platforms.
Commit
81971c12c920b6721d153d15d0196802fdf6b47d
Parent
efbecda47076d88…
2 files changed
+38
-28
+36
+38
-28
| --- src/cson_amalgamation.c | ||
| +++ src/cson_amalgamation.c | ||
| @@ -1616,11 +1616,17 @@ | ||
| 1616 | 1616 | |
| 1617 | 1617 | |
| 1618 | 1618 | |
| 1619 | 1619 | #define CSON_CAST(T,V) ((T*)((V)->value)) |
| 1620 | 1620 | #define CSON_VCAST(V) ((cson_value *)(((unsigned char *)(V))-sizeof(cson_value))) |
| 1621 | -#define CSON_INT(V) ((cson_int_t*)(V)->value) | |
| 1621 | + | |
| 1622 | +#if CSON_VOID_PTR_IS_BIG | |
| 1623 | +# define CSON_INT(V) ((cson_int_t*)(&((V)->value))) | |
| 1624 | +#else | |
| 1625 | +# define CSON_INT(V) ((cson_int_t*)(V)->value) | |
| 1626 | +#endif | |
| 1627 | + | |
| 1622 | 1628 | #define CSON_DBL(V) CSON_CAST(cson_double_t,(V)) |
| 1623 | 1629 | #define CSON_STR(V) CSON_CAST(cson_string,(V)) |
| 1624 | 1630 | #define CSON_OBJ(V) CSON_CAST(cson_object,(V)) |
| 1625 | 1631 | #define CSON_ARRAY(V) CSON_CAST(cson_array,(V)) |
| 1626 | 1632 | |
| @@ -1958,11 +1964,11 @@ | ||
| 1958 | 1964 | #if 1 |
| 1959 | 1965 | if( ! v ) return NULL; |
| 1960 | 1966 | else if( v == &CSON_EMPTY_HOLDER.stringValue ) return ""; |
| 1961 | 1967 | else { |
| 1962 | 1968 | assert((0 < v->length) && "How do we have a non-singleton empty string?"); |
| 1963 | - return (char *)((unsigned char *)(v+1)); | |
| 1969 | + return (char const *)((unsigned char const *)(v+1)); | |
| 1964 | 1970 | } |
| 1965 | 1971 | #else |
| 1966 | 1972 | return (NULL == v) |
| 1967 | 1973 | ? NULL |
| 1968 | 1974 | : (v->length |
| @@ -2039,10 +2045,13 @@ | ||
| 2039 | 2045 | }; |
| 2040 | 2046 | #define cson_kvp_empty_m {NULL,NULL} |
| 2041 | 2047 | static const cson_kvp cson_kvp_empty = cson_kvp_empty_m; |
| 2042 | 2048 | |
| 2043 | 2049 | /** @def CSON_OBJECT_PROPS_SORT |
| 2050 | + | |
| 2051 | + Don't use this - it has not been updated to account for internal | |
| 2052 | + changes in cson_object. | |
| 2044 | 2053 | |
| 2045 | 2054 | If CSON_OBJECT_PROPS_SORT is set to a true value then |
| 2046 | 2055 | qsort() and bsearch() are used to sort (upon insertion) |
| 2047 | 2056 | and search cson_object::kvp property lists. This costs us |
| 2048 | 2057 | a re-sort on each insertion but searching is O(log n) |
| @@ -2221,11 +2230,12 @@ | ||
| 2221 | 2230 | of the string to allocate + 1 byte (for the NUL). |
| 2222 | 2231 | |
| 2223 | 2232 | The returned value->api member will be set appropriately and |
| 2224 | 2233 | val->value will be set to point to the memory allocated to hold the |
| 2225 | 2234 | native value type. Use the internal CSON_CAST() family of macros to |
| 2226 | - convert them. | |
| 2235 | + convert the cson_values to their corresponding native | |
| 2236 | + representation. | |
| 2227 | 2237 | |
| 2228 | 2238 | Returns NULL on allocation error. |
| 2229 | 2239 | |
| 2230 | 2240 | @see cson_value_new_array() |
| 2231 | 2241 | @see cson_value_new_object() |
| @@ -2257,17 +2267,14 @@ | ||
| 2257 | 2267 | tx = sizeof(cson_double_t); |
| 2258 | 2268 | reason = "cson_value:double"; |
| 2259 | 2269 | break; |
| 2260 | 2270 | case CSON_TYPE_INTEGER: |
| 2261 | 2271 | assert( 0 == extra ); |
| 2262 | - /* FIXME: if sizeof(void*) >= sizeof(cson_int_t) then store | |
| 2263 | - the int value directly in the void pointer (requires no | |
| 2264 | - extra alloc). The current behaviour requires 32 | |
| 2265 | - bytes(!!!) on 64-bit builds. | |
| 2266 | - */ | |
| 2267 | 2272 | def = cson_value_integer_empty; |
| 2273 | +#if !CSON_VOID_PTR_IS_BIG | |
| 2268 | 2274 | tx = sizeof(cson_int_t); |
| 2275 | +#endif | |
| 2269 | 2276 | reason = "cson_value:int"; |
| 2270 | 2277 | break; |
| 2271 | 2278 | case CSON_TYPE_STRING: |
| 2272 | 2279 | assert( 0 != extra ); |
| 2273 | 2280 | def = cson_value_string_empty; |
| @@ -2657,13 +2664,14 @@ | ||
| 2657 | 2664 | } |
| 2658 | 2665 | case CSON_TYPE_STRING: |
| 2659 | 2666 | case CSON_TYPE_ARRAY: |
| 2660 | 2667 | case CSON_TYPE_OBJECT: |
| 2661 | 2668 | default: |
| 2662 | - break; | |
| 2669 | + rc = cson_rc.TypeError; | |
| 2670 | + break; | |
| 2663 | 2671 | } |
| 2664 | - if(v) *v = i; | |
| 2672 | + if(!rc && v) *v = i; | |
| 2665 | 2673 | return rc; |
| 2666 | 2674 | } |
| 2667 | 2675 | } |
| 2668 | 2676 | |
| 2669 | 2677 | cson_int_t cson_value_get_integer( cson_value const * val ) |
| @@ -2872,11 +2880,13 @@ | ||
| 2872 | 2880 | { |
| 2873 | 2881 | if( 0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_INT_0]; |
| 2874 | 2882 | else |
| 2875 | 2883 | { |
| 2876 | 2884 | cson_value * c = cson_value_new(CSON_TYPE_INTEGER,0); |
| 2877 | - | |
| 2885 | +#if !defined(NDEBUG) && CSON_VOID_PTR_IS_BIG | |
| 2886 | + assert( sizeof(cson_int_t) <= sizeof(void *) ); | |
| 2887 | +#endif | |
| 2878 | 2888 | if( c ) |
| 2879 | 2889 | { |
| 2880 | 2890 | *CSON_INT(c) = v; |
| 2881 | 2891 | } |
| 2882 | 2892 | return c; |
| @@ -4597,13 +4607,13 @@ | ||
| 4597 | 4607 | |
| 4598 | 4608 | |
| 4599 | 4609 | /** |
| 4600 | 4610 | If v is-a Object or Array then this function returns a deep |
| 4601 | 4611 | clone, otherwise it returns v. In either case, the refcount |
| 4602 | - of the returned value is increased by 1. | |
| 4612 | + of the returned value is increased by 1 by this call. | |
| 4603 | 4613 | */ |
| 4604 | -static cson_value * cson_value_clone_shared( cson_value * v ) | |
| 4614 | +static cson_value * cson_value_clone_ref( cson_value * v ) | |
| 4605 | 4615 | { |
| 4606 | 4616 | cson_value * rc = NULL; |
| 4607 | 4617 | #define TRY_SHARING 1 |
| 4608 | 4618 | #if TRY_SHARING |
| 4609 | 4619 | if(!v ) return rc; |
| @@ -4644,11 +4654,11 @@ | ||
| 4644 | 4654 | for( ; i < alen; ++i ) |
| 4645 | 4655 | { |
| 4646 | 4656 | cson_value * ch = cson_array_get( asrc, i ); |
| 4647 | 4657 | if( NULL != ch ) |
| 4648 | 4658 | { |
| 4649 | - cson_value * cl = cson_value_clone_shared( ch ); | |
| 4659 | + cson_value * cl = cson_value_clone_ref( ch ); | |
| 4650 | 4660 | if( NULL == cl ) |
| 4651 | 4661 | { |
| 4652 | 4662 | cson_value_free( destV ); |
| 4653 | 4663 | return NULL; |
| 4654 | 4664 | } |
| @@ -4687,12 +4697,12 @@ | ||
| 4687 | 4697 | while( (kvp = cson_object_iter_next( &iter )) ) |
| 4688 | 4698 | { |
| 4689 | 4699 | cson_value * key = NULL; |
| 4690 | 4700 | cson_value * val = NULL; |
| 4691 | 4701 | assert( kvp->key && (kvp->key->refcount>0) ); |
| 4692 | - key = cson_value_clone_shared(kvp->key); | |
| 4693 | - val = key ? cson_value_clone_shared(kvp->value) : NULL; | |
| 4702 | + key = cson_value_clone_ref(kvp->key); | |
| 4703 | + val = key ? cson_value_clone_ref(kvp->value) : NULL; | |
| 4694 | 4704 | if( ! key || !val ){ |
| 4695 | 4705 | goto error; |
| 4696 | 4706 | } |
| 4697 | 4707 | assert( CSON_STR(key) ); |
| 4698 | 4708 | if( 0 != cson_object_set_s( dest, CSON_STR(key), val ) ) |
| @@ -5000,27 +5010,29 @@ | ||
| 5000 | 5010 | return 0; |
| 5001 | 5011 | } |
| 5002 | 5012 | |
| 5003 | 5013 | static cson_value * cson_guess_arg_type(char const *arg){ |
| 5004 | 5014 | char * end = NULL; |
| 5005 | - if(('0'<=*arg) && ('9'>=*arg)){ | |
| 5015 | + if(!arg || !*arg) return cson_value_null(); | |
| 5016 | + else if(('0'>*arg) || ('9'<*arg)){ | |
| 5006 | 5017 | goto do_string; |
| 5007 | 5018 | } |
| 5008 | - { | |
| 5019 | + else{ /* try numbers... */ | |
| 5009 | 5020 | long const val = strtol(arg, &end, 10); |
| 5010 | 5021 | if(!*end){ |
| 5011 | 5022 | return cson_value_new_integer( (cson_int_t)val); |
| 5012 | 5023 | } |
| 5013 | - } | |
| 5014 | - { | |
| 5015 | - double const val = strtod(arg, &end); | |
| 5016 | - if(!*end){ | |
| 5017 | - return cson_value_new_double(val); | |
| 5024 | + else if( '.' != *end ) { | |
| 5025 | + goto do_string; | |
| 5026 | + } | |
| 5027 | + else { | |
| 5028 | + double const val = strtod(arg, &end); | |
| 5029 | + if(!*end){ | |
| 5030 | + return cson_value_new_double(val); | |
| 5031 | + } | |
| 5018 | 5032 | } |
| 5019 | 5033 | } |
| 5020 | - | |
| 5021 | - | |
| 5022 | 5034 | do_string: |
| 5023 | 5035 | return cson_value_new_string(arg, strlen(arg)); |
| 5024 | 5036 | } |
| 5025 | 5037 | |
| 5026 | 5038 | |
| @@ -5051,13 +5063,11 @@ | ||
| 5051 | 5063 | if(!*pos){ /** --key */ |
| 5052 | 5064 | v = cson_value_true(); |
| 5053 | 5065 | }else{ /** --key=...*/ |
| 5054 | 5066 | assert('=' == *pos); |
| 5055 | 5067 | ++pos /*skip '='*/; |
| 5056 | - v = *pos | |
| 5057 | - ? cson_guess_arg_type(pos) | |
| 5058 | - : cson_value_null(); | |
| 5068 | + v = cson_guess_arg_type(pos); | |
| 5059 | 5069 | } |
| 5060 | 5070 | if(0 != (rc=cson_object_set_s(o, k, v))){ |
| 5061 | 5071 | cson_free_string(k); |
| 5062 | 5072 | cson_value_free(v); |
| 5063 | 5073 | break; |
| 5064 | 5074 |
| --- src/cson_amalgamation.c | |
| +++ src/cson_amalgamation.c | |
| @@ -1616,11 +1616,17 @@ | |
| 1616 | |
| 1617 | |
| 1618 | |
| 1619 | #define CSON_CAST(T,V) ((T*)((V)->value)) |
| 1620 | #define CSON_VCAST(V) ((cson_value *)(((unsigned char *)(V))-sizeof(cson_value))) |
| 1621 | #define CSON_INT(V) ((cson_int_t*)(V)->value) |
| 1622 | #define CSON_DBL(V) CSON_CAST(cson_double_t,(V)) |
| 1623 | #define CSON_STR(V) CSON_CAST(cson_string,(V)) |
| 1624 | #define CSON_OBJ(V) CSON_CAST(cson_object,(V)) |
| 1625 | #define CSON_ARRAY(V) CSON_CAST(cson_array,(V)) |
| 1626 | |
| @@ -1958,11 +1964,11 @@ | |
| 1958 | #if 1 |
| 1959 | if( ! v ) return NULL; |
| 1960 | else if( v == &CSON_EMPTY_HOLDER.stringValue ) return ""; |
| 1961 | else { |
| 1962 | assert((0 < v->length) && "How do we have a non-singleton empty string?"); |
| 1963 | return (char *)((unsigned char *)(v+1)); |
| 1964 | } |
| 1965 | #else |
| 1966 | return (NULL == v) |
| 1967 | ? NULL |
| 1968 | : (v->length |
| @@ -2039,10 +2045,13 @@ | |
| 2039 | }; |
| 2040 | #define cson_kvp_empty_m {NULL,NULL} |
| 2041 | static const cson_kvp cson_kvp_empty = cson_kvp_empty_m; |
| 2042 | |
| 2043 | /** @def CSON_OBJECT_PROPS_SORT |
| 2044 | |
| 2045 | If CSON_OBJECT_PROPS_SORT is set to a true value then |
| 2046 | qsort() and bsearch() are used to sort (upon insertion) |
| 2047 | and search cson_object::kvp property lists. This costs us |
| 2048 | a re-sort on each insertion but searching is O(log n) |
| @@ -2221,11 +2230,12 @@ | |
| 2221 | of the string to allocate + 1 byte (for the NUL). |
| 2222 | |
| 2223 | The returned value->api member will be set appropriately and |
| 2224 | val->value will be set to point to the memory allocated to hold the |
| 2225 | native value type. Use the internal CSON_CAST() family of macros to |
| 2226 | convert them. |
| 2227 | |
| 2228 | Returns NULL on allocation error. |
| 2229 | |
| 2230 | @see cson_value_new_array() |
| 2231 | @see cson_value_new_object() |
| @@ -2257,17 +2267,14 @@ | |
| 2257 | tx = sizeof(cson_double_t); |
| 2258 | reason = "cson_value:double"; |
| 2259 | break; |
| 2260 | case CSON_TYPE_INTEGER: |
| 2261 | assert( 0 == extra ); |
| 2262 | /* FIXME: if sizeof(void*) >= sizeof(cson_int_t) then store |
| 2263 | the int value directly in the void pointer (requires no |
| 2264 | extra alloc). The current behaviour requires 32 |
| 2265 | bytes(!!!) on 64-bit builds. |
| 2266 | */ |
| 2267 | def = cson_value_integer_empty; |
| 2268 | tx = sizeof(cson_int_t); |
| 2269 | reason = "cson_value:int"; |
| 2270 | break; |
| 2271 | case CSON_TYPE_STRING: |
| 2272 | assert( 0 != extra ); |
| 2273 | def = cson_value_string_empty; |
| @@ -2657,13 +2664,14 @@ | |
| 2657 | } |
| 2658 | case CSON_TYPE_STRING: |
| 2659 | case CSON_TYPE_ARRAY: |
| 2660 | case CSON_TYPE_OBJECT: |
| 2661 | default: |
| 2662 | break; |
| 2663 | } |
| 2664 | if(v) *v = i; |
| 2665 | return rc; |
| 2666 | } |
| 2667 | } |
| 2668 | |
| 2669 | cson_int_t cson_value_get_integer( cson_value const * val ) |
| @@ -2872,11 +2880,13 @@ | |
| 2872 | { |
| 2873 | if( 0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_INT_0]; |
| 2874 | else |
| 2875 | { |
| 2876 | cson_value * c = cson_value_new(CSON_TYPE_INTEGER,0); |
| 2877 | |
| 2878 | if( c ) |
| 2879 | { |
| 2880 | *CSON_INT(c) = v; |
| 2881 | } |
| 2882 | return c; |
| @@ -4597,13 +4607,13 @@ | |
| 4597 | |
| 4598 | |
| 4599 | /** |
| 4600 | If v is-a Object or Array then this function returns a deep |
| 4601 | clone, otherwise it returns v. In either case, the refcount |
| 4602 | of the returned value is increased by 1. |
| 4603 | */ |
| 4604 | static cson_value * cson_value_clone_shared( cson_value * v ) |
| 4605 | { |
| 4606 | cson_value * rc = NULL; |
| 4607 | #define TRY_SHARING 1 |
| 4608 | #if TRY_SHARING |
| 4609 | if(!v ) return rc; |
| @@ -4644,11 +4654,11 @@ | |
| 4644 | for( ; i < alen; ++i ) |
| 4645 | { |
| 4646 | cson_value * ch = cson_array_get( asrc, i ); |
| 4647 | if( NULL != ch ) |
| 4648 | { |
| 4649 | cson_value * cl = cson_value_clone_shared( ch ); |
| 4650 | if( NULL == cl ) |
| 4651 | { |
| 4652 | cson_value_free( destV ); |
| 4653 | return NULL; |
| 4654 | } |
| @@ -4687,12 +4697,12 @@ | |
| 4687 | while( (kvp = cson_object_iter_next( &iter )) ) |
| 4688 | { |
| 4689 | cson_value * key = NULL; |
| 4690 | cson_value * val = NULL; |
| 4691 | assert( kvp->key && (kvp->key->refcount>0) ); |
| 4692 | key = cson_value_clone_shared(kvp->key); |
| 4693 | val = key ? cson_value_clone_shared(kvp->value) : NULL; |
| 4694 | if( ! key || !val ){ |
| 4695 | goto error; |
| 4696 | } |
| 4697 | assert( CSON_STR(key) ); |
| 4698 | if( 0 != cson_object_set_s( dest, CSON_STR(key), val ) ) |
| @@ -5000,27 +5010,29 @@ | |
| 5000 | return 0; |
| 5001 | } |
| 5002 | |
| 5003 | static cson_value * cson_guess_arg_type(char const *arg){ |
| 5004 | char * end = NULL; |
| 5005 | if(('0'<=*arg) && ('9'>=*arg)){ |
| 5006 | goto do_string; |
| 5007 | } |
| 5008 | { |
| 5009 | long const val = strtol(arg, &end, 10); |
| 5010 | if(!*end){ |
| 5011 | return cson_value_new_integer( (cson_int_t)val); |
| 5012 | } |
| 5013 | } |
| 5014 | { |
| 5015 | double const val = strtod(arg, &end); |
| 5016 | if(!*end){ |
| 5017 | return cson_value_new_double(val); |
| 5018 | } |
| 5019 | } |
| 5020 | |
| 5021 | |
| 5022 | do_string: |
| 5023 | return cson_value_new_string(arg, strlen(arg)); |
| 5024 | } |
| 5025 | |
| 5026 | |
| @@ -5051,13 +5063,11 @@ | |
| 5051 | if(!*pos){ /** --key */ |
| 5052 | v = cson_value_true(); |
| 5053 | }else{ /** --key=...*/ |
| 5054 | assert('=' == *pos); |
| 5055 | ++pos /*skip '='*/; |
| 5056 | v = *pos |
| 5057 | ? cson_guess_arg_type(pos) |
| 5058 | : cson_value_null(); |
| 5059 | } |
| 5060 | if(0 != (rc=cson_object_set_s(o, k, v))){ |
| 5061 | cson_free_string(k); |
| 5062 | cson_value_free(v); |
| 5063 | break; |
| 5064 |
| --- src/cson_amalgamation.c | |
| +++ src/cson_amalgamation.c | |
| @@ -1616,11 +1616,17 @@ | |
| 1616 | |
| 1617 | |
| 1618 | |
| 1619 | #define CSON_CAST(T,V) ((T*)((V)->value)) |
| 1620 | #define CSON_VCAST(V) ((cson_value *)(((unsigned char *)(V))-sizeof(cson_value))) |
| 1621 | |
| 1622 | #if CSON_VOID_PTR_IS_BIG |
| 1623 | # define CSON_INT(V) ((cson_int_t*)(&((V)->value))) |
| 1624 | #else |
| 1625 | # define CSON_INT(V) ((cson_int_t*)(V)->value) |
| 1626 | #endif |
| 1627 | |
| 1628 | #define CSON_DBL(V) CSON_CAST(cson_double_t,(V)) |
| 1629 | #define CSON_STR(V) CSON_CAST(cson_string,(V)) |
| 1630 | #define CSON_OBJ(V) CSON_CAST(cson_object,(V)) |
| 1631 | #define CSON_ARRAY(V) CSON_CAST(cson_array,(V)) |
| 1632 | |
| @@ -1958,11 +1964,11 @@ | |
| 1964 | #if 1 |
| 1965 | if( ! v ) return NULL; |
| 1966 | else if( v == &CSON_EMPTY_HOLDER.stringValue ) return ""; |
| 1967 | else { |
| 1968 | assert((0 < v->length) && "How do we have a non-singleton empty string?"); |
| 1969 | return (char const *)((unsigned char const *)(v+1)); |
| 1970 | } |
| 1971 | #else |
| 1972 | return (NULL == v) |
| 1973 | ? NULL |
| 1974 | : (v->length |
| @@ -2039,10 +2045,13 @@ | |
| 2045 | }; |
| 2046 | #define cson_kvp_empty_m {NULL,NULL} |
| 2047 | static const cson_kvp cson_kvp_empty = cson_kvp_empty_m; |
| 2048 | |
| 2049 | /** @def CSON_OBJECT_PROPS_SORT |
| 2050 | |
| 2051 | Don't use this - it has not been updated to account for internal |
| 2052 | changes in cson_object. |
| 2053 | |
| 2054 | If CSON_OBJECT_PROPS_SORT is set to a true value then |
| 2055 | qsort() and bsearch() are used to sort (upon insertion) |
| 2056 | and search cson_object::kvp property lists. This costs us |
| 2057 | a re-sort on each insertion but searching is O(log n) |
| @@ -2221,11 +2230,12 @@ | |
| 2230 | of the string to allocate + 1 byte (for the NUL). |
| 2231 | |
| 2232 | The returned value->api member will be set appropriately and |
| 2233 | val->value will be set to point to the memory allocated to hold the |
| 2234 | native value type. Use the internal CSON_CAST() family of macros to |
| 2235 | convert the cson_values to their corresponding native |
| 2236 | representation. |
| 2237 | |
| 2238 | Returns NULL on allocation error. |
| 2239 | |
| 2240 | @see cson_value_new_array() |
| 2241 | @see cson_value_new_object() |
| @@ -2257,17 +2267,14 @@ | |
| 2267 | tx = sizeof(cson_double_t); |
| 2268 | reason = "cson_value:double"; |
| 2269 | break; |
| 2270 | case CSON_TYPE_INTEGER: |
| 2271 | assert( 0 == extra ); |
| 2272 | def = cson_value_integer_empty; |
| 2273 | #if !CSON_VOID_PTR_IS_BIG |
| 2274 | tx = sizeof(cson_int_t); |
| 2275 | #endif |
| 2276 | reason = "cson_value:int"; |
| 2277 | break; |
| 2278 | case CSON_TYPE_STRING: |
| 2279 | assert( 0 != extra ); |
| 2280 | def = cson_value_string_empty; |
| @@ -2657,13 +2664,14 @@ | |
| 2664 | } |
| 2665 | case CSON_TYPE_STRING: |
| 2666 | case CSON_TYPE_ARRAY: |
| 2667 | case CSON_TYPE_OBJECT: |
| 2668 | default: |
| 2669 | rc = cson_rc.TypeError; |
| 2670 | break; |
| 2671 | } |
| 2672 | if(!rc && v) *v = i; |
| 2673 | return rc; |
| 2674 | } |
| 2675 | } |
| 2676 | |
| 2677 | cson_int_t cson_value_get_integer( cson_value const * val ) |
| @@ -2872,11 +2880,13 @@ | |
| 2880 | { |
| 2881 | if( 0 == v ) return &CSON_SPECIAL_VALUES[CSON_VAL_INT_0]; |
| 2882 | else |
| 2883 | { |
| 2884 | cson_value * c = cson_value_new(CSON_TYPE_INTEGER,0); |
| 2885 | #if !defined(NDEBUG) && CSON_VOID_PTR_IS_BIG |
| 2886 | assert( sizeof(cson_int_t) <= sizeof(void *) ); |
| 2887 | #endif |
| 2888 | if( c ) |
| 2889 | { |
| 2890 | *CSON_INT(c) = v; |
| 2891 | } |
| 2892 | return c; |
| @@ -4597,13 +4607,13 @@ | |
| 4607 | |
| 4608 | |
| 4609 | /** |
| 4610 | If v is-a Object or Array then this function returns a deep |
| 4611 | clone, otherwise it returns v. In either case, the refcount |
| 4612 | of the returned value is increased by 1 by this call. |
| 4613 | */ |
| 4614 | static cson_value * cson_value_clone_ref( cson_value * v ) |
| 4615 | { |
| 4616 | cson_value * rc = NULL; |
| 4617 | #define TRY_SHARING 1 |
| 4618 | #if TRY_SHARING |
| 4619 | if(!v ) return rc; |
| @@ -4644,11 +4654,11 @@ | |
| 4654 | for( ; i < alen; ++i ) |
| 4655 | { |
| 4656 | cson_value * ch = cson_array_get( asrc, i ); |
| 4657 | if( NULL != ch ) |
| 4658 | { |
| 4659 | cson_value * cl = cson_value_clone_ref( ch ); |
| 4660 | if( NULL == cl ) |
| 4661 | { |
| 4662 | cson_value_free( destV ); |
| 4663 | return NULL; |
| 4664 | } |
| @@ -4687,12 +4697,12 @@ | |
| 4697 | while( (kvp = cson_object_iter_next( &iter )) ) |
| 4698 | { |
| 4699 | cson_value * key = NULL; |
| 4700 | cson_value * val = NULL; |
| 4701 | assert( kvp->key && (kvp->key->refcount>0) ); |
| 4702 | key = cson_value_clone_ref(kvp->key); |
| 4703 | val = key ? cson_value_clone_ref(kvp->value) : NULL; |
| 4704 | if( ! key || !val ){ |
| 4705 | goto error; |
| 4706 | } |
| 4707 | assert( CSON_STR(key) ); |
| 4708 | if( 0 != cson_object_set_s( dest, CSON_STR(key), val ) ) |
| @@ -5000,27 +5010,29 @@ | |
| 5010 | return 0; |
| 5011 | } |
| 5012 | |
| 5013 | static cson_value * cson_guess_arg_type(char const *arg){ |
| 5014 | char * end = NULL; |
| 5015 | if(!arg || !*arg) return cson_value_null(); |
| 5016 | else if(('0'>*arg) || ('9'<*arg)){ |
| 5017 | goto do_string; |
| 5018 | } |
| 5019 | else{ /* try numbers... */ |
| 5020 | long const val = strtol(arg, &end, 10); |
| 5021 | if(!*end){ |
| 5022 | return cson_value_new_integer( (cson_int_t)val); |
| 5023 | } |
| 5024 | else if( '.' != *end ) { |
| 5025 | goto do_string; |
| 5026 | } |
| 5027 | else { |
| 5028 | double const val = strtod(arg, &end); |
| 5029 | if(!*end){ |
| 5030 | return cson_value_new_double(val); |
| 5031 | } |
| 5032 | } |
| 5033 | } |
| 5034 | do_string: |
| 5035 | return cson_value_new_string(arg, strlen(arg)); |
| 5036 | } |
| 5037 | |
| 5038 | |
| @@ -5051,13 +5063,11 @@ | |
| 5063 | if(!*pos){ /** --key */ |
| 5064 | v = cson_value_true(); |
| 5065 | }else{ /** --key=...*/ |
| 5066 | assert('=' == *pos); |
| 5067 | ++pos /*skip '='*/; |
| 5068 | v = cson_guess_arg_type(pos); |
| 5069 | } |
| 5070 | if(0 != (rc=cson_object_set_s(o, k, v))){ |
| 5071 | cson_free_string(k); |
| 5072 | cson_value_free(v); |
| 5073 | break; |
| 5074 |
+36
| --- src/cson_amalgamation.h | ||
| +++ src/cson_amalgamation.h | ||
| @@ -74,10 +74,46 @@ | ||
| 74 | 74 | #else |
| 75 | 75 | typedef double cson_double_t; |
| 76 | 76 | #define CSON_DOUBLE_T_SFMT "f" |
| 77 | 77 | #define CSON_DOUBLE_T_PFMT "f" |
| 78 | 78 | #endif |
| 79 | + | |
| 80 | +/** @def CSON_VOID_PTR_IS_BIG | |
| 81 | + | |
| 82 | +ONLY define this to a true value if you know that | |
| 83 | + | |
| 84 | +(sizeof(cson_int_t) <= sizeof(void*)) | |
| 85 | + | |
| 86 | +If that is the case, cson does not need to dynamically | |
| 87 | +allocate integers. However, enabling this may cause | |
| 88 | +compilation warnings in 32-bit builds even though the code | |
| 89 | +being warned about cannot ever be called. To get around such | |
| 90 | +warnings, when building on a 64-bit environment you can define | |
| 91 | +this to 1 to get "big" integer support. HOWEVER, all clients must | |
| 92 | +also use the same value for this macro. If i knew a halfway reliable | |
| 93 | +way to determine this automatically at preprocessor-time, i would | |
| 94 | +automate this. We might be able to do halfway reliably by looking | |
| 95 | +for a large INT_MAX value? | |
| 96 | +*/ | |
| 97 | +#if !defined(CSON_VOID_PTR_IS_BIG) | |
| 98 | + | |
| 99 | +/* Largely taken from http://predef.sourceforge.net/prearch.html | |
| 100 | + | |
| 101 | +See also: http://poshlib.hookatooka.com/poshlib/trac.cgi/browser/posh.h | |
| 102 | +*/ | |
| 103 | +# if defined(_WIN64) || defined(__LP64__)/*gcc*/ \ | |
| 104 | + || defined(_M_X64) || defined(__amd64__) || defined(__amd64) \ | |
| 105 | + || defined(__x86_64__) || defined(__x86_64) \ | |
| 106 | + || defined(__ia64__) || defined(__ia64) || defined(_IA64) || defined(__IA64__) \ | |
| 107 | + || defined(_M_IA64) \ | |
| 108 | + || defined(__sparc_v9__) || defined(__sparcv9) || defined(_ADDR64) \ | |
| 109 | + || defined(__64BIT__) | |
| 110 | +# define CSON_VOID_PTR_IS_BIG 1 | |
| 111 | +# else | |
| 112 | +# define CSON_VOID_PTR_IS_BIG 0 | |
| 113 | +# endif | |
| 114 | +#endif | |
| 79 | 115 | |
| 80 | 116 | /** @def CSON_INT_T_SFMT |
| 81 | 117 | |
| 82 | 118 | scanf()-compatible format token for cson_int_t. |
| 83 | 119 | */ |
| 84 | 120 |
| --- src/cson_amalgamation.h | |
| +++ src/cson_amalgamation.h | |
| @@ -74,10 +74,46 @@ | |
| 74 | #else |
| 75 | typedef double cson_double_t; |
| 76 | #define CSON_DOUBLE_T_SFMT "f" |
| 77 | #define CSON_DOUBLE_T_PFMT "f" |
| 78 | #endif |
| 79 | |
| 80 | /** @def CSON_INT_T_SFMT |
| 81 | |
| 82 | scanf()-compatible format token for cson_int_t. |
| 83 | */ |
| 84 |
| --- src/cson_amalgamation.h | |
| +++ src/cson_amalgamation.h | |
| @@ -74,10 +74,46 @@ | |
| 74 | #else |
| 75 | typedef double cson_double_t; |
| 76 | #define CSON_DOUBLE_T_SFMT "f" |
| 77 | #define CSON_DOUBLE_T_PFMT "f" |
| 78 | #endif |
| 79 | |
| 80 | /** @def CSON_VOID_PTR_IS_BIG |
| 81 | |
| 82 | ONLY define this to a true value if you know that |
| 83 | |
| 84 | (sizeof(cson_int_t) <= sizeof(void*)) |
| 85 | |
| 86 | If that is the case, cson does not need to dynamically |
| 87 | allocate integers. However, enabling this may cause |
| 88 | compilation warnings in 32-bit builds even though the code |
| 89 | being warned about cannot ever be called. To get around such |
| 90 | warnings, when building on a 64-bit environment you can define |
| 91 | this to 1 to get "big" integer support. HOWEVER, all clients must |
| 92 | also use the same value for this macro. If i knew a halfway reliable |
| 93 | way to determine this automatically at preprocessor-time, i would |
| 94 | automate this. We might be able to do halfway reliably by looking |
| 95 | for a large INT_MAX value? |
| 96 | */ |
| 97 | #if !defined(CSON_VOID_PTR_IS_BIG) |
| 98 | |
| 99 | /* Largely taken from http://predef.sourceforge.net/prearch.html |
| 100 | |
| 101 | See also: http://poshlib.hookatooka.com/poshlib/trac.cgi/browser/posh.h |
| 102 | */ |
| 103 | # if defined(_WIN64) || defined(__LP64__)/*gcc*/ \ |
| 104 | || defined(_M_X64) || defined(__amd64__) || defined(__amd64) \ |
| 105 | || defined(__x86_64__) || defined(__x86_64) \ |
| 106 | || defined(__ia64__) || defined(__ia64) || defined(_IA64) || defined(__IA64__) \ |
| 107 | || defined(_M_IA64) \ |
| 108 | || defined(__sparc_v9__) || defined(__sparcv9) || defined(_ADDR64) \ |
| 109 | || defined(__64BIT__) |
| 110 | # define CSON_VOID_PTR_IS_BIG 1 |
| 111 | # else |
| 112 | # define CSON_VOID_PTR_IS_BIG 0 |
| 113 | # endif |
| 114 | #endif |
| 115 | |
| 116 | /** @def CSON_INT_T_SFMT |
| 117 | |
| 118 | scanf()-compatible format token for cson_int_t. |
| 119 | */ |
| 120 |