From 61287aea590bb00824fa693d19c59d45d3e58a19 Mon Sep 17 00:00:00 2001
From: "Hossein.M" <hossein.m9877@gmail.com>
Date: Sun, 17 Apr 2022 19:21:09 +0430
Subject: [PATCH 1/4] Fix error: too few arguments

---
 samples/src/example.c |  57 +++++++--------
 tests/src/test.c      | 158 +++++++++++++++++++++++-------------------
 2 files changed, 114 insertions(+), 101 deletions(-)

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/tests/src/test.c b/tests/src/test.c
index a8f0bac..dfee179 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 ) );
@@ -135,14 +138,15 @@ static int empty( void ) {
 
 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 +162,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 +188,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 +201,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 +215,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,11 +228,12 @@ 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 );
@@ -235,13 +245,14 @@ static int integers( void ) {
 
 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 +261,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]}";

From 8f5a96a24fb29895dfad0c55c06f7d5de531d956 Mon Sep 17 00:00:00 2001
From: "Hossein.M" <hossein.m9877@gmail.com>
Date: Wed, 25 Oct 2023 09:56:21 +0330
Subject: [PATCH 2/4] fix: buffer overflow and NO_SPRINTF functionality

---
 src/json-maker.c | 80 ++++++++++++++++++++++++++++++------------------
 1 file changed, 50 insertions(+), 30 deletions(-)

diff --git a/src/json-maker.c b/src/json-maker.c
index 129a2c3..af49a69 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,29 +264,30 @@ 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        ) \
@@ -284,8 +304,8 @@ ALL_TYPES
 ALL_TYPES
 #undef X
 
-char* json_double( char* dest, char const* name, double value ) {
-    return json_verylong( dest, name, value );
+char* json_double( char* dest, char const* name, double value, size_t* remLen ) {
+    return json_verylong( dest, name, value, remLen );
 }
 
 #else

From 317bed38d70bec4104600df0cd1b005f128f9550 Mon Sep 17 00:00:00 2001
From: "Hossein.M" <hossein.m9877@gmail.com>
Date: Wed, 25 Oct 2023 10:07:53 +0330
Subject: [PATCH 3/4] feat: add json_uverylong function

---
 src/include/json-maker/json-maker.h |  8 ++++++++
 src/json-maker.c                    | 30 +++++++++++++++--------------
 2 files changed, 24 insertions(+), 14 deletions(-)

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 af49a69..f4d7021 100644
--- a/src/json-maker.c
+++ b/src/json-maker.c
@@ -290,11 +290,12 @@ char* func( char* dest, char const* name, type value, size_t *remLen ) {    \
 }                                                           
 
 #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
@@ -312,22 +313,23 @@ char* json_double( char* dest, char const* name, double value, size_t* remLen )
 
 #include <stdio.h>
 
-#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" ) \
+    X( json_double,    double,             "%g"   )
 
 
-#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 );                                              \

From 26925010aab8c4f7386cdc86d9d178154c471581 Mon Sep 17 00:00:00 2001
From: "Hossein.M" <hossein.m9877@gmail.com>
Date: Wed, 25 Oct 2023 10:21:43 +0330
Subject: [PATCH 4/4] test: add test for json_uverylong

---
 tests/src/test.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/tests/src/test.c b/tests/src/test.c
index dfee179..0639be4 100644
--- a/tests/src/test.c
+++ b/tests/src/test.c
@@ -136,6 +136,11 @@ 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];
     size_t remLen = sizeof(buff);
@@ -240,6 +245,19 @@ static int integers( void ) {
         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();
 }