diff --git a/samples/src/example.c b/samples/src/example.c index da00594..62a56b7 100644 --- a/samples/src/example.c +++ b/samples/src/example.c @@ -51,45 +51,45 @@ struct data { /* Add a time object property in a JSON string. "name":{"temp":-5,"hum":48}, */ -char* json_weather( char* dest, char const* name, struct weather const* weather ) { - dest = json_objOpen( dest, name ); // --> "name":{\0 - dest = json_int( dest, "temp", weather->temp ); // --> "name":{"temp":22,\0 - dest = json_int( dest, "hum", weather->hum ); // --> "name":{"temp":22,"hum":45,\0 - dest = json_objClose( dest ); // --> "name":{"temp":22,"hum":45},\0 +char* json_weather( char* dest, char const* name, struct weather const* weather, size_t* remLen ) { + dest = json_objOpen( dest, name, remLen ); // --> "name":{\0 + dest = json_int( dest, "temp", weather->temp, remLen ); // --> "name":{"temp":22,\0 + dest = json_int( dest, "hum", weather->hum, remLen ); // --> "name":{"temp":22,"hum":45,\0 + dest = json_objClose( dest, remLen ); // --> "name":{"temp":22,"hum":45},\0 return dest; } /* Add a time object property in a JSON string. "name":{"hour":18,"minute":32}, */ -char* json_time( char* dest, char const* name, struct time const* time ) { - dest = json_objOpen( dest, name ); - dest = json_int( dest, "hour", time->hour ); - dest = json_int( dest, "minute", time->minute ); - dest = json_objClose( dest ); +char* json_time( char* dest, char const* name, struct time const* time, size_t* remLen ) { + dest = json_objOpen( dest, name, remLen ); + dest = json_int( dest, "hour", time->hour, remLen ); + dest = json_int( dest, "minute", time->minute, remLen ); + dest = json_objClose( dest, remLen ); return dest; } /* Add a measure object property in a JSON string. "name":{"weather":{"temp":-5,"hum":48},"time":{"hour":18,"minute":32}}, */ -char* json_measure( char* dest, char const* name, struct measure const* measure ) { - dest = json_objOpen( dest, name ); - dest = json_weather( dest, "weather", &measure->weather ); - dest = json_time( dest, "time", &measure->time ); - dest = json_objClose( dest ); +char* json_measure( char* dest, char const* name, struct measure const* measure, size_t* remLen ) { + dest = json_objOpen( dest, name, remLen ); + dest = json_weather( dest, "weather", &measure->weather, remLen ); + dest = json_time( dest, "time", &measure->time, remLen ); + dest = json_objClose( dest, remLen ); return dest; } /* Add a data object property in a JSON string. */ -char* json_data( char* dest, char const* name, struct data const* data ) { - dest = json_objOpen( dest, NULL ); - dest = json_str( dest, "city", data->city ); - dest = json_str( dest, "street", data->street ); - dest = json_measure( dest, "measure", &data->measure ); - dest = json_arrOpen( dest, "samples" ); +char* json_data( char* dest, char const* name, struct data const* data, size_t* remLen ) { + dest = json_objOpen( dest, NULL, remLen ); + dest = json_str( dest, "city", data->city, remLen ); + dest = json_str( dest, "street", data->street, remLen ); + dest = json_measure( dest, "measure", &data->measure, remLen ); + dest = json_arrOpen( dest, "samples", remLen ); for( int i = 0; i < 4; ++i ) - dest = json_int( dest, NULL, data->samples[i] ); - dest = json_arrClose( dest ); - dest = json_objClose( dest ); + dest = json_int( dest, NULL, data->samples[i], remLen ); + dest = json_arrClose( dest, remLen ); + dest = json_objClose( dest, remLen ); return dest; } @@ -97,9 +97,9 @@ char* json_data( char* dest, char const* name, struct data const* data ) { * @param dest Destination memory block. * @param data Source data structure. * @return The JSON string length. */ -int data_to_json( char* dest, struct data const* data ) { - char* p = json_data( dest, NULL, data ); - p = json_end( p ); +int data_to_json( char* dest, struct data const* data, size_t* remLen ) { + char* p = json_data( dest, NULL, data, remLen ); + p = json_end( p, remLen ); return p - dest; } @@ -149,7 +149,8 @@ int main(int argc, char** argv) { } }; char buff[512]; - int len = data_to_json( buff, &data ); + size_t remLen = sizeof(buff); + int len = data_to_json( buff, &data, &remLen ); if( len >= sizeof buff ) { fprintf( stderr, "%s%d%s%d\n", "Error. Len: ", len, " Max: ", (int)sizeof buff - 1 ); return EXIT_FAILURE; diff --git a/src/include/json-maker/json-maker.h b/src/include/json-maker/json-maker.h index ed539e5..8f01290 100644 --- a/src/include/json-maker/json-maker.h +++ b/src/include/json-maker/json-maker.h @@ -142,6 +142,14 @@ char* json_ulong( char* dest, char const* name, unsigned long int value, size_t* * @return Pointer to the new end of JSON under construction. */ char* json_verylong( char* dest, char const* name, long long int value, size_t* remLen ); +/** Add a unsigned long long integer property in a JSON string. + * @param dest Pointer to the end of JSON under construction. + * @param name Pointer to null-terminated string or null for unnamed. + * @param value Value of the property. + * @param remLen Pointer to remaining length of dest + * @return Pointer to the new end of JSON under construction. */ +char* json_uverylong( char* dest, char const* name, unsigned long long int value, size_t* remLen ); + /** Add a double precision number property in a JSON string. * @param dest Pointer to the end of JSON under construction. * @param name Pointer to null-terminated string or null for unnamed. diff --git a/src/json-maker.c b/src/json-maker.c index 129a2c3..40d8ae9 100644 --- a/src/json-maker.c +++ b/src/json-maker.c @@ -32,11 +32,16 @@ * @param remLen Pointer to remaining length of dest * @return Pointer to the null character of the destination string. */ static char* chtoa( char* dest, char ch, size_t* remLen ) { - if (*remLen != 0) { + if (0 != *remLen) { --*remLen; - *dest = ch; - *++dest = '\0'; + *dest++ = ch; } + if (0 == *remLen) + { + ++*remLen; + --dest; + } + *dest = '\0'; return dest; } @@ -48,6 +53,11 @@ static char* chtoa( char* dest, char ch, size_t* remLen ) { static char* atoa( char* dest, char const* src, size_t* remLen ) { for( ; *src != '\0' && *remLen != 0; ++dest, ++src, --*remLen ) *dest = *src; + if (0 == *remLen) + { + ++*remLen; + --dest; + } *dest = '\0'; return dest; } @@ -222,6 +232,7 @@ char* json_end( char* dest, size_t* remLen ) { if ( ',' == dest[-1] ) { dest[-1] = '\0'; --dest; + *dest = '\0'; ++*remLen; } return dest; @@ -229,9 +240,17 @@ char* json_end( char* dest, size_t* remLen ) { #ifdef NO_SPRINTF -static char* format( char* dest, int len, int isnegative ) { - if ( isnegative ) +static char* format( char* dest, int len, int isnegative, size_t *remLen ) { + if ( isnegative && 0 != *remLen ) + { dest[ len++ ] = '-'; + --*remLen; + } + if (0 == *remLen) + { + --len; + ++*remLen; + } dest[ len ] = '\0'; int head = 0; int tail = len - 1; @@ -245,36 +264,38 @@ static char* format( char* dest, int len, int isnegative ) { return dest + len; } -#define numtoa( func, type, utype ) \ -static char* func( char* dest, type val ) { \ - enum { base = 10 }; \ - if ( 0 == val ) \ - return chtoa( dest, '0' ); \ - int const isnegative = 0 > val; \ - utype num = isnegative ? -val : val; \ - int len = 0; \ - while( 0 != num ) { \ - int rem = num % base; \ - dest[ len++ ] = rem + '0'; \ - num = num / base; \ - } \ - return format( dest, len, isnegative ); \ -} \ - -#define json_num( func, func2, type ) \ -char* func( char* dest, char const* name, type value ) { \ - dest = primitivename( dest, name ); \ - dest = func2( dest, value ); \ - dest = chtoa( dest, ',' ); \ - return dest; \ -} \ +#define numtoa( func, type, utype ) \ +static char* func( char* dest, type val, size_t *remLen ) { \ + enum { base = 10 }; \ + if ( 0 == val ) \ + return chtoa( dest, '0', remLen ); \ + int const isnegative = 0 > val; \ + utype num = isnegative ? -val : val; \ + int len = 0; \ + while( 0 != num && *remLen != 0 ) { \ + int rem = num % base; \ + dest[ len++ ] = rem + '0'; \ + --*remLen; \ + num = num / base; \ + } \ + return format( dest, len, isnegative, remLen ); \ +} + +#define json_num( func, func2, type ) \ +char* func( char* dest, char const* name, type value, size_t *remLen ) { \ + dest = primitivename( dest, name, remLen ); \ + dest = func2( dest, value, remLen ); \ + dest = chtoa( dest, ',', remLen ); \ + return dest; \ +} #define ALL_TYPES \ - X( int, int, unsigned int ) \ - X( long, long, unsigned long ) \ - X( uint, unsigned int, unsigned int ) \ - X( ulong, unsigned long, unsigned long ) \ - X( verylong, long long, unsigned long long ) \ + X( int, int, unsigned int ) \ + X( long, long, unsigned long ) \ + X( uint, unsigned int, unsigned int ) \ + X( ulong, unsigned long, unsigned long ) \ + X( verylong, long long, unsigned long long ) \ + X( uverylong, unsigned long long, unsigned long long ) #define X( name, type, utype ) numtoa( name##toa, type, utype ) ALL_TYPES @@ -284,30 +305,102 @@ ALL_TYPES ALL_TYPES #undef X -char* json_double( char* dest, char const* name, double value ) { - return json_verylong( dest, name, value ); +#ifndef JSON_DBL_PREC +#define JSON_DBL_PREC 6 /* Default fractional precision for double output */ +#endif + +/* Simple check for finiteness: true if neither NaN nor Inf */ +static int json_isfinite(double x) { + return (x == x) && ((x - x) == 0.0); /* NaN != NaN and Inf - Inf → NaN */ +} + +/* Precomputed powers of ten for fractional scaling */ +static const unsigned long long json_pow10[] = { + 1ULL, 10ULL, 100ULL, 1000ULL, 10000ULL, 100000ULL, + 1000000ULL, 10000000ULL, 100000000ULL, 1000000000ULL, + 10000000000ULL, 100000000000ULL, 1000000000000ULL, + 10000000000000ULL, 100000000000000ULL, 1000000000000000ULL, +}; + +/* Write the fractional digits with zero padding up to `prec` digits */ +static char* json_write_frac_fixed(char* dest, + unsigned long long frac_scaled, + int prec, + size_t* remLen) { + for (int i = prec - 1; i >= 0; --i) { + unsigned long long div = json_pow10[i]; + char d = (char)('0' + (char)((frac_scaled / div) % 10ULL)); + dest = chtoa(dest, d, remLen); + } + return dest; +} + +char* json_double(char* dest, char const* name, double value, size_t* remLen) { + dest = primitivename(dest, name, remLen); + + if (!json_isfinite(value)) { + /* JSON does not support NaN/Infinity → map to null */ + dest = atoa(dest, "null,", remLen); + return dest; + } + + /* Handle sign */ + if (value < 0) { + dest = chtoa(dest, '-', remLen); + value = -value; + } + + /* Split into integer and fractional part */ + unsigned long long ipart = (unsigned long long)value; + double frac = value - (double)ipart; + + int prec = (JSON_DBL_PREC < (int)(sizeof(json_pow10)/sizeof(json_pow10[0]))-1) + ? JSON_DBL_PREC + : (int)(sizeof(json_pow10)/sizeof(json_pow10[0]))-1; + + unsigned long long scale = json_pow10[prec]; + /* +0.5 for rounding */ + unsigned long long fscaled = (unsigned long long)(frac * (double)scale + 0.5); + + /* Handle fractional overflow, e.g. 0.999999 → 1.000000 */ + if (fscaled >= scale) { + fscaled = 0; + ++ipart; + } + + /* Write integer part */ + dest = uverylongtoa(dest, ipart, remLen); + + if (prec > 0) { + dest = chtoa(dest, '.', remLen); + dest = json_write_frac_fixed(dest, fscaled, prec, remLen); + } + + dest = chtoa(dest, ',', remLen); + return dest; } #else #include +#include -#define ALL_TYPES \ - X( json_int, int, "%d" ) \ - X( json_long, long, "%ld" ) \ - X( json_uint, unsigned int, "%u" ) \ - X( json_ulong, unsigned long, "%lu" ) \ - X( json_verylong, long long, "%lld" ) \ - X( json_double, double, "%g" ) \ +#define ALL_TYPES \ + X( json_int, int, "%d" ) \ + X( json_long, long, "%ld" ) \ + X( json_uint, unsigned int, "%u" ) \ + X( json_ulong, unsigned long, "%lu" ) \ + X( json_verylong, long long, "%lld" ) \ + X( json_uverylong, unsigned long long, "%llu" ) -#define json_num( funcname, type, fmt ) \ +#define json_num( funcname, type, fmt ) \ char* funcname( char* dest, char const* name, type value, size_t* remLen ) { \ int digitLen; \ dest = primitivename( dest, name, remLen ); \ digitLen = snprintf( dest, *remLen, fmt, value ); \ if(digitLen >= (int)*remLen+1){ \ - digitLen = (int)*remLen;} \ + digitLen = (int)*remLen;} \ *remLen -= (size_t)digitLen; \ dest += digitLen; \ dest = chtoa( dest, ',', remLen ); \ @@ -318,5 +411,32 @@ char* funcname( char* dest, char const* name, type value, size_t* remLen ) { ALL_TYPES #undef X +char* json_double(char* dest, char const* name, double value, size_t* remLen) { + dest = primitivename(dest, name, remLen); + + if (!isfinite(value)) { + dest = atoa(dest, "null,", remLen); + return dest; + } + + /* Use high precision for JSON serialization */ + int wrote = snprintf(dest, *remLen, "%.17g", value); + + if (wrote < 0) { + /* snprintf error → fallback to null */ + dest = atoa(dest, "null,", remLen); + return dest; + } else if ((size_t)wrote >= *remLen) { + /* Output was truncated: snprintf wrote *remLen-1 chars + NUL */ + dest += *remLen - 1; + *remLen = 1; + } else { + dest += wrote; + *remLen -= (size_t)wrote; + } + + dest = chtoa(dest, ',', remLen); + return dest; +} #endif diff --git a/tests/src/test.c b/tests/src/test.c index a8f0bac..0639be4 100644 --- a/tests/src/test.c +++ b/tests/src/test.c @@ -68,10 +68,11 @@ static int test_suit( struct test const* tests, int numtests ) { static int escape( void ) { char buff[512]; - char* p = json_objOpen( buff, NULL ); - p = json_str( p, "name", "\tHello: \"man\"\n" ); - p = json_objClose( p ); - p = json_end( p ); + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_str( p, "name", "\tHello: \"man\"\n", &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); printf( "\n\n%s\n\n", buff ); static char const rslt[] = "{\"name\":\"\\tHello: \\\"man\\\"\\n\"}"; check( p - buff == sizeof rslt - 1 ); @@ -81,10 +82,11 @@ static int escape( void ) { static int len( void ) { char buff[512]; - char* p = json_objOpen( buff, NULL ); - p = json_nstr( p, "name", "\tHello: \"man\"\n", 6 ); - p = json_objClose( p ); - p = json_end( p ); + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_nstr( p, "name", "\tHello: \"man\"\n", 6, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); static char const rslt[] = "{\"name\":\"\\tHello\"}"; check( p - buff == sizeof rslt - 1 ); check( 0 == strcmp( buff, rslt ) ); @@ -93,34 +95,35 @@ static int len( void ) { static int empty( void ) { char buff[512]; + size_t remLen = sizeof(buff); { - char* p = json_objOpen( buff, NULL ); - p = json_objClose( p ); - p = json_end( p ); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); static char const rslt[] = "{}"; check( p - buff == sizeof rslt - 1 ); check( 0 == strcmp( buff, rslt ) ); } { - char* p = json_objOpen( buff, NULL ); - p = json_arrOpen( p, "a" ); - p = json_arrClose( p ); - p = json_objClose( p ); - p = json_end( p ); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_arrOpen( p, "a", &remLen ); + p = json_arrClose( p, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); static char const rslt[] = "{\"a\":[]}"; check( p - buff == sizeof rslt - 1 ); check( 0 == strcmp( buff, rslt ) ); } { - char* p = json_objOpen( buff, NULL ); - p = json_arrOpen( p, "a" ); - p = json_objOpen( p, NULL ); - p = json_objClose( p ); - p = json_objOpen( p, NULL ); - p = json_objClose( p ); - p = json_arrClose( p ); - p = json_objClose( p ); - p = json_end( p ); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_arrOpen( p, "a", &remLen ); + p = json_objOpen( p, NULL, &remLen ); + p = json_objClose( p, &remLen ); + p = json_objOpen( p, NULL, &remLen ); + p = json_objClose( p, &remLen ); + p = json_arrClose( p, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); static char const rslt[] = "{\"a\":[{},{}]}"; check( p - buff == sizeof rslt - 1 ); check( 0 == strcmp( buff, rslt ) ); @@ -133,16 +136,22 @@ static int empty( void ) { #define LONG_LONG_MIN LLONG_MIN #endif +#ifndef ULONG_LONG_MAX +#define ULONG_LONG_MAX ULLONG_MAX +#define ULONG_LONG_MIN 0 +#endif + static int primitive( void ) { char buff[512]; - char* p = json_objOpen( buff, NULL ); - p = json_verylong( p, "max", LONG_LONG_MAX ); - p = json_verylong( p, "min", LONG_LONG_MIN ); - p = json_bool( p, "boolvar0", 0 ); - p = json_bool( p, "boolvar1", 1 ); - p = json_null( p, "nullvar" ); - p = json_objClose( p ); - p = json_end( p ); + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_verylong( p, "max", LONG_LONG_MAX, &remLen ); + p = json_verylong( p, "min", LONG_LONG_MIN, &remLen ); + p = json_bool( p, "boolvar0", 0, &remLen ); + p = json_bool( p, "boolvar1", 1, &remLen ); + p = json_null( p, "nullvar", &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); static char const rslt[] = "{" "\"max\":9223372036854775807," "\"min\":-9223372036854775808," @@ -158,22 +167,24 @@ static int primitive( void ) { static int integers( void ) { { char buff[64]; - char* p = json_objOpen( buff, NULL ); - p = json_int( p, "a", 0 ); - p = json_int( p, "b", 1 ); - p = json_objClose( p ); - p = json_end( p ); + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_int( p, "a", 0, &remLen ); + p = json_int( p, "b", 1, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); static char const rslt[] = "{\"a\":0,\"b\":1}"; check( p - buff == sizeof rslt - 1 ); check( 0 == strcmp( buff, rslt ) ); } { char buff[64]; - char* p = json_objOpen( buff, NULL ); - p = json_int( p, "max", INT_MAX ); - p = json_int( p, "min", INT_MIN ); - p = json_objClose( p ); - p = json_end( p ); + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_int( p, "max", INT_MAX, &remLen ); + p = json_int( p, "min", INT_MIN, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); char rslt[ sizeof buff ]; int len = sprintf( rslt, "{\"max\":%d,\"min\":%d}", INT_MAX, INT_MIN ); check( len < sizeof buff ); @@ -182,10 +193,11 @@ static int integers( void ) { } { char buff[64]; - char* p = json_objOpen( buff, NULL ); - p = json_uint( p, "max", UINT_MAX ); - p = json_objClose( p ); - p = json_end( p ); + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_uint( p, "max", UINT_MAX, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); char rslt[ sizeof buff ]; int len = sprintf( rslt, "{\"max\":%u}", UINT_MAX ); check( len < sizeof buff ); @@ -194,11 +206,12 @@ static int integers( void ) { } { char buff[64]; - char* p = json_objOpen( buff, NULL ); - p = json_long( p, "max", LONG_MAX ); - p = json_long( p, "min", LONG_MIN ); - p = json_objClose( p ); - p = json_end( p ); + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_long( p, "max", LONG_MAX, &remLen ); + p = json_long( p, "min", LONG_MIN, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); char rslt[ sizeof buff ]; int len = sprintf( rslt, "{\"max\":%ld,\"min\":%ld}", LONG_MAX, LONG_MIN ); check( len < sizeof buff ); @@ -207,10 +220,11 @@ static int integers( void ) { } { char buff[64]; - char* p = json_objOpen( buff, NULL ); - p = json_ulong( p, "max", ULONG_MAX ); - p = json_objClose( p ); - p = json_end( p ); + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_ulong( p, "max", ULONG_MAX, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); char rslt[ sizeof buff ]; int len = sprintf( rslt, "{\"max\":%lu}", ULONG_MAX ); check( len < sizeof buff ); @@ -219,29 +233,44 @@ static int integers( void ) { } { char buff[64]; - char* p = json_objOpen( buff, NULL ); - p = json_verylong( p, "max", LONG_LONG_MAX ); - p = json_verylong( p, "min", LONG_LONG_MIN ); - p = json_objClose( p ); - p = json_end( p ); + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_verylong( p, "max", LONG_LONG_MAX, &remLen ); + p = json_verylong( p, "min", LONG_LONG_MIN, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); char rslt[ sizeof buff ]; int len = sprintf( rslt, "{\"max\":%lld,\"min\":%lld}", LONG_LONG_MAX, LONG_LONG_MIN ); check( len < sizeof buff ); check( p - buff == len ); check( 0 == strcmp( buff, rslt ) ); } + { + char buff[64]; + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_uverylong( p, "max", ULONG_LONG_MAX, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); + char rslt[ sizeof buff ]; + int len = sprintf( rslt, "{\"max\":%lld}", ULONG_LONG_MAX ); + check( len < sizeof buff ); + check( p - buff == len ); + check( 0 == strcmp( buff, rslt ) ); + } done(); } static int array( void ) { char buff[64]; - char* p = json_objOpen( buff, NULL ); - p = json_arrOpen( p, "a" ); + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_arrOpen( p, "a", &remLen ); for( int i = 0; i < 4; ++i ) - p = json_int( p, NULL, i ); - p = json_arrClose( p ); - p = json_objClose( p ); - p = json_end( p ); + p = json_int( p, NULL, i, &remLen ); + p = json_arrClose( p, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); static char const rslt[] = "{\"a\":[0,1,2,3]}"; check( p - buff == sizeof rslt - 1 ); check( 0 == strcmp( buff, rslt ) ); @@ -250,14 +279,15 @@ static int array( void ) { static int real( void ) { char buff[64]; - char* p = json_objOpen( buff, NULL ); - p = json_arrOpen( p, "data" ); + size_t remLen = sizeof(buff); + char* p = json_objOpen( buff, NULL, &remLen ); + p = json_arrOpen( p, "data", &remLen ); static double const lut[] = { 0.2, 2e-6, 5e6 }; for( int i = 0; i < sizeof lut / sizeof *lut; ++i ) - p = json_double( p, NULL, lut[i] ); - p = json_arrClose( p ); - p = json_objClose( p ); - p = json_end( p ); + p = json_double( p, NULL, lut[i], &remLen ); + p = json_arrClose( p, &remLen ); + p = json_objClose( p, &remLen ); + p = json_end( p, &remLen ); #ifdef NO_SPRINTF static char const rslt1[] = "{\"data\":[0,0,5000000]}"; static char const rslt2[] = "{\"data\":[0,0,5000000]}";