Browse Source

clang-format the files

tags/json-c-0.14-20200419
dota17 5 years ago
parent
commit
8b162c4b89
54 changed files with 2928 additions and 2781 deletions
  1. +79
    -75
      arraylist.c
  2. +15
    -24
      arraylist.h
  3. +38
    -25
      debug.c
  4. +28
    -13
      debug.h
  5. +8
    -7
      fuzz/tokener_parse_ex_fuzzer.cc
  6. +5
    -5
      json.h
  7. +0
    -1
      json_c_version.c
  8. +4
    -5
      json_c_version.h
  9. +451
    -479
      json_object.c
  10. +114
    -128
      json_object.h
  11. +42
    -53
      json_object_iterator.c
  12. +13
    -26
      json_object_iterator.h
  13. +39
    -33
      json_object_private.h
  14. +65
    -40
      json_pointer.c
  15. +8
    -5
      json_pointer.h
  16. +956
    -815
      json_tokener.c
  17. +69
    -67
      json_tokener.h
  18. +87
    -71
      json_util.c
  19. +7
    -9
      json_util.h
  20. +30
    -35
      json_visit.c
  21. +5
    -7
      json_visit.h
  22. +4
    -4
      libjson.c
  23. +103
    -88
      linkhash.c
  24. +20
    -32
      linkhash.h
  25. +4
    -4
      math_compat.h
  26. +65
    -55
      printbuf.c
  27. +28
    -27
      printbuf.h
  28. +1
    -1
      snprintf_compat.h
  29. +3
    -3
      strdup_compat.h
  30. +5
    -4
      strerror_override.c
  31. +2
    -2
      strerror_override.h
  32. +9
    -8
      tests/parse_flags.c
  33. +28
    -25
      tests/test1.c
  34. +9
    -5
      tests/test2.c
  35. +10
    -7
      tests/test4.c
  36. +4
    -4
      tests/testReplaceExisting.c
  37. +17
    -30
      tests/test_cast.c
  38. +5
    -5
      tests/test_charcase.c
  39. +1
    -1
      tests/test_compare.c
  40. +81
    -76
      tests/test_deep_copy.c
  41. +5
    -4
      tests/test_double_serializer.c
  42. +18
    -18
      tests/test_float.c
  43. +1
    -1
      tests/test_int_add.c
  44. +21
    -16
      tests/test_json_pointer.c
  45. +6
    -7
      tests/test_locale.c
  46. +7
    -5
      tests/test_null.c
  47. +231
    -232
      tests/test_parse.c
  48. +4
    -4
      tests/test_parse_int64.c
  49. +11
    -9
      tests/test_printbuf.c
  50. +8
    -8
      tests/test_set_serializer.c
  51. +68
    -68
      tests/test_set_value.c
  52. +47
    -58
      tests/test_util_file.c
  53. +19
    -38
      tests/test_visit.c
  54. +20
    -9
      vasprintf_compat.h

+ 79
- 75
arraylist.c View File

@@ -14,12 +14,12 @@
#include <limits.h> #include <limits.h>


#ifdef STDC_HEADERS #ifdef STDC_HEADERS
# include <stdlib.h>
# include <string.h>
#include <stdlib.h>
#include <string.h>
#endif /* STDC_HEADERS */ #endif /* STDC_HEADERS */


#if defined(HAVE_STRINGS_H) && !defined(_STRING_H) && !defined(__USE_BSD) #if defined(HAVE_STRINGS_H) && !defined(_STRING_H) && !defined(__USE_BSD)
# include <strings.h>
#include <strings.h>
#endif /* HAVE_STRINGS_H */ #endif /* HAVE_STRINGS_H */


#ifndef SIZE_T_MAX #ifndef SIZE_T_MAX
@@ -36,111 +36,115 @@


#include "arraylist.h" #include "arraylist.h"


struct array_list*
array_list_new(array_list_free_fn *free_fn)
struct array_list *array_list_new(array_list_free_fn *free_fn)
{ {
struct array_list *arr;

arr = (struct array_list*)calloc(1, sizeof(struct array_list));
if(!arr) return NULL;
arr->size = ARRAY_LIST_DEFAULT_SIZE;
arr->length = 0;
arr->free_fn = free_fn;
if(!(arr->array = (void**)calloc(arr->size, sizeof(void*)))) {
free(arr);
return NULL;
}
return arr;
struct array_list *arr;

arr = (struct array_list *)calloc(1, sizeof(struct array_list));
if (!arr)
return NULL;
arr->size = ARRAY_LIST_DEFAULT_SIZE;
arr->length = 0;
arr->free_fn = free_fn;
if (!(arr->array = (void **)calloc(arr->size, sizeof(void *))))
{
free(arr);
return NULL;
}
return arr;
} }


extern void
array_list_free(struct array_list *arr)
extern void array_list_free(struct array_list *arr)
{ {
size_t i;
for(i = 0; i < arr->length; i++)
if(arr->array[i]) arr->free_fn(arr->array[i]);
free(arr->array);
free(arr);
size_t i;
for (i = 0; i < arr->length; i++)
if (arr->array[i])
arr->free_fn(arr->array[i]);
free(arr->array);
free(arr);
} }


void*
array_list_get_idx(struct array_list *arr, size_t i)
void *array_list_get_idx(struct array_list *arr, size_t i)
{ {
if(i >= arr->length) return NULL;
return arr->array[i];
if (i >= arr->length)
return NULL;
return arr->array[i];
} }


static int array_list_expand_internal(struct array_list *arr, size_t max) static int array_list_expand_internal(struct array_list *arr, size_t max)
{ {
void *t;
size_t new_size;

if(max < arr->size) return 0;
/* Avoid undefined behaviour on size_t overflow */
if( arr->size >= SIZE_T_MAX / 2 )
new_size = max;
else
{
new_size = arr->size << 1;
if (new_size < max)
new_size = max;
}
if (new_size > (~((size_t)0)) / sizeof(void*)) return -1;
if (!(t = realloc(arr->array, new_size*sizeof(void*)))) return -1;
arr->array = (void**)t;
(void)memset(arr->array + arr->size, 0, (new_size-arr->size)*sizeof(void*));
arr->size = new_size;
return 0;
void *t;
size_t new_size;

if (max < arr->size)
return 0;
/* Avoid undefined behaviour on size_t overflow */
if (arr->size >= SIZE_T_MAX / 2)
new_size = max;
else
{
new_size = arr->size << 1;
if (new_size < max)
new_size = max;
}
if (new_size > (~((size_t)0)) / sizeof(void *))
return -1;
if (!(t = realloc(arr->array, new_size * sizeof(void *))))
return -1;
arr->array = (void **)t;
(void)memset(arr->array + arr->size, 0, (new_size - arr->size) * sizeof(void *));
arr->size = new_size;
return 0;
} }


int
array_list_put_idx(struct array_list *arr, size_t idx, void *data)
int array_list_put_idx(struct array_list *arr, size_t idx, void *data)
{ {
if (idx > SIZE_T_MAX - 1 ) return -1;
if(array_list_expand_internal(arr, idx+1)) return -1;
if(idx < arr->length && arr->array[idx])
arr->free_fn(arr->array[idx]);
arr->array[idx] = data;
if(arr->length <= idx) arr->length = idx + 1;
return 0;
if (idx > SIZE_T_MAX - 1)
return -1;
if (array_list_expand_internal(arr, idx + 1))
return -1;
if (idx < arr->length && arr->array[idx])
arr->free_fn(arr->array[idx]);
arr->array[idx] = data;
if (arr->length <= idx)
arr->length = idx + 1;
return 0;
} }


int
array_list_add(struct array_list *arr, void *data)
int array_list_add(struct array_list *arr, void *data)
{ {
return array_list_put_idx(arr, arr->length, data);
return array_list_put_idx(arr, arr->length, data);
} }


void
array_list_sort(struct array_list *arr, int(*compar)(const void *, const void *))
void array_list_sort(struct array_list *arr, int (*compar)(const void *, const void *))
{ {
qsort(arr->array, arr->length, sizeof(arr->array[0]), compar);
qsort(arr->array, arr->length, sizeof(arr->array[0]), compar);
} }


void* array_list_bsearch(const void **key, struct array_list *arr,
int (*compar)(const void *, const void *))
void *array_list_bsearch(const void **key, struct array_list *arr,
int (*compar)(const void *, const void *))
{ {
return bsearch(key, arr->array, arr->length, sizeof(arr->array[0]),
compar);
return bsearch(key, arr->array, arr->length, sizeof(arr->array[0]), compar);
} }


size_t
array_list_length(struct array_list *arr)
size_t array_list_length(struct array_list *arr)
{ {
return arr->length;
return arr->length;
} }


int
array_list_del_idx( struct array_list *arr, size_t idx, size_t count )
int array_list_del_idx(struct array_list *arr, size_t idx, size_t count)
{ {
size_t i, stop; size_t i, stop;


stop = idx + count; stop = idx + count;
if ( idx >= arr->length || stop > arr->length ) return -1;
for ( i = idx; i < stop; ++i ) {
if ( arr->array[i] ) arr->free_fn( arr->array[i] );
if (idx >= arr->length || stop > arr->length)
return -1;
for (i = idx; i < stop; ++i)
{
if (arr->array[i])
arr->free_fn(arr->array[i]);
} }
memmove( arr->array + idx, arr->array + stop, (arr->length - stop) * sizeof(void*) );
memmove(arr->array + idx, arr->array + stop, (arr->length - stop) * sizeof(void *));
arr->length -= count; arr->length -= count;
return 0; return 0;
} }

+ 15
- 24
arraylist.h View File

@@ -24,44 +24,35 @@ extern "C" {


#define ARRAY_LIST_DEFAULT_SIZE 32 #define ARRAY_LIST_DEFAULT_SIZE 32


typedef void (array_list_free_fn) (void *data);
typedef void(array_list_free_fn)(void *data);


struct array_list struct array_list
{ {
void **array;
size_t length;
size_t size;
array_list_free_fn *free_fn;
void **array;
size_t length;
size_t size;
array_list_free_fn *free_fn;
}; };
typedef struct array_list array_list; typedef struct array_list array_list;


extern struct array_list*
array_list_new(array_list_free_fn *free_fn);
extern struct array_list *array_list_new(array_list_free_fn *free_fn);


extern void
array_list_free(struct array_list *al);
extern void array_list_free(struct array_list *al);


extern void*
array_list_get_idx(struct array_list *al, size_t i);
extern void *array_list_get_idx(struct array_list *al, size_t i);


extern int
array_list_put_idx(struct array_list *al, size_t i, void *data);
extern int array_list_put_idx(struct array_list *al, size_t i, void *data);


extern int
array_list_add(struct array_list *al, void *data);
extern int array_list_add(struct array_list *al, void *data);


extern size_t
array_list_length(struct array_list *al);
extern size_t array_list_length(struct array_list *al);


extern void
array_list_sort(struct array_list *arr, int(*compar)(const void *, const void *));
extern void array_list_sort(struct array_list *arr, int (*compar)(const void *, const void *));


extern void*
array_list_bsearch(const void **key, struct array_list *arr,
int (*compar)(const void *, const void *));
extern void *array_list_bsearch(const void **key, struct array_list *arr,
int (*compar)(const void *, const void *));


extern int
array_list_del_idx(struct array_list *arr, size_t idx, size_t count);
extern int array_list_del_idx(struct array_list *arr, size_t idx, size_t count);


#ifdef __cplusplus #ifdef __cplusplus
} }


+ 38
- 25
debug.c View File

@@ -11,17 +11,17 @@


#include "config.h" #include "config.h"


#include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdarg.h>


#if HAVE_SYSLOG_H #if HAVE_SYSLOG_H
# include <syslog.h>
#include <syslog.h>
#endif /* HAVE_SYSLOG_H */ #endif /* HAVE_SYSLOG_H */


#if HAVE_UNISTD_H #if HAVE_UNISTD_H
# include <unistd.h>
#include <unistd.h>
#endif /* HAVE_UNISTD_H */ #endif /* HAVE_UNISTD_H */


#if HAVE_SYS_PARAM_H #if HAVE_SYS_PARAM_H
@@ -33,51 +33,64 @@
static int _syslog = 0; static int _syslog = 0;
static int _debug = 0; static int _debug = 0;


void mc_set_debug(int debug) { _debug = debug; }
int mc_get_debug(void) { return _debug; }
void mc_set_debug(int debug)
{
_debug = debug;
}
int mc_get_debug(void)
{
return _debug;
}


extern void mc_set_syslog(int syslog) extern void mc_set_syslog(int syslog)
{ {
_syslog = syslog;
_syslog = syslog;
} }


void mc_debug(const char *msg, ...) void mc_debug(const char *msg, ...)
{ {
va_list ap;
if(_debug) {
va_start(ap, msg);
va_list ap;
if (_debug)
{
va_start(ap, msg);
#if HAVE_VSYSLOG #if HAVE_VSYSLOG
if(_syslog) {
vsyslog(LOG_DEBUG, msg, ap);
} else
if (_syslog)
{
vsyslog(LOG_DEBUG, msg, ap);
}
else
#endif #endif
vprintf(msg, ap);
va_end(ap);
}
vprintf(msg, ap);
va_end(ap);
}
} }


void mc_error(const char *msg, ...) void mc_error(const char *msg, ...)
{ {
va_list ap;
va_start(ap, msg);
va_list ap;
va_start(ap, msg);
#if HAVE_VSYSLOG #if HAVE_VSYSLOG
if(_syslog) {
if (_syslog)
{
vsyslog(LOG_ERR, msg, ap); vsyslog(LOG_ERR, msg, ap);
} else
}
else
#endif #endif
vfprintf(stderr, msg, ap); vfprintf(stderr, msg, ap);
va_end(ap);
va_end(ap);
} }


void mc_info(const char *msg, ...) void mc_info(const char *msg, ...)
{ {
va_list ap;
va_start(ap, msg);
va_list ap;
va_start(ap, msg);
#if HAVE_VSYSLOG #if HAVE_VSYSLOG
if(_syslog) {
if (_syslog)
{
vsyslog(LOG_INFO, msg, ap); vsyslog(LOG_INFO, msg, ap);
} else
}
else
#endif #endif
vfprintf(stderr, msg, ap); vfprintf(stderr, msg, ap);
va_end(ap);
va_end(ap);
} }

+ 28
- 13
debug.h View File

@@ -24,7 +24,7 @@ extern "C" {
#endif #endif


#ifndef JSON_EXPORT #ifndef JSON_EXPORT
#if defined(_MSC_VER)
#if defined(_MSC_VER)
#define JSON_EXPORT __declspec(dllexport) #define JSON_EXPORT __declspec(dllexport)
#else #else
#define JSON_EXPORT extern #define JSON_EXPORT extern
@@ -46,17 +46,24 @@ JSON_EXPORT void mc_info(const char *msg, ...);


#ifndef PARSER_BROKEN_FIXED #ifndef PARSER_BROKEN_FIXED


#define JASSERT(cond) do {} while(0)
#define JASSERT(cond) \
do \
{ \
} while (0)


#else #else


#define JASSERT(cond) do { \
if (!(cond)) { \
mc_error("cjson assert failure %s:%d : cond \"" __STRING(cond) "failed\n", __FILE__, __LINE__); \
*(int *)0 = 1;\
abort(); \
}\
} while(0)
#define JASSERT(cond) \
do \
{ \
if (!(cond)) \
{ \
mc_error("cjson assert failure %s:%d : cond \"" __STRING(cond) "failed\n", \
__FILE__, __LINE__); \
*(int *)0 = 1; \
abort(); \
} \
} while (0)


#endif #endif


@@ -69,11 +76,19 @@ JSON_EXPORT void mc_info(const char *msg, ...);
#define MC_DEBUG(x, ...) mc_debug(x, ##__VA_ARGS__) #define MC_DEBUG(x, ...) mc_debug(x, ##__VA_ARGS__)
#define MC_INFO(x, ...) mc_info(x, ##__VA_ARGS__) #define MC_INFO(x, ...) mc_info(x, ##__VA_ARGS__)
#else #else
#define MC_SET_DEBUG(x) if (0) mc_set_debug(x)
#define MC_SET_DEBUG(x) \
if (0) \
mc_set_debug(x)
#define MC_GET_DEBUG() (0) #define MC_GET_DEBUG() (0)
#define MC_SET_SYSLOG(x) if (0) mc_set_syslog(x)
#define MC_DEBUG(x, ...) if (0) mc_debug(x, ##__VA_ARGS__)
#define MC_INFO(x, ...) if (0) mc_info(x, ##__VA_ARGS__)
#define MC_SET_SYSLOG(x) \
if (0) \
mc_set_syslog(x)
#define MC_DEBUG(x, ...) \
if (0) \
mc_debug(x, ##__VA_ARGS__)
#define MC_INFO(x, ...) \
if (0) \
mc_info(x, ##__VA_ARGS__)
#endif #endif


#ifdef __cplusplus #ifdef __cplusplus


+ 8
- 7
fuzz/tokener_parse_ex_fuzzer.cc View File

@@ -2,12 +2,13 @@


#include <json.h> #include <json.h>


extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
const char *data1 = reinterpret_cast<const char *>(data);
json_tokener *tok = json_tokener_new();
json_object *obj = json_tokener_parse_ex(tok, data1, size);
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
const char *data1 = reinterpret_cast<const char *>(data);
json_tokener *tok = json_tokener_new();
json_object *obj = json_tokener_parse_ex(tok, data1, size);


json_object_put(obj);
json_tokener_free(tok);
return 0;
json_object_put(obj);
json_tokener_free(tok);
return 0;
} }

+ 5
- 5
json.h View File

@@ -21,15 +21,15 @@
extern "C" { extern "C" {
#endif #endif


#include "debug.h"
#include "linkhash.h"
#include "arraylist.h" #include "arraylist.h"
#include "json_util.h"
#include "debug.h"
#include "json_c_version.h"
#include "json_object.h" #include "json_object.h"
#include "json_object_iterator.h"
#include "json_pointer.h" #include "json_pointer.h"
#include "json_tokener.h" #include "json_tokener.h"
#include "json_object_iterator.h"
#include "json_c_version.h"
#include "json_util.h"
#include "linkhash.h"


#ifdef __cplusplus #ifdef __cplusplus
} }


+ 0
- 1
json_c_version.c View File

@@ -17,4 +17,3 @@ int json_c_version_num(void)
{ {
return JSON_C_VERSION_NUM; return JSON_C_VERSION_NUM;
} }


+ 4
- 5
json_c_version.h View File

@@ -15,13 +15,12 @@
#define JSON_C_MAJOR_VERSION 0 #define JSON_C_MAJOR_VERSION 0
#define JSON_C_MINOR_VERSION 13 #define JSON_C_MINOR_VERSION 13
#define JSON_C_MICRO_VERSION 99 #define JSON_C_MICRO_VERSION 99
#define JSON_C_VERSION_NUM ((JSON_C_MAJOR_VERSION << 16) | \
(JSON_C_MINOR_VERSION << 8) | \
JSON_C_MICRO_VERSION)
#define JSON_C_VERSION_NUM \
((JSON_C_MAJOR_VERSION << 16) | (JSON_C_MINOR_VERSION << 8) | JSON_C_MICRO_VERSION)
#define JSON_C_VERSION "0.13.99" #define JSON_C_VERSION "0.13.99"


#ifndef JSON_EXPORT #ifndef JSON_EXPORT
#if defined(_MSC_VER)
#if defined(_MSC_VER)
#define JSON_EXPORT __declspec(dllexport) #define JSON_EXPORT __declspec(dllexport)
#else #else
#define JSON_EXPORT extern #define JSON_EXPORT extern
@@ -43,6 +42,6 @@ JSON_EXPORT const char *json_c_version(void); /* Returns JSON_C_VERSION */
* @see JSON_C_VERSION_NUM * @see JSON_C_VERSION_NUM
* @return the version of the json-c library as an int * @return the version of the json-c library as an int
*/ */
JSON_EXPORT int json_c_version_num(void); /* Returns JSON_C_VERSION_NUM */
JSON_EXPORT int json_c_version_num(void); /* Returns JSON_C_VERSION_NUM */


#endif #endif

+ 451
- 479
json_object.c
File diff suppressed because it is too large
View File


+ 114
- 128
json_object.h View File

@@ -18,7 +18,7 @@
#define _json_object_h_ #define _json_object_h_


#ifdef __GNUC__ #ifdef __GNUC__
#define THIS_FUNCTION_IS_DEPRECATED(func) func __attribute__ ((deprecated))
#define THIS_FUNCTION_IS_DEPRECATED(func) func __attribute__((deprecated))
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
#define THIS_FUNCTION_IS_DEPRECATED(func) __declspec(deprecated) func #define THIS_FUNCTION_IS_DEPRECATED(func) __declspec(deprecated) func
#elif defined(__clang__) #elif defined(__clang__)
@@ -34,16 +34,16 @@
#endif #endif


#ifndef JSON_EXPORT #ifndef JSON_EXPORT
#if defined(_MSC_VER)
#if defined(_MSC_VER)
#define JSON_EXPORT __declspec(dllexport) #define JSON_EXPORT __declspec(dllexport)
#else #else
#define JSON_EXPORT extern #define JSON_EXPORT extern
#endif #endif
#endif #endif


#include <stddef.h>
#include "json_inttypes.h" #include "json_inttypes.h"
#include "printbuf.h" #include "printbuf.h"
#include <stddef.h>


#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -56,13 +56,13 @@ extern "C" {
* json_object_to_file_ext() functions which causes the output * json_object_to_file_ext() functions which causes the output
* to have no extra whitespace or formatting applied. * to have no extra whitespace or formatting applied.
*/ */
#define JSON_C_TO_STRING_PLAIN 0
#define JSON_C_TO_STRING_PLAIN 0
/** /**
* A flag for the json_object_to_json_string_ext() and * A flag for the json_object_to_json_string_ext() and
* json_object_to_file_ext() functions which causes the output to have * json_object_to_file_ext() functions which causes the output to have
* minimal whitespace inserted to make things slightly more readable. * minimal whitespace inserted to make things slightly more readable.
*/ */
#define JSON_C_TO_STRING_SPACED (1<<0)
#define JSON_C_TO_STRING_SPACED (1 << 0)
/** /**
* A flag for the json_object_to_json_string_ext() and * A flag for the json_object_to_json_string_ext() and
* json_object_to_file_ext() functions which causes * json_object_to_file_ext() functions which causes
@@ -71,7 +71,7 @@ extern "C" {
* See the "Two Space Tab" option at http://jsonformatter.curiousconcept.com/ * See the "Two Space Tab" option at http://jsonformatter.curiousconcept.com/
* for an example of the format. * for an example of the format.
*/ */
#define JSON_C_TO_STRING_PRETTY (1<<1)
#define JSON_C_TO_STRING_PRETTY (1 << 1)
/** /**
* A flag for the json_object_to_json_string_ext() and * A flag for the json_object_to_json_string_ext() and
* json_object_to_file_ext() functions which causes * json_object_to_file_ext() functions which causes
@@ -79,16 +79,16 @@ extern "C" {
* *
* Instead of a "Two Space Tab" this gives a single tab character. * Instead of a "Two Space Tab" this gives a single tab character.
*/ */
#define JSON_C_TO_STRING_PRETTY_TAB (1<<3)
#define JSON_C_TO_STRING_PRETTY_TAB (1 << 3)
/** /**
* A flag to drop trailing zero for float values * A flag to drop trailing zero for float values
*/ */
#define JSON_C_TO_STRING_NOZERO (1<<2)
#define JSON_C_TO_STRING_NOZERO (1 << 2)


/** /**
* Don't escape forward slashes. * Don't escape forward slashes.
*/ */
#define JSON_C_TO_STRING_NOSLASHESCAPE (1<<4)
#define JSON_C_TO_STRING_NOSLASHESCAPE (1 << 4)


/** /**
* A flag for the json_object_object_add_ex function which * A flag for the json_object_object_add_ex function which
@@ -100,7 +100,7 @@ extern "C" {
* knows for sure the key values are unique (e.g. because the * knows for sure the key values are unique (e.g. because the
* code adds a well-known set of constant key values). * code adds a well-known set of constant key values).
*/ */
#define JSON_C_OBJECT_ADD_KEY_IS_NEW (1<<1)
#define JSON_C_OBJECT_ADD_KEY_IS_NEW (1 << 1)
/** /**
* A flag for the json_object_object_add_ex function which * A flag for the json_object_object_add_ex function which
* flags the key as being constant memory. This means that * flags the key as being constant memory. This means that
@@ -118,7 +118,7 @@ extern "C" {
* json_object_object_add_ex(obj, "ip", json, * json_object_object_add_ex(obj, "ip", json,
* JSON_C_OBJECT_KEY_IS_CONSTANT); * JSON_C_OBJECT_KEY_IS_CONSTANT);
*/ */
#define JSON_C_OBJECT_KEY_IS_CONSTANT (1<<2)
#define JSON_C_OBJECT_KEY_IS_CONSTANT (1 << 2)


/** /**
* Set the global value of an option, which will apply to all * Set the global value of an option, which will apply to all
@@ -158,27 +158,26 @@ typedef struct json_object json_object;
/** /**
* Type of custom user delete functions. See json_object_set_serializer. * Type of custom user delete functions. See json_object_set_serializer.
*/ */
typedef void (json_object_delete_fn)(struct json_object *jso, void *userdata);
typedef void(json_object_delete_fn)(struct json_object *jso, void *userdata);


/** /**
* Type of a custom serialization function. See json_object_set_serializer. * Type of a custom serialization function. See json_object_set_serializer.
*/ */
typedef int (json_object_to_json_string_fn)(struct json_object *jso,
struct printbuf *pb,
int level,
int flags);
typedef int(json_object_to_json_string_fn)(struct json_object *jso, struct printbuf *pb, int level,
int flags);


/* supported object types */ /* supported object types */


typedef enum json_type {
/* If you change this, be sure to update json_type_to_name() too */
json_type_null,
json_type_boolean,
json_type_double,
json_type_int,
json_type_object,
json_type_array,
json_type_string
typedef enum json_type
{
/* If you change this, be sure to update json_type_to_name() too */
json_type_null,
json_type_boolean,
json_type_double,
json_type_int,
json_type_object,
json_type_array,
json_type_string
} json_type; } json_type;


/* reference counting functions */ /* reference counting functions */
@@ -189,7 +188,7 @@ typedef enum json_type {
* *
* @param obj the json_object instance * @param obj the json_object instance
*/ */
JSON_EXPORT struct json_object* json_object_get(struct json_object *obj);
JSON_EXPORT struct json_object *json_object_get(struct json_object *obj);


/** /**
* Decrement the reference count of json_object and free if it reaches zero. * Decrement the reference count of json_object and free if it reaches zero.
@@ -232,7 +231,6 @@ JSON_EXPORT int json_object_is_type(const struct json_object *obj, enum json_typ
*/ */
JSON_EXPORT enum json_type json_object_get_type(const struct json_object *obj); JSON_EXPORT enum json_type json_object_get_type(const struct json_object *obj);



/** Stringify object to json format. /** Stringify object to json format.
* Equivalent to json_object_to_json_string_ext(obj, JSON_C_TO_STRING_SPACED) * Equivalent to json_object_to_json_string_ext(obj, JSON_C_TO_STRING_SPACED)
* The pointer you get is an internal of your json object. You don't * The pointer you get is an internal of your json object. You don't
@@ -242,7 +240,7 @@ JSON_EXPORT enum json_type json_object_get_type(const struct json_object *obj);
* @param obj the json_object instance * @param obj the json_object instance
* @returns a string in JSON format * @returns a string in JSON format
*/ */
JSON_EXPORT const char* json_object_to_json_string(struct json_object *obj);
JSON_EXPORT const char *json_object_to_json_string(struct json_object *obj);


/** Stringify object to json format /** Stringify object to json format
* @see json_object_to_json_string() for details on how to free string. * @see json_object_to_json_string() for details on how to free string.
@@ -250,8 +248,7 @@ JSON_EXPORT const char* json_object_to_json_string(struct json_object *obj);
* @param flags formatting options, see JSON_C_TO_STRING_PRETTY and other constants * @param flags formatting options, see JSON_C_TO_STRING_PRETTY and other constants
* @returns a string in JSON format * @returns a string in JSON format
*/ */
JSON_EXPORT const char* json_object_to_json_string_ext(struct json_object *obj, int
flags);
JSON_EXPORT const char *json_object_to_json_string_ext(struct json_object *obj, int flags);


/** Stringify object to json format /** Stringify object to json format
* @see json_object_to_json_string() for details on how to free string. * @see json_object_to_json_string() for details on how to free string.
@@ -260,8 +257,8 @@ flags);
* @param length a pointer where, if not NULL, the length (without null) is stored * @param length a pointer where, if not NULL, the length (without null) is stored
* @returns a string in JSON format and the length if not NULL * @returns a string in JSON format and the length if not NULL
*/ */
JSON_EXPORT const char* json_object_to_json_string_length(struct json_object *obj, int
flags, size_t *length);
JSON_EXPORT const char *json_object_to_json_string_length(struct json_object *obj, int flags,
size_t *length);


/** /**
* Returns the userdata set by json_object_set_userdata() or * Returns the userdata set by json_object_set_userdata() or
@@ -269,7 +266,7 @@ flags, size_t *length);
* *
* @param jso the object to return the userdata for * @param jso the object to return the userdata for
*/ */
JSON_EXPORT void* json_object_get_userdata(json_object *jso);
JSON_EXPORT void *json_object_get_userdata(json_object *jso);


/** /**
* Set an opaque userdata value for an object * Set an opaque userdata value for an object
@@ -297,7 +294,7 @@ JSON_EXPORT void* json_object_get_userdata(json_object *jso);
* @param user_delete an optional function from freeing userdata * @param user_delete an optional function from freeing userdata
*/ */
JSON_EXPORT void json_object_set_userdata(json_object *jso, void *userdata, JSON_EXPORT void json_object_set_userdata(json_object *jso, void *userdata,
json_object_delete_fn *user_delete);
json_object_delete_fn *user_delete);


/** /**
* Set a custom serialization function to be used when this particular object * Set a custom serialization function to be used when this particular object
@@ -330,9 +327,8 @@ JSON_EXPORT void json_object_set_userdata(json_object *jso, void *userdata,
* @param user_delete an optional function from freeing userdata * @param user_delete an optional function from freeing userdata
*/ */
JSON_EXPORT void json_object_set_serializer(json_object *jso, JSON_EXPORT void json_object_set_serializer(json_object *jso,
json_object_to_json_string_fn *to_string_func,
void *userdata,
json_object_delete_fn *user_delete);
json_object_to_json_string_fn *to_string_func,
void *userdata, json_object_delete_fn *user_delete);


#ifdef __clang__ #ifdef __clang__
/* /*
@@ -369,7 +365,6 @@ JSON_EXPORT json_object_to_json_string_fn json_object_userdata_to_json_string;
#pragma clang diagnostic pop #pragma clang diagnostic pop
#endif #endif



/* object type methods */ /* object type methods */


/** Create a new empty object with a reference count of 1. The caller of /** Create a new empty object with a reference count of 1. The caller of
@@ -382,18 +377,18 @@ JSON_EXPORT json_object_to_json_string_fn json_object_userdata_to_json_string;
* *
* @returns a json_object of type json_type_object * @returns a json_object of type json_type_object
*/ */
JSON_EXPORT struct json_object* json_object_new_object(void);
JSON_EXPORT struct json_object *json_object_new_object(void);


/** Get the hashtable of a json_object of type json_type_object /** Get the hashtable of a json_object of type json_type_object
* @param obj the json_object instance * @param obj the json_object instance
* @returns a linkhash * @returns a linkhash
*/ */
JSON_EXPORT struct lh_table* json_object_get_object(const struct json_object *obj);
JSON_EXPORT struct lh_table *json_object_get_object(const struct json_object *obj);


/** Get the size of an object in terms of the number of fields it has. /** Get the size of an object in terms of the number of fields it has.
* @param obj the json_object whose length to return * @param obj the json_object whose length to return
*/ */
JSON_EXPORT int json_object_object_length(const struct json_object* obj);
JSON_EXPORT int json_object_object_length(const struct json_object *obj);


/** Get the sizeof (struct json_object). /** Get the sizeof (struct json_object).
* @returns a size_t with the sizeof (struct json_object) * @returns a size_t with the sizeof (struct json_object)
@@ -419,8 +414,8 @@ JSON_C_CONST_FUNCTION(JSON_EXPORT size_t json_c_object_sizeof(void));
* @return On success, <code>0</code> is returned. * @return On success, <code>0</code> is returned.
* On error, a negative value is returned. * On error, a negative value is returned.
*/ */
JSON_EXPORT int json_object_object_add(struct json_object* obj, const char *key,
struct json_object *val);
JSON_EXPORT int json_object_object_add(struct json_object *obj, const char *key,
struct json_object *val);


/** Add an object field to a json_object of type json_type_object /** Add an object field to a json_object of type json_type_object
* *
@@ -435,10 +430,8 @@ JSON_EXPORT int json_object_object_add(struct json_object* obj, const char *key,
* @param opts process-modifying options. To specify multiple options, use * @param opts process-modifying options. To specify multiple options, use
* arithmetic or (OPT1|OPT2) * arithmetic or (OPT1|OPT2)
*/ */
JSON_EXPORT int json_object_object_add_ex(struct json_object* obj,
const char *const key,
struct json_object *const val,
const unsigned opts);
JSON_EXPORT int json_object_object_add_ex(struct json_object *obj, const char *const key,
struct json_object *const val, const unsigned opts);


/** Get the json_object associate with a given object field. /** Get the json_object associate with a given object field.
* Deprecated/discouraged: used json_object_object_get_ex instead. * Deprecated/discouraged: used json_object_object_get_ex instead.
@@ -461,8 +454,8 @@ JSON_EXPORT int json_object_object_add_ex(struct json_object* obj,
* @param key the object field name * @param key the object field name
* @returns the json_object associated with the given field name * @returns the json_object associated with the given field name
*/ */
JSON_EXPORT struct json_object* json_object_object_get(const struct json_object* obj,
const char *key);
JSON_EXPORT struct json_object *json_object_object_get(const struct json_object *obj,
const char *key);


/** Get the json_object associated with a given object field. /** Get the json_object associated with a given object field.
* *
@@ -482,9 +475,8 @@ JSON_EXPORT struct json_object* json_object_object_get(const struct json_object*
* It is safe to pass a NULL value. * It is safe to pass a NULL value.
* @returns whether or not the key exists * @returns whether or not the key exists
*/ */
JSON_EXPORT json_bool json_object_object_get_ex(const struct json_object* obj,
const char *key,
struct json_object **value);
JSON_EXPORT json_bool json_object_object_get_ex(const struct json_object *obj, const char *key,
struct json_object **value);


/** Delete the given json_object field /** Delete the given json_object field
* *
@@ -495,7 +487,7 @@ JSON_EXPORT json_bool json_object_object_get_ex(const struct json_object* obj,
* @param obj the json_object instance * @param obj the json_object instance
* @param key the object field name * @param key the object field name
*/ */
JSON_EXPORT void json_object_object_del(struct json_object* obj, const char *key);
JSON_EXPORT void json_object_object_del(struct json_object *obj, const char *key);


/** /**
* Iterate through all keys and values of an object. * Iterate through all keys and values of an object.
@@ -512,31 +504,35 @@ JSON_EXPORT void json_object_object_del(struct json_object* obj, const char *key
*/ */
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && __STDC_VERSION__ >= 199901L #if defined(__GNUC__) && !defined(__STRICT_ANSI__) && __STDC_VERSION__ >= 199901L


# define json_object_object_foreach(obj,key,val) \
char *key = NULL; \
struct json_object *val __attribute__((__unused__)) = NULL; \
for(struct lh_entry *entry ## key = json_object_get_object(obj)->head, *entry_next ## key = NULL; \
({ if(entry ## key) { \
key = (char*)lh_entry_k(entry ## key); \
val = (struct json_object*)lh_entry_v(entry ## key); \
entry_next ## key = entry ## key->next; \
} ; entry ## key; }); \
entry ## key = entry_next ## key )
#define json_object_object_foreach(obj, key, val) \
char *key = NULL; \
struct json_object *val __attribute__((__unused__)) = NULL; \
for (struct lh_entry *entry##key = json_object_get_object(obj)->head, \
*entry_next##key = NULL; \
({ \
if (entry##key) \
{ \
key = (char *)lh_entry_k(entry##key); \
val = (struct json_object *)lh_entry_v(entry##key); \
entry_next##key = entry##key->next; \
}; \
entry##key; \
}); \
entry##key = entry_next##key)


#else /* ANSI C or MSC */ #else /* ANSI C or MSC */


# define json_object_object_foreach(obj,key,val) \
char *key = NULL;\
struct json_object *val = NULL; \
struct lh_entry *entry ## key; \
struct lh_entry *entry_next ## key = NULL; \
for(entry ## key = json_object_get_object(obj)->head; \
(entry ## key ? ( \
key = (char*)lh_entry_k(entry ## key), \
val = (struct json_object*)lh_entry_v(entry ## key), \
entry_next ## key = entry ## key->next, \
entry ## key) : 0); \
entry ## key = entry_next ## key)
#define json_object_object_foreach(obj, key, val) \
char *key = NULL; \
struct json_object *val = NULL; \
struct lh_entry *entry##key; \
struct lh_entry *entry_next##key = NULL; \
for (entry##key = json_object_get_object(obj)->head; \
(entry##key ? (key = (char *)lh_entry_k(entry##key), \
val = (struct json_object *)lh_entry_v(entry##key), \
entry_next##key = entry##key->next, entry##key) \
: 0); \
entry##key = entry_next##key)


#endif /* defined(__GNUC__) && !defined(__STRICT_ANSI__) && __STDC_VERSION__ >= 199901L */ #endif /* defined(__GNUC__) && !defined(__STRICT_ANSI__) && __STDC_VERSION__ >= 199901L */


@@ -544,23 +540,25 @@ JSON_EXPORT void json_object_object_del(struct json_object* obj, const char *key
* @param obj the json_object instance * @param obj the json_object instance
* @param iter the object iterator, use type json_object_iter * @param iter the object iterator, use type json_object_iter
*/ */
#define json_object_object_foreachC(obj,iter) \
for(iter.entry = json_object_get_object(obj)->head; \
(iter.entry ? (iter.key = (char*)lh_entry_k(iter.entry), iter.val = (struct json_object*)lh_entry_v(iter.entry), iter.entry) : 0); \
iter.entry = iter.entry->next)
#define json_object_object_foreachC(obj, iter) \
for (iter.entry = json_object_get_object(obj)->head; \
(iter.entry ? (iter.key = (char *)lh_entry_k(iter.entry), \
iter.val = (struct json_object *)lh_entry_v(iter.entry), iter.entry) \
: 0); \
iter.entry = iter.entry->next)


/* Array type methods */ /* Array type methods */


/** Create a new empty json_object of type json_type_array /** Create a new empty json_object of type json_type_array
* @returns a json_object of type json_type_array * @returns a json_object of type json_type_array
*/ */
JSON_EXPORT struct json_object* json_object_new_array(void);
JSON_EXPORT struct json_object *json_object_new_array(void);


/** Get the arraylist of a json_object of type json_type_array /** Get the arraylist of a json_object of type json_type_array
* @param obj the json_object instance * @param obj the json_object instance
* @returns an arraylist * @returns an arraylist
*/ */
JSON_EXPORT struct array_list* json_object_get_array(const struct json_object *obj);
JSON_EXPORT struct array_list *json_object_get_array(const struct json_object *obj);


/** Get the length of a json_object of type json_type_array /** Get the length of a json_object of type json_type_array
* @param obj the json_object instance * @param obj the json_object instance
@@ -576,7 +574,8 @@ JSON_EXPORT size_t json_object_array_length(const struct json_object *obj);
* @param jso the json_object instance * @param jso the json_object instance
* @param sort_fn a sorting function * @param sort_fn a sorting function
*/ */
JSON_EXPORT void json_object_array_sort(struct json_object *jso, int(*sort_fn)(const void *, const void *));
JSON_EXPORT void json_object_array_sort(struct json_object *jso,
int (*sort_fn)(const void *, const void *));


/** Binary search a sorted array for a specified key object. /** Binary search a sorted array for a specified key object.
* *
@@ -592,10 +591,9 @@ JSON_EXPORT void json_object_array_sort(struct json_object *jso, int(*sort_fn)(c
* *
* @return the wanted json_object instance * @return the wanted json_object instance
*/ */
JSON_EXPORT struct json_object* json_object_array_bsearch(
const struct json_object *key,
const struct json_object *jso,
int (*sort_fn)(const void *, const void *));
JSON_EXPORT struct json_object *
json_object_array_bsearch(const struct json_object *key, const struct json_object *jso,
int (*sort_fn)(const void *, const void *));


/** Add an element to the end of a json_object of type json_type_array /** Add an element to the end of a json_object of type json_type_array
* *
@@ -606,8 +604,7 @@ JSON_EXPORT struct json_object* json_object_array_bsearch(
* @param obj the json_object instance * @param obj the json_object instance
* @param val the json_object to be added * @param val the json_object to be added
*/ */
JSON_EXPORT int json_object_array_add(struct json_object *obj,
struct json_object *val);
JSON_EXPORT int json_object_array_add(struct json_object *obj, struct json_object *val);


/** Insert or replace an element at a specified index in an array (a json_object of type json_type_array) /** Insert or replace an element at a specified index in an array (a json_object of type json_type_array)
* *
@@ -625,15 +622,15 @@ JSON_EXPORT int json_object_array_add(struct json_object *obj,
* @param val the json_object to be added * @param val the json_object to be added
*/ */
JSON_EXPORT int json_object_array_put_idx(struct json_object *obj, size_t idx, JSON_EXPORT int json_object_array_put_idx(struct json_object *obj, size_t idx,
struct json_object *val);
struct json_object *val);


/** Get the element at specified index of the array (a json_object of type json_type_array) /** Get the element at specified index of the array (a json_object of type json_type_array)
* @param obj the json_object instance * @param obj the json_object instance
* @param idx the index to get the element at * @param idx the index to get the element at
* @returns the json_object at the specified index (or NULL) * @returns the json_object at the specified index (or NULL)
*/ */
JSON_EXPORT struct json_object* json_object_array_get_idx(const struct json_object *obj,
size_t idx);
JSON_EXPORT struct json_object *json_object_array_get_idx(const struct json_object *obj,
size_t idx);


/** Delete an elements from a specified index in an array (a json_object of type json_type_array) /** Delete an elements from a specified index in an array (a json_object of type json_type_array)
* *
@@ -654,7 +651,7 @@ JSON_EXPORT int json_object_array_del_idx(struct json_object *obj, size_t idx, s
* @param b a json_bool 1 or 0 * @param b a json_bool 1 or 0
* @returns a json_object of type json_type_boolean * @returns a json_object of type json_type_boolean
*/ */
JSON_EXPORT struct json_object* json_object_new_boolean(json_bool b);
JSON_EXPORT struct json_object *json_object_new_boolean(json_bool b);


/** Get the json_bool value of a json_object /** Get the json_bool value of a json_object
* *
@@ -669,7 +666,6 @@ JSON_EXPORT struct json_object* json_object_new_boolean(json_bool b);
*/ */
JSON_EXPORT json_bool json_object_get_boolean(const struct json_object *obj); JSON_EXPORT json_bool json_object_get_boolean(const struct json_object *obj);



/** Set the json_bool value of a json_object /** Set the json_bool value of a json_object
* *
* The type of obj is checked to be a json_type_boolean and 0 is returned * The type of obj is checked to be a json_type_boolean and 0 is returned
@@ -680,8 +676,7 @@ JSON_EXPORT json_bool json_object_get_boolean(const struct json_object *obj);
* @param new_value the value to be set * @param new_value the value to be set
* @returns 1 if value is set correctly, 0 otherwise * @returns 1 if value is set correctly, 0 otherwise
*/ */
JSON_EXPORT int json_object_set_boolean(struct json_object *obj,json_bool new_value);

JSON_EXPORT int json_object_set_boolean(struct json_object *obj, json_bool new_value);


/* int type methods */ /* int type methods */


@@ -691,22 +686,19 @@ JSON_EXPORT int json_object_set_boolean(struct json_object *obj,json_bool new_va
* @param i the integer * @param i the integer
* @returns a json_object of type json_type_int * @returns a json_object of type json_type_int
*/ */
JSON_EXPORT struct json_object* json_object_new_int(int32_t i);

JSON_EXPORT struct json_object *json_object_new_int(int32_t i);


/** Create a new empty json_object of type json_type_int /** Create a new empty json_object of type json_type_int
* @param i the integer * @param i the integer
* @returns a json_object of type json_type_int * @returns a json_object of type json_type_int
*/ */
JSON_EXPORT struct json_object* json_object_new_int64(int64_t i);

JSON_EXPORT struct json_object *json_object_new_int64(int64_t i);


/** Create a new empty json_object of type json_type_uint /** Create a new empty json_object of type json_type_uint
* @param i the integer * @param i the integer
* @returns a json_object of type json_type_uint * @returns a json_object of type json_type_uint
*/ */
JSON_EXPORT struct json_object* json_object_new_uint64(uint64_t i);

JSON_EXPORT struct json_object *json_object_new_uint64(uint64_t i);


/** Get the int value of a json_object /** Get the int value of a json_object
* *
@@ -734,7 +726,7 @@ JSON_EXPORT int32_t json_object_get_int(const struct json_object *obj);
* @param new_value the value to be set * @param new_value the value to be set
* @returns 1 if value is set correctly, 0 otherwise * @returns 1 if value is set correctly, 0 otherwise
*/ */
JSON_EXPORT int json_object_set_int(struct json_object *obj,int new_value);
JSON_EXPORT int json_object_set_int(struct json_object *obj, int new_value);


/** Increment a json_type_int object by the given amount, which may be negative. /** Increment a json_type_int object by the given amount, which may be negative.
* *
@@ -792,7 +784,7 @@ JSON_EXPORT uint64_t json_object_get_uint64(const struct json_object *obj);
* @param new_value the value to be set * @param new_value the value to be set
* @returns 1 if value is set correctly, 0 otherwise * @returns 1 if value is set correctly, 0 otherwise
*/ */
JSON_EXPORT int json_object_set_int64(struct json_object *obj,int64_t new_value);
JSON_EXPORT int json_object_set_int64(struct json_object *obj, int64_t new_value);


/** Set the uint64_t value of a json_object /** Set the uint64_t value of a json_object
* *
@@ -804,7 +796,7 @@ JSON_EXPORT int json_object_set_int64(struct json_object *obj,int64_t new_value)
* @param new_value the value to be set * @param new_value the value to be set
* @returns 1 if value is set correctly, 0 otherwise * @returns 1 if value is set correctly, 0 otherwise
*/ */
JSON_EXPORT int json_object_set_uint64(struct json_object *obj,uint64_t new_value);
JSON_EXPORT int json_object_set_uint64(struct json_object *obj, uint64_t new_value);


/* double type methods */ /* double type methods */


@@ -815,7 +807,7 @@ JSON_EXPORT int json_object_set_uint64(struct json_object *obj,uint64_t new_valu
* @param d the double * @param d the double
* @returns a json_object of type json_type_double * @returns a json_object of type json_type_double
*/ */
JSON_EXPORT struct json_object* json_object_new_double(double d);
JSON_EXPORT struct json_object *json_object_new_double(double d);


/** /**
* Create a new json_object of type json_type_double, using * Create a new json_object of type json_type_double, using
@@ -844,7 +836,7 @@ JSON_EXPORT struct json_object* json_object_new_double(double d);
* @param d the numeric value of the double. * @param d the numeric value of the double.
* @param ds the string representation of the double. This will be copied. * @param ds the string representation of the double. This will be copied.
*/ */
JSON_EXPORT struct json_object* json_object_new_double_s(double d, const char *ds);
JSON_EXPORT struct json_object *json_object_new_double_s(double d, const char *ds);


/** /**
* Set a global or thread-local json-c option, depending on whether * Set a global or thread-local json-c option, depending on whether
@@ -858,9 +850,8 @@ JSON_EXPORT struct json_object* json_object_new_double_s(double d, const char *d
* *
* @return -1 on errors, 0 on success. * @return -1 on errors, 0 on success.
*/ */
JSON_EXPORT int json_c_set_serialization_double_format(const char *double_format, int global_or_thread);


JSON_EXPORT int json_c_set_serialization_double_format(const char *double_format,
int global_or_thread);


/** Serialize a json_object of type json_type_double to a string. /** Serialize a json_object of type json_type_double to a string.
* *
@@ -881,10 +872,8 @@ JSON_EXPORT int json_c_set_serialization_double_format(const char *double_format
* @param level Ignored. * @param level Ignored.
* @param flags Ignored. * @param flags Ignored.
*/ */
JSON_EXPORT int json_object_double_to_json_string(struct json_object* jso,
struct printbuf *pb,
int level,
int flags);
JSON_EXPORT int json_object_double_to_json_string(struct json_object *jso, struct printbuf *pb,
int level, int flags);


/** Get the double floating point value of a json_object /** Get the double floating point value of a json_object
* *
@@ -911,7 +900,6 @@ JSON_EXPORT int json_object_double_to_json_string(struct json_object* jso,
*/ */
JSON_EXPORT double json_object_get_double(const struct json_object *obj); JSON_EXPORT double json_object_get_double(const struct json_object *obj);



/** Set the double value of a json_object /** Set the double value of a json_object
* *
* The type of obj is checked to be a json_type_double and 0 is returned * The type of obj is checked to be a json_type_double and 0 is returned
@@ -925,9 +913,7 @@ JSON_EXPORT double json_object_get_double(const struct json_object *obj);
* @param new_value the value to be set * @param new_value the value to be set
* @returns 1 if value is set correctly, 0 otherwise * @returns 1 if value is set correctly, 0 otherwise
*/ */
JSON_EXPORT int json_object_set_double(struct json_object *obj,double new_value);


JSON_EXPORT int json_object_set_double(struct json_object *obj, double new_value);


/* string type methods */ /* string type methods */


@@ -939,7 +925,7 @@ JSON_EXPORT int json_object_set_double(struct json_object *obj,double new_value)
* @returns a json_object of type json_type_string * @returns a json_object of type json_type_string
* @see json_object_new_string_len() * @see json_object_new_string_len()
*/ */
JSON_EXPORT struct json_object* json_object_new_string(const char *s);
JSON_EXPORT struct json_object *json_object_new_string(const char *s);


/** Create a new empty json_object of type json_type_string and allocate /** Create a new empty json_object of type json_type_string and allocate
* len characters for the new string. * len characters for the new string.
@@ -951,7 +937,7 @@ JSON_EXPORT struct json_object* json_object_new_string(const char *s);
* @returns a json_object of type json_type_string * @returns a json_object of type json_type_string
* @see json_object_new_string() * @see json_object_new_string()
*/ */
JSON_EXPORT struct json_object* json_object_new_string_len(const char *s, const int len);
JSON_EXPORT struct json_object *json_object_new_string_len(const char *s, const int len);


/** Get the string value of a json_object /** Get the string value of a json_object
* *
@@ -969,7 +955,7 @@ JSON_EXPORT struct json_object* json_object_new_string_len(const char *s, const
* @param obj the json_object instance * @param obj the json_object instance
* @returns a string or NULL * @returns a string or NULL
*/ */
JSON_EXPORT const char* json_object_get_string(struct json_object *obj);
JSON_EXPORT const char *json_object_get_string(struct json_object *obj);


/** Get the string length of a json_object /** Get the string length of a json_object
* *
@@ -981,12 +967,11 @@ JSON_EXPORT const char* json_object_get_string(struct json_object *obj);
*/ */
JSON_EXPORT int json_object_get_string_len(const struct json_object *obj); JSON_EXPORT int json_object_get_string_len(const struct json_object *obj);



/** Set the string value of a json_object with zero terminated strings /** Set the string value of a json_object with zero terminated strings
* equivalent to json_object_set_string_len (obj, new_value, strlen(new_value)) * equivalent to json_object_set_string_len (obj, new_value, strlen(new_value))
* @returns 1 if value is set correctly, 0 otherwise * @returns 1 if value is set correctly, 0 otherwise
*/ */
JSON_EXPORT int json_object_set_string(json_object* obj, const char* new_value);
JSON_EXPORT int json_object_set_string(json_object *obj, const char *new_value);


/** Set the string value of a json_object str /** Set the string value of a json_object str
* *
@@ -999,13 +984,13 @@ JSON_EXPORT int json_object_set_string(json_object* obj, const char* new_value);
* @param len the length of new_value * @param len the length of new_value
* @returns 1 if value is set correctly, 0 otherwise * @returns 1 if value is set correctly, 0 otherwise
*/ */
JSON_EXPORT int json_object_set_string_len(json_object* obj, const char* new_value, int len);
JSON_EXPORT int json_object_set_string_len(json_object *obj, const char *new_value, int len);


/** This method exists only to provide a complementary function /** This method exists only to provide a complementary function
* along the lines of the other json_object_new_* functions. * along the lines of the other json_object_new_* functions.
* It always returns NULL, and it is entirely acceptable to simply use NULL directly. * It always returns NULL, and it is entirely acceptable to simply use NULL directly.
*/ */
JSON_EXPORT struct json_object* json_object_new_null();
JSON_EXPORT struct json_object *json_object_new_null();


/** Check if two json_object's are equal /** Check if two json_object's are equal
* *
@@ -1024,8 +1009,7 @@ JSON_EXPORT struct json_object* json_object_new_null();
* @param obj2 the second json_object instance * @param obj2 the second json_object instance
* @returns whether both objects are equal or not * @returns whether both objects are equal or not
*/ */
JSON_EXPORT int json_object_equal(struct json_object *obj1,
struct json_object *obj2);
JSON_EXPORT int json_object_equal(struct json_object *obj1, struct json_object *obj2);


/** /**
* Perform a shallow copy of src into *dst as part of an overall json_object_deep_copy(). * Perform a shallow copy of src into *dst as part of an overall json_object_deep_copy().
@@ -1041,7 +1025,8 @@ JSON_EXPORT int json_object_equal(struct json_object *obj1,
* *
* @return On success 1 or 2, -1 on errors * @return On success 1 or 2, -1 on errors
*/ */
typedef int (json_c_shallow_copy_fn)(json_object *src, json_object *parent, const char *key, size_t index, json_object **dst);
typedef int(json_c_shallow_copy_fn)(json_object *src, json_object *parent, const char *key,
size_t index, json_object **dst);


/** /**
* The default shallow copy implementation for use with json_object_deep_copy(). * The default shallow copy implementation for use with json_object_deep_copy().
@@ -1076,7 +1061,8 @@ JSON_EXPORT json_c_shallow_copy_fn json_c_shallow_copy_default;
* or if the destination pointer is non-NULL * or if the destination pointer is non-NULL
*/ */


JSON_EXPORT int json_object_deep_copy(struct json_object *src, struct json_object **dst, json_c_shallow_copy_fn *shallow_copy);
JSON_EXPORT int json_object_deep_copy(struct json_object *src, struct json_object **dst,
json_c_shallow_copy_fn *shallow_copy);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif


+ 42
- 53
json_object_iterator.c View File

@@ -53,111 +53,100 @@
/// Our current representation of the "end" iterator; /// Our current representation of the "end" iterator;
/// ///
/// @note May not always be NULL /// @note May not always be NULL
static const void* kObjectEndIterValue = NULL;
static const void *kObjectEndIterValue = NULL;


/** /**
* **************************************************************************** * ****************************************************************************
*/ */
struct json_object_iterator
json_object_iter_begin(struct json_object* obj)
struct json_object_iterator json_object_iter_begin(struct json_object *obj)
{ {
struct json_object_iterator iter;
struct lh_table* pTable;
/// @note json_object_get_object will return NULL if passed NULL
/// or a non-json_type_object instance
pTable = json_object_get_object(obj);
JASSERT(NULL != pTable);
/// @note For a pair-less Object, head is NULL, which matches our
/// definition of the "end" iterator
iter.opaque_ = pTable->head;
return iter;
struct json_object_iterator iter;
struct lh_table *pTable;
/// @note json_object_get_object will return NULL if passed NULL
/// or a non-json_type_object instance
pTable = json_object_get_object(obj);
JASSERT(NULL != pTable);
/// @note For a pair-less Object, head is NULL, which matches our
/// definition of the "end" iterator
iter.opaque_ = pTable->head;
return iter;
} }


/** /**
* **************************************************************************** * ****************************************************************************
*/ */
struct json_object_iterator
json_object_iter_end(const struct json_object* obj)
struct json_object_iterator json_object_iter_end(const struct json_object *obj)
{ {
struct json_object_iterator iter;
struct json_object_iterator iter;


JASSERT(NULL != obj);
JASSERT(json_object_is_type(obj, json_type_object));
JASSERT(NULL != obj);
JASSERT(json_object_is_type(obj, json_type_object));


iter.opaque_ = kObjectEndIterValue;
iter.opaque_ = kObjectEndIterValue;


return iter;
return iter;
} }


/** /**
* **************************************************************************** * ****************************************************************************
*/ */
void
json_object_iter_next(struct json_object_iterator* iter)
void json_object_iter_next(struct json_object_iterator *iter)
{ {
JASSERT(NULL != iter);
JASSERT(kObjectEndIterValue != iter->opaque_);
JASSERT(NULL != iter);
JASSERT(kObjectEndIterValue != iter->opaque_);


iter->opaque_ = ((const struct lh_entry *)iter->opaque_)->next;
iter->opaque_ = ((const struct lh_entry *)iter->opaque_)->next;
} }



/** /**
* **************************************************************************** * ****************************************************************************
*/ */
const char*
json_object_iter_peek_name(const struct json_object_iterator* iter)
const char *json_object_iter_peek_name(const struct json_object_iterator *iter)
{ {
JASSERT(NULL != iter);
JASSERT(kObjectEndIterValue != iter->opaque_);
JASSERT(NULL != iter);
JASSERT(kObjectEndIterValue != iter->opaque_);


return (const char*)(((const struct lh_entry *)iter->opaque_)->k);
return (const char *)(((const struct lh_entry *)iter->opaque_)->k);
} }



/** /**
* **************************************************************************** * ****************************************************************************
*/ */
struct json_object*
json_object_iter_peek_value(const struct json_object_iterator* iter)
struct json_object *json_object_iter_peek_value(const struct json_object_iterator *iter)
{ {
JASSERT(NULL != iter);
JASSERT(kObjectEndIterValue != iter->opaque_);
JASSERT(NULL != iter);
JASSERT(kObjectEndIterValue != iter->opaque_);


return (struct json_object*)lh_entry_v((const struct lh_entry *)iter->opaque_);
return (struct json_object *)lh_entry_v((const struct lh_entry *)iter->opaque_);
} }



/** /**
* **************************************************************************** * ****************************************************************************
*/ */
json_bool
json_object_iter_equal(const struct json_object_iterator* iter1,
const struct json_object_iterator* iter2)
json_bool json_object_iter_equal(const struct json_object_iterator *iter1,
const struct json_object_iterator *iter2)
{ {
JASSERT(NULL != iter1);
JASSERT(NULL != iter2);
JASSERT(NULL != iter1);
JASSERT(NULL != iter2);


return (iter1->opaque_ == iter2->opaque_);
return (iter1->opaque_ == iter2->opaque_);
} }



/** /**
* **************************************************************************** * ****************************************************************************
*/ */
struct json_object_iterator
json_object_iter_init_default(void)
struct json_object_iterator json_object_iter_init_default(void)
{ {
struct json_object_iterator iter;
struct json_object_iterator iter;


/**
/**
* @note Make this a negative, invalid value, such that * @note Make this a negative, invalid value, such that
* accidental access to it would likely be trapped by the * accidental access to it would likely be trapped by the
* hardware as an invalid address. * hardware as an invalid address.
*/ */
iter.opaque_ = NULL;
iter.opaque_ = NULL;


return iter;
return iter;
} }

+ 13
- 26
json_object_iterator.h View File

@@ -20,14 +20,13 @@
******************************************************************************* *******************************************************************************
*/ */



#ifndef JSON_OBJECT_ITERATOR_H #ifndef JSON_OBJECT_ITERATOR_H
#define JSON_OBJECT_ITERATOR_H #define JSON_OBJECT_ITERATOR_H


#include <stddef.h> #include <stddef.h>


#ifndef JSON_EXPORT #ifndef JSON_EXPORT
#if defined(_MSC_VER)
#if defined(_MSC_VER)
#define JSON_EXPORT __declspec(dllexport) #define JSON_EXPORT __declspec(dllexport)
#else #else
#define JSON_EXPORT extern #define JSON_EXPORT extern
@@ -47,17 +46,16 @@ struct json_object_iter_info_;
* The opaque iterator that references a name/value pair within * The opaque iterator that references a name/value pair within
* a JSON Object instance or the "end" iterator value. * a JSON Object instance or the "end" iterator value.
*/ */
struct json_object_iterator {
const void* opaque_;
struct json_object_iterator
{
const void *opaque_;
}; };



/** /**
* forward declaration of json-c's JSON value instance structure * forward declaration of json-c's JSON value instance structure
*/ */
struct json_object; struct json_object;



/** /**
* Initializes an iterator structure to a "default" value that * Initializes an iterator structure to a "default" value that
* is convenient for initializing an iterator variable to a * is convenient for initializing an iterator variable to a
@@ -80,8 +78,7 @@ struct json_object;
* *
* @return json_object_iterator * @return json_object_iterator
*/ */
JSON_EXPORT struct json_object_iterator
json_object_iter_init_default(void);
JSON_EXPORT struct json_object_iterator json_object_iter_init_default(void);


/** Retrieves an iterator to the first pair of the JSON Object. /** Retrieves an iterator to the first pair of the JSON Object.
* *
@@ -114,8 +111,7 @@ json_object_iter_init_default(void);
* *
* @endcode * @endcode
*/ */
JSON_EXPORT struct json_object_iterator
json_object_iter_begin(struct json_object* obj);
JSON_EXPORT struct json_object_iterator json_object_iter_begin(struct json_object *obj);


/** Retrieves the iterator that represents the position beyond the /** Retrieves the iterator that represents the position beyond the
* last pair of the given JSON Object instance. * last pair of the given JSON Object instance.
@@ -145,8 +141,7 @@ json_object_iter_begin(struct json_object* obj);
* (i.e., NOT the last pair, but "beyond the last * (i.e., NOT the last pair, but "beyond the last
* pair" value) * pair" value)
*/ */
JSON_EXPORT struct json_object_iterator
json_object_iter_end(const struct json_object* obj);
JSON_EXPORT struct json_object_iterator json_object_iter_end(const struct json_object *obj);


/** Returns an iterator to the next pair, if any /** Returns an iterator to the next pair, if any
* *
@@ -163,9 +158,7 @@ json_object_iter_end(const struct json_object* obj);
* of json_object_iter_end() for the same JSON Object * of json_object_iter_end() for the same JSON Object
* instance. * instance.
*/ */
JSON_EXPORT void
json_object_iter_next(struct json_object_iterator* iter);

JSON_EXPORT void json_object_iter_next(struct json_object_iterator *iter);


/** Returns a const pointer to the name of the pair referenced /** Returns a const pointer to the name of the pair referenced
* by the given iterator. * by the given iterator.
@@ -182,9 +175,7 @@ json_object_iter_next(struct json_object_iterator* iter);
* deleted or modified, and MUST NOT be modified or * deleted or modified, and MUST NOT be modified or
* freed by the user. * freed by the user.
*/ */
JSON_EXPORT const char*
json_object_iter_peek_name(const struct json_object_iterator* iter);

JSON_EXPORT const char *json_object_iter_peek_name(const struct json_object_iterator *iter);


/** Returns a pointer to the json-c instance representing the /** Returns a pointer to the json-c instance representing the
* value of the referenced name/value pair, without altering * value of the referenced name/value pair, without altering
@@ -205,9 +196,8 @@ json_object_iter_peek_name(const struct json_object_iterator* iter);
* the JSON Null value as a NULL json_object instance * the JSON Null value as a NULL json_object instance
* pointer. * pointer.
*/ */
JSON_EXPORT struct json_object*
json_object_iter_peek_value(const struct json_object_iterator* iter);

JSON_EXPORT struct json_object *
json_object_iter_peek_value(const struct json_object_iterator *iter);


/** Tests two iterators for equality. Typically used to test /** Tests two iterators for equality. Typically used to test
* for end of iteration by comparing an iterator to the * for end of iteration by comparing an iterator to the
@@ -235,14 +225,11 @@ json_object_iter_peek_value(const struct json_object_iterator* iter);
* reference the same name/value pair or are both at * reference the same name/value pair or are both at
* "end"); zero if they are not equal. * "end"); zero if they are not equal.
*/ */
JSON_EXPORT json_bool
json_object_iter_equal(const struct json_object_iterator* iter1,
const struct json_object_iterator* iter2);

JSON_EXPORT json_bool json_object_iter_equal(const struct json_object_iterator *iter1,
const struct json_object_iterator *iter2);


#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif



#endif /* JSON_OBJECT_ITERATOR_H */ #endif /* JSON_OBJECT_ITERATOR_H */

+ 39
- 33
json_object_private.h View File

@@ -23,46 +23,52 @@ extern "C" {
/**< how many bytes are directly stored in json_object for strings? */ /**< how many bytes are directly stored in json_object for strings? */
#define LEN_DIRECT_STRING_DATA 32 #define LEN_DIRECT_STRING_DATA 32


typedef void (json_object_private_delete_fn)(struct json_object *o);
typedef void(json_object_private_delete_fn)(struct json_object *o);


/* json object int type, support extension*/ /* json object int type, support extension*/
typedef enum json_object_int_type {
json_object_int_type_int64,
json_object_int_type_uint64
}json_object_int_type;
typedef enum json_object_int_type
{
json_object_int_type_int64,
json_object_int_type_uint64
} json_object_int_type;


struct json_object struct json_object
{ {
enum json_type o_type;
uint32_t _ref_count;
json_object_private_delete_fn *_delete;
json_object_to_json_string_fn *_to_json_string;
struct printbuf *_pb;
union data {
json_bool c_boolean;
double c_double;
struct {
union {
int64_t c_int64;
uint64_t c_uint64;
} cint;
enum json_object_int_type cint_type;
} c_int;
struct lh_table *c_object;
struct array_list *c_array;
struct {
union {
/* optimize: if we have small strings, we can store them
enum json_type o_type;
uint32_t _ref_count;
json_object_private_delete_fn *_delete;
json_object_to_json_string_fn *_to_json_string;
struct printbuf *_pb;
union data
{
json_bool c_boolean;
double c_double;
struct
{
union
{
int64_t c_int64;
uint64_t c_uint64;
} cint;
enum json_object_int_type cint_type;
} c_int;
struct lh_table *c_object;
struct array_list *c_array;
struct
{
union
{
/* optimize: if we have small strings, we can store them
* directly. This saves considerable CPU cycles AND memory. * directly. This saves considerable CPU cycles AND memory.
*/ */
char *ptr;
char data[LEN_DIRECT_STRING_DATA];
} str;
int len;
} c_string;
} o;
json_object_delete_fn *_user_delete;
void *_userdata;
char *ptr;
char data[LEN_DIRECT_STRING_DATA];
} str;
int len;
} c_string;
} o;
json_object_delete_fn *_user_delete;
void *_userdata;
}; };


void _json_c_set_last_err(const char *err_fmt, ...); void _json_c_set_last_err(const char *err_fmt, ...);


+ 65
- 40
json_pointer.c View File

@@ -10,11 +10,11 @@


#include "strerror_override.h" #include "strerror_override.h"


#include <ctype.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <ctype.h>


#include "json_pointer.h" #include "json_pointer.h"
#include "strdup_compat.h" #include "strdup_compat.h"
@@ -30,7 +30,8 @@ static void string_replace_all_occurrences_with_char(char *s, const char *occur,
int slen = strlen(s); int slen = strlen(s);
int skip = strlen(occur) - 1; /* length of the occurrence, minus the char we're replacing */ int skip = strlen(occur) - 1; /* length of the occurrence, minus the char we're replacing */
char *p = s; char *p = s;
while ((p = strstr(p, occur))) {
while ((p = strstr(p, occur)))
{
*p = repl_char; *p = repl_char;
p++; p++;
slen -= skip; slen -= skip;
@@ -44,8 +45,10 @@ static int is_valid_index(struct json_object *jo, const char *path, int32_t *idx
/* this code-path optimizes a bit, for when we reference the 0-9 index range /* this code-path optimizes a bit, for when we reference the 0-9 index range
* in a JSON array and because leading zeros not allowed * in a JSON array and because leading zeros not allowed
*/ */
if (len == 1) {
if (isdigit((unsigned char)path[0])) {
if (len == 1)
{
if (isdigit((unsigned char)path[0]))
{
*idx = (path[0] - '0'); *idx = (path[0] - '0');
goto check_oob; goto check_oob;
} }
@@ -53,26 +56,31 @@ static int is_valid_index(struct json_object *jo, const char *path, int32_t *idx
return 0; return 0;
} }
/* leading zeros not allowed per RFC */ /* leading zeros not allowed per RFC */
if (path[0] == '0') {
if (path[0] == '0')
{
errno = EINVAL; errno = EINVAL;
return 0; return 0;
} }
/* RFC states base-10 decimals */ /* RFC states base-10 decimals */
for (i = 0; i < len; i++) {
if (!isdigit((unsigned char)path[i])) {
for (i = 0; i < len; i++)
{
if (!isdigit((unsigned char)path[i]))
{
errno = EINVAL; errno = EINVAL;
return 0; return 0;
} }
} }


*idx = strtol(path, NULL, 10); *idx = strtol(path, NULL, 10);
if (*idx < 0) {
if (*idx < 0)
{
errno = EINVAL; errno = EINVAL;
return 0; return 0;
} }
check_oob: check_oob:
len = json_object_array_length(jo); len = json_object_array_length(jo);
if (*idx >= len) {
if (*idx >= len)
{
errno = ENOENT; errno = ENOENT;
return 0; return 0;
} }
@@ -80,14 +88,17 @@ check_oob:
return 1; return 1;
} }


static int json_pointer_get_single_path(struct json_object *obj, char *path, struct json_object **value)
static int json_pointer_get_single_path(struct json_object *obj, char *path,
struct json_object **value)
{ {
if (json_object_is_type(obj, json_type_array)) {
if (json_object_is_type(obj, json_type_array))
{
int32_t idx; int32_t idx;
if (!is_valid_index(obj, path, &idx)) if (!is_valid_index(obj, path, &idx))
return -1; return -1;
obj = json_object_array_get_idx(obj, idx); obj = json_object_array_get_idx(obj, idx);
if (obj) {
if (obj)
{
if (value) if (value)
*value = obj; *value = obj;
return 0; return 0;
@@ -101,7 +112,8 @@ static int json_pointer_get_single_path(struct json_object *obj, char *path, str
string_replace_all_occurrences_with_char(path, "~1", '/'); string_replace_all_occurrences_with_char(path, "~1", '/');
string_replace_all_occurrences_with_char(path, "~0", '~'); string_replace_all_occurrences_with_char(path, "~0", '~');


if (!json_object_object_get_ex(obj, path, value)) {
if (!json_object_object_get_ex(obj, path, value))
{
errno = ENOENT; errno = ENOENT;
return -1; return -1;
} }
@@ -109,12 +121,11 @@ static int json_pointer_get_single_path(struct json_object *obj, char *path, str
return 0; return 0;
} }


static int json_pointer_set_single_path(
struct json_object *parent,
const char *path,
struct json_object *value)
static int json_pointer_set_single_path(struct json_object *parent, const char *path,
struct json_object *value)
{ {
if (json_object_is_type(parent, json_type_array)) {
if (json_object_is_type(parent, json_type_array))
{
int32_t idx; int32_t idx;
/* RFC (Chapter 4) states that '-' may be used to add new elements to an array */ /* RFC (Chapter 4) states that '-' may be used to add new elements to an array */
if (path[0] == '-' && path[1] == '\0') if (path[0] == '-' && path[1] == '\0')
@@ -137,16 +148,15 @@ static int json_pointer_set_single_path(
return -1; return -1;
} }


static int json_pointer_get_recursive(
struct json_object *obj,
char *path,
struct json_object **value)
static int json_pointer_get_recursive(struct json_object *obj, char *path,
struct json_object **value)
{ {
char *endp; char *endp;
int rc; int rc;


/* All paths (on each recursion level must have a leading '/' */ /* All paths (on each recursion level must have a leading '/' */
if (path[0] != '/') {
if (path[0] != '/')
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@@ -160,7 +170,8 @@ static int json_pointer_get_recursive(
if ((rc = json_pointer_get_single_path(obj, path, &obj))) if ((rc = json_pointer_get_single_path(obj, path, &obj)))
return rc; return rc;


if (endp) {
if (endp)
{
/* Put the slash back, so that the sanity check passes on next recursion level */ /* Put the slash back, so that the sanity check passes on next recursion level */
*endp = '/'; *endp = '/';
return json_pointer_get_recursive(obj, endp, value); return json_pointer_get_recursive(obj, endp, value);
@@ -178,19 +189,22 @@ int json_pointer_get(struct json_object *obj, const char *path, struct json_obje
char *path_copy = NULL; char *path_copy = NULL;
int rc; int rc;


if (!obj || !path) {
if (!obj || !path)
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }


if (path[0] == '\0') {
if (path[0] == '\0')
{
if (res) if (res)
*res = obj; *res = obj;
return 0; return 0;
} }


/* pass a working copy to the recursive call */ /* pass a working copy to the recursive call */
if (!(path_copy = strdup(path))) {
if (!(path_copy = strdup(path)))
{
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
} }
@@ -206,7 +220,8 @@ int json_pointer_getf(struct json_object *obj, struct json_object **res, const c
int rc = 0; int rc = 0;
va_list args; va_list args;


if (!obj || !path_fmt) {
if (!obj || !path_fmt)
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@@ -218,7 +233,8 @@ int json_pointer_getf(struct json_object *obj, struct json_object **res, const c
if (rc < 0) if (rc < 0)
return rc; return rc;


if (path_copy[0] == '\0') {
if (path_copy[0] == '\0')
{
if (res) if (res)
*res = obj; *res = obj;
goto out; goto out;
@@ -238,30 +254,35 @@ int json_pointer_set(struct json_object **obj, const char *path, struct json_obj
struct json_object *set = NULL; struct json_object *set = NULL;
int rc; int rc;


if (!obj || !path) {
if (!obj || !path)
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }


if (path[0] == '\0') {
if (path[0] == '\0')
{
json_object_put(*obj); json_object_put(*obj);
*obj = value; *obj = value;
return 0; return 0;
} }


if (path[0] != '/') {
if (path[0] != '/')
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }


/* If there's only 1 level to set, stop here */ /* If there's only 1 level to set, stop here */
if ((endp = strrchr(path, '/')) == path) {
if ((endp = strrchr(path, '/')) == path)
{
path++; path++;
return json_pointer_set_single_path(*obj, path, value); return json_pointer_set_single_path(*obj, path, value);
} }


/* pass a working copy to the recursive call */ /* pass a working copy to the recursive call */
if (!(path_copy = strdup(path))) {
if (!(path_copy = strdup(path)))
{
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
} }
@@ -276,7 +297,8 @@ int json_pointer_set(struct json_object **obj, const char *path, struct json_obj
return json_pointer_set_single_path(set, endp, value); return json_pointer_set_single_path(set, endp, value);
} }


int json_pointer_setf(struct json_object **obj, struct json_object *value, const char *path_fmt, ...)
int json_pointer_setf(struct json_object **obj, struct json_object *value, const char *path_fmt,
...)
{ {
char *endp; char *endp;
char *path_copy = NULL; char *path_copy = NULL;
@@ -284,7 +306,8 @@ int json_pointer_setf(struct json_object **obj, struct json_object *value, const
va_list args; va_list args;
int rc = 0; int rc = 0;


if (!obj || !path_fmt) {
if (!obj || !path_fmt)
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@@ -297,20 +320,23 @@ int json_pointer_setf(struct json_object **obj, struct json_object *value, const
if (rc < 0) if (rc < 0)
return rc; return rc;


if (path_copy[0] == '\0') {
if (path_copy[0] == '\0')
{
json_object_put(*obj); json_object_put(*obj);
*obj = value; *obj = value;
goto out; goto out;
} }


if (path_copy[0] != '/') {
if (path_copy[0] != '/')
{
errno = EINVAL; errno = EINVAL;
rc = -1; rc = -1;
goto out; goto out;
} }


/* If there's only 1 level to set, stop here */ /* If there's only 1 level to set, stop here */
if ((endp = strrchr(path_copy, '/')) == path_copy) {
if ((endp = strrchr(path_copy, '/')) == path_copy)
{
set = *obj; set = *obj;
goto set_single_path; goto set_single_path;
} }
@@ -328,4 +354,3 @@ out:
free(path_copy); free(path_copy);
return rc; return rc;
} }


+ 8
- 5
json_pointer.h View File

@@ -44,7 +44,8 @@ extern "C" {
* *
* @return negative if an error (or not found), or 0 if succeeded * @return negative if an error (or not found), or 0 if succeeded
*/ */
JSON_EXPORT int json_pointer_get(struct json_object *obj, const char *path, struct json_object **res);
JSON_EXPORT int json_pointer_get(struct json_object *obj, const char *path,
struct json_object **res);


/** /**
* This is a variant of 'json_pointer_get()' that supports printf() style arguments. * This is a variant of 'json_pointer_get()' that supports printf() style arguments.
@@ -62,7 +63,8 @@ JSON_EXPORT int json_pointer_get(struct json_object *obj, const char *path, stru
* *
* @return negative if an error (or not found), or 0 if succeeded * @return negative if an error (or not found), or 0 if succeeded
*/ */
JSON_EXPORT int json_pointer_getf(struct json_object *obj, struct json_object **res, const char *path_fmt, ...);
JSON_EXPORT int json_pointer_getf(struct json_object *obj, struct json_object **res,
const char *path_fmt, ...);


/** /**
* Sets JSON object 'value' in the 'obj' tree at the location specified * Sets JSON object 'value' in the 'obj' tree at the location specified
@@ -93,7 +95,8 @@ JSON_EXPORT int json_pointer_getf(struct json_object *obj, struct json_object **
* *
* @return negative if an error (or not found), or 0 if succeeded * @return negative if an error (or not found), or 0 if succeeded
*/ */
JSON_EXPORT int json_pointer_set(struct json_object **obj, const char *path, struct json_object *value);
JSON_EXPORT int json_pointer_set(struct json_object **obj, const char *path,
struct json_object *value);


/** /**
* This is a variant of 'json_pointer_set()' that supports printf() style arguments. * This is a variant of 'json_pointer_set()' that supports printf() style arguments.
@@ -110,8 +113,8 @@ JSON_EXPORT int json_pointer_set(struct json_object **obj, const char *path, str
* *
* @return negative if an error (or not found), or 0 if succeeded * @return negative if an error (or not found), or 0 if succeeded
*/ */
JSON_EXPORT int json_pointer_setf(struct json_object **obj, struct json_object *value, const char *path_fmt, ...);
JSON_EXPORT int json_pointer_setf(struct json_object **obj, struct json_object *value,
const char *path_fmt, ...);


#ifdef __cplusplus #ifdef __cplusplus
} }


+ 956
- 815
json_tokener.c
File diff suppressed because it is too large
View File


+ 69
- 67
json_tokener.h View File

@@ -16,66 +16,68 @@
#ifndef _json_tokener_h_ #ifndef _json_tokener_h_
#define _json_tokener_h_ #define _json_tokener_h_


#include <stddef.h>
#include "json_object.h" #include "json_object.h"
#include <stddef.h>


#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif


enum json_tokener_error {
json_tokener_success,
json_tokener_continue,
json_tokener_error_depth,
json_tokener_error_parse_eof,
json_tokener_error_parse_unexpected,
json_tokener_error_parse_null,
json_tokener_error_parse_boolean,
json_tokener_error_parse_number,
json_tokener_error_parse_array,
json_tokener_error_parse_object_key_name,
json_tokener_error_parse_object_key_sep,
json_tokener_error_parse_object_value_sep,
json_tokener_error_parse_string,
json_tokener_error_parse_comment,
json_tokener_error_parse_utf8_string,
json_tokener_error_size
enum json_tokener_error
{
json_tokener_success,
json_tokener_continue,
json_tokener_error_depth,
json_tokener_error_parse_eof,
json_tokener_error_parse_unexpected,
json_tokener_error_parse_null,
json_tokener_error_parse_boolean,
json_tokener_error_parse_number,
json_tokener_error_parse_array,
json_tokener_error_parse_object_key_name,
json_tokener_error_parse_object_key_sep,
json_tokener_error_parse_object_value_sep,
json_tokener_error_parse_string,
json_tokener_error_parse_comment,
json_tokener_error_parse_utf8_string,
json_tokener_error_size
}; };


enum json_tokener_state {
json_tokener_state_eatws,
json_tokener_state_start,
json_tokener_state_finish,
json_tokener_state_null,
json_tokener_state_comment_start,
json_tokener_state_comment,
json_tokener_state_comment_eol,
json_tokener_state_comment_end,
json_tokener_state_string,
json_tokener_state_string_escape,
json_tokener_state_escape_unicode,
json_tokener_state_boolean,
json_tokener_state_number,
json_tokener_state_array,
json_tokener_state_array_add,
json_tokener_state_array_sep,
json_tokener_state_object_field_start,
json_tokener_state_object_field,
json_tokener_state_object_field_end,
json_tokener_state_object_value,
json_tokener_state_object_value_add,
json_tokener_state_object_sep,
json_tokener_state_array_after_sep,
json_tokener_state_object_field_start_after_sep,
json_tokener_state_inf
enum json_tokener_state
{
json_tokener_state_eatws,
json_tokener_state_start,
json_tokener_state_finish,
json_tokener_state_null,
json_tokener_state_comment_start,
json_tokener_state_comment,
json_tokener_state_comment_eol,
json_tokener_state_comment_end,
json_tokener_state_string,
json_tokener_state_string_escape,
json_tokener_state_escape_unicode,
json_tokener_state_boolean,
json_tokener_state_number,
json_tokener_state_array,
json_tokener_state_array_add,
json_tokener_state_array_sep,
json_tokener_state_object_field_start,
json_tokener_state_object_field,
json_tokener_state_object_field_end,
json_tokener_state_object_value,
json_tokener_state_object_value_add,
json_tokener_state_object_sep,
json_tokener_state_array_after_sep,
json_tokener_state_object_field_start_after_sep,
json_tokener_state_inf
}; };


struct json_tokener_srec struct json_tokener_srec
{ {
enum json_tokener_state state, saved_state;
struct json_object *obj;
struct json_object *current;
char *obj_field_name;
enum json_tokener_state state, saved_state;
struct json_object *obj;
struct json_object *current;
char *obj_field_name;
}; };


#define JSON_TOKENER_DEFAULT_DEPTH 32 #define JSON_TOKENER_DEFAULT_DEPTH 32
@@ -89,18 +91,18 @@ struct json_tokener_srec
*/ */
struct json_tokener struct json_tokener
{ {
char *str;
struct printbuf *pb;
int max_depth, depth, is_double, st_pos;
/**
char *str;
struct printbuf *pb;
int max_depth, depth, is_double, st_pos;
/**
* See json_tokener_get_parse_end() * See json_tokener_get_parse_end()
*/ */
int char_offset;
enum json_tokener_error err;
unsigned int ucs_char;
char quote_char;
struct json_tokener_srec *stack;
int flags;
int char_offset;
enum json_tokener_error err;
unsigned int ucs_char;
char quote_char;
struct json_tokener_srec *stack;
int flags;
}; };


/** /**
@@ -119,7 +121,6 @@ struct json_tokener
*/ */
JSON_EXPORT size_t json_tokener_get_parse_end(struct json_tokener *tok); JSON_EXPORT size_t json_tokener_get_parse_end(struct json_tokener *tok);



/** /**
* @deprecated Unused in json-c code * @deprecated Unused in json-c code
*/ */
@@ -135,7 +136,7 @@ typedef struct json_tokener json_tokener;
* *
* @see json_tokener_set_flags() * @see json_tokener_set_flags()
*/ */
#define JSON_TOKENER_STRICT 0x01
#define JSON_TOKENER_STRICT 0x01


/** /**
* Allow json_tokener_parse_ex() validate utf-8 char. * Allow json_tokener_parse_ex() validate utf-8 char.
@@ -146,7 +147,7 @@ typedef struct json_tokener json_tokener;
* *
* @see json_tokener_set_flags() * @see json_tokener_set_flags()
*/ */
#define JSON_TOKENER_VALIDATE_UTF8 0x10
#define JSON_TOKENER_VALIDATE_UTF8 0x10


/** /**
* Given an error previously returned by json_tokener_get_error(), * Given an error previously returned by json_tokener_get_error(),
@@ -167,12 +168,13 @@ JSON_EXPORT const char *json_tokener_error_desc(enum json_tokener_error jerr);
*/ */
JSON_EXPORT enum json_tokener_error json_tokener_get_error(struct json_tokener *tok); JSON_EXPORT enum json_tokener_error json_tokener_get_error(struct json_tokener *tok);


JSON_EXPORT struct json_tokener* json_tokener_new(void);
JSON_EXPORT struct json_tokener* json_tokener_new_ex(int depth);
JSON_EXPORT struct json_tokener *json_tokener_new(void);
JSON_EXPORT struct json_tokener *json_tokener_new_ex(int depth);
JSON_EXPORT void json_tokener_free(struct json_tokener *tok); JSON_EXPORT void json_tokener_free(struct json_tokener *tok);
JSON_EXPORT void json_tokener_reset(struct json_tokener *tok); JSON_EXPORT void json_tokener_reset(struct json_tokener *tok);
JSON_EXPORT struct json_object* json_tokener_parse(const char *str);
JSON_EXPORT struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error);
JSON_EXPORT struct json_object *json_tokener_parse(const char *str);
JSON_EXPORT struct json_object *json_tokener_parse_verbose(const char *str,
enum json_tokener_error *error);


/** /**
* validete the utf-8 string in strict model. * validete the utf-8 string in strict model.
@@ -253,8 +255,8 @@ if (json_tokener_get_parse_end(tok) < stringlen)
* @param str an string with any valid JSON expression, or portion of. This does not need to be null terminated. * @param str an string with any valid JSON expression, or portion of. This does not need to be null terminated.
* @param len the length of str * @param len the length of str
*/ */
JSON_EXPORT struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
const char *str, int len);
JSON_EXPORT struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *str,
int len);


#ifdef __cplusplus #ifdef __cplusplus
} }


+ 87
- 71
json_util.c View File

@@ -14,13 +14,13 @@


#include "strerror_override.h" #include "strerror_override.h"


#include <ctype.h>
#include <limits.h>
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h>
#include <limits.h>
#include <string.h> #include <string.h>
#include <ctype.h>


#ifdef HAVE_SYS_TYPES_H #ifdef HAVE_SYS_TYPES_H
#include <sys/types.h> #include <sys/types.h>
@@ -35,32 +35,32 @@
#endif /* HAVE_FCNTL_H */ #endif /* HAVE_FCNTL_H */


#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
# include <unistd.h>
#include <unistd.h>
#endif /* HAVE_UNISTD_H */ #endif /* HAVE_UNISTD_H */


#ifdef WIN32 #ifdef WIN32
# if MSC_VER < 1800
#if MSC_VER < 1800
/* strtoll/strtoull is available only since Visual Studio 2013 */ /* strtoll/strtoull is available only since Visual Studio 2013 */
# define strtoll _strtoi64
# define strtoull _strtoui64
# endif
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# include <io.h>
#define strtoll _strtoi64
#define strtoull _strtoui64
#endif
#define WIN32_LEAN_AND_MEAN
#include <io.h>
#include <windows.h>
#endif /* defined(WIN32) */ #endif /* defined(WIN32) */


#if !defined(HAVE_OPEN) && defined(WIN32) #if !defined(HAVE_OPEN) && defined(WIN32)
# define open _open
#define open _open
#endif #endif


#include "snprintf_compat.h" #include "snprintf_compat.h"


#include "debug.h" #include "debug.h"
#include "printbuf.h"
#include "json_inttypes.h" #include "json_inttypes.h"
#include "json_object.h" #include "json_object.h"
#include "json_tokener.h" #include "json_tokener.h"
#include "json_util.h" #include "json_util.h"
#include "printbuf.h"


static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const char *filename); static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const char *filename);


@@ -82,66 +82,74 @@ void _json_c_set_last_err(const char *err_fmt, ...)
va_end(ap); va_end(ap);
} }


struct json_object* json_object_from_fd(int fd)
struct json_object *json_object_from_fd(int fd)
{ {
return json_object_from_fd_ex(fd, -1); return json_object_from_fd_ex(fd, -1);
} }
struct json_object* json_object_from_fd_ex(int fd, int in_depth)
struct json_object *json_object_from_fd_ex(int fd, int in_depth)
{ {
struct printbuf *pb;
struct json_object *obj;
char buf[JSON_FILE_BUF_SIZE];
int ret;
struct printbuf *pb;
struct json_object *obj;
char buf[JSON_FILE_BUF_SIZE];
int ret;
int depth = JSON_TOKENER_DEFAULT_DEPTH; int depth = JSON_TOKENER_DEFAULT_DEPTH;
json_tokener *tok; json_tokener *tok;


if(!(pb = printbuf_new())) {
_json_c_set_last_err("json_object_from_file: printbuf_new failed\n");
return NULL;
}
if (!(pb = printbuf_new()))
{
_json_c_set_last_err("json_object_from_file: printbuf_new failed\n");
return NULL;
}


if (in_depth != -1) if (in_depth != -1)
depth = in_depth; depth = in_depth;
tok = json_tokener_new_ex(depth); tok = json_tokener_new_ex(depth);
if (!tok) if (!tok)
{ {
_json_c_set_last_err("json_object_from_fd: unable to allocate json_tokener(depth=%d): %s\n", depth, strerror(errno));
_json_c_set_last_err(
"json_object_from_fd: unable to allocate json_tokener(depth=%d): %s\n", depth,
strerror(errno));
printbuf_free(pb); printbuf_free(pb);
return NULL; return NULL;
} }


while((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) {
printbuf_memappend(pb, buf, ret);
}
if(ret < 0) {
_json_c_set_last_err("json_object_from_fd: error reading fd %d: %s\n", fd, strerror(errno));
json_tokener_free(tok);
printbuf_free(pb);
return NULL;
}
while ((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0)
{
printbuf_memappend(pb, buf, ret);
}
if (ret < 0)
{
_json_c_set_last_err("json_object_from_fd: error reading fd %d: %s\n", fd,
strerror(errno));
json_tokener_free(tok);
printbuf_free(pb);
return NULL;
}


obj = json_tokener_parse_ex(tok, pb->buf, printbuf_length(pb));
obj = json_tokener_parse_ex(tok, pb->buf, printbuf_length(pb));
if (obj == NULL) if (obj == NULL)
_json_c_set_last_err("json_tokener_parse_ex failed: %s\n", json_tokener_error_desc(json_tokener_get_error(tok)));
_json_c_set_last_err("json_tokener_parse_ex failed: %s\n",
json_tokener_error_desc(json_tokener_get_error(tok)));


json_tokener_free(tok); json_tokener_free(tok);
printbuf_free(pb); printbuf_free(pb);
return obj; return obj;
} }


struct json_object* json_object_from_file(const char *filename)
struct json_object *json_object_from_file(const char *filename)
{ {
struct json_object *obj;
int fd;

if((fd = open(filename, O_RDONLY)) < 0) {
_json_c_set_last_err("json_object_from_file: error opening file %s: %s\n",
filename, strerror(errno));
return NULL;
}
obj = json_object_from_fd(fd);
close(fd);
return obj;
struct json_object *obj;
int fd;

if ((fd = open(filename, O_RDONLY)) < 0)
{
_json_c_set_last_err("json_object_from_file: error opening file %s: %s\n", filename,
strerror(errno));
return NULL;
}
obj = json_object_from_fd(fd);
close(fd);
return obj;
} }


/* extended "format and write to file" function */ /* extended "format and write to file" function */
@@ -151,14 +159,16 @@ int json_object_to_file_ext(const char *filename, struct json_object *obj, int f
int fd, ret; int fd, ret;
int saved_errno; int saved_errno;


if (!obj) {
if (!obj)
{
_json_c_set_last_err("json_object_to_file: object is null\n"); _json_c_set_last_err("json_object_to_file: object is null\n");
return -1; return -1;
} }


if ((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) {
_json_c_set_last_err("json_object_to_file: error opening file %s: %s\n",
filename, strerror(errno));
if ((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0)
{
_json_c_set_last_err("json_object_to_file: error opening file %s: %s\n", filename,
strerror(errno));
return -1; return -1;
} }
ret = _json_object_to_fd(fd, obj, flags, filename); ret = _json_object_to_fd(fd, obj, flags, filename);
@@ -170,7 +180,8 @@ int json_object_to_file_ext(const char *filename, struct json_object *obj, int f


int json_object_to_fd(int fd, struct json_object *obj, int flags) int json_object_to_fd(int fd, struct json_object *obj, int flags)
{ {
if (!obj) {
if (!obj)
{
_json_c_set_last_err("json_object_to_fd: object is null\n"); _json_c_set_last_err("json_object_to_fd: object is null\n");
return -1; return -1;
} }
@@ -185,18 +196,21 @@ static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const


filename = filename ? filename : "(fd)"; filename = filename ? filename : "(fd)";


if (!(json_str = json_object_to_json_string_ext(obj,flags))) {
if (!(json_str = json_object_to_json_string_ext(obj, flags)))
{
return -1; return -1;
} }


/* CAW: probably unnecessary, but the most 64bit safe */ /* CAW: probably unnecessary, but the most 64bit safe */
wsize = (unsigned int)(strlen(json_str) & UINT_MAX); wsize = (unsigned int)(strlen(json_str) & UINT_MAX);
wpos = 0; wpos = 0;
while(wpos < wsize) {
if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) {
_json_c_set_last_err("json_object_to_file: error writing file %s: %s\n",
filename, strerror(errno));
return -1;
while (wpos < wsize)
{
if ((ret = write(fd, json_str + wpos, wsize - wpos)) < 0)
{
_json_c_set_last_err("json_object_to_file: error writing file %s: %s\n",
filename, strerror(errno));
return -1;
} }


/* because of the above check for ret < 0, we can safely cast and add */ /* because of the above check for ret < 0, we can safely cast and add */
@@ -210,14 +224,14 @@ static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const


int json_object_to_file(const char *filename, struct json_object *obj) int json_object_to_file(const char *filename, struct json_object *obj)
{ {
return json_object_to_file_ext(filename, obj, JSON_C_TO_STRING_PLAIN);
return json_object_to_file_ext(filename, obj, JSON_C_TO_STRING_PLAIN);
} }


int json_parse_double(const char *buf, double *retval) int json_parse_double(const char *buf, double *retval)
{ {
char *end;
*retval = strtod(buf, &end);
return end == buf ? 1 : 0;
char *end;
*retval = strtod(buf, &end);
return end == buf ? 1 : 0;
} }


int json_parse_int64(const char *buf, int64_t *retval) int json_parse_int64(const char *buf, int64_t *retval)
@@ -238,10 +252,12 @@ int json_parse_uint64(const char *buf, uint64_t *retval)
uint64_t val; uint64_t val;
errno = 1; errno = 1;


while (*buf == ' ') {
while (*buf == ' ')
{
buf++; buf++;
} }
if (*buf == '-') errno = 0;
if (*buf == '-')
errno = 0;


val = strtoull(buf, &end, 10); val = strtoull(buf, &end, 10);
if (end != buf) if (end != buf)
@@ -250,7 +266,7 @@ int json_parse_uint64(const char *buf, uint64_t *retval)
} }


#ifndef HAVE_REALLOC #ifndef HAVE_REALLOC
void* rpl_realloc(void* p, size_t n)
void *rpl_realloc(void *p, size_t n)
{ {
if (n == 0) if (n == 0)
n = 1; n = 1;
@@ -260,7 +276,7 @@ void* rpl_realloc(void* p, size_t n)
} }
#endif #endif


#define NELEM(a) (sizeof(a) / sizeof(a[0]))
#define NELEM(a) (sizeof(a) / sizeof(a[0]))
/* clang-format off */ /* clang-format off */
static const char *json_type_name[] = { static const char *json_type_name[] = {
/* If you change this, be sure to update the enum json_type definition too */ /* If you change this, be sure to update the enum json_type definition too */
@@ -279,7 +295,8 @@ const char *json_type_to_name(enum json_type o_type)
int o_type_int = (int)o_type; int o_type_int = (int)o_type;
if (o_type_int < 0 || o_type_int >= (int)NELEM(json_type_name)) if (o_type_int < 0 || o_type_int >= (int)NELEM(json_type_name))
{ {
_json_c_set_last_err("json_type_to_name: type %d is out of range [0,%d]\n", o_type, NELEM(json_type_name));
_json_c_set_last_err("json_type_to_name: type %d is out of range [0,%d]\n", o_type,
NELEM(json_type_name));
return NULL; return NULL;
} }
return json_type_name[o_type]; return json_type_name[o_type];
@@ -287,8 +304,7 @@ const char *json_type_to_name(enum json_type o_type)


void json_abort(const char *message) void json_abort(const char *message)
{ {
if (message != NULL)
fprintf (stderr, "json-c aborts with error: %s\n", message);
abort();
if (message != NULL)
fprintf(stderr, "json-c aborts with error: %s\n", message);
abort();
} }


+ 7
- 9
json_util.h View File

@@ -12,21 +12,20 @@
/** /**
* @file * @file
* @brief Miscllaneous utility functions and macros. * @brief Miscllaneous utility functions and macros.
*/
*/
#ifndef _json_util_h_ #ifndef _json_util_h_
#define _json_util_h_ #define _json_util_h_


#include "json_object.h" #include "json_object.h"


#ifndef json_min #ifndef json_min
#define json_min(a,b) ((a) < (b) ? (a) : (b))
#define json_min(a, b) ((a) < (b) ? (a) : (b))
#endif #endif


#ifndef json_max #ifndef json_max
#define json_max(a,b) ((a) > (b) ? (a) : (b))
#define json_max(a, b) ((a) > (b) ? (a) : (b))
#endif #endif



#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@@ -40,7 +39,7 @@ extern "C" {
* *
* Returns NULL on failure. See json_util_get_last_err() for details. * Returns NULL on failure. See json_util_get_last_err() for details.
*/ */
JSON_EXPORT struct json_object* json_object_from_file(const char *filename);
JSON_EXPORT struct json_object *json_object_from_file(const char *filename);


/** /**
* Create a JSON object from already opened file descriptor. * Create a JSON object from already opened file descriptor.
@@ -56,7 +55,7 @@ JSON_EXPORT struct json_object* json_object_from_file(const char *filename);
* *
* Returns NULL on failure. See json_util_get_last_err() for details. * Returns NULL on failure. See json_util_get_last_err() for details.
*/ */
JSON_EXPORT struct json_object* json_object_from_fd_ex(int fd, int depth);
JSON_EXPORT struct json_object *json_object_from_fd_ex(int fd, int depth);


/** /**
* Create a JSON object from an already opened file descriptor, using * Create a JSON object from an already opened file descriptor, using
@@ -64,7 +63,7 @@ JSON_EXPORT struct json_object* json_object_from_fd_ex(int fd, int depth);
* *
* See json_object_from_fd_ex() for details. * See json_object_from_fd_ex() for details.
*/ */
JSON_EXPORT struct json_object* json_object_from_fd(int fd);
JSON_EXPORT struct json_object *json_object_from_fd(int fd);


/** /**
* Equivalent to: * Equivalent to:
@@ -101,7 +100,6 @@ JSON_EXPORT int json_object_to_fd(int fd, struct json_object *obj, int flags);
*/ */
JSON_EXPORT const char *json_util_get_last_err(void); JSON_EXPORT const char *json_util_get_last_err(void);



JSON_EXPORT int json_parse_int64(const char *buf, int64_t *retval); JSON_EXPORT int json_parse_int64(const char *buf, int64_t *retval);
JSON_EXPORT int json_parse_uint64(const char *buf, uint64_t *retval); JSON_EXPORT int json_parse_uint64(const char *buf, uint64_t *retval);
JSON_EXPORT int json_parse_double(const char *buf, double *retval); JSON_EXPORT int json_parse_double(const char *buf, double *retval);
@@ -119,7 +117,7 @@ JSON_EXPORT const char *json_type_to_name(enum json_type o_type);
/* 'cold' attribute is for optimization, telling the computer this code /* 'cold' attribute is for optimization, telling the computer this code
* path is unlikely. * path is unlikely.
*/ */
#define JSON_NORETURN __attribute__ ((noreturn, cold))
#define JSON_NORETURN __attribute__((noreturn, cold))
#endif #endif
#endif #endif
/** /**


+ 30
- 35
json_visit.c View File

@@ -13,45 +13,39 @@
#include "json_visit.h" #include "json_visit.h"
#include "linkhash.h" #include "linkhash.h"


static int _json_c_visit(json_object *jso, json_object *parent_jso,
const char *jso_key, size_t *jso_index,
json_c_visit_userfunc *userfunc, void *userarg);
static int _json_c_visit(json_object *jso, json_object *parent_jso, const char *jso_key,
size_t *jso_index, json_c_visit_userfunc *userfunc, void *userarg);


int json_c_visit(json_object *jso, int future_flags,
json_c_visit_userfunc *userfunc, void *userarg)
int json_c_visit(json_object *jso, int future_flags, json_c_visit_userfunc *userfunc, void *userarg)
{ {
int ret = _json_c_visit(jso, NULL, NULL, NULL, userfunc, userarg); int ret = _json_c_visit(jso, NULL, NULL, NULL, userfunc, userarg);
switch(ret)
switch (ret)
{ {
case JSON_C_VISIT_RETURN_CONTINUE: case JSON_C_VISIT_RETURN_CONTINUE:
case JSON_C_VISIT_RETURN_SKIP: case JSON_C_VISIT_RETURN_SKIP:
case JSON_C_VISIT_RETURN_POP: case JSON_C_VISIT_RETURN_POP:
case JSON_C_VISIT_RETURN_STOP:
return 0;
default:
return JSON_C_VISIT_RETURN_ERROR;
case JSON_C_VISIT_RETURN_STOP: return 0;
default: return JSON_C_VISIT_RETURN_ERROR;
} }
} }
static int _json_c_visit(json_object *jso, json_object *parent_jso,
const char *jso_key, size_t *jso_index,
json_c_visit_userfunc *userfunc, void *userarg)
static int _json_c_visit(json_object *jso, json_object *parent_jso, const char *jso_key,
size_t *jso_index, json_c_visit_userfunc *userfunc, void *userarg)
{ {
int userret = userfunc(jso, 0, parent_jso, jso_key, jso_index, userarg); int userret = userfunc(jso, 0, parent_jso, jso_key, jso_index, userarg);
switch(userret)
switch (userret)
{ {
case JSON_C_VISIT_RETURN_CONTINUE:
break;
case JSON_C_VISIT_RETURN_CONTINUE: break;
case JSON_C_VISIT_RETURN_SKIP: case JSON_C_VISIT_RETURN_SKIP:
case JSON_C_VISIT_RETURN_POP: case JSON_C_VISIT_RETURN_POP:
case JSON_C_VISIT_RETURN_STOP: case JSON_C_VISIT_RETURN_STOP:
case JSON_C_VISIT_RETURN_ERROR:
return userret;
case JSON_C_VISIT_RETURN_ERROR: return userret;
default: default:
fprintf(stderr, "ERROR: invalid return value from json_c_visit userfunc: %d\n", userret);
fprintf(stderr, "ERROR: invalid return value from json_c_visit userfunc: %d\n",
userret);
return JSON_C_VISIT_RETURN_ERROR; return JSON_C_VISIT_RETURN_ERROR;
} }


switch(json_object_get_type(jso))
switch (json_object_get_type(jso))
{ {
case json_type_null: case json_type_null:
case json_type_boolean: case json_type_boolean:
@@ -69,12 +63,13 @@ static int _json_c_visit(json_object *jso, json_object *parent_jso,
if (userret == JSON_C_VISIT_RETURN_POP) if (userret == JSON_C_VISIT_RETURN_POP)
break; break;
if (userret == JSON_C_VISIT_RETURN_STOP || if (userret == JSON_C_VISIT_RETURN_STOP ||
userret == JSON_C_VISIT_RETURN_ERROR)
userret == JSON_C_VISIT_RETURN_ERROR)
return userret; return userret;
if (userret != JSON_C_VISIT_RETURN_CONTINUE && if (userret != JSON_C_VISIT_RETURN_CONTINUE &&
userret != JSON_C_VISIT_RETURN_SKIP)
userret != JSON_C_VISIT_RETURN_SKIP)
{ {
fprintf(stderr, "INTERNAL ERROR: _json_c_visit returned %d\n", userret);
fprintf(stderr, "INTERNAL ERROR: _json_c_visit returned %d\n",
userret);
return JSON_C_VISIT_RETURN_ERROR; return JSON_C_VISIT_RETURN_ERROR;
} }
} }
@@ -91,19 +86,21 @@ static int _json_c_visit(json_object *jso, json_object *parent_jso,
if (userret == JSON_C_VISIT_RETURN_POP) if (userret == JSON_C_VISIT_RETURN_POP)
break; break;
if (userret == JSON_C_VISIT_RETURN_STOP || if (userret == JSON_C_VISIT_RETURN_STOP ||
userret == JSON_C_VISIT_RETURN_ERROR)
userret == JSON_C_VISIT_RETURN_ERROR)
return userret; return userret;
if (userret != JSON_C_VISIT_RETURN_CONTINUE && if (userret != JSON_C_VISIT_RETURN_CONTINUE &&
userret != JSON_C_VISIT_RETURN_SKIP)
userret != JSON_C_VISIT_RETURN_SKIP)
{ {
fprintf(stderr, "INTERNAL ERROR: _json_c_visit returned %d\n", userret);
fprintf(stderr, "INTERNAL ERROR: _json_c_visit returned %d\n",
userret);
return JSON_C_VISIT_RETURN_ERROR; return JSON_C_VISIT_RETURN_ERROR;
} }
} }
break; break;
} }
default: default:
fprintf(stderr, "INTERNAL ERROR: _json_c_visit found object of unknown type: %d\n", json_object_get_type(jso));
fprintf(stderr, "INTERNAL ERROR: _json_c_visit found object of unknown type: %d\n",
json_object_get_type(jso));
return JSON_C_VISIT_RETURN_ERROR; return JSON_C_VISIT_RETURN_ERROR;
} }


@@ -112,22 +109,20 @@ static int _json_c_visit(json_object *jso, json_object *parent_jso,
// Non-container types will have already returned before this point. // Non-container types will have already returned before this point.


userret = userfunc(jso, JSON_C_VISIT_SECOND, parent_jso, jso_key, jso_index, userarg); userret = userfunc(jso, JSON_C_VISIT_SECOND, parent_jso, jso_key, jso_index, userarg);
switch(userret)
switch (userret)
{ {
case JSON_C_VISIT_RETURN_SKIP: case JSON_C_VISIT_RETURN_SKIP:
case JSON_C_VISIT_RETURN_POP: case JSON_C_VISIT_RETURN_POP:
// These are not really sensible during JSON_C_VISIT_SECOND,
// These are not really sensible during JSON_C_VISIT_SECOND,
// but map them to JSON_C_VISIT_CONTINUE anyway. // but map them to JSON_C_VISIT_CONTINUE anyway.
// FALLTHROUGH // FALLTHROUGH
case JSON_C_VISIT_RETURN_CONTINUE:
return JSON_C_VISIT_RETURN_CONTINUE;
case JSON_C_VISIT_RETURN_CONTINUE: return JSON_C_VISIT_RETURN_CONTINUE;
case JSON_C_VISIT_RETURN_STOP: case JSON_C_VISIT_RETURN_STOP:
case JSON_C_VISIT_RETURN_ERROR:
return userret;
case JSON_C_VISIT_RETURN_ERROR: return userret;
default: default:
fprintf(stderr, "ERROR: invalid return value from json_c_visit userfunc: %d\n", userret);
fprintf(stderr, "ERROR: invalid return value from json_c_visit userfunc: %d\n",
userret);
return JSON_C_VISIT_RETURN_ERROR; return JSON_C_VISIT_RETURN_ERROR;
} }
// NOTREACHED // NOTREACHED
} }


+ 5
- 7
json_visit.h View File

@@ -8,9 +8,8 @@
*/ */
#include "json_object.h" #include "json_object.h"


typedef int (json_c_visit_userfunc)(json_object *jso, int flags,
json_object *parent_jso, const char *jso_key,
size_t *jso_index, void *userarg);
typedef int(json_c_visit_userfunc)(json_object *jso, int flags, json_object *parent_jso,
const char *jso_key, size_t *jso_index, void *userarg);


/** /**
* Visit each object in the JSON hierarchy starting at jso. * Visit each object in the JSON hierarchy starting at jso.
@@ -31,15 +30,15 @@ typedef int (json_c_visit_userfunc)(json_object *jso, int flags,
* Returns <0 if an error occurred during iteration, including if * Returns <0 if an error occurred during iteration, including if
* userfunc returned JSON_C_VISIT_RETURN_ERROR. * userfunc returned JSON_C_VISIT_RETURN_ERROR.
*/ */
JSON_EXPORT int json_c_visit(json_object *jso, int future_flags,
json_c_visit_userfunc *userfunc, void *userarg);
JSON_EXPORT int json_c_visit(json_object *jso, int future_flags, json_c_visit_userfunc *userfunc,
void *userarg);


/** /**
* Passed to json_c_visit_userfunc as one of the flags values to indicate * Passed to json_c_visit_userfunc as one of the flags values to indicate
* that this is the second time a container (array or object) is being * that this is the second time a container (array or object) is being
* called, after all of it's members have been iterated over. * called, after all of it's members have been iterated over.
*/ */
#define JSON_C_VISIT_SECOND 0x02
#define JSON_C_VISIT_SECOND 0x02


/** /**
* This json_c_visit_userfunc return value indicates that iteration * This json_c_visit_userfunc return value indicates that iteration
@@ -47,7 +46,6 @@ JSON_EXPORT int json_c_visit(json_object *jso, int future_flags,
*/ */
#define JSON_C_VISIT_RETURN_CONTINUE 0 #define JSON_C_VISIT_RETURN_CONTINUE 0



/** /**
* This json_c_visit_userfunc return value indicates that iteration * This json_c_visit_userfunc return value indicates that iteration
* over the members of the current object should be skipped. * over the members of the current object should be skipped.


+ 4
- 4
libjson.c View File

@@ -7,13 +7,13 @@


#ifndef __warn_references #ifndef __warn_references


#if defined(__GNUC__) && defined (HAS_GNU_WARNING_LONG)
#if defined(__GNUC__) && defined(HAS_GNU_WARNING_LONG)


#define __warn_references(sym,msg) \
__asm__(".section .gnu" #sym ",\n\t.ascii \"" msg "\"\n\t.text");
#define __warn_references(sym, msg) \
__asm__(".section .gnu" #sym ",\n\t.ascii \"" msg "\"\n\t.text");


#else #else
#define __warn_references(sym,msg) /* nothing */
#define __warn_references(sym, msg) /* nothing */
#endif #endif


#endif #endif


+ 103
- 88
linkhash.c View File

@@ -12,24 +12,24 @@


#include "config.h" #include "config.h"


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h> #include <stddef.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#ifdef HAVE_ENDIAN_H #ifdef HAVE_ENDIAN_H
# include <endian.h> /* attempt to define endianness */
#include <endian.h> /* attempt to define endianness */
#endif #endif


#if defined(_MSC_VER) || defined(__MINGW32__) #if defined(_MSC_VER) || defined(__MINGW32__)
# define WIN32_LEAN_AND_MEAN
# include <windows.h> /* Get InterlockedCompareExchange */
#define WIN32_LEAN_AND_MEAN
#include <windows.h> /* Get InterlockedCompareExchange */
#endif #endif


#include "random_seed.h"
#include "linkhash.h" #include "linkhash.h"
#include "random_seed.h"


/* hash functions */ /* hash functions */
static unsigned long lh_char_hash(const void *k); static unsigned long lh_char_hash(const void *k);
@@ -40,18 +40,13 @@ static lh_hash_fn *char_hash_fn = lh_char_hash;
int lh_char_equal(const void *k1, const void *k2); int lh_char_equal(const void *k1, const void *k2);
int lh_ptr_equal(const void *k1, const void *k2); int lh_ptr_equal(const void *k1, const void *k2);


int
json_global_set_string_hash(const int h)
int json_global_set_string_hash(const int h)
{ {
switch(h) {
case JSON_C_STR_HASH_DFLT:
char_hash_fn = lh_char_hash;
break;
case JSON_C_STR_HASH_PERLLIKE:
char_hash_fn = lh_perllike_str_hash;
break;
default:
return -1;
switch (h)
{
case JSON_C_STR_HASH_DFLT: char_hash_fn = lh_char_hash; break;
case JSON_C_STR_HASH_PERLLIKE: char_hash_fn = lh_perllike_str_hash; break;
default: return -1;
} }
return 0; return 0;
} }
@@ -114,25 +109,23 @@ on 1 byte), but shoehorning those bytes into integers efficiently is messy.
* My best guess at if you are big-endian or little-endian. This may * My best guess at if you are big-endian or little-endian. This may
* need adjustment. * need adjustment.
*/ */
#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
__BYTE_ORDER == __LITTLE_ENDIAN) || \
(defined(i386) || defined(__i386__) || defined(__i486__) || \
defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL))
# define HASH_LITTLE_ENDIAN 1
# define HASH_BIG_ENDIAN 0
#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
__BYTE_ORDER == __BIG_ENDIAN) || \
(defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
# define HASH_LITTLE_ENDIAN 0
# define HASH_BIG_ENDIAN 1
#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN) || \
(defined(i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) || \
defined(__i686__) || defined(vax) || defined(MIPSEL))
#define HASH_LITTLE_ENDIAN 1
#define HASH_BIG_ENDIAN 0
#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN) || \
(defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
#define HASH_LITTLE_ENDIAN 0
#define HASH_BIG_ENDIAN 1
#else #else
# define HASH_LITTLE_ENDIAN 0
# define HASH_BIG_ENDIAN 0
#define HASH_LITTLE_ENDIAN 0
#define HASH_BIG_ENDIAN 0
#endif #endif


#define hashsize(n) ((uint32_t)1<<(n))
#define hashmask(n) (hashsize(n)-1)
#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
#define hashsize(n) ((uint32_t)1 << (n))
#define hashmask(n) (hashsize(n) - 1)
#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))


/* /*
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@@ -228,7 +221,6 @@ and these came close:
} }
/* clang-format on */ /* clang-format on */



/* /*
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
hashlittle() -- hash a variable-length key into a 32-bit value hashlittle() -- hash a variable-length key into a 32-bit value
@@ -449,15 +441,15 @@ static uint32_t hashlittle(const void *key, size_t length, uint32_t initval)
/* a simple hash function similiar to what perl does for strings. /* a simple hash function similiar to what perl does for strings.
* for good results, the string should not be excessivly large. * for good results, the string should not be excessivly large.
*/ */
static unsigned long lh_perllike_str_hash(const void *k)
static unsigned long lh_perllike_str_hash(const void *k)
{ {
const char *rkey = (const char *)k;
unsigned hashval = 1;
const char *rkey = (const char *)k;
unsigned hashval = 1;


while (*rkey)
hashval = hashval * 33 + *rkey++;
while (*rkey)
hashval = hashval * 33 + *rkey++;


return hashval;
return hashval;
} }


static unsigned long lh_char_hash(const void *k) static unsigned long lh_char_hash(const void *k)
@@ -469,7 +461,8 @@ static unsigned long lh_char_hash(const void *k)
#endif #endif
static volatile RANDOM_SEED_TYPE random_seed = -1; static volatile RANDOM_SEED_TYPE random_seed = -1;


if (random_seed == -1) {
if (random_seed == -1)
{
RANDOM_SEED_TYPE seed; RANDOM_SEED_TYPE seed;
/* we can't use -1 as it is the unitialized sentinel */ /* we can't use -1 as it is the unitialized sentinel */
while ((seed = json_c_get_random_seed()) == -1) {} while ((seed = json_c_get_random_seed()) == -1) {}
@@ -487,34 +480,32 @@ static unsigned long lh_char_hash(const void *k)
#elif defined _MSC_VER || defined __MINGW32__ #elif defined _MSC_VER || defined __MINGW32__
InterlockedCompareExchange(&random_seed, seed, -1); InterlockedCompareExchange(&random_seed, seed, -1);
#else #else
//#warning "racy random seed initializtion if used by multiple threads"
//#warning "racy random seed initializtion if used by multiple threads"
random_seed = seed; /* potentially racy */ random_seed = seed; /* potentially racy */
#endif #endif
} }


return hashlittle((const char*)k, strlen((const char*)k), random_seed);
return hashlittle((const char *)k, strlen((const char *)k), random_seed);
} }


int lh_char_equal(const void *k1, const void *k2) int lh_char_equal(const void *k1, const void *k2)
{ {
return (strcmp((const char*)k1, (const char*)k2) == 0);
return (strcmp((const char *)k1, (const char *)k2) == 0);
} }


struct lh_table* lh_table_new(int size,
lh_entry_free_fn *free_fn,
lh_hash_fn *hash_fn,
lh_equal_fn *equal_fn)
struct lh_table *lh_table_new(int size, lh_entry_free_fn *free_fn, lh_hash_fn *hash_fn,
lh_equal_fn *equal_fn)
{ {
int i; int i;
struct lh_table *t; struct lh_table *t;


t = (struct lh_table*)calloc(1, sizeof(struct lh_table));
t = (struct lh_table *)calloc(1, sizeof(struct lh_table));
if (!t) if (!t)
return NULL; return NULL;


t->count = 0; t->count = 0;
t->size = size; t->size = size;
t->table = (struct lh_entry*)calloc(size, sizeof(struct lh_entry));
t->table = (struct lh_entry *)calloc(size, sizeof(struct lh_entry));
if (!t->table) if (!t->table)
{ {
free(t); free(t);
@@ -523,18 +514,17 @@ struct lh_table* lh_table_new(int size,
t->free_fn = free_fn; t->free_fn = free_fn;
t->hash_fn = hash_fn; t->hash_fn = hash_fn;
t->equal_fn = equal_fn; t->equal_fn = equal_fn;
for(i = 0; i < size; i++) t->table[i].k = LH_EMPTY;
for (i = 0; i < size; i++)
t->table[i].k = LH_EMPTY;
return t; return t;
} }


struct lh_table* lh_kchar_table_new(int size,
lh_entry_free_fn *free_fn)
struct lh_table *lh_kchar_table_new(int size, lh_entry_free_fn *free_fn)
{ {
return lh_table_new(size, free_fn, char_hash_fn, lh_char_equal); return lh_table_new(size, free_fn, char_hash_fn, lh_char_equal);
} }


struct lh_table* lh_kptr_table_new(int size,
lh_entry_free_fn *free_fn)
struct lh_table *lh_kptr_table_new(int size, lh_entry_free_fn *free_fn)
{ {
return lh_table_new(size, free_fn, lh_ptr_hash, lh_ptr_equal); return lh_table_new(size, free_fn, lh_ptr_hash, lh_ptr_equal);
} }
@@ -573,16 +563,17 @@ int lh_table_resize(struct lh_table *t, int new_size)
void lh_table_free(struct lh_table *t) void lh_table_free(struct lh_table *t)
{ {
struct lh_entry *c; struct lh_entry *c;
if(t->free_fn) {
for(c = t->head; c != NULL; c = c->next)
if (t->free_fn)
{
for (c = t->head; c != NULL; c = c->next)
t->free_fn(c); t->free_fn(c);
} }
free(t->table); free(t->table);
free(t); free(t);
} }


int lh_table_insert_w_hash(struct lh_table *t, const void *k, const void *v, const unsigned long h, const unsigned opts)
int lh_table_insert_w_hash(struct lh_table *t, const void *k, const void *v, const unsigned long h,
const unsigned opts)
{ {
unsigned long n; unsigned long n;


@@ -592,9 +583,12 @@ int lh_table_insert_w_hash(struct lh_table *t, const void *k, const void *v, con


n = h % t->size; n = h % t->size;


while( 1 ) {
if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) break;
if ((int)++n == t->size) n = 0;
while (1)
{
if (t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED)
break;
if ((int)++n == t->size)
n = 0;
} }


t->table[n].k = k; t->table[n].k = k;
@@ -602,10 +596,13 @@ int lh_table_insert_w_hash(struct lh_table *t, const void *k, const void *v, con
t->table[n].v = v; t->table[n].v = v;
t->count++; t->count++;


if(t->head == NULL) {
if (t->head == NULL)
{
t->head = t->tail = &t->table[n]; t->head = t->tail = &t->table[n];
t->table[n].next = t->table[n].prev = NULL; t->table[n].next = t->table[n].prev = NULL;
} else {
}
else
{
t->tail->next = &t->table[n]; t->tail->next = &t->table[n];
t->table[n].prev = t->tail; t->table[n].prev = t->tail;
t->table[n].next = NULL; t->table[n].next = NULL;
@@ -619,36 +616,42 @@ int lh_table_insert(struct lh_table *t, const void *k, const void *v)
return lh_table_insert_w_hash(t, k, v, lh_get_hash(t, k), 0); return lh_table_insert_w_hash(t, k, v, lh_get_hash(t, k), 0);
} }


struct lh_entry* lh_table_lookup_entry_w_hash(struct lh_table *t, const void *k, const unsigned long h)
struct lh_entry *lh_table_lookup_entry_w_hash(struct lh_table *t, const void *k,
const unsigned long h)
{ {
unsigned long n = h % t->size; unsigned long n = h % t->size;
int count = 0; int count = 0;


while( count < t->size ) {
if(t->table[n].k == LH_EMPTY) return NULL;
if(t->table[n].k != LH_FREED &&
t->equal_fn(t->table[n].k, k)) return &t->table[n];
if ((int)++n == t->size) n = 0;
while (count < t->size)
{
if (t->table[n].k == LH_EMPTY)
return NULL;
if (t->table[n].k != LH_FREED && t->equal_fn(t->table[n].k, k))
return &t->table[n];
if ((int)++n == t->size)
n = 0;
count++; count++;
} }
return NULL; return NULL;
} }


struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k)
struct lh_entry *lh_table_lookup_entry(struct lh_table *t, const void *k)
{ {
return lh_table_lookup_entry_w_hash(t, k, lh_get_hash(t, k)); return lh_table_lookup_entry_w_hash(t, k, lh_get_hash(t, k));
} }


json_bool lh_table_lookup_ex(struct lh_table* t, const void* k, void **v)
json_bool lh_table_lookup_ex(struct lh_table *t, const void *k, void **v)
{ {
struct lh_entry *e = lh_table_lookup_entry(t, k); struct lh_entry *e = lh_table_lookup_entry(t, k);
if (e != NULL) {
if (v != NULL) *v = lh_entry_v(e);
if (e != NULL)
{
if (v != NULL)
*v = lh_entry_v(e);
return 1; /* key found */ return 1; /* key found */
} }
if (v != NULL) *v = NULL;
return 0; /* key not found */
if (v != NULL)
*v = NULL;
return 0; /* key not found */
} }


int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e) int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e)
@@ -657,22 +660,34 @@ int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e)
ptrdiff_t n = (ptrdiff_t)(e - t->table); ptrdiff_t n = (ptrdiff_t)(e - t->table);


/* CAW: this is bad, really bad, maybe stack goes other direction on this machine... */ /* CAW: this is bad, really bad, maybe stack goes other direction on this machine... */
if(n < 0) { return -2; }
if (n < 0)
{
return -2;
}


if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) return -1;
if (t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED)
return -1;
t->count--; t->count--;
if(t->free_fn) t->free_fn(e);
if (t->free_fn)
t->free_fn(e);
t->table[n].v = NULL; t->table[n].v = NULL;
t->table[n].k = LH_FREED; t->table[n].k = LH_FREED;
if(t->tail == &t->table[n] && t->head == &t->table[n]) {
if (t->tail == &t->table[n] && t->head == &t->table[n])
{
t->head = t->tail = NULL; t->head = t->tail = NULL;
} else if (t->head == &t->table[n]) {
}
else if (t->head == &t->table[n])
{
t->head->next->prev = NULL; t->head->next->prev = NULL;
t->head = t->head->next; t->head = t->head->next;
} else if (t->tail == &t->table[n]) {
}
else if (t->tail == &t->table[n])
{
t->tail->prev->next = NULL; t->tail->prev->next = NULL;
t->tail = t->tail->prev; t->tail = t->tail->prev;
} else {
}
else
{
t->table[n].prev->next = t->table[n].next; t->table[n].prev->next = t->table[n].next;
t->table[n].next->prev = t->table[n].prev; t->table[n].next->prev = t->table[n].prev;
} }
@@ -680,11 +695,11 @@ int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e)
return 0; return 0;
} }



int lh_table_delete(struct lh_table *t, const void *k) int lh_table_delete(struct lh_table *t, const void *k)
{ {
struct lh_entry *e = lh_table_lookup_entry(t, k); struct lh_entry *e = lh_table_lookup_entry(t, k);
if(!e) return -1;
if (!e)
return -1;
return lh_table_delete_entry(t, e); return lh_table_delete_entry(t, e);
} }




+ 20
- 32
linkhash.h View File

@@ -40,12 +40,12 @@ extern "C" {
/** /**
* sentinel pointer value for empty slots * sentinel pointer value for empty slots
*/ */
#define LH_EMPTY (void*)-1
#define LH_EMPTY (void *)-1


/** /**
* sentinel pointer value for freed slots * sentinel pointer value for freed slots
*/ */
#define LH_FREED (void*)-2
#define LH_FREED (void *)-2


/** /**
* default string hash function * default string hash function
@@ -69,20 +69,21 @@ struct lh_entry;
/** /**
* callback function prototypes * callback function prototypes
*/ */
typedef void (lh_entry_free_fn) (struct lh_entry *e);
typedef void(lh_entry_free_fn)(struct lh_entry *e);
/** /**
* callback function prototypes * callback function prototypes
*/ */
typedef unsigned long (lh_hash_fn) (const void *k);
typedef unsigned long(lh_hash_fn)(const void *k);
/** /**
* callback function prototypes * callback function prototypes
*/ */
typedef int (lh_equal_fn) (const void *k1, const void *k2);
typedef int(lh_equal_fn)(const void *k1, const void *k2);


/** /**
* An entry in the hash table * An entry in the hash table
*/ */
struct lh_entry {
struct lh_entry
{
/** /**
* The key. Use lh_entry_k() instead of accessing this directly. * The key. Use lh_entry_k() instead of accessing this directly.
*/ */
@@ -106,11 +107,11 @@ struct lh_entry {
struct lh_entry *prev; struct lh_entry *prev;
}; };



/** /**
* The hash table structure. * The hash table structure.
*/ */
struct lh_table {
struct lh_table
{
/** /**
* Size of our hash. * Size of our hash.
*/ */
@@ -141,12 +142,10 @@ struct lh_table {
}; };
typedef struct lh_table lh_table; typedef struct lh_table lh_table;



/** /**
* Convenience list iterator. * Convenience list iterator.
*/ */
#define lh_foreach(table, entry) \
for(entry = table->head; entry; entry = entry->next)
#define lh_foreach(table, entry) for (entry = table->head; entry; entry = entry->next)


/** /**
* lh_foreach_safe allows calling of deletion routine while iterating. * lh_foreach_safe allows calling of deletion routine while iterating.
@@ -156,9 +155,7 @@ for(entry = table->head; entry; entry = entry->next)
* @param tmp a struct lh_entry * variable to hold a temporary pointer to the next element * @param tmp a struct lh_entry * variable to hold a temporary pointer to the next element
*/ */
#define lh_foreach_safe(table, entry, tmp) \ #define lh_foreach_safe(table, entry, tmp) \
for(entry = table->head; entry && ((tmp = entry->next) || 1); entry = tmp)


for (entry = table->head; entry && ((tmp = entry->next) || 1); entry = tmp)


/** /**
* Create a new linkhash table. * Create a new linkhash table.
@@ -178,10 +175,8 @@ for(entry = table->head; entry && ((tmp = entry->next) || 1); entry = tmp)
* @return On success, a pointer to the new linkhash table is returned. * @return On success, a pointer to the new linkhash table is returned.
* On error, a null pointer is returned. * On error, a null pointer is returned.
*/ */
extern struct lh_table* lh_table_new(int size,
lh_entry_free_fn *free_fn,
lh_hash_fn *hash_fn,
lh_equal_fn *equal_fn);
extern struct lh_table *lh_table_new(int size, lh_entry_free_fn *free_fn, lh_hash_fn *hash_fn,
lh_equal_fn *equal_fn);


/** /**
* Convenience function to create a new linkhash table with char keys. * Convenience function to create a new linkhash table with char keys.
@@ -191,9 +186,7 @@ extern struct lh_table* lh_table_new(int size,
* @return On success, a pointer to the new linkhash table is returned. * @return On success, a pointer to the new linkhash table is returned.
* On error, a null pointer is returned. * On error, a null pointer is returned.
*/ */
extern struct lh_table* lh_kchar_table_new(int size,
lh_entry_free_fn *free_fn);

extern struct lh_table *lh_kchar_table_new(int size, lh_entry_free_fn *free_fn);


/** /**
* Convenience function to create a new linkhash table with ptr keys. * Convenience function to create a new linkhash table with ptr keys.
@@ -203,9 +196,7 @@ extern struct lh_table* lh_kchar_table_new(int size,
* @return On success, a pointer to the new linkhash table is returned. * @return On success, a pointer to the new linkhash table is returned.
* On error, a null pointer is returned. * On error, a null pointer is returned.
*/ */
extern struct lh_table* lh_kptr_table_new(int size,
lh_entry_free_fn *free_fn);

extern struct lh_table *lh_kptr_table_new(int size, lh_entry_free_fn *free_fn);


/** /**
* Free a linkhash table. * Free a linkhash table.
@@ -217,7 +208,6 @@ extern struct lh_table* lh_kptr_table_new(int size,
*/ */
extern void lh_table_free(struct lh_table *t); extern void lh_table_free(struct lh_table *t);



/** /**
* Insert a record into the table. * Insert a record into the table.
* *
@@ -230,7 +220,6 @@ extern void lh_table_free(struct lh_table *t);
*/ */
extern int lh_table_insert(struct lh_table *t, const void *k, const void *v); extern int lh_table_insert(struct lh_table *t, const void *k, const void *v);



/** /**
* Insert a record into the table using a precalculated key hash. * Insert a record into the table using a precalculated key hash.
* *
@@ -245,8 +234,8 @@ extern int lh_table_insert(struct lh_table *t, const void *k, const void *v);
* @param opts if set to JSON_C_OBJECT_KEY_IS_CONSTANT, sets lh_entry.k_is_constant * @param opts if set to JSON_C_OBJECT_KEY_IS_CONSTANT, sets lh_entry.k_is_constant
* so t's free function knows to avoid freeing the key. * so t's free function knows to avoid freeing the key.
*/ */
extern int lh_table_insert_w_hash(struct lh_table *t, const void *k, const void *v, const unsigned long h, const unsigned opts);
extern int lh_table_insert_w_hash(struct lh_table *t, const void *k, const void *v,
const unsigned long h, const unsigned opts);


/** /**
* Lookup a record in the table. * Lookup a record in the table.
@@ -255,7 +244,7 @@ extern int lh_table_insert_w_hash(struct lh_table *t, const void *k, const void
* @param k a pointer to the key to lookup * @param k a pointer to the key to lookup
* @return a pointer to the record structure of the value or NULL if it does not exist. * @return a pointer to the record structure of the value or NULL if it does not exist.
*/ */
extern struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k);
extern struct lh_entry *lh_table_lookup_entry(struct lh_table *t, const void *k);


/** /**
* Lookup a record in the table using a precalculated key hash. * Lookup a record in the table using a precalculated key hash.
@@ -269,7 +258,8 @@ extern struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k)
* @param h hash value of the key to lookup * @param h hash value of the key to lookup
* @return a pointer to the record structure of the value or NULL if it does not exist. * @return a pointer to the record structure of the value or NULL if it does not exist.
*/ */
extern struct lh_entry* lh_table_lookup_entry_w_hash(struct lh_table *t, const void *k, const unsigned long h);
extern struct lh_entry *lh_table_lookup_entry_w_hash(struct lh_table *t, const void *k,
const unsigned long h);


/** /**
* Lookup a record in the table. * Lookup a record in the table.
@@ -293,7 +283,6 @@ extern json_bool lh_table_lookup_ex(struct lh_table *t, const void *k, void **v)
*/ */
extern int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e); extern int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e);



/** /**
* Delete a record from the table. * Delete a record from the table.
* *
@@ -319,7 +308,6 @@ extern int lh_table_length(struct lh_table *t);
*/ */
int lh_table_resize(struct lh_table *t, int new_size); int lh_table_resize(struct lh_table *t, int new_size);



/** /**
* @deprecated Don't use this outside of linkhash.h: * @deprecated Don't use this outside of linkhash.h:
*/ */


+ 4
- 4
math_compat.h View File

@@ -9,17 +9,17 @@
/* Define isnan, isinf, infinity and nan on Windows/MSVC */ /* Define isnan, isinf, infinity and nan on Windows/MSVC */


#ifndef HAVE_DECL_ISNAN #ifndef HAVE_DECL_ISNAN
# ifdef HAVE_DECL__ISNAN
#ifdef HAVE_DECL__ISNAN
#include <float.h> #include <float.h>
#define isnan(x) _isnan(x) #define isnan(x) _isnan(x)
# endif
#endif
#endif #endif


#ifndef HAVE_DECL_ISINF #ifndef HAVE_DECL_ISINF
# ifdef HAVE_DECL__FINITE
#ifdef HAVE_DECL__FINITE
#include <float.h> #include <float.h>
#define isinf(x) (!_finite(x)) #define isinf(x) (!_finite(x))
# endif
#endif
#endif #endif


#ifndef HAVE_DECL_INFINITY #ifndef HAVE_DECL_INFINITY


+ 65
- 55
printbuf.c View File

@@ -20,9 +20,9 @@
#include <string.h> #include <string.h>


#ifdef HAVE_STDARG_H #ifdef HAVE_STDARG_H
# include <stdarg.h>
#include <stdarg.h>
#else /* !HAVE_STDARG_H */ #else /* !HAVE_STDARG_H */
# error Not enough var arg support!
#error Not enough var arg support!
#endif /* HAVE_STDARG_H */ #endif /* HAVE_STDARG_H */


#include "debug.h" #include "debug.h"
@@ -32,23 +32,24 @@


static int printbuf_extend(struct printbuf *p, int min_size); static int printbuf_extend(struct printbuf *p, int min_size);


struct printbuf* printbuf_new(void)
struct printbuf *printbuf_new(void)
{ {
struct printbuf *p;

p = (struct printbuf*)calloc(1, sizeof(struct printbuf));
if(!p) return NULL;
p->size = 32;
p->bpos = 0;
if(!(p->buf = (char*)malloc(p->size))) {
free(p);
return NULL;
}
p->buf[0]= '\0';
return p;
struct printbuf *p;

p = (struct printbuf *)calloc(1, sizeof(struct printbuf));
if (!p)
return NULL;
p->size = 32;
p->bpos = 0;
if (!(p->buf = (char *)malloc(p->size)))
{
free(p);
return NULL;
}
p->buf[0] = '\0';
return p;
} }



/** /**
* Extend the buffer p so it has a size of at least min_size. * Extend the buffer p so it has a size of at least min_size.
* *
@@ -67,13 +68,13 @@ static int printbuf_extend(struct printbuf *p, int min_size)


new_size = p->size * 2; new_size = p->size * 2;
if (new_size < min_size + 8) if (new_size < min_size + 8)
new_size = min_size + 8;
new_size = min_size + 8;
#ifdef PRINTBUF_DEBUG #ifdef PRINTBUF_DEBUG
MC_DEBUG("printbuf_memappend: realloc " MC_DEBUG("printbuf_memappend: realloc "
"bpos=%d min_size=%d old_size=%d new_size=%d\n",
p->bpos, min_size, p->size, new_size);
"bpos=%d min_size=%d old_size=%d new_size=%d\n",
p->bpos, min_size, p->size, new_size);
#endif /* PRINTBUF_DEBUG */ #endif /* PRINTBUF_DEBUG */
if(!(t = (char*)realloc(p->buf, new_size)))
if (!(t = (char *)realloc(p->buf, new_size)))
return -1; return -1;
p->size = new_size; p->size = new_size;
p->buf = t; p->buf = t;
@@ -82,14 +83,15 @@ static int printbuf_extend(struct printbuf *p, int min_size)


int printbuf_memappend(struct printbuf *p, const char *buf, int size) int printbuf_memappend(struct printbuf *p, const char *buf, int size)
{ {
if (p->size <= p->bpos + size + 1) {
if (printbuf_extend(p, p->bpos + size + 1) < 0)
return -1;
}
memcpy(p->buf + p->bpos, buf, size);
p->bpos += size;
p->buf[p->bpos]= '\0';
return size;
if (p->size <= p->bpos + size + 1)
{
if (printbuf_extend(p, p->bpos + size + 1) < 0)
return -1;
}
memcpy(p->buf + p->bpos, buf, size);
p->bpos += size;
p->buf[p->bpos] = '\0';
return size;
} }


int printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len) int printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len)
@@ -114,43 +116,51 @@ int printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len)


int sprintbuf(struct printbuf *p, const char *msg, ...) int sprintbuf(struct printbuf *p, const char *msg, ...)
{ {
va_list ap;
char *t;
int size;
char buf[128];
/* user stack buffer first */
va_start(ap, msg);
size = vsnprintf(buf, 128, msg, ap);
va_end(ap);
/* if string is greater than stack buffer, then use dynamic string
va_list ap;
char *t;
int size;
char buf[128];
/* user stack buffer first */
va_start(ap, msg);
size = vsnprintf(buf, 128, msg, ap);
va_end(ap);
/* if string is greater than stack buffer, then use dynamic string
* with vasprintf. Note: some implementation of vsnprintf return -1 * with vasprintf. Note: some implementation of vsnprintf return -1
* if output is truncated whereas some return the number of bytes that * if output is truncated whereas some return the number of bytes that
* would have been written - this code handles both cases. * would have been written - this code handles both cases.
*/ */
if(size == -1 || size > 127) {
va_start(ap, msg);
if((size = vasprintf(&t, msg, ap)) < 0) { va_end(ap); return -1; }
va_end(ap);
printbuf_memappend(p, t, size);
free(t);
return size;
} else {
printbuf_memappend(p, buf, size);
return size;
}
if (size == -1 || size > 127)
{
va_start(ap, msg);
if ((size = vasprintf(&t, msg, ap)) < 0)
{
va_end(ap);
return -1;
}
va_end(ap);
printbuf_memappend(p, t, size);
free(t);
return size;
}
else
{
printbuf_memappend(p, buf, size);
return size;
}
} }


void printbuf_reset(struct printbuf *p) void printbuf_reset(struct printbuf *p)
{ {
p->buf[0] = '\0';
p->bpos = 0;
p->buf[0] = '\0';
p->bpos = 0;
} }


void printbuf_free(struct printbuf *p) void printbuf_free(struct printbuf *p)
{ {
if(p) {
free(p->buf);
free(p);
}
if (p)
{
free(p->buf);
free(p);
}
} }

+ 28
- 27
printbuf.h View File

@@ -24,7 +24,7 @@
#define _printbuf_h_ #define _printbuf_h_


#ifndef JSON_EXPORT #ifndef JSON_EXPORT
#if defined(_MSC_VER)
#if defined(_MSC_VER)
#define JSON_EXPORT __declspec(dllexport) #define JSON_EXPORT __declspec(dllexport)
#else #else
#define JSON_EXPORT extern #define JSON_EXPORT extern
@@ -35,15 +35,15 @@
extern "C" { extern "C" {
#endif #endif


struct printbuf {
char *buf;
int bpos;
int size;
struct printbuf
{
char *buf;
int bpos;
int size;
}; };
typedef struct printbuf printbuf; typedef struct printbuf printbuf;


JSON_EXPORT struct printbuf*
printbuf_new(void);
JSON_EXPORT struct printbuf *printbuf_new(void);


/* As an optimization, printbuf_memappend_fast() is defined as a macro /* As an optimization, printbuf_memappend_fast() is defined as a macro
* that handles copying data if the buffer is large enough; otherwise * that handles copying data if the buffer is large enough; otherwise
@@ -53,17 +53,22 @@ printbuf_new(void);
* Your code should not use printbuf_memappend() directly unless it * Your code should not use printbuf_memappend() directly unless it
* checks the return code. Use printbuf_memappend_fast() instead. * checks the return code. Use printbuf_memappend_fast() instead.
*/ */
JSON_EXPORT int
printbuf_memappend(struct printbuf *p, const char *buf, int size);

#define printbuf_memappend_fast(p, bufptr, bufsize) \
do { \
if ((p->size - p->bpos) > bufsize) { \
memcpy(p->buf + p->bpos, (bufptr), bufsize); \
p->bpos += bufsize; \
p->buf[p->bpos]= '\0'; \
} else { printbuf_memappend(p, (bufptr), bufsize); } \
} while (0)
JSON_EXPORT int printbuf_memappend(struct printbuf *p, const char *buf, int size);

#define printbuf_memappend_fast(p, bufptr, bufsize) \
do \
{ \
if ((p->size - p->bpos) > bufsize) \
{ \
memcpy(p->buf + p->bpos, (bufptr), bufsize); \
p->bpos += bufsize; \
p->buf[p->bpos] = '\0'; \
} \
else \
{ \
printbuf_memappend(p, (bufptr), bufsize); \
} \
} while (0)


#define printbuf_length(p) ((p)->bpos) #define printbuf_length(p) ((p)->bpos)


@@ -87,7 +92,7 @@ do { \
* sprintbuf() * sprintbuf()
*/ */
#define printbuf_strappend(pb, str) \ #define printbuf_strappend(pb, str) \
printbuf_memappend ((pb), _printbuf_check_literal(str), sizeof(str) - 1)
printbuf_memappend((pb), _printbuf_check_literal(str), sizeof(str) - 1)


/** /**
* Set len bytes of the buffer to charvalue, starting at offset offset. * Set len bytes of the buffer to charvalue, starting at offset offset.
@@ -97,8 +102,7 @@ do { \
* *
* If offset is -1, this starts at the end of the current data in the buffer. * If offset is -1, this starts at the end of the current data in the buffer.
*/ */
JSON_EXPORT int
printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len);
JSON_EXPORT int printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len);


/** /**
* Formatted print to printbuf. * Formatted print to printbuf.
@@ -114,14 +118,11 @@ printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len);
* printbuf_memappend() * printbuf_memappend()
* printbuf_strappend() * printbuf_strappend()
*/ */
JSON_EXPORT int
sprintbuf(struct printbuf *p, const char *msg, ...);
JSON_EXPORT int sprintbuf(struct printbuf *p, const char *msg, ...);


JSON_EXPORT void
printbuf_reset(struct printbuf *p);
JSON_EXPORT void printbuf_reset(struct printbuf *p);


JSON_EXPORT void
printbuf_free(struct printbuf *p);
JSON_EXPORT void printbuf_free(struct printbuf *p);


#ifdef __cplusplus #ifdef __cplusplus
} }


+ 1
- 1
snprintf_compat.h View File

@@ -35,7 +35,7 @@ static int json_c_snprintf(char *str, size_t size, const char *format, ...)
#define snprintf json_c_snprintf #define snprintf json_c_snprintf


#elif !defined(HAVE_SNPRINTF) /* !HAVE_SNPRINTF */ #elif !defined(HAVE_SNPRINTF) /* !HAVE_SNPRINTF */
# error Need vsnprintf!
#error Need vsnprintf!
#endif /* !HAVE_SNPRINTF && defined(WIN32) */ #endif /* !HAVE_SNPRINTF && defined(WIN32) */


#endif /* __snprintf_compat_h */ #endif /* __snprintf_compat_h */

+ 3
- 3
strdup_compat.h View File

@@ -7,10 +7,10 @@
*/ */


#if !defined(HAVE_STRDUP) && defined(_MSC_VER) #if !defined(HAVE_STRDUP) && defined(_MSC_VER)
/* MSC has the version as _strdup */
# define strdup _strdup
/* MSC has the version as _strdup */
#define strdup _strdup
#elif !defined(HAVE_STRDUP) #elif !defined(HAVE_STRDUP)
# error You do not have strdup on your system.
#error You do not have strdup on your system.
#endif /* HAVE_STRDUP */ #endif /* HAVE_STRDUP */


#endif #endif

+ 5
- 4
strerror_override.c View File

@@ -5,7 +5,8 @@
* Override strerror() to get consistent output across platforms. * Override strerror() to get consistent output across platforms.
*/ */


static struct {
static struct
{
int errno_value; int errno_value;
const char *errno_str; const char *errno_str;
} errno_list[] = { } errno_list[] = {
@@ -78,7 +79,8 @@ char *_json_c_strerror(int errno_in)
if (errno_list[ii].errno_value != errno_in) if (errno_list[ii].errno_value != errno_in)
continue; continue;


for (start_idx = sizeof(PREFIX) - 1, jj = 0; errno_str[jj] != '\0'; jj++, start_idx++)
for (start_idx = sizeof(PREFIX) - 1, jj = 0; errno_str[jj] != '\0';
jj++, start_idx++)
{ {
errno_buf[start_idx] = errno_str[jj]; errno_buf[start_idx] = errno_str[jj];
} }
@@ -94,10 +96,9 @@ char *_json_c_strerror(int errno_in)
digbuf[ii] = "0123456789"[(errno_in % 10)]; digbuf[ii] = "0123456789"[(errno_in % 10)];


// Reverse the digits // Reverse the digits
for (start_idx = sizeof(PREFIX) - 1 ; ii >= 0; ii--, start_idx++)
for (start_idx = sizeof(PREFIX) - 1; ii >= 0; ii--, start_idx++)
{ {
errno_buf[start_idx] = digbuf[ii]; errno_buf[start_idx] = digbuf[ii];
} }
return errno_buf; return errno_buf;
} }


+ 2
- 2
strerror_override.h View File

@@ -20,11 +20,11 @@ extern "C" {
JSON_EXPORT char *_json_c_strerror(int errno_in); JSON_EXPORT char *_json_c_strerror(int errno_in);


#ifndef STRERROR_OVERRIDE_IMPL #ifndef STRERROR_OVERRIDE_IMPL
#define strerror _json_c_strerror
#define strerror _json_c_strerror
#endif #endif


#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif


#endif /* _json_strerror_override_h_ */
#endif /* _json_strerror_override_h_ */

+ 9
- 8
tests/parse_flags.c View File

@@ -7,19 +7,20 @@
#include "parse_flags.h" #include "parse_flags.h"


#if !defined(HAVE_STRCASECMP) && defined(_MSC_VER) #if !defined(HAVE_STRCASECMP) && defined(_MSC_VER)
# define strcasecmp _stricmp
#define strcasecmp _stricmp
#elif !defined(HAVE_STRCASECMP) #elif !defined(HAVE_STRCASECMP)
# error You do not have strcasecmp on your system.
#error You do not have strcasecmp on your system.
#endif /* HAVE_STRNCASECMP */ #endif /* HAVE_STRNCASECMP */


static struct {
static struct
{
const char *arg; const char *arg;
int flag; int flag;
} format_args[] = { } format_args[] = {
{ "plain", JSON_C_TO_STRING_PLAIN },
{ "spaced", JSON_C_TO_STRING_SPACED },
{ "pretty", JSON_C_TO_STRING_PRETTY },
{ "pretty_tab", JSON_C_TO_STRING_PRETTY_TAB },
{"plain", JSON_C_TO_STRING_PLAIN},
{"spaced", JSON_C_TO_STRING_SPACED},
{"pretty", JSON_C_TO_STRING_PRETTY},
{"pretty_tab", JSON_C_TO_STRING_PRETTY_TAB},
}; };


#ifndef NELEM #ifndef NELEM
@@ -30,7 +31,7 @@ int parse_flags(int argc, char **argv)
{ {
int arg_idx; int arg_idx;
int sflags = 0; int sflags = 0;
for (arg_idx = 1; arg_idx < argc ; arg_idx++)
for (arg_idx = 1; arg_idx < argc; arg_idx++)
{ {
int jj; int jj;
for (jj = 0; jj < (int)NELEM(format_args); jj++) for (jj = 0; jj < (int)NELEM(format_args); jj++)


+ 28
- 25
tests/test1.c View File

@@ -1,19 +1,19 @@
#include <assert.h>
#include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h>
#include <string.h> #include <string.h>
#include <assert.h>


#include "json.h" #include "json.h"
#include "parse_flags.h" #include "parse_flags.h"


static int sort_fn (const void *j1, const void *j2)
static int sort_fn(const void *j1, const void *j2)
{ {
json_object * const *jso1, * const *jso2;
json_object *const *jso1, *const *jso2;
int i1, i2; int i1, i2;


jso1 = (json_object* const*)j1;
jso2 = (json_object* const*)j2;
jso1 = (json_object *const *)j1;
jso2 = (json_object *const *)j2;
if (!*jso1 && !*jso2) if (!*jso1 && !*jso2)
return 0; return 0;
if (!*jso1) if (!*jso1)
@@ -38,7 +38,8 @@ static const char *to_json_string(json_object *obj, int flags)
copy = strdup(result); copy = strdup(result);
if (copy == NULL) if (copy == NULL)
printf("to_json_string: Allocation failed!\n"); printf("to_json_string: Allocation failed!\n");
else {
else
{
result = json_object_to_json_string_ext(obj, flags); result = json_object_to_json_string_ext(obj, flags);
if (length != strlen(result)) if (length != strlen(result))
printf("to_json_string: Length mismatch!\n"); printf("to_json_string: Length mismatch!\n");
@@ -48,7 +49,7 @@ static const char *to_json_string(json_object *obj, int flags)
} }
return result; return result;
} }
#define json_object_to_json_string(obj) to_json_string(obj,sflags)
#define json_object_to_json_string(obj) to_json_string(obj, sflags)
#else #else
/* no special define */ /* no special define */
#endif #endif
@@ -84,7 +85,7 @@ void test_array_del_idx()
orig_array_len = json_object_array_length(my_array); orig_array_len = json_object_array_length(my_array);


printf("my_array=\n"); printf("my_array=\n");
for(ii = 0; ii < json_object_array_length(my_array); ii++)
for (ii = 0; ii < json_object_array_length(my_array); ii++)
{ {
json_object *obj = json_object_array_get_idx(my_array, ii); json_object *obj = json_object_array_get_idx(my_array, ii);
printf("\t[%d]=%s\n", (int)ii, json_object_to_json_string(obj)); printf("\t[%d]=%s\n", (int)ii, json_object_to_json_string(obj));
@@ -94,38 +95,38 @@ void test_array_del_idx()
for (ii = 0; ii < orig_array_len; ii++) for (ii = 0; ii < orig_array_len; ii++)
{ {
rc = json_object_array_del_idx(my_array, 0, 1); rc = json_object_array_del_idx(my_array, 0, 1);
printf("after del_idx(0,1)=%d, my_array.to_string()=%s\n",
rc, json_object_to_json_string(my_array));
printf("after del_idx(0,1)=%d, my_array.to_string()=%s\n", rc,
json_object_to_json_string(my_array));
} }


/* One more time, with the empty array: */ /* One more time, with the empty array: */
rc = json_object_array_del_idx(my_array, 0, 1); rc = json_object_array_del_idx(my_array, 0, 1);
printf("after del_idx(0,1)=%d, my_array.to_string()=%s\n",
rc, json_object_to_json_string(my_array));
printf("after del_idx(0,1)=%d, my_array.to_string()=%s\n", rc,
json_object_to_json_string(my_array));


json_object_put(my_array); json_object_put(my_array);


/* Delete all array indexes at once */ /* Delete all array indexes at once */
my_array = make_array(); my_array = make_array();
rc = json_object_array_del_idx(my_array, 0, orig_array_len); rc = json_object_array_del_idx(my_array, 0, orig_array_len);
printf("after del_idx(0,%d)=%d, my_array.to_string()=%s\n",
(int)orig_array_len, rc, json_object_to_json_string(my_array));
printf("after del_idx(0,%d)=%d, my_array.to_string()=%s\n", (int)orig_array_len, rc,
json_object_to_json_string(my_array));


json_object_put(my_array); json_object_put(my_array);


/* Delete *more* than all array indexes at once */ /* Delete *more* than all array indexes at once */
my_array = make_array(); my_array = make_array();
rc = json_object_array_del_idx(my_array, 0, orig_array_len + 1); rc = json_object_array_del_idx(my_array, 0, orig_array_len + 1);
printf("after del_idx(0,%d)=%d, my_array.to_string()=%s\n",
(int)(orig_array_len + 1), rc, json_object_to_json_string(my_array));
printf("after del_idx(0,%d)=%d, my_array.to_string()=%s\n", (int)(orig_array_len + 1), rc,
json_object_to_json_string(my_array));


json_object_put(my_array); json_object_put(my_array);
/* Delete some array indexes, then add more */ /* Delete some array indexes, then add more */
my_array = make_array(); my_array = make_array();
rc = json_object_array_del_idx(my_array, 0, orig_array_len - 1); rc = json_object_array_del_idx(my_array, 0, orig_array_len - 1);
printf("after del_idx(0,%d)=%d, my_array.to_string()=%s\n",
(int)(orig_array_len - 1), rc, json_object_to_json_string(my_array));
printf("after del_idx(0,%d)=%d, my_array.to_string()=%s\n", (int)(orig_array_len - 1), rc,
json_object_to_json_string(my_array));
json_object_array_add(my_array, json_object_new_string("s1")); json_object_array_add(my_array, json_object_new_string("s1"));
json_object_array_add(my_array, json_object_new_string("s2")); json_object_array_add(my_array, json_object_new_string("s2"));
json_object_array_add(my_array, json_object_new_string("s3")); json_object_array_add(my_array, json_object_new_string("s3"));
@@ -162,13 +163,15 @@ int main(int argc, char **argv)
my_string = json_object_new_string("/"); my_string = json_object_new_string("/");
printf("my_string=%s\n", json_object_get_string(my_string)); printf("my_string=%s\n", json_object_get_string(my_string));
printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string)); printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string));
printf("my_string.to_string(NOSLASHESCAPE)=%s\n", json_object_to_json_string_ext(my_string, JSON_C_TO_STRING_NOSLASHESCAPE));
printf("my_string.to_string(NOSLASHESCAPE)=%s\n",
json_object_to_json_string_ext(my_string, JSON_C_TO_STRING_NOSLASHESCAPE));
json_object_put(my_string); json_object_put(my_string);


my_string = json_object_new_string("/foo/bar/baz"); my_string = json_object_new_string("/foo/bar/baz");
printf("my_string=%s\n", json_object_get_string(my_string)); printf("my_string=%s\n", json_object_get_string(my_string));
printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string)); printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string));
printf("my_string.to_string(NOSLASHESCAPE)=%s\n", json_object_to_json_string_ext(my_string, JSON_C_TO_STRING_NOSLASHESCAPE));
printf("my_string.to_string(NOSLASHESCAPE)=%s\n",
json_object_to_json_string_ext(my_string, JSON_C_TO_STRING_NOSLASHESCAPE));
json_object_put(my_string); json_object_put(my_string);


my_string = json_object_new_string("foo"); my_string = json_object_new_string("foo");
@@ -188,7 +191,7 @@ int main(int argc, char **argv)
json_object_array_add(my_array, json_object_new_int(3)); json_object_array_add(my_array, json_object_new_int(3));
json_object_array_put_idx(my_array, 4, json_object_new_int(5)); json_object_array_put_idx(my_array, 4, json_object_new_int(5));
printf("my_array=\n"); printf("my_array=\n");
for(i=0; i < json_object_array_length(my_array); i++)
for (i = 0; i < json_object_array_length(my_array); i++)
{ {
json_object *obj = json_object_array_get_idx(my_array, i); json_object *obj = json_object_array_get_idx(my_array, i);
printf("\t[%d]=%s\n", (int)i, json_object_to_json_string(obj)); printf("\t[%d]=%s\n", (int)i, json_object_to_json_string(obj));
@@ -205,7 +208,7 @@ int main(int argc, char **argv)
json_object_array_add(my_array, json_object_new_int(2)); json_object_array_add(my_array, json_object_new_int(2));
json_object_array_put_idx(my_array, 4, json_object_new_int(0)); json_object_array_put_idx(my_array, 4, json_object_new_int(0));
printf("my_array=\n"); printf("my_array=\n");
for(i=0; i < json_object_array_length(my_array); i++)
for (i = 0; i < json_object_array_length(my_array); i++)
{ {
json_object *obj = json_object_array_get_idx(my_array, i); json_object *obj = json_object_array_get_idx(my_array, i);
printf("\t[%d]=%s\n", (int)i, json_object_to_json_string(obj)); printf("\t[%d]=%s\n", (int)i, json_object_to_json_string(obj));
@@ -213,7 +216,7 @@ int main(int argc, char **argv)
printf("my_array.to_string()=%s\n", json_object_to_json_string(my_array)); printf("my_array.to_string()=%s\n", json_object_to_json_string(my_array));
json_object_array_sort(my_array, sort_fn); json_object_array_sort(my_array, sort_fn);
printf("my_array=\n"); printf("my_array=\n");
for(i=0; i < json_object_array_length(my_array); i++)
for (i = 0; i < json_object_array_length(my_array); i++)
{ {
json_object *obj = json_object_array_get_idx(my_array, i); json_object *obj = json_object_array_get_idx(my_array, i);
printf("\t[%d]=%s\n", (int)i, json_object_to_json_string(obj)); printf("\t[%d]=%s\n", (int)i, json_object_to_json_string(obj));


+ 9
- 5
tests/test2.c View File

@@ -1,18 +1,17 @@
#include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h>
#include <string.h> #include <string.h>


#include "json.h" #include "json.h"
#include "parse_flags.h" #include "parse_flags.h"


#ifdef TEST_FORMATTED #ifdef TEST_FORMATTED
#define json_object_to_json_string(obj) json_object_to_json_string_ext(obj,sflags)
#define json_object_to_json_string(obj) json_object_to_json_string_ext(obj, sflags)
#else #else
/* no special define */ /* no special define */
#endif #endif



int main(int argc, char **argv) int main(int argc, char **argv)
{ {
json_object *new_obj; json_object *new_obj;
@@ -26,8 +25,13 @@ int main(int argc, char **argv)
sflags = parse_flags(argc, argv); sflags = parse_flags(argc, argv);
#endif #endif


new_obj = json_tokener_parse("/* more difficult test case */"
"{ \"glossary\": { \"title\": \"example glossary\", \"GlossDiv\": { \"title\": \"S\", \"GlossList\": [ { \"ID\": \"SGML\", \"SortAs\": \"SGML\", \"GlossTerm\": \"Standard Generalized Markup Language\", \"Acronym\": \"SGML\", \"Abbrev\": \"ISO 8879:1986\", \"GlossDef\": \"A meta-markup language, used to create markup languages such as DocBook.\", \"GlossSeeAlso\": [\"GML\", \"XML\", \"markup\"] } ] } } }");
new_obj = json_tokener_parse(
"/* more difficult test case */"
"{ \"glossary\": { \"title\": \"example glossary\", \"GlossDiv\": { \"title\": \"S\", "
"\"GlossList\": [ { \"ID\": \"SGML\", \"SortAs\": \"SGML\", \"GlossTerm\": \"Standard "
"Generalized Markup Language\", \"Acronym\": \"SGML\", \"Abbrev\": \"ISO 8879:1986\", "
"\"GlossDef\": \"A meta-markup language, used to create markup languages such as "
"DocBook.\", \"GlossSeeAlso\": [\"GML\", \"XML\", \"markup\"] } ] } } }");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj); json_object_put(new_obj);




+ 10
- 7
tests/test4.c View File

@@ -2,24 +2,24 @@
* gcc -o utf8 utf8.c -I/home/y/include -L./.libs -ljson * gcc -o utf8 utf8.c -I/home/y/include -L./.libs -ljson
*/ */


#include "config.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "config.h"


#include "json_inttypes.h" #include "json_inttypes.h"
#include "json_object.h" #include "json_object.h"
#include "json_tokener.h" #include "json_tokener.h"


void print_hex(const char* s)
void print_hex(const char *s)
{ {
const char *iter = s; const char *iter = s;
unsigned char ch; unsigned char ch;
while ((ch = *iter++) != 0) while ((ch = *iter++) != 0)
{ {
if( ',' != ch)
if (',' != ch)
printf("%x ", ch); printf("%x ", ch);
else else
printf( ",");
printf(",");
} }
putchar('\n'); putchar('\n');
} }
@@ -27,19 +27,22 @@ void print_hex(const char* s)
int main(void) int main(void)
{ {
const char *input = "\"\\ud840\\udd26,\\ud840\\udd27,\\ud800\\udd26,\\ud800\\udd27\""; const char *input = "\"\\ud840\\udd26,\\ud840\\udd27,\\ud800\\udd26,\\ud800\\udd27\"";
const char *expected = "\xF0\xA0\x84\xA6,\xF0\xA0\x84\xA7,\xF0\x90\x84\xA6,\xF0\x90\x84\xA7";
const char *expected =
"\xF0\xA0\x84\xA6,\xF0\xA0\x84\xA7,\xF0\x90\x84\xA6,\xF0\x90\x84\xA7";
struct json_object *parse_result = json_tokener_parse(input); struct json_object *parse_result = json_tokener_parse(input);
const char *unjson = json_object_get_string(parse_result); const char *unjson = json_object_get_string(parse_result);


printf("input: %s\n", input); printf("input: %s\n", input);


int strings_match = !strcmp( expected, unjson);
int strings_match = !strcmp(expected, unjson);
int retval = 0; int retval = 0;
if (strings_match) if (strings_match)
{ {
printf("JSON parse result is correct: %s\n", unjson); printf("JSON parse result is correct: %s\n", unjson);
puts("PASS"); puts("PASS");
} else {
}
else
{
printf("JSON parse result doesn't match expected string\n"); printf("JSON parse result doesn't match expected string\n");
printf("expected string bytes: "); printf("expected string bytes: ");
print_hex(expected); print_hex(expected);


+ 4
- 4
tests/testReplaceExisting.c View File

@@ -1,6 +1,6 @@
#include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h>
#include <string.h> #include <string.h>


#include "json.h" #include "json.h"
@@ -67,12 +67,12 @@ int main(int argc, char **argv)
} }
if (new_count != orig_count) if (new_count != orig_count)
{ {
printf("mismatch between original count (%d) and new count (%d)\n",
orig_count, new_count);
printf("mismatch between original count (%d) and new count (%d)\n", orig_count,
new_count);
retval = 1; retval = 1;
} }


json_object_put( my_object );
json_object_put(my_object);


return retval; return retval;
} }

+ 17
- 30
tests/test_cast.c View File

@@ -3,10 +3,10 @@
* Also checks the json_object_get_type and json_object_is_type functions. * Also checks the json_object_get_type and json_object_is_type functions.
*/ */


#include "config.h"
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include "config.h"
#include <string.h>


#include "json_inttypes.h" #include "json_inttypes.h"
#include "json_object.h" #include "json_object.h"
@@ -75,44 +75,31 @@ static void getit(struct json_object *new_obj, const char *field)
printf("Field %s does not exist\n", field); printf("Field %s does not exist\n", field);


enum json_type o_type = json_object_get_type(o); enum json_type o_type = json_object_get_type(o);
printf("new_obj.%s json_object_get_type()=%s\n", field,
json_type_to_name(o_type));
printf("new_obj.%s json_object_get_int()=%d\n", field,
json_object_get_int(o));
printf("new_obj.%s json_object_get_int64()=%" PRId64 "\n", field,
json_object_get_int64(o));
printf("new_obj.%s json_object_get_type()=%s\n", field, json_type_to_name(o_type));
printf("new_obj.%s json_object_get_int()=%d\n", field, json_object_get_int(o));
printf("new_obj.%s json_object_get_int64()=%" PRId64 "\n", field, json_object_get_int64(o));
printf("new_obj.%s json_object_get_uint64()=%" PRIu64 "\n", field, printf("new_obj.%s json_object_get_uint64()=%" PRIu64 "\n", field,
json_object_get_uint64(o)); json_object_get_uint64(o));
printf("new_obj.%s json_object_get_boolean()=%d\n", field,
json_object_get_boolean(o));
printf("new_obj.%s json_object_get_double()=%f\n", field,
json_object_get_double(o));
printf("new_obj.%s json_object_get_boolean()=%d\n", field, json_object_get_boolean(o));
printf("new_obj.%s json_object_get_double()=%f\n", field, json_object_get_double(o));
} }


static void checktype_header() static void checktype_header()
{ {
printf("json_object_is_type: %s,%s,%s,%s,%s,%s,%s\n",
json_type_to_name(json_type_null),
json_type_to_name(json_type_boolean),
json_type_to_name(json_type_double),
json_type_to_name(json_type_int),
json_type_to_name(json_type_object),
json_type_to_name(json_type_array),
json_type_to_name(json_type_string));
printf("json_object_is_type: %s,%s,%s,%s,%s,%s,%s\n", json_type_to_name(json_type_null),
json_type_to_name(json_type_boolean), json_type_to_name(json_type_double),
json_type_to_name(json_type_int), json_type_to_name(json_type_object),
json_type_to_name(json_type_array), json_type_to_name(json_type_string));
} }
static void checktype(struct json_object *new_obj, const char *field) static void checktype(struct json_object *new_obj, const char *field)
{ {
struct json_object *o = new_obj; struct json_object *o = new_obj;
if (field && !json_object_object_get_ex(new_obj, field, &o)) if (field && !json_object_object_get_ex(new_obj, field, &o))
printf("Field %s does not exist\n", field); printf("Field %s does not exist\n", field);
printf("new_obj%s%-18s: %d,%d,%d,%d,%d,%d,%d\n",
field ? "." : " ", field ? field : "",
json_object_is_type(o, json_type_null),
json_object_is_type(o, json_type_boolean),
json_object_is_type(o, json_type_double),
json_object_is_type(o, json_type_int),
json_object_is_type(o, json_type_object),
json_object_is_type(o, json_type_array),
json_object_is_type(o, json_type_string));

printf("new_obj%s%-18s: %d,%d,%d,%d,%d,%d,%d\n", field ? "." : " ", field ? field : "",
json_object_is_type(o, json_type_null), json_object_is_type(o, json_type_boolean),
json_object_is_type(o, json_type_double), json_object_is_type(o, json_type_int),
json_object_is_type(o, json_type_object), json_object_is_type(o, json_type_array),
json_object_is_type(o, json_type_string));
} }

+ 5
- 5
tests/test_charcase.c View File

@@ -1,8 +1,8 @@
#include <assert.h>
#include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h>
#include <string.h> #include <string.h>
#include <assert.h>


#include "json.h" #include "json.h"
#include "json_tokener.h" #include "json_tokener.h"
@@ -28,13 +28,13 @@ static void test_case_parse()
json_tokener_set_flags(tok, JSON_TOKENER_STRICT); json_tokener_set_flags(tok, JSON_TOKENER_STRICT);


new_obj = json_tokener_parse_ex(tok, "True", 4); new_obj = json_tokener_parse_ex(tok, "True", 4);
assert (new_obj == NULL);
assert(new_obj == NULL);


new_obj = json_tokener_parse_ex(tok, "False", 5); new_obj = json_tokener_parse_ex(tok, "False", 5);
assert (new_obj == NULL);
assert(new_obj == NULL);


new_obj = json_tokener_parse_ex(tok, "Null", 4); new_obj = json_tokener_parse_ex(tok, "Null", 4);
assert (new_obj == NULL);
assert(new_obj == NULL);


printf("OK\n"); printf("OK\n");




+ 1
- 1
tests/test_compare.c View File

@@ -2,9 +2,9 @@
* Tests if json_object_equal behaves correct. * Tests if json_object_equal behaves correct.
*/ */


#include "config.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "config.h"


#include "json_inttypes.h" #include "json_inttypes.h"
#include "json_object.h" #include "json_object.h"


+ 81
- 76
tests/test_deep_copy.c View File

@@ -1,6 +1,6 @@
#include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h>
#include <string.h> #include <string.h>
#ifdef NDEBUG #ifdef NDEBUG
#undef NDEBUG #undef NDEBUG
@@ -14,76 +14,76 @@


static void do_benchmark(json_object *src1); static void do_benchmark(json_object *src1);


static const char *json_str1 =
"{"
" \"glossary\": {"
" \"title\": \"example glossary\","
" \"GlossDiv\": {"
" \"number\": 16446744073709551615,"
" \"title\": \"S\","
" \"null_obj\": null, "
" \"exixt\": false,"
" \"quantity\":20,"
" \"univalent\":19.8,"
" \"GlossList\": {"
" \"GlossEntry\": {"
" \"ID\": \"SGML\","
" \"SortAs\": \"SGML\","
" \"GlossTerm\": \"Standard Generalized Markup Language\","
" \"Acronym\": \"SGML\","
" \"Abbrev\": \"ISO 8879:1986\","
" \"GlossDef\": {"
" \"para\": \"A meta-markup language, used to create markup languages such as DocBook.\","
" \"GlossSeeAlso\": [\"GML\", \"XML\"]"
" },"
" \"GlossSee\": \"markup\""
" }"
" }"
" }"
" }"
"}";
static const char *json_str1 =
"{"
" \"glossary\": {"
" \"title\": \"example glossary\","
" \"GlossDiv\": {"
" \"number\": 16446744073709551615,"
" \"title\": \"S\","
" \"null_obj\": null, "
" \"exixt\": false,"
" \"quantity\":20,"
" \"univalent\":19.8,"
" \"GlossList\": {"
" \"GlossEntry\": {"
" \"ID\": \"SGML\","
" \"SortAs\": \"SGML\","
" \"GlossTerm\": \"Standard Generalized Markup Language\","
" \"Acronym\": \"SGML\","
" \"Abbrev\": \"ISO 8879:1986\","
" \"GlossDef\": {"
" \"para\": \"A meta-markup language, used to create markup languages "
"such as DocBook.\","
" \"GlossSeeAlso\": [\"GML\", \"XML\"]"
" },"
" \"GlossSee\": \"markup\""
" }"
" }"
" }"
" }"
"}";


static const char *json_str2 = static const char *json_str2 =
"{\"menu\": {"
" \"header\": \"SVG Viewer\","
" \"items\": ["
" {\"id\": \"Open\"},"
" {\"id\": \"OpenNew\", \"label\": \"Open New\"},"
" null,"
" {\"id\": \"ZoomIn\", \"label\": \"Zoom In\"},"
" {\"id\": \"ZoomOut\", \"label\": \"Zoom Out\"},"
" {\"id\": \"OriginalView\", \"label\": \"Original View\"},"
" null,"
" {\"id\": \"Quality\", \"another_null\": null},"
" {\"id\": \"Pause\"},"
" {\"id\": \"Mute\"},"
" null,"
" {\"id\": \"Find\", \"label\": \"Find...\"},"
" {\"id\": \"FindAgain\", \"label\": \"Find Again\"},"
" {\"id\": \"Copy\"},"
" {\"id\": \"CopyAgain\", \"label\": \"Copy Again\"},"
" {\"id\": \"CopySVG\", \"label\": \"Copy SVG\"},"
" {\"id\": \"ViewSVG\", \"label\": \"View SVG\"},"
" {\"id\": \"ViewSource\", \"label\": \"View Source\"},"
" {\"id\": \"SaveAs\", \"label\": \"Save As\"},"
" null,"
" {\"id\": \"Help\"},"
" {\"id\": \"About\", \"label\": \"About Adobe CVG Viewer...\"}"
" ]"
"}}";

static const char *json_str3 =
"{\"menu\": {"
" \"id\": \"file\","
" \"value\": \"File\","
" \"popup\": {"
" \"menuitem\": ["
" {\"value\": \"New\", \"onclick\": \"CreateNewDoc()\"},"
" {\"value\": \"Open\", \"onclick\": \"OpenDoc()\"},"
" {\"value\": \"Close\", \"onclick\": \"CloseDoc()\"}"
" ]"
" }"
"}}";
"{\"menu\": {"
" \"header\": \"SVG Viewer\","
" \"items\": ["
" {\"id\": \"Open\"},"
" {\"id\": \"OpenNew\", \"label\": \"Open New\"},"
" null,"
" {\"id\": \"ZoomIn\", \"label\": \"Zoom In\"},"
" {\"id\": \"ZoomOut\", \"label\": \"Zoom Out\"},"
" {\"id\": \"OriginalView\", \"label\": \"Original View\"},"
" null,"
" {\"id\": \"Quality\", \"another_null\": null},"
" {\"id\": \"Pause\"},"
" {\"id\": \"Mute\"},"
" null,"
" {\"id\": \"Find\", \"label\": \"Find...\"},"
" {\"id\": \"FindAgain\", \"label\": \"Find Again\"},"
" {\"id\": \"Copy\"},"
" {\"id\": \"CopyAgain\", \"label\": \"Copy Again\"},"
" {\"id\": \"CopySVG\", \"label\": \"Copy SVG\"},"
" {\"id\": \"ViewSVG\", \"label\": \"View SVG\"},"
" {\"id\": \"ViewSource\", \"label\": \"View Source\"},"
" {\"id\": \"SaveAs\", \"label\": \"Save As\"},"
" null,"
" {\"id\": \"Help\"},"
" {\"id\": \"About\", \"label\": \"About Adobe CVG Viewer...\"}"
" ]"
"}}";

static const char *json_str3 = "{\"menu\": {"
" \"id\": \"file\","
" \"value\": \"File\","
" \"popup\": {"
" \"menuitem\": ["
" {\"value\": \"New\", \"onclick\": \"CreateNewDoc()\"},"
" {\"value\": \"Open\", \"onclick\": \"OpenDoc()\"},"
" {\"value\": \"Close\", \"onclick\": \"CloseDoc()\"}"
" ]"
" }"
"}}";


json_object_to_json_string_fn my_custom_serializer; json_object_to_json_string_fn my_custom_serializer;
int my_custom_serializer(struct json_object *jso, struct printbuf *pb, int level, int flags) int my_custom_serializer(struct json_object *jso, struct printbuf *pb, int level, int flags)
@@ -93,7 +93,8 @@ int my_custom_serializer(struct json_object *jso, struct printbuf *pb, int level
} }


json_c_shallow_copy_fn my_shallow_copy; json_c_shallow_copy_fn my_shallow_copy;
int my_shallow_copy(json_object *src, json_object *parent, const char *key, size_t index, json_object **dst)
int my_shallow_copy(json_object *src, json_object *parent, const char *key, size_t index,
json_object **dst)
{ {
int rc; int rc;
rc = json_c_shallow_copy_default(src, parent, key, index, dst); rc = json_c_shallow_copy_default(src, parent, key, index, dst);
@@ -109,7 +110,6 @@ int my_shallow_copy(json_object *src, json_object *parent, const char *key, size
return rc; return rc;
} }



int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct json_object *src1, *src2, *src3; struct json_object *src1, *src2, *src3;
@@ -238,19 +238,24 @@ static void do_benchmark(json_object *src2)
time_t start = time(NULL); time_t start = time(NULL);


start = time(NULL); start = time(NULL);
for (ii = 0; ii < iterations; ii++) {
for (ii = 0; ii < iterations; ii++)
{
dst2 = json_tokener_parse(json_object_get_string(src2)); dst2 = json_tokener_parse(json_object_get_string(src2));
json_object_put(dst2); json_object_put(dst2);
} }
printf("BENCHMARK - %d iterations of 'dst2 = json_tokener_parse(json_object_get_string(src2))' took %d seconds\n", iterations, (int)(time(NULL) - start));
printf("BENCHMARK - %d iterations of 'dst2 = "
"json_tokener_parse(json_object_get_string(src2))' took %d seconds\n",
iterations, (int)(time(NULL) - start));


start = time(NULL); start = time(NULL);
dst2 = NULL; dst2 = NULL;
for (ii = 0; ii < iterations; ii++) {
for (ii = 0; ii < iterations; ii++)
{
json_object_deep_copy(src2, &dst2, NULL); json_object_deep_copy(src2, &dst2, NULL);
json_object_put(dst2); json_object_put(dst2);
dst2 = NULL; dst2 = NULL;
} }
printf("BENCHMARK - %d iterations of 'json_object_deep_copy(src2, &dst2, NULL)' took %d seconds\n", iterations, (int)(time(NULL) - start));
printf("BENCHMARK - %d iterations of 'json_object_deep_copy(src2, &dst2, NULL)' took %d "
"seconds\n",
iterations, (int)(time(NULL) - start));
} }


+ 5
- 4
tests/test_double_serializer.c View File

@@ -2,8 +2,8 @@
* Tests if the format string for double serialization is handled correctly * Tests if the format string for double serialization is handled correctly
*/ */


#include <stdio.h>
#include "config.h" #include "config.h"
#include <stdio.h>


#include "json_object.h" #include "json_object.h"
#include "json_object_private.h" #include "json_object_private.h"
@@ -49,7 +49,8 @@ int main()
if (json_c_set_serialization_double_format("T%0.2fX", JSON_C_OPTION_THREAD) < 0) if (json_c_set_serialization_double_format("T%0.2fX", JSON_C_OPTION_THREAD) < 0)
printf("ERROR: json_c_set_serialization_double_format() failed"); printf("ERROR: json_c_set_serialization_double_format() failed");
printf("obj.to_string(with thread format)=%s\n", json_object_to_json_string(obj)); printf("obj.to_string(with thread format)=%s\n", json_object_to_json_string(obj));
if (json_c_set_serialization_double_format("Ttttttttttttt%0.2fxxxxxxxxxxxxxxxxxxX", JSON_C_OPTION_THREAD) < 0)
if (json_c_set_serialization_double_format("Ttttttttttttt%0.2fxxxxxxxxxxxxxxxxxxX",
JSON_C_OPTION_THREAD) < 0)
printf("ERROR: json_c_set_serialization_double_format() failed"); printf("ERROR: json_c_set_serialization_double_format() failed");
printf("obj.to_string(long thread format)=%s\n", json_object_to_json_string(obj)); printf("obj.to_string(long thread format)=%s\n", json_object_to_json_string(obj));
if (json_c_set_serialization_double_format(NULL, JSON_C_OPTION_THREAD) < 0) if (json_c_set_serialization_double_format(NULL, JSON_C_OPTION_THREAD) < 0)
@@ -96,11 +97,11 @@ int main()
json_object_put(obj); json_object_put(obj);


/* Test Infinity and -Infinity handling */ /* Test Infinity and -Infinity handling */
obj = json_object_new_double(1.0/zero_dot_zero);
obj = json_object_new_double(1.0 / zero_dot_zero);
printf("obj(1.0/0.0)=%s\n", json_object_to_json_string(obj)); printf("obj(1.0/0.0)=%s\n", json_object_to_json_string(obj));
json_object_put(obj); json_object_put(obj);


obj = json_object_new_double(-1.0/zero_dot_zero);
obj = json_object_new_double(-1.0 / zero_dot_zero);
printf("obj(-1.0/0.0)=%s\n", json_object_to_json_string(obj)); printf("obj(-1.0/0.0)=%s\n", json_object_to_json_string(obj));
json_object_put(obj); json_object_put(obj);




+ 18
- 18
tests/test_float.c View File

@@ -1,28 +1,28 @@
/* Copyright (C) 2016 by Rainer Gerhards /* Copyright (C) 2016 by Rainer Gerhards
* Released under ASL 2.0 */ * Released under ASL 2.0 */
#include "config.h" #include "config.h"
#include <stdio.h>
#include "json_object.h" #include "json_object.h"
#include "json_tokener.h" #include "json_tokener.h"
#include <stdio.h>
int main(void) int main(void)
{ {
json_object *json;
json_object *json;


json = json_object_new_double(1.0);
printf("json = %s\n", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
json_object_put(json);
json = json_object_new_double(1.0);
printf("json = %s\n", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
json_object_put(json);


json = json_object_new_double(-1.0);
printf("json = %s\n", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
json_object_put(json);
json = json_object_new_double(1.23);
printf("json = %s\n", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
json_object_put(json);
json = json_object_new_double(123456789.0);
printf("json = %s\n", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
json_object_put(json);
json = json_object_new_double(123456789.123);
printf("json = %s\n", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
json_object_put(json);
return 0;
json = json_object_new_double(-1.0);
printf("json = %s\n", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
json_object_put(json);
json = json_object_new_double(1.23);
printf("json = %s\n", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
json_object_put(json);
json = json_object_new_double(123456789.0);
printf("json = %s\n", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
json_object_put(json);
json = json_object_new_double(123456789.123);
printf("json = %s\n", json_object_to_json_string_ext(json, JSON_C_TO_STRING_PRETTY));
json_object_put(json);
return 0;
} }

+ 1
- 1
tests/test_int_add.c View File

@@ -43,7 +43,7 @@ int main(int argc, char **argv)
assert(json_object_get_int64(tmp) != INT64_MIN); assert(json_object_get_int64(tmp) != INT64_MIN);
json_object_put(tmp); json_object_put(tmp);
printf("INT64 ADD UNDERFLOW PASSED\n"); printf("INT64 ADD UNDERFLOW PASSED\n");
// uint64 + negative int64--> negative int64
// uint64 + negative int64--> negative int64
tmp = json_object_new_uint64(400); tmp = json_object_new_uint64(400);
json_object_int_inc(tmp, -200); json_object_int_inc(tmp, -200);
assert(json_object_get_int64(tmp) == 200); assert(json_object_get_int64(tmp) == 200);


+ 21
- 16
tests/test_json_pointer.c View File

@@ -20,17 +20,17 @@ static void test_example_int(struct json_object *jo1, const char *json_pointer,
} }


static const char *input_json_str = "{ " static const char *input_json_str = "{ "
"'foo': ['bar', 'baz'], "
"'': 0, "
"'a/b': 1, "
"'c%d': 2, "
"'e^f': 3, "
"'g|h': 4, "
"'i\\\\j': 5, "
"'k\\\"l': 6, "
"' ': 7, "
"'m~n': 8 "
"}";
"'foo': ['bar', 'baz'], "
"'': 0, "
"'a/b': 1, "
"'c%d': 2, "
"'e^f': 3, "
"'g|h': 4, "
"'i\\\\j': 5, "
"'k\\\"l': 6, "
"' ': 7, "
"'m~n': 8 "
"}";


/* clang-format off */ /* clang-format off */
static const char *rec_input_json_str = static const char *rec_input_json_str =
@@ -64,7 +64,8 @@ static void test_example_get()
{ {
int i; int i;
struct json_object *jo1, *jo2, *jo3; struct json_object *jo1, *jo2, *jo3;
struct json_pointer_map_s_i {
struct json_pointer_map_s_i
{
const char *s; const char *s;
int i; int i;
}; };
@@ -118,7 +119,7 @@ static void test_example_get()
assert(0 == strcmp("bar", json_object_get_string(jo2))); assert(0 == strcmp("bar", json_object_get_string(jo2)));
printf("PASSED - GET - /foo/0 == 'bar'\n"); printf("PASSED - GET - /foo/0 == 'bar'\n");


for (i = 0 ; json_pointers[i].s; i++)
for (i = 0; json_pointers[i].s; i++)
test_example_int(jo1, json_pointers[i].s, json_pointers[i].i); test_example_int(jo1, json_pointers[i].s, json_pointers[i].i);


json_object_put(jo1); json_object_put(jo1);
@@ -239,7 +240,8 @@ static void test_example_set()
printf("%s\n", json_object_get_string(jo1)); printf("%s\n", json_object_get_string(jo1));


assert(0 == json_pointer_set(&jo1, "/foo/1", json_object_new_string("cod"))); assert(0 == json_pointer_set(&jo1, "/foo/1", json_object_new_string("cod")));
assert(0 == strcmp("cod", json_object_get_string(json_object_array_get_idx(json_object_object_get(jo1, "foo"), 1))));
assert(0 == strcmp("cod", json_object_get_string(json_object_array_get_idx(
json_object_object_get(jo1, "foo"), 1))));
printf("PASSED - SET - 'cod' in /foo/1\n"); printf("PASSED - SET - 'cod' in /foo/1\n");
assert(0 != json_pointer_set(&jo1, "/fud/gaw", (jo2 = json_tokener_parse("[1,2,3]")))); assert(0 != json_pointer_set(&jo1, "/fud/gaw", (jo2 = json_tokener_parse("[1,2,3]"))));
assert(errno == ENOENT); assert(errno == ENOENT);
@@ -256,7 +258,9 @@ static void test_example_set()
assert(0 == json_pointer_set(&jo1, "/", json_object_new_int(9))); assert(0 == json_pointer_set(&jo1, "/", json_object_new_int(9)));
printf("PASSED - SET - / == 9\n"); printf("PASSED - SET - / == 9\n");


jo2 = json_tokener_parse("{ 'foo': [ 'bar', 'cod' ], '': 9, 'a/b': 1, 'c%d': 2, 'e^f': 3, 'g|h': 4, 'i\\\\j': 5, 'k\\\"l': 6, ' ': 7, 'm~n': 8, 'fud': { 'gaw': [ 0, 2, 3, 4 ] } }");
jo2 = json_tokener_parse(
"{ 'foo': [ 'bar', 'cod' ], '': 9, 'a/b': 1, 'c%d': 2, 'e^f': 3, 'g|h': 4, 'i\\\\j': "
"5, 'k\\\"l': 6, ' ': 7, 'm~n': 8, 'fud': { 'gaw': [ 0, 2, 3, 4 ] } }");
assert(json_object_equal(jo2, jo1)); assert(json_object_equal(jo2, jo1));
printf("PASSED - SET - Final JSON is: %s\n", json_object_get_string(jo1)); printf("PASSED - SET - Final JSON is: %s\n", json_object_get_string(jo1));
json_object_put(jo2); json_object_put(jo2);
@@ -286,7 +290,8 @@ static void test_wrong_inputs_set()
printf("PASSED - SET - failed 'cod' with path 'foo/bar'\n"); printf("PASSED - SET - failed 'cod' with path 'foo/bar'\n");
json_object_put(jo2); json_object_put(jo2);


assert(0 != json_pointer_setf(&jo1, (jo2 = json_object_new_string("cod")), "%s", "foo/bar"));
assert(0 !=
json_pointer_setf(&jo1, (jo2 = json_object_new_string("cod")), "%s", "foo/bar"));
printf("PASSED - SET - failed 'cod' with path 'foo/bar'\n"); printf("PASSED - SET - failed 'cod' with path 'foo/bar'\n");
json_object_put(jo2); json_object_put(jo2);




+ 6
- 7
tests/test_locale.c View File

@@ -1,8 +1,8 @@
#include <assert.h>
#include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h>
#include <string.h> #include <string.h>
#include <assert.h>


#include "config.h" #include "config.h"
#include "json.h" #include "json.h"
@@ -37,8 +37,7 @@ int main(int argc, char **argv)


(void)snprintf(buf2, sizeof(buf2), "%f", 0.1); (void)snprintf(buf2, sizeof(buf2), "%f", 0.1);
if (strcmp(buf1, buf2) != 0) if (strcmp(buf1, buf2) != 0)
printf("ERROR: Original locale not restored \"%s\" != \"%s\"",
buf1, buf2);
printf("ERROR: Original locale not restored \"%s\" != \"%s\"", buf1, buf2);


#ifdef HAVE_SETLOCALE #ifdef HAVE_SETLOCALE
setlocale(LC_NUMERIC, "C"); setlocale(LC_NUMERIC, "C");
@@ -49,16 +48,16 @@ int main(int argc, char **argv)
// string that was parsed. (see json_object_new_double_s()) // string that was parsed. (see json_object_new_double_s())
printf("new_obj.to_string()=["); printf("new_obj.to_string()=[");
unsigned int ii; unsigned int ii;
for (ii = 0 ; ii < json_object_array_length(new_obj); ii++)
for (ii = 0; ii < json_object_array_length(new_obj); ii++)
{ {
json_object *val = json_object_array_get_idx(new_obj, ii); json_object *val = json_object_array_get_idx(new_obj, ii);
printf("%s%.2lf", (ii > 0) ? "," : "", json_object_get_double(val)); printf("%s%.2lf", (ii > 0) ? "," : "", json_object_get_double(val));
} }
printf("]\n"); printf("]\n");


printf("new_obj.to_string()=%s\n", json_object_to_json_string_ext(new_obj,JSON_C_TO_STRING_NOZERO));
printf("new_obj.to_string()=%s\n",
json_object_to_json_string_ext(new_obj, JSON_C_TO_STRING_NOZERO));
json_object_put(new_obj); json_object_put(new_obj);


return 0; return 0;
} }


+ 7
- 5
tests/test_null.c View File

@@ -2,9 +2,9 @@
* Tests if binary strings are supported. * Tests if binary strings are supported.
*/ */


#include "config.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "config.h"


#include "json_inttypes.h" #include "json_inttypes.h"
#include "json_object.h" #include "json_object.h"
@@ -18,20 +18,22 @@ int main(void)
struct json_object *string = json_object_new_string_len(input, 3); struct json_object *string = json_object_new_string_len(input, 3);
const char *json = json_object_to_json_string(string); const char *json = json_object_to_json_string(string);


int strings_match = !strcmp( expected, json);
int strings_match = !strcmp(expected, json);
int retval = 0; int retval = 0;
if (strings_match) if (strings_match)
{ {
printf("JSON write result is correct: %s\n", json); printf("JSON write result is correct: %s\n", json);
puts("PASS"); puts("PASS");
} else {
}
else
{
puts("JSON write result doesn't match expected string"); puts("JSON write result doesn't match expected string");
printf("expected string: "); printf("expected string: ");
puts(expected); puts(expected);
printf("parsed string: "); printf("parsed string: ");
puts(json); puts(json);
puts("FAIL"); puts("FAIL");
retval=1;
retval = 1;
} }
json_object_put(string); json_object_put(string);


@@ -42,7 +44,7 @@ int main(void)
const char *parsed_cstr = json_object_get_string(parsed_str); const char *parsed_cstr = json_object_get_string(parsed_str);
int ii; int ii;
printf("Re-parsed object string len=%d, chars=[", parsed_len); printf("Re-parsed object string len=%d, chars=[", parsed_len);
for (ii = 0; ii < parsed_len ; ii++)
for (ii = 0; ii < parsed_len; ii++)
{ {
printf("%s%d", (ii ? ", " : ""), (int)parsed_cstr[ii]); printf("%s%d", (ii ? ", " : ""), (int)parsed_cstr[ii]);
} }


+ 231
- 232
tests/test_parse.c View File

@@ -1,8 +1,8 @@
#include <assert.h>
#include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h>
#include <string.h> #include <string.h>
#include <assert.h>


#include "json.h" #include "json.h"
#include "json_tokener.h" #include "json_tokener.h"
@@ -106,7 +106,7 @@ static void test_basic_parse()


single_basic_parse("{\"FoO\" : -12.3E512}", 0); single_basic_parse("{\"FoO\" : -12.3E512}", 0);
single_basic_parse("{\"FoO\" : -12.3e512}", 0); single_basic_parse("{\"FoO\" : -12.3e512}", 0);
single_basic_parse("{\"FoO\" : -12.3E51.2}", 0); /* non-sensical, returns null */
single_basic_parse("{\"FoO\" : -12.3E51.2}", 0); /* non-sensical, returns null */
single_basic_parse("{\"FoO\" : -12.3E512E12}", 0); /* non-sensical, returns null */ single_basic_parse("{\"FoO\" : -12.3E512E12}", 0); /* non-sensical, returns null */
single_basic_parse("[\"\\n\"]", 0); single_basic_parse("[\"\\n\"]", 0);
single_basic_parse("[\"\\nabc\\n\"]", 0); single_basic_parse("[\"\\nabc\\n\"]", 0);
@@ -119,7 +119,9 @@ static void test_basic_parse()
single_basic_parse("{ \'foo\': \'bar\' }", 0); single_basic_parse("{ \'foo\': \'bar\' }", 0);
single_basic_parse("{ \"foo\": \"bar\", \"baz\": null, \"bool0\": true }", 0); single_basic_parse("{ \"foo\": \"bar\", \"baz\": null, \"bool0\": true }", 0);
single_basic_parse("{ \"foo\": [null, \"foo\"] }", 0); single_basic_parse("{ \"foo\": [null, \"foo\"] }", 0);
single_basic_parse("{ \"abc\": 12, \"foo\": \"bar\", \"bool0\": false, \"bool1\": true, \"arr\": [ 1, 2, 3, null, 5 ] }", 0);
single_basic_parse("{ \"abc\": 12, \"foo\": \"bar\", \"bool0\": false, \"bool1\": true, "
"\"arr\": [ 1, 2, 3, null, 5 ] }",
0);
single_basic_parse("{ \"abc\": \"blue\nred\\ngreen\" }", 0); single_basic_parse("{ \"abc\": \"blue\nred\\ngreen\" }", 0);


// Clear serializer for these tests so we see the actual parsed value. // Clear serializer for these tests so we see the actual parsed value.
@@ -130,7 +132,7 @@ static void test_basic_parse()
single_basic_parse("[0e+-1]", 1); single_basic_parse("[0e+-1]", 1);
single_basic_parse("\"hello world!\"", 1); single_basic_parse("\"hello world!\"", 1);


// uint64/int64 range test
// uint64/int64 range test
single_basic_parse("[9223372036854775806]", 1); single_basic_parse("[9223372036854775806]", 1);
single_basic_parse("[9223372036854775807]", 1); single_basic_parse("[9223372036854775807]", 1);
single_basic_parse("[9223372036854775808]", 1); single_basic_parse("[9223372036854775808]", 1);
@@ -147,8 +149,8 @@ static void test_utf8_parse()
// json_tokener_parse doesn't support checking for byte order marks. // json_tokener_parse doesn't support checking for byte order marks.
// It's the responsibility of the caller to detect and skip a BOM. // It's the responsibility of the caller to detect and skip a BOM.
// Both of these checks return null. // Both of these checks return null.
char utf8_bom[] = { 0xEF, 0xBB, 0xBF, 0x00 };
char utf8_bom_and_chars[] = { 0xEF, 0xBB, 0xBF, '{', '}', 0x00 };
char utf8_bom[] = {0xEF, 0xBB, 0xBF, 0x00};
char utf8_bom_and_chars[] = {0xEF, 0xBB, 0xBF, '{', '}', 0x00};
single_basic_parse(utf8_bom, 0); single_basic_parse(utf8_bom, 0);
single_basic_parse(utf8_bom_and_chars, 0); single_basic_parse(utf8_bom_and_chars, 0);
} }
@@ -161,10 +163,8 @@ static void do_clear_serializer(json_object *jso)
json_c_visit(jso, 0, clear_serializer, NULL); json_c_visit(jso, 0, clear_serializer, NULL);
} }


static int clear_serializer(json_object *jso, int flags,
json_object *parent_jso,
const char *jso_key,
size_t *jso_index, void *userarg)
static int clear_serializer(json_object *jso, int flags, json_object *parent_jso,
const char *jso_key, size_t *jso_index, void *userarg)
{ {
if (jso) if (jso)
json_object_set_serializer(jso, NULL, NULL, NULL); json_object_set_serializer(jso, NULL, NULL, NULL);
@@ -177,24 +177,25 @@ static void test_verbose_parse()
enum json_tokener_error error = json_tokener_success; enum json_tokener_error error = json_tokener_success;


new_obj = json_tokener_parse_verbose("{ foo }", &error); new_obj = json_tokener_parse_verbose("{ foo }", &error);
assert (error == json_tokener_error_parse_object_key_name);
assert (new_obj == NULL);
assert(error == json_tokener_error_parse_object_key_name);
assert(new_obj == NULL);


new_obj = json_tokener_parse("{ foo }"); new_obj = json_tokener_parse("{ foo }");
assert (new_obj == NULL);
assert(new_obj == NULL);


new_obj = json_tokener_parse("foo"); new_obj = json_tokener_parse("foo");
assert (new_obj == NULL);
assert(new_obj == NULL);
new_obj = json_tokener_parse_verbose("foo", &error); new_obj = json_tokener_parse_verbose("foo", &error);
assert (new_obj == NULL);
assert(new_obj == NULL);


/* b/c the string starts with 'f' parsing return a boolean error */ /* b/c the string starts with 'f' parsing return a boolean error */
assert (error == json_tokener_error_parse_boolean);
assert(error == json_tokener_error_parse_boolean);


puts("json_tokener_parse_verbose() OK"); puts("json_tokener_parse_verbose() OK");
} }


struct incremental_step {
struct incremental_step
{
const char *string_to_parse; const char *string_to_parse;
int length; int length;
int char_offset; int char_offset;
@@ -202,205 +203,205 @@ struct incremental_step {
int reset_tokener; int reset_tokener;
} incremental_steps[] = { } incremental_steps[] = {


/* Check that full json messages can be parsed, both w/ and w/o a reset */
{ "{ \"foo\": 123 }", -1, -1, json_tokener_success, 0 },
{ "{ \"foo\": 456 }", -1, -1, json_tokener_success, 1 },
{ "{ \"foo\": 789 }", -1, -1, json_tokener_success, 1 },
/* Check the comment parse*/
{ "/* hello */{ \"foo\"", -1, -1, json_tokener_continue, 0 },
{ "/* hello */:/* hello */", -1, -1, json_tokener_continue, 0 },
{ "\"bar\"/* hello */", -1, -1, json_tokener_continue, 0 },
{ "}/* hello */", -1, -1, json_tokener_success, 1 },
{ "/ hello ", -1, 1, json_tokener_error_parse_comment, 1 },
{ "/* hello\"foo\"", -1, -1, json_tokener_continue, 1 },
{ "/* hello*\"foo\"", -1, -1, json_tokener_continue, 1 },
{ "// hello\"foo\"", -1, -1, json_tokener_continue, 1 },
/* Check a basic incremental parse */
{ "{ \"foo", -1, -1, json_tokener_continue, 0 },
{ "\": {\"bar", -1, -1, json_tokener_continue, 0 },
{ "\":13}}", -1, -1, json_tokener_success, 1 },
/* Check that json_tokener_reset actually resets */
{ "{ \"foo", -1, -1, json_tokener_continue, 1 },
{ ": \"bar\"}", -1, 0, json_tokener_error_parse_unexpected, 1 },
/* Check incremental parsing with trailing characters */
{ "{ \"foo", -1, -1, json_tokener_continue, 0 },
{ "\": {\"bar", -1, -1, json_tokener_continue, 0 },
{ "\":13}}XXXX", 10, 6, json_tokener_success, 0 },
{ "XXXX", 4, 0, json_tokener_error_parse_unexpected, 1 },
/* Check that trailing characters can change w/o a reset */
{ "{\"x\": 123 }\"X\"", -1, 11, json_tokener_success, 0 },
{ "\"Y\"", -1, -1, json_tokener_success, 1 },
/* To stop parsing a number we need to reach a non-digit, e.g. a \0 */
{ "1", 1, 1, json_tokener_continue, 0 },
/* This should parse as the number 12, since it continues the "1" */
{ "2", 2, 1, json_tokener_success, 0 },
{ "12{", 3, 2, json_tokener_success, 1 },
/* Parse number in strict model */
{ "[02]", -1, 3, json_tokener_error_parse_number, 3 },
/* Similar tests for other kinds of objects: */
/* These could all return success immediately, since regardless of
/* Check that full json messages can be parsed, both w/ and w/o a reset */
{"{ \"foo\": 123 }", -1, -1, json_tokener_success, 0},
{"{ \"foo\": 456 }", -1, -1, json_tokener_success, 1},
{"{ \"foo\": 789 }", -1, -1, json_tokener_success, 1},
/* Check the comment parse*/
{"/* hello */{ \"foo\"", -1, -1, json_tokener_continue, 0},
{"/* hello */:/* hello */", -1, -1, json_tokener_continue, 0},
{"\"bar\"/* hello */", -1, -1, json_tokener_continue, 0},
{"}/* hello */", -1, -1, json_tokener_success, 1},
{"/ hello ", -1, 1, json_tokener_error_parse_comment, 1},
{"/* hello\"foo\"", -1, -1, json_tokener_continue, 1},
{"/* hello*\"foo\"", -1, -1, json_tokener_continue, 1},
{"// hello\"foo\"", -1, -1, json_tokener_continue, 1},
/* Check a basic incremental parse */
{"{ \"foo", -1, -1, json_tokener_continue, 0},
{"\": {\"bar", -1, -1, json_tokener_continue, 0},
{"\":13}}", -1, -1, json_tokener_success, 1},
/* Check that json_tokener_reset actually resets */
{"{ \"foo", -1, -1, json_tokener_continue, 1},
{": \"bar\"}", -1, 0, json_tokener_error_parse_unexpected, 1},
/* Check incremental parsing with trailing characters */
{"{ \"foo", -1, -1, json_tokener_continue, 0},
{"\": {\"bar", -1, -1, json_tokener_continue, 0},
{"\":13}}XXXX", 10, 6, json_tokener_success, 0},
{"XXXX", 4, 0, json_tokener_error_parse_unexpected, 1},
/* Check that trailing characters can change w/o a reset */
{"{\"x\": 123 }\"X\"", -1, 11, json_tokener_success, 0},
{"\"Y\"", -1, -1, json_tokener_success, 1},
/* To stop parsing a number we need to reach a non-digit, e.g. a \0 */
{"1", 1, 1, json_tokener_continue, 0},
/* This should parse as the number 12, since it continues the "1" */
{"2", 2, 1, json_tokener_success, 0},
{"12{", 3, 2, json_tokener_success, 1},
/* Parse number in strict model */
{"[02]", -1, 3, json_tokener_error_parse_number, 3},
/* Similar tests for other kinds of objects: */
/* These could all return success immediately, since regardless of
what follows the false/true/null token we *will* return a json object, what follows the false/true/null token we *will* return a json object,
but it currently doesn't work that way. hmm... */ but it currently doesn't work that way. hmm... */
{ "false", 5, 5, json_tokener_continue, 1 },
{ "false", 6, 5, json_tokener_success, 1 },
{ "true", 4, 4, json_tokener_continue, 1 },
{ "true", 5, 4, json_tokener_success, 1 },
{ "null", 4, 4, json_tokener_continue, 1 },
{ "null", 5, 4, json_tokener_success, 1 },
{ "Infinity", 9, 8, json_tokener_success, 1 },
{ "infinity", 9, 8, json_tokener_success, 1 },
{ "-infinity", 10, 9, json_tokener_success, 1 },
{ "infinity", 9, 0, json_tokener_error_parse_unexpected, 3 },
{ "-infinity", 10, 1, json_tokener_error_parse_unexpected, 3 },
{ "inf", 3, 3, json_tokener_continue, 0 },
{ "inity", 6, 5, json_tokener_success, 1 },
{ "-inf", 4, 4, json_tokener_continue, 0 },
{ "inity", 6, 5, json_tokener_success, 1 },
{ "i", 1, 1, json_tokener_continue, 0 },
{ "n", 1, 1, json_tokener_continue, 0 },
{ "f", 1, 1, json_tokener_continue, 0 },
{ "i", 1, 1, json_tokener_continue, 0 },
{ "n", 1, 1, json_tokener_continue, 0 },
{ "i", 1, 1, json_tokener_continue, 0 },
{ "t", 1, 1, json_tokener_continue, 0 },
{ "y", 1, 1, json_tokener_continue, 0 },
{ "", 1, 0, json_tokener_success, 1 },
{ "-", 1, 1, json_tokener_continue, 0 },
{ "inf", 3, 3, json_tokener_continue, 0 },
{ "ini", 3, 3, json_tokener_continue, 0 },
{ "ty", 3, 2, json_tokener_success, 1 },
{ "-", 1, 1, json_tokener_continue, 0 },
{ "i", 1, 1, json_tokener_continue, 0 },
{ "nfini", 5, 5, json_tokener_continue, 0 },
{ "ty", 3, 2, json_tokener_success, 1 },
{ "-i", 2, 2, json_tokener_continue, 0 },
{ "nfinity", 8, 7, json_tokener_success, 1 },
{ "InfinityX", 10, 8, json_tokener_success, 0 },
{ "X", 1, 0, json_tokener_error_parse_unexpected, 1 },
{ "Infinity1234", 13, 8, json_tokener_success, 0 },
{ "1234", 5, 4, json_tokener_success, 1 },
{ "Infinity9999", 8, 8, json_tokener_continue, 0 },
/* returns the Infinity loaded up by the previous call: */
{ "1234", 5, 0, json_tokener_success, 0 },
{ "1234", 5, 4, json_tokener_success, 1 },
/* offset=1 because "n" is the start of "null". hmm... */
{ "noodle", 7, 1, json_tokener_error_parse_null, 1 },
/* offset=2 because "na" is the start of "nan". hmm... */
{ "naodle", 7, 2, json_tokener_error_parse_null, 1 },
/* offset=2 because "tr" is the start of "true". hmm... */
{ "track", 6, 2, json_tokener_error_parse_boolean, 1 },
{ "fail", 5, 2, json_tokener_error_parse_boolean, 1 },
/* Although they may initially look like they should fail,
{"false", 5, 5, json_tokener_continue, 1},
{"false", 6, 5, json_tokener_success, 1},
{"true", 4, 4, json_tokener_continue, 1},
{"true", 5, 4, json_tokener_success, 1},
{"null", 4, 4, json_tokener_continue, 1},
{"null", 5, 4, json_tokener_success, 1},
{"Infinity", 9, 8, json_tokener_success, 1},
{"infinity", 9, 8, json_tokener_success, 1},
{"-infinity", 10, 9, json_tokener_success, 1},
{"infinity", 9, 0, json_tokener_error_parse_unexpected, 3},
{"-infinity", 10, 1, json_tokener_error_parse_unexpected, 3},
{"inf", 3, 3, json_tokener_continue, 0},
{"inity", 6, 5, json_tokener_success, 1},
{"-inf", 4, 4, json_tokener_continue, 0},
{"inity", 6, 5, json_tokener_success, 1},
{"i", 1, 1, json_tokener_continue, 0},
{"n", 1, 1, json_tokener_continue, 0},
{"f", 1, 1, json_tokener_continue, 0},
{"i", 1, 1, json_tokener_continue, 0},
{"n", 1, 1, json_tokener_continue, 0},
{"i", 1, 1, json_tokener_continue, 0},
{"t", 1, 1, json_tokener_continue, 0},
{"y", 1, 1, json_tokener_continue, 0},
{"", 1, 0, json_tokener_success, 1},
{"-", 1, 1, json_tokener_continue, 0},
{"inf", 3, 3, json_tokener_continue, 0},
{"ini", 3, 3, json_tokener_continue, 0},
{"ty", 3, 2, json_tokener_success, 1},
{"-", 1, 1, json_tokener_continue, 0},
{"i", 1, 1, json_tokener_continue, 0},
{"nfini", 5, 5, json_tokener_continue, 0},
{"ty", 3, 2, json_tokener_success, 1},
{"-i", 2, 2, json_tokener_continue, 0},
{"nfinity", 8, 7, json_tokener_success, 1},
{"InfinityX", 10, 8, json_tokener_success, 0},
{"X", 1, 0, json_tokener_error_parse_unexpected, 1},
{"Infinity1234", 13, 8, json_tokener_success, 0},
{"1234", 5, 4, json_tokener_success, 1},
{"Infinity9999", 8, 8, json_tokener_continue, 0},
/* returns the Infinity loaded up by the previous call: */
{"1234", 5, 0, json_tokener_success, 0},
{"1234", 5, 4, json_tokener_success, 1},
/* offset=1 because "n" is the start of "null". hmm... */
{"noodle", 7, 1, json_tokener_error_parse_null, 1},
/* offset=2 because "na" is the start of "nan". hmm... */
{"naodle", 7, 2, json_tokener_error_parse_null, 1},
/* offset=2 because "tr" is the start of "true". hmm... */
{"track", 6, 2, json_tokener_error_parse_boolean, 1},
{"fail", 5, 2, json_tokener_error_parse_boolean, 1},
/* Although they may initially look like they should fail,
* the next few tests check that parsing multiple sequential * the next few tests check that parsing multiple sequential
* json objects in the input works as expected * json objects in the input works as expected
*/ */
{ "null123", 9, 4, json_tokener_success, 0 },
{ &"null123"[4], 4, 3, json_tokener_success, 1 },
{ "nullx", 5, 4, json_tokener_success, 0 },
{ &"nullx"[4], 2, 0, json_tokener_error_parse_unexpected, 1 },
{ "{\"a\":1}{\"b\":2}",15, 7, json_tokener_success, 0 },
{ &"{\"a\":1}{\"b\":2}"[7],
8, 7, json_tokener_success, 1 },

/* Some bad formatting. Check we get the correct error status */
{ "2015-01-15", 10, 4, json_tokener_error_parse_number, 1 },

/* Strings have a well defined end point, so we can stop at the quote */
{ "\"blue\"", -1, -1, json_tokener_success, 0 },

/* Check each of the escape sequences defined by the spec */
{ "\"\\\"\"", -1, -1, json_tokener_success, 0 },
{ "\"\\\\\"", -1, -1, json_tokener_success, 0 },
{ "\"\\b\"", -1, -1, json_tokener_success, 0 },
{ "\"\\f\"", -1, -1, json_tokener_success, 0 },
{ "\"\\n\"", -1, -1, json_tokener_success, 0 },
{ "\"\\r\"", -1, -1, json_tokener_success, 0 },
{ "\"\\t\"", -1, -1, json_tokener_success, 0 },
{ "\"\\/\"", -1, -1, json_tokener_success, 0 },
// Escaping a forward slash is optional
{ "\"/\"", -1, -1, json_tokener_success, 0 },
/* Check wrong escape sequences */
{ "\"\\a\"", -1, 2, json_tokener_error_parse_string, 1 },

/* Check '\'' in strict model */
{ "\'foo\'", -1, 0, json_tokener_error_parse_unexpected, 3 },

/* Parse array/object */
{ "[1,2,3]", -1, -1, json_tokener_success, 0 },
{ "[1,2,3}", -1, 6, json_tokener_error_parse_array, 1 },
{ "{\"a\"}", -1, 4, json_tokener_error_parse_object_key_sep, 1 },
{ "{\"a\":1]", -1, 6, json_tokener_error_parse_object_value_sep, 1 },
{ "{\"a\"::1}", -1, 5, json_tokener_error_parse_unexpected, 1 },
{ "{\"a\":}", -1, 5, json_tokener_error_parse_unexpected, 1 },
{ "{\"a\":1,\"a\":2}",-1, -1, json_tokener_success, 1 },
{ "\"a\":1}", -1, 3, json_tokener_success, 1 },
{ "{\"a\":1", -1, -1, json_tokener_continue, 1 },
{ "[,]", -1, 1, json_tokener_error_parse_unexpected, 1 },
{ "[,1]", -1, 1, json_tokener_error_parse_unexpected, 1 },

/* This behaviour doesn't entirely follow the json spec, but until we have
{"null123", 9, 4, json_tokener_success, 0},
{&"null123"[4], 4, 3, json_tokener_success, 1},
{"nullx", 5, 4, json_tokener_success, 0},
{&"nullx"[4], 2, 0, json_tokener_error_parse_unexpected, 1},
{"{\"a\":1}{\"b\":2}", 15, 7, json_tokener_success, 0},
{&"{\"a\":1}{\"b\":2}"[7], 8, 7, json_tokener_success, 1},

/* Some bad formatting. Check we get the correct error status */
{"2015-01-15", 10, 4, json_tokener_error_parse_number, 1},

/* Strings have a well defined end point, so we can stop at the quote */
{"\"blue\"", -1, -1, json_tokener_success, 0},

/* Check each of the escape sequences defined by the spec */
{"\"\\\"\"", -1, -1, json_tokener_success, 0},
{"\"\\\\\"", -1, -1, json_tokener_success, 0},
{"\"\\b\"", -1, -1, json_tokener_success, 0},
{"\"\\f\"", -1, -1, json_tokener_success, 0},
{"\"\\n\"", -1, -1, json_tokener_success, 0},
{"\"\\r\"", -1, -1, json_tokener_success, 0},
{"\"\\t\"", -1, -1, json_tokener_success, 0},
{"\"\\/\"", -1, -1, json_tokener_success, 0},
// Escaping a forward slash is optional
{"\"/\"", -1, -1, json_tokener_success, 0},
/* Check wrong escape sequences */
{"\"\\a\"", -1, 2, json_tokener_error_parse_string, 1},

/* Check '\'' in strict model */
{"\'foo\'", -1, 0, json_tokener_error_parse_unexpected, 3},

/* Parse array/object */
{"[1,2,3]", -1, -1, json_tokener_success, 0},
{"[1,2,3}", -1, 6, json_tokener_error_parse_array, 1},
{"{\"a\"}", -1, 4, json_tokener_error_parse_object_key_sep, 1},
{"{\"a\":1]", -1, 6, json_tokener_error_parse_object_value_sep, 1},
{"{\"a\"::1}", -1, 5, json_tokener_error_parse_unexpected, 1},
{"{\"a\":}", -1, 5, json_tokener_error_parse_unexpected, 1},
{"{\"a\":1,\"a\":2}", -1, -1, json_tokener_success, 1},
{"\"a\":1}", -1, 3, json_tokener_success, 1},
{"{\"a\":1", -1, -1, json_tokener_continue, 1},
{"[,]", -1, 1, json_tokener_error_parse_unexpected, 1},
{"[,1]", -1, 1, json_tokener_error_parse_unexpected, 1},

/* This behaviour doesn't entirely follow the json spec, but until we have
* a way to specify how strict to be we follow Postel's Law and be liberal * a way to specify how strict to be we follow Postel's Law and be liberal
* in what we accept (up to a point). * in what we accept (up to a point).
*/ */
{ "[1,2,3,]", -1, -1, json_tokener_success, 0 },
{ "[1,2,,3,]", -1, 5, json_tokener_error_parse_unexpected, 0 },

{ "[1,2,3,]", -1, 7, json_tokener_error_parse_unexpected, 3 },
{ "{\"a\":1,}", -1, 7, json_tokener_error_parse_unexpected, 3 },

// utf-8 test
// acsll encoding
{ "\x22\x31\x32\x33\x61\x73\x63\x24\x25\x26\x22",-1, -1, json_tokener_success, 5 },
{ "\x22\x31\x32\x33\x61\x73\x63\x24\x25\x26\x22",-1, -1, json_tokener_success, 1 },
// utf-8 encoding
{ "\x22\xe4\xb8\x96\xe7\x95\x8c\x22",-1, -1, json_tokener_success, 5 },
{ "\x22\xe4\xb8",-1, 3, json_tokener_error_parse_utf8_string, 4 },
{ "\x96\xe7\x95\x8c\x22",-1, 0, json_tokener_error_parse_utf8_string, 5 },
{ "\x22\xe4\xb8\x96\xe7\x95\x8c\x22",-1, -1, json_tokener_success, 1 },
{ "\x22\xcf\x80\xcf\x86\x22",-1, -1, json_tokener_success, 5 },
{ "\x22\xf0\xa5\x91\x95\x22",-1, -1, json_tokener_success, 5 },
// wrong utf-8 encoding
{ "\x22\xe6\x9d\x4e\x22",-1, 3, json_tokener_error_parse_utf8_string, 5 },
{ "\x22\xe6\x9d\x4e\x22",-1, 5, json_tokener_success, 1 },
// GBK encoding
{ "\x22\xc0\xee\xc5\xf4\x22",-1, 2, json_tokener_error_parse_utf8_string, 5 },
{ "\x22\xc0\xee\xc5\xf4\x22",-1, 6, json_tokener_success, 1 },
// char after space
{ "\x20\x20\x22\xe4\xb8\x96\x22",-1, -1, json_tokener_success, 5 },
{ "\x20\x20\x81\x22\xe4\xb8\x96\x22",-1, 2, json_tokener_error_parse_utf8_string, 5 },
{ "\x5b\x20\x81\x31\x5d",-1, 2, json_tokener_error_parse_utf8_string, 5 },
// char in state inf
{ "\x49\x6e\x66\x69\x6e\x69\x74\x79",9, 8, json_tokener_success, 1 },
{ "\x49\x6e\x66\x81\x6e\x69\x74\x79",-1, 3, json_tokener_error_parse_utf8_string, 5 },
// char in escape unicode
{ "\x22\x5c\x75\x64\x38\x35\x35\x5c\x75\x64\x63\x35\x35\x22",15, 14, json_tokener_success, 5 },
{ "\x22\x5c\x75\x64\x38\x35\x35\xc0\x75\x64\x63\x35\x35\x22",-1, 8, json_tokener_error_parse_utf8_string, 5 },
{ "\x22\x5c\x75\x64\x30\x30\x33\x31\xc0\x22",-1, 9, json_tokener_error_parse_utf8_string, 5 },
// char in number
{ "\x31\x31\x81\x31\x31",-1, 2, json_tokener_error_parse_utf8_string, 5 },
// char in object
{ "\x7b\x22\x31\x81\x22\x3a\x31\x7d",-1, 3, json_tokener_error_parse_utf8_string, 5 },

{ NULL, -1, -1, json_tokener_success, 0 },
{"[1,2,3,]", -1, -1, json_tokener_success, 0},
{"[1,2,,3,]", -1, 5, json_tokener_error_parse_unexpected, 0},

{"[1,2,3,]", -1, 7, json_tokener_error_parse_unexpected, 3},
{"{\"a\":1,}", -1, 7, json_tokener_error_parse_unexpected, 3},

// utf-8 test
// acsll encoding
{"\x22\x31\x32\x33\x61\x73\x63\x24\x25\x26\x22", -1, -1, json_tokener_success, 5},
{"\x22\x31\x32\x33\x61\x73\x63\x24\x25\x26\x22", -1, -1, json_tokener_success, 1},
// utf-8 encoding
{"\x22\xe4\xb8\x96\xe7\x95\x8c\x22", -1, -1, json_tokener_success, 5},
{"\x22\xe4\xb8", -1, 3, json_tokener_error_parse_utf8_string, 4},
{"\x96\xe7\x95\x8c\x22", -1, 0, json_tokener_error_parse_utf8_string, 5},
{"\x22\xe4\xb8\x96\xe7\x95\x8c\x22", -1, -1, json_tokener_success, 1},
{"\x22\xcf\x80\xcf\x86\x22", -1, -1, json_tokener_success, 5},
{"\x22\xf0\xa5\x91\x95\x22", -1, -1, json_tokener_success, 5},
// wrong utf-8 encoding
{"\x22\xe6\x9d\x4e\x22", -1, 3, json_tokener_error_parse_utf8_string, 5},
{"\x22\xe6\x9d\x4e\x22", -1, 5, json_tokener_success, 1},
// GBK encoding
{"\x22\xc0\xee\xc5\xf4\x22", -1, 2, json_tokener_error_parse_utf8_string, 5},
{"\x22\xc0\xee\xc5\xf4\x22", -1, 6, json_tokener_success, 1},
// char after space
{"\x20\x20\x22\xe4\xb8\x96\x22", -1, -1, json_tokener_success, 5},
{"\x20\x20\x81\x22\xe4\xb8\x96\x22", -1, 2, json_tokener_error_parse_utf8_string, 5},
{"\x5b\x20\x81\x31\x5d", -1, 2, json_tokener_error_parse_utf8_string, 5},
// char in state inf
{"\x49\x6e\x66\x69\x6e\x69\x74\x79", 9, 8, json_tokener_success, 1},
{"\x49\x6e\x66\x81\x6e\x69\x74\x79", -1, 3, json_tokener_error_parse_utf8_string, 5},
// char in escape unicode
{"\x22\x5c\x75\x64\x38\x35\x35\x5c\x75\x64\x63\x35\x35\x22", 15, 14, json_tokener_success, 5},
{"\x22\x5c\x75\x64\x38\x35\x35\xc0\x75\x64\x63\x35\x35\x22", -1, 8,
json_tokener_error_parse_utf8_string, 5},
{"\x22\x5c\x75\x64\x30\x30\x33\x31\xc0\x22", -1, 9, json_tokener_error_parse_utf8_string, 5},
// char in number
{"\x31\x31\x81\x31\x31", -1, 2, json_tokener_error_parse_utf8_string, 5},
// char in object
{"\x7b\x22\x31\x81\x22\x3a\x31\x7d", -1, 3, json_tokener_error_parse_utf8_string, 5},

{NULL, -1, -1, json_tokener_success, 0},
}; };


static void test_incremental_parse() static void test_incremental_parse()
@@ -422,7 +423,8 @@ static void test_incremental_parse()
string_to_parse = "{ \"foo"; /* } */ string_to_parse = "{ \"foo"; /* } */
printf("json_tokener_parse(%s) ... ", string_to_parse); printf("json_tokener_parse(%s) ... ", string_to_parse);
new_obj = json_tokener_parse(string_to_parse); new_obj = json_tokener_parse(string_to_parse);
if (new_obj == NULL) puts("got error as expected");
if (new_obj == NULL)
puts("got error as expected");


/* test incremental parsing in various forms */ /* test incremental parsing in various forms */
tok = json_tokener_new(); tok = json_tokener_new();
@@ -434,19 +436,19 @@ static void test_incremental_parse()
size_t expected_char_offset; size_t expected_char_offset;


if (step->reset_tokener & 2) if (step->reset_tokener & 2)
{
if (step->reset_tokener & 4)
json_tokener_set_flags(tok, 3);
else
json_tokener_set_flags(tok, JSON_TOKENER_STRICT);
}
{
if (step->reset_tokener & 4)
json_tokener_set_flags(tok, 3);
else
json_tokener_set_flags(tok, JSON_TOKENER_STRICT);
}
else else
{
if (step->reset_tokener & 4)
json_tokener_set_flags(tok, JSON_TOKENER_VALIDATE_UTF8);
else
json_tokener_set_flags(tok, 0);
}
{
if (step->reset_tokener & 4)
json_tokener_set_flags(tok, JSON_TOKENER_VALIDATE_UTF8);
else
json_tokener_set_flags(tok, 0);
}


if (length == -1) if (length == -1)
length = strlen(step->string_to_parse); length = strlen(step->string_to_parse);
@@ -455,8 +457,8 @@ static void test_incremental_parse()
else else
expected_char_offset = step->char_offset; expected_char_offset = step->char_offset;


printf("json_tokener_parse_ex(tok, %-12s, %3d) ... ",
step->string_to_parse, length);
printf("json_tokener_parse_ex(tok, %-12s, %3d) ... ", step->string_to_parse,
length);
new_obj = json_tokener_parse_ex(tok, step->string_to_parse, length); new_obj = json_tokener_parse_ex(tok, step->string_to_parse, length);


jerr = json_tokener_get_error(tok); jerr = json_tokener_get_error(tok);
@@ -470,8 +472,7 @@ static void test_incremental_parse()
json_tokener_error_desc(jerr)); json_tokener_error_desc(jerr));
else if (json_tokener_get_parse_end(tok) != expected_char_offset) else if (json_tokener_get_parse_end(tok) != expected_char_offset)
printf("ERROR: wrong char_offset %zu != expected %zu\n", printf("ERROR: wrong char_offset %zu != expected %zu\n",
json_tokener_get_parse_end(tok),
expected_char_offset);
json_tokener_get_parse_end(tok), expected_char_offset);
else else
{ {
printf("OK: got correct error: %s\n", printf("OK: got correct error: %s\n",
@@ -482,19 +483,17 @@ static void test_incremental_parse()
else else
{ {
if (new_obj == NULL && if (new_obj == NULL &&
!(step->length >= 4 &&
strncmp(step->string_to_parse, "null", 4) == 0))
!(step->length >= 4 && strncmp(step->string_to_parse, "null", 4) == 0))
printf("ERROR: expected valid object, instead: %s\n", printf("ERROR: expected valid object, instead: %s\n",
json_tokener_error_desc(jerr)); json_tokener_error_desc(jerr));
else if (json_tokener_get_parse_end(tok) != expected_char_offset) else if (json_tokener_get_parse_end(tok) != expected_char_offset)
printf("ERROR: wrong char_offset %zu != expected %zu\n", printf("ERROR: wrong char_offset %zu != expected %zu\n",
json_tokener_get_parse_end(tok),
expected_char_offset);
json_tokener_get_parse_end(tok), expected_char_offset);
else else
{ {
printf("OK: got object of type [%s]: %s\n", printf("OK: got object of type [%s]: %s\n",
json_type_to_name(json_object_get_type(new_obj)),
json_object_to_json_string(new_obj));
json_type_to_name(json_object_get_type(new_obj)),
json_object_to_json_string(new_obj));
this_step_ok = 1; this_step_ok = 1;
} }
} }


+ 4
- 4
tests/test_parse_int64.c View File

@@ -35,7 +35,7 @@ int main()
{ {
char buf[100]; char buf[100];


printf("==========json_parse_int64() test===========\n");
printf("==========json_parse_int64() test===========\n");
checkit("x"); checkit("x");


checkit("0"); checkit("0");
@@ -70,7 +70,7 @@ int main()
strcpy(buf, "4294967295"); // aka UINT32_MAX strcpy(buf, "4294967295"); // aka UINT32_MAX
checkit(buf); checkit(buf);


strcpy(buf, "4294967296"); // aka UINT32_MAX + 1
strcpy(buf, "4294967296"); // aka UINT32_MAX + 1
checkit(buf); checkit(buf);


strcpy(buf, "21474836470"); // INT32_MAX * 10 strcpy(buf, "21474836470"); // INT32_MAX * 10
@@ -122,7 +122,7 @@ int main()
strcpy(buf, "123"); strcpy(buf, "123");
checkit(buf); checkit(buf);


printf("\n==========json_parse_uint64() test===========\n");
printf("\n==========json_parse_uint64() test===========\n");
checkit_uint("x"); checkit_uint("x");


checkit_uint("0"); checkit_uint("0");
@@ -154,7 +154,7 @@ int main()
strcpy(buf, "4294967295"); // aka UINT32_MAX strcpy(buf, "4294967295"); // aka UINT32_MAX
checkit_uint(buf); checkit_uint(buf);


strcpy(buf, "4294967296"); // aka UINT32_MAX + 1
strcpy(buf, "4294967296"); // aka UINT32_MAX + 1
checkit_uint(buf); checkit_uint(buf);


strcpy(buf, "21474836470"); // INT32_MAX * 10 strcpy(buf, "21474836470"); // INT32_MAX * 10


+ 11
- 9
tests/test_printbuf.c View File

@@ -1,9 +1,9 @@
#include <assert.h> #include <assert.h>
#include <limits.h>
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h>


#include "debug.h" #include "debug.h"
#include "printbuf.h" #include "printbuf.h"
@@ -78,7 +78,7 @@ static void test_printbuf_memappend(int *before_resize)


initial_size = pb->size; initial_size = pb->size;


while(pb->size == initial_size)
while (pb->size == initial_size)
{ {
printbuf_memappend_fast(pb, "x", 1); printbuf_memappend_fast(pb, "x", 1);
} }
@@ -89,7 +89,7 @@ static void test_printbuf_memappend(int *before_resize)
printbuf_memappend_fast(pb, "bluexyz123", 3); printbuf_memappend_fast(pb, "bluexyz123", 3);
printf("Partial append: %d, [%s]\n", printbuf_length(pb), pb->buf); printf("Partial append: %d, [%s]\n", printbuf_length(pb), pb->buf);


char with_nulls[] = { 'a', 'b', '\0', 'c' };
char with_nulls[] = {'a', 'b', '\0', 'c'};
printbuf_reset(pb); printbuf_reset(pb);
printbuf_memappend_fast(pb, with_nulls, (int)sizeof(with_nulls)); printbuf_memappend_fast(pb, with_nulls, (int)sizeof(with_nulls));
printf("With embedded \\0 character: %d, [%s]\n", printbuf_length(pb), pb->buf); printf("With embedded \\0 character: %d, [%s]\n", printbuf_length(pb), pb->buf);
@@ -118,7 +118,7 @@ static void test_printbuf_memappend(int *before_resize)
printbuf_strappend(pb, SA_TEST_STR); printbuf_strappend(pb, SA_TEST_STR);
printf("Buffer size after printbuf_strappend(): %d, [%s]\n", printbuf_length(pb), pb->buf); printf("Buffer size after printbuf_strappend(): %d, [%s]\n", printbuf_length(pb), pb->buf);
printbuf_free(pb); printbuf_free(pb);
#undef SA_TEST_STR
#undef SA_TEST_STR


printf("%s: end test\n", __func__); printf("%s: end test\n", __func__);
} }
@@ -127,10 +127,11 @@ static void test_sprintbuf(int before_resize);
static void test_sprintbuf(int before_resize) static void test_sprintbuf(int before_resize)
{ {
struct printbuf *pb; struct printbuf *pb;
const char *max_char = "if string is greater than stack buffer, then use dynamic string"
" with vasprintf. Note: some implementation of vsnprintf return -1 "
" if output is truncated whereas some return the number of bytes that "
" would have been written - this code handles both cases.";
const char *max_char =
"if string is greater than stack buffer, then use dynamic string"
" with vasprintf. Note: some implementation of vsnprintf return -1 "
" if output is truncated whereas some return the number of bytes that "
" would have been written - this code handles both cases.";


printf("%s: starting test\n", __func__); printf("%s: starting test\n", __func__);
pb = printbuf_new(); pb = printbuf_new();
@@ -141,7 +142,8 @@ static void test_sprintbuf(int before_resize)
data[before_resize + 1] = '\0'; data[before_resize + 1] = '\0';
sprintbuf(pb, "%s", data); sprintbuf(pb, "%s", data);
free(data); free(data);
printf("sprintbuf to just after resize(%d+1): %d, [%s], strlen(buf)=%d\n", before_resize, printbuf_length(pb), pb->buf, (int)strlen(pb->buf));
printf("sprintbuf to just after resize(%d+1): %d, [%s], strlen(buf)=%d\n", before_resize,
printbuf_length(pb), pb->buf, (int)strlen(pb->buf));


printbuf_reset(pb); printbuf_reset(pb);
sprintbuf(pb, "plain"); sprintbuf(pb, "plain");


+ 8
- 8
tests/test_set_serializer.c View File

@@ -5,7 +5,8 @@
#include "json.h" #include "json.h"
#include "printbuf.h" #include "printbuf.h"


struct myinfo {
struct myinfo
{
int value; int value;
}; };


@@ -17,10 +18,7 @@ static void freeit(json_object *jso, void *userdata)
// Don't actually free anything here, the userdata is stack allocated. // Don't actually free anything here, the userdata is stack allocated.
freeit_was_called = 1; freeit_was_called = 1;
} }
static int custom_serializer(struct json_object *o,
struct printbuf *pb,
int level,
int flags)
static int custom_serializer(struct json_object *o, struct printbuf *pb, int level, int flags)
{ {
sprintbuf(pb, "Custom Output"); sprintbuf(pb, "Custom Output");
return 0; return 0;
@@ -39,10 +37,11 @@ int main(int argc, char **argv)


printf("my_object.to_string(standard)=%s\n", json_object_to_json_string(my_object)); printf("my_object.to_string(standard)=%s\n", json_object_to_json_string(my_object));


struct myinfo userdata = { .value = 123 };
struct myinfo userdata = {.value = 123};
json_object_set_serializer(my_object, custom_serializer, &userdata, freeit); json_object_set_serializer(my_object, custom_serializer, &userdata, freeit);


printf("my_object.to_string(custom serializer)=%s\n", json_object_to_json_string(my_object));
printf("my_object.to_string(custom serializer)=%s\n",
json_object_to_json_string(my_object));


printf("Next line of output should be from the custom freeit function:\n"); printf("Next line of output should be from the custom freeit function:\n");
freeit_was_called = 0; freeit_was_called = 0;
@@ -60,7 +59,8 @@ int main(int argc, char **argv)
json_object_set_serializer(my_object, custom_serializer, &userdata, freeit); json_object_set_serializer(my_object, custom_serializer, &userdata, freeit);
json_object_get(my_object); json_object_get(my_object);
json_object_put(my_object); json_object_put(my_object);
printf("my_object.to_string(custom serializer)=%s\n", json_object_to_json_string(my_object));
printf("my_object.to_string(custom serializer)=%s\n",
json_object_to_json_string(my_object));
printf("Next line of output should be from the custom freeit function:\n"); printf("Next line of output should be from the custom freeit function:\n");


freeit_was_called = 0; freeit_was_called = 0;


+ 68
- 68
tests/test_set_value.c View File

@@ -6,85 +6,85 @@


int main(int argc, char **argv) int main(int argc, char **argv)
{ {
json_object *tmp=json_object_new_int(123);
assert (json_object_get_int(tmp)==123);
json_object_set_int(tmp,321);
assert (json_object_get_int(tmp)==321);
json_object *tmp = json_object_new_int(123);
assert(json_object_get_int(tmp) == 123);
json_object_set_int(tmp, 321);
assert(json_object_get_int(tmp) == 321);
printf("INT PASSED\n"); printf("INT PASSED\n");
json_object_set_int64(tmp,(int64_t)321321321);
assert (json_object_get_int64(tmp)==321321321);
json_object_set_int64(tmp, (int64_t)321321321);
assert(json_object_get_int64(tmp) == 321321321);
json_object_put(tmp); json_object_put(tmp);
printf("INT64 PASSED\n"); printf("INT64 PASSED\n");
tmp=json_object_new_uint64(123);
assert (json_object_get_boolean(tmp)==1);
assert (json_object_get_int(tmp)==123);
assert (json_object_get_int64(tmp)==123);
assert (json_object_get_uint64(tmp)==123);
assert (json_object_get_double(tmp)==123.000000);
json_object_set_uint64(tmp,(uint64_t)321321321);
assert (json_object_get_uint64(tmp)==321321321);
json_object_set_uint64(tmp,9223372036854775808U);
assert (json_object_get_int(tmp)==INT32_MAX);
assert (json_object_get_uint64(tmp)==9223372036854775808U);
tmp = json_object_new_uint64(123);
assert(json_object_get_boolean(tmp) == 1);
assert(json_object_get_int(tmp) == 123);
assert(json_object_get_int64(tmp) == 123);
assert(json_object_get_uint64(tmp) == 123);
assert(json_object_get_double(tmp) == 123.000000);
json_object_set_uint64(tmp, (uint64_t)321321321);
assert(json_object_get_uint64(tmp) == 321321321);
json_object_set_uint64(tmp, 9223372036854775808U);
assert(json_object_get_int(tmp) == INT32_MAX);
assert(json_object_get_uint64(tmp) == 9223372036854775808U);
json_object_put(tmp); json_object_put(tmp);
printf("UINT64 PASSED\n"); printf("UINT64 PASSED\n");
tmp=json_object_new_boolean(1);
assert (json_object_get_boolean(tmp)==1);
json_object_set_boolean(tmp,0);
assert (json_object_get_boolean(tmp)==0);
json_object_set_boolean(tmp,1);
assert (json_object_get_boolean(tmp)==1);
tmp = json_object_new_boolean(1);
assert(json_object_get_boolean(tmp) == 1);
json_object_set_boolean(tmp, 0);
assert(json_object_get_boolean(tmp) == 0);
json_object_set_boolean(tmp, 1);
assert(json_object_get_boolean(tmp) == 1);
json_object_put(tmp); json_object_put(tmp);
printf("BOOL PASSED\n"); printf("BOOL PASSED\n");
tmp=json_object_new_double(12.34);
assert (json_object_get_double(tmp)==12.34);
json_object_set_double(tmp,34.56);
assert (json_object_get_double(tmp)==34.56);
json_object_set_double(tmp,6435.34);
assert (json_object_get_double(tmp)==6435.34);
json_object_set_double(tmp,2e21);
assert (json_object_get_int(tmp)==INT32_MAX);
assert (json_object_get_int64(tmp)==INT64_MAX);
assert (json_object_get_uint64(tmp)==UINT64_MAX);
json_object_set_double(tmp,-2e21);
assert (json_object_get_int(tmp)==INT32_MIN);
assert (json_object_get_int64(tmp)==INT64_MIN);
assert (json_object_get_uint64(tmp)==0);
tmp = json_object_new_double(12.34);
assert(json_object_get_double(tmp) == 12.34);
json_object_set_double(tmp, 34.56);
assert(json_object_get_double(tmp) == 34.56);
json_object_set_double(tmp, 6435.34);
assert(json_object_get_double(tmp) == 6435.34);
json_object_set_double(tmp, 2e21);
assert(json_object_get_int(tmp) == INT32_MAX);
assert(json_object_get_int64(tmp) == INT64_MAX);
assert(json_object_get_uint64(tmp) == UINT64_MAX);
json_object_set_double(tmp, -2e21);
assert(json_object_get_int(tmp) == INT32_MIN);
assert(json_object_get_int64(tmp) == INT64_MIN);
assert(json_object_get_uint64(tmp) == 0);
json_object_put(tmp); json_object_put(tmp);
printf("DOUBLE PASSED\n"); printf("DOUBLE PASSED\n");
#define SHORT "SHORT"
#define MID "A MID STRING"
// 12345678901234567890123456789012....
#define HUGE "A string longer than 32 chars as to check non local buf codepath"
tmp=json_object_new_string(SHORT);
assert (strcmp(json_object_get_string(tmp),SHORT)==0);
json_object_set_string(tmp,MID);
assert (strcmp(json_object_get_string(tmp),MID)==0);
json_object_set_string(tmp,HUGE);
assert (strcmp(json_object_get_string(tmp),HUGE)==0);
json_object_set_string(tmp,SHORT);
assert (strcmp(json_object_get_string(tmp),SHORT)==0);
#define SHORT "SHORT"
#define MID "A MID STRING"
// 12345678901234567890123456789012....
#define HUGE "A string longer than 32 chars as to check non local buf codepath"
tmp = json_object_new_string(SHORT);
assert(strcmp(json_object_get_string(tmp), SHORT) == 0);
json_object_set_string(tmp, MID);
assert(strcmp(json_object_get_string(tmp), MID) == 0);
json_object_set_string(tmp, HUGE);
assert(strcmp(json_object_get_string(tmp), HUGE) == 0);
json_object_set_string(tmp, SHORT);
assert(strcmp(json_object_get_string(tmp), SHORT) == 0);
json_object_put(tmp); json_object_put(tmp);
printf("STRING PASSED\n"); printf("STRING PASSED\n");


#define STR "STR"
#define DOUBLE "123.123"
#define DOUBLE_E "12E+3"
#define DOUBLE_STR "123.123STR"
#define DOUBLE_OVER "1.8E+308"
#define DOUBLE_OVER_NEGATIVE "-1.8E+308"
tmp=json_object_new_string(STR);
assert (json_object_get_double(tmp)==0.0);
json_object_set_string(tmp,DOUBLE);
assert (json_object_get_double(tmp)==123.123000);
json_object_set_string(tmp,DOUBLE_E);
assert (json_object_get_double(tmp)==12000.000000);
json_object_set_string(tmp,DOUBLE_STR);
assert (json_object_get_double(tmp)==0.0);
json_object_set_string(tmp,DOUBLE_OVER);
assert (json_object_get_double(tmp)==0.0);
json_object_set_string(tmp,DOUBLE_OVER_NEGATIVE);
assert (json_object_get_double(tmp)==0.0);
#define STR "STR"
#define DOUBLE "123.123"
#define DOUBLE_E "12E+3"
#define DOUBLE_STR "123.123STR"
#define DOUBLE_OVER "1.8E+308"
#define DOUBLE_OVER_NEGATIVE "-1.8E+308"
tmp = json_object_new_string(STR);
assert(json_object_get_double(tmp) == 0.0);
json_object_set_string(tmp, DOUBLE);
assert(json_object_get_double(tmp) == 123.123000);
json_object_set_string(tmp, DOUBLE_E);
assert(json_object_get_double(tmp) == 12000.000000);
json_object_set_string(tmp, DOUBLE_STR);
assert(json_object_get_double(tmp) == 0.0);
json_object_set_string(tmp, DOUBLE_OVER);
assert(json_object_get_double(tmp) == 0.0);
json_object_set_string(tmp, DOUBLE_OVER_NEGATIVE);
assert(json_object_get_double(tmp) == 0.0);
json_object_put(tmp); json_object_put(tmp);
printf("STRINGTODOUBLE PASSED\n"); printf("STRINGTODOUBLE PASSED\n");


@@ -92,7 +92,7 @@ int main(int argc, char **argv)
json_object_set_double(tmp, 12.3); json_object_set_double(tmp, 12.3);
const char *serialized = json_object_to_json_string(tmp); const char *serialized = json_object_to_json_string(tmp);
fprintf(stderr, "%s\n", serialized); fprintf(stderr, "%s\n", serialized);
assert(strncmp(serialized, "12.3", 4)==0);
assert(strncmp(serialized, "12.3", 4) == 0);
json_object_put(tmp); json_object_put(tmp);
printf("PARSE AND SET PASSED\n"); printf("PARSE AND SET PASSED\n");




+ 47
- 58
tests/test_util_file.c View File

@@ -2,20 +2,20 @@
#include "strerror_override_private.h" #include "strerror_override_private.h"
#ifdef WIN32 #ifdef WIN32
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <io.h> #include <io.h>
#endif /* defined(WIN32) */
#include <windows.h>
#endif /* defined(WIN32) */
#include <fcntl.h>
#include <limits.h>
#include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h>
#include <string.h> #include <string.h>
#include <fcntl.h>
#include <limits.h>
#if HAVE_UNISTD_H #if HAVE_UNISTD_H
# include <unistd.h>
#include <unistd.h>
#endif /* HAVE_UNISTD_H */ #endif /* HAVE_UNISTD_H */
#include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h>


#include "json.h" #include "json.h"
#include "json_util.h" #include "json_util.h"
@@ -38,21 +38,20 @@ static void test_write_to_file()
json_object *jso; json_object *jso;


jso = json_tokener_parse("{" jso = json_tokener_parse("{"
"\"foo\":1234,"
"\"foo1\":\"abcdefghijklmnopqrstuvwxyz\","
"\"foo2\":\"abcdefghijklmnopqrstuvwxyz\","
"\"foo3\":\"abcdefghijklmnopqrstuvwxyz\","
"\"foo4\":\"abcdefghijklmnopqrstuvwxyz\","
"\"foo5\":\"abcdefghijklmnopqrstuvwxyz\","
"\"foo6\":\"abcdefghijklmnopqrstuvwxyz\","
"\"foo7\":\"abcdefghijklmnopqrstuvwxyz\","
"\"foo8\":\"abcdefghijklmnopqrstuvwxyz\","
"\"foo9\":\"abcdefghijklmnopqrstuvwxyz\""
"}");
"\"foo\":1234,"
"\"foo1\":\"abcdefghijklmnopqrstuvwxyz\","
"\"foo2\":\"abcdefghijklmnopqrstuvwxyz\","
"\"foo3\":\"abcdefghijklmnopqrstuvwxyz\","
"\"foo4\":\"abcdefghijklmnopqrstuvwxyz\","
"\"foo5\":\"abcdefghijklmnopqrstuvwxyz\","
"\"foo6\":\"abcdefghijklmnopqrstuvwxyz\","
"\"foo7\":\"abcdefghijklmnopqrstuvwxyz\","
"\"foo8\":\"abcdefghijklmnopqrstuvwxyz\","
"\"foo9\":\"abcdefghijklmnopqrstuvwxyz\""
"}");
const char *outfile = "json.out"; const char *outfile = "json.out";
int rv = json_object_to_file(outfile, jso); int rv = json_object_to_file(outfile, jso);
printf("%s: json_object_to_file(%s, jso)=%d\n",
(rv == 0) ? "OK" : "FAIL", outfile, rv);
printf("%s: json_object_to_file(%s, jso)=%d\n", (rv == 0) ? "OK" : "FAIL", outfile, rv);
if (rv == 0) if (rv == 0)
stat_and_cat(outfile); stat_and_cat(outfile);


@@ -66,7 +65,7 @@ static void test_write_to_file()
stat_and_cat(outfile2); stat_and_cat(outfile2);


const char *outfile3 = "json3.out"; const char *outfile3 = "json3.out";
int d = open(outfile3, O_WRONLY|O_CREAT, 0600);
int d = open(outfile3, O_WRONLY | O_CREAT, 0600);
if (d < 0) if (d < 0)
{ {
printf("FAIL: unable to open %s %s\n", outfile3, strerror(errno)); printf("FAIL: unable to open %s %s\n", outfile3, strerror(errno));
@@ -92,19 +91,17 @@ static void stat_and_cat(const char *file)
int d = open(file, O_RDONLY, 0600); int d = open(file, O_RDONLY, 0600);
if (d < 0) if (d < 0)
{ {
printf("FAIL: unable to open %s: %s\n",
file, strerror(errno));
printf("FAIL: unable to open %s: %s\n", file, strerror(errno));
return; return;
} }
if (fstat(d, &sb) < 0) if (fstat(d, &sb) < 0)
{ {
printf("FAIL: unable to stat %s: %s\n",
file, strerror(errno));
printf("FAIL: unable to stat %s: %s\n", file, strerror(errno));
close(d); close(d);
return; return;
} }
char *buf = malloc(sb.st_size + 1); char *buf = malloc(sb.st_size + 1);
if(!buf)
if (!buf)
{ {
printf("FAIL: unable to allocate memory\n"); printf("FAIL: unable to allocate memory\n");
close(d); close(d);
@@ -112,8 +109,7 @@ static void stat_and_cat(const char *file)
} }
if (read(d, buf, sb.st_size) < sb.st_size) if (read(d, buf, sb.st_size) < sb.st_size)
{ {
printf("FAIL: unable to read all of %s: %s\n",
file, strerror(errno));
printf("FAIL: unable to read all of %s: %s\n", file, strerror(errno));
free(buf); free(buf);
close(d); close(d);
return; return;
@@ -126,8 +122,8 @@ static void stat_and_cat(const char *file)


int main(int argc, char **argv) int main(int argc, char **argv)
{ {
// json_object_to_file(file, obj);
// json_object_to_file_ext(file, obj, flags);
// json_object_to_file(file, obj);
// json_object_to_file_ext(file, obj, flags);


_json_c_strerror_enable = 1; _json_c_strerror_enable = 1;


@@ -135,9 +131,9 @@ int main(int argc, char **argv)
if (argc < 2) if (argc < 2)
{ {
fprintf(stderr, fprintf(stderr,
"Usage: %s <testdir>\n"
" <testdir> is the location of input files\n",
argv[0]);
"Usage: %s <testdir>\n"
" <testdir> is the location of input files\n",
argv[0]);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
testdir = argv[1]; testdir = argv[1];
@@ -158,23 +154,19 @@ static void test_read_valid_with_fd(const char *testdir)
int d = open(filename, O_RDONLY, 0); int d = open(filename, O_RDONLY, 0);
if (d < 0) if (d < 0)
{ {
fprintf(stderr,
"FAIL: unable to open %s: %s\n",
filename, strerror(errno));
fprintf(stderr, "FAIL: unable to open %s: %s\n", filename, strerror(errno));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
json_object *jso = json_object_from_fd(d); json_object *jso = json_object_from_fd(d);
if (jso != NULL) if (jso != NULL)
{ {
printf("OK: json_object_from_fd(valid.json)=%s\n",
json_object_to_json_string(jso));
printf("OK: json_object_from_fd(valid.json)=%s\n", json_object_to_json_string(jso));
json_object_put(jso); json_object_put(jso);
} }
else else
{ {
fprintf(stderr,
"FAIL: unable to parse contents of %s: %s\n",
filename, json_util_get_last_err());
fprintf(stderr, "FAIL: unable to parse contents of %s: %s\n", filename,
json_util_get_last_err());
} }
close(d); close(d);
} }
@@ -187,9 +179,7 @@ static void test_read_valid_nested_with_fd(const char *testdir)
int d = open(filename, O_RDONLY, 0); int d = open(filename, O_RDONLY, 0);
if (d < 0) if (d < 0)
{ {
fprintf(stderr,
"FAIL: unable to open %s: %s\n",
filename, strerror(errno));
fprintf(stderr, "FAIL: unable to open %s: %s\n", filename, strerror(errno));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
json_object *jso = json_object_from_fd_ex(d, 20); json_object *jso = json_object_from_fd_ex(d, 20);
@@ -201,9 +191,8 @@ static void test_read_valid_nested_with_fd(const char *testdir)
} }
else else
{ {
fprintf(stderr,
"FAIL: unable to parse contents of %s: %s\n",
filename, json_util_get_last_err());
fprintf(stderr, "FAIL: unable to parse contents of %s: %s\n", filename,
json_util_get_last_err());
} }


(void)lseek(d, SEEK_SET, 0); (void)lseek(d, SEEK_SET, 0);
@@ -211,14 +200,15 @@ static void test_read_valid_nested_with_fd(const char *testdir)
jso = json_object_from_fd_ex(d, 3); jso = json_object_from_fd_ex(d, 3);
if (jso != NULL) if (jso != NULL)
{ {
printf("FAIL: json_object_from_fd_ex(%s, 3)=%s\n",
filename, json_object_to_json_string(jso));
printf("FAIL: json_object_from_fd_ex(%s, 3)=%s\n", filename,
json_object_to_json_string(jso));
json_object_put(jso); json_object_put(jso);
} }
else else
{ {
printf("OK: correctly unable to parse contents of valid_nested.json with low max depth: %s\n",
json_util_get_last_err());
printf("OK: correctly unable to parse contents of valid_nested.json with low max "
"depth: %s\n",
json_util_get_last_err());
} }
close(d); close(d);
} }
@@ -230,14 +220,14 @@ static void test_read_nonexistant()
json_object *jso = json_object_from_file(filename); json_object *jso = json_object_from_file(filename);
if (jso != NULL) if (jso != NULL)
{ {
printf("FAIL: json_object_from_file(%s) returned %p when NULL expected\n",
filename, (void *)jso);
printf("FAIL: json_object_from_file(%s) returned %p when NULL expected\n", filename,
(void *)jso);
json_object_put(jso); json_object_put(jso);
} }
else else
{ {
printf("OK: json_object_from_file(%s) correctly returned NULL: %s\n",
filename, json_util_get_last_err());
printf("OK: json_object_from_file(%s) correctly returned NULL: %s\n", filename,
json_util_get_last_err());
} }
} }


@@ -245,7 +235,7 @@ static void test_read_closed()
{ {
// Test reading from a closed fd // Test reading from a closed fd
int d = open("/dev/null", O_RDONLY, 0); int d = open("/dev/null", O_RDONLY, 0);
if(d < 0)
if (d < 0)
{ {
puts("FAIL: unable to open"); puts("FAIL: unable to open");
} }
@@ -261,8 +251,7 @@ static void test_read_closed()
json_object *jso = json_object_from_fd(fixed_d); json_object *jso = json_object_from_fd(fixed_d);
if (jso != NULL) if (jso != NULL)
{ {
printf("FAIL: read from closed fd returning non-NULL: %p\n",
(void *)jso);
printf("FAIL: read from closed fd returning non-NULL: %p\n", (void *)jso);
fflush(stdout); fflush(stdout);
printf(" jso=%s\n", json_object_to_json_string(jso)); printf(" jso=%s\n", json_object_to_json_string(jso));
json_object_put(jso); json_object_put(jso);


+ 19
- 38
tests/test_visit.c View File

@@ -1,8 +1,8 @@
#include <assert.h>
#include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h>
#include <string.h> #include <string.h>
#include <assert.h>


#include "json.h" #include "json.h"
#include "json_tokener.h" #include "json_tokener.h"
@@ -68,24 +68,17 @@ int main(void)
return 0; return 0;
} }



static int emit_object(json_object *jso, int flags,
json_object *parent_jso,
const char *jso_key,
size_t *jso_index, void *userarg)
static int emit_object(json_object *jso, int flags, json_object *parent_jso, const char *jso_key,
size_t *jso_index, void *userarg)
{ {
printf("flags: 0x%x, key: %s, index: %ld, value: %s\n",
flags,
(jso_key ? jso_key : "(null)"),
(jso_index ? (long)*jso_index : -1L),
printf("flags: 0x%x, key: %s, index: %ld, value: %s\n", flags,
(jso_key ? jso_key : "(null)"), (jso_index ? (long)*jso_index : -1L),
json_object_to_json_string(jso)); json_object_to_json_string(jso));
return JSON_C_VISIT_RETURN_CONTINUE; return JSON_C_VISIT_RETURN_CONTINUE;
} }


static int skip_arrays(json_object *jso, int flags,
json_object *parent_jso,
const char *jso_key,
size_t *jso_index, void *userarg)
static int skip_arrays(json_object *jso, int flags, json_object *parent_jso, const char *jso_key,
size_t *jso_index, void *userarg)
{ {
(void)emit_object(jso, flags, parent_jso, jso_key, jso_index, userarg); (void)emit_object(jso, flags, parent_jso, jso_key, jso_index, userarg);
if (json_object_get_type(jso) == json_type_array) if (json_object_get_type(jso) == json_type_array)
@@ -93,10 +86,8 @@ static int skip_arrays(json_object *jso, int flags,
return JSON_C_VISIT_RETURN_CONTINUE; return JSON_C_VISIT_RETURN_CONTINUE;
} }


static int pop_and_stop(json_object *jso, int flags,
json_object *parent_jso,
const char *jso_key,
size_t *jso_index, void *userarg)
static int pop_and_stop(json_object *jso, int flags, json_object *parent_jso, const char *jso_key,
size_t *jso_index, void *userarg)
{ {
(void)emit_object(jso, flags, parent_jso, jso_key, jso_index, userarg); (void)emit_object(jso, flags, parent_jso, jso_key, jso_index, userarg);
if (jso_key != NULL && strcmp(jso_key, "subobj1") == 0) if (jso_key != NULL && strcmp(jso_key, "subobj1") == 0)
@@ -112,10 +103,8 @@ static int pop_and_stop(json_object *jso, int flags,
return JSON_C_VISIT_RETURN_CONTINUE; return JSON_C_VISIT_RETURN_CONTINUE;
} }


static int err_on_subobj2(json_object *jso, int flags,
json_object *parent_jso,
const char *jso_key,
size_t *jso_index, void *userarg)
static int err_on_subobj2(json_object *jso, int flags, json_object *parent_jso, const char *jso_key,
size_t *jso_index, void *userarg)
{ {
(void)emit_object(jso, flags, parent_jso, jso_key, jso_index, userarg); (void)emit_object(jso, flags, parent_jso, jso_key, jso_index, userarg);
if (jso_key != NULL && strcmp(jso_key, "subobj2") == 0) if (jso_key != NULL && strcmp(jso_key, "subobj2") == 0)
@@ -126,9 +115,7 @@ static int err_on_subobj2(json_object *jso, int flags,
return JSON_C_VISIT_RETURN_CONTINUE; return JSON_C_VISIT_RETURN_CONTINUE;
} }


static int pop_array(json_object *jso, int flags,
json_object *parent_jso,
const char *jso_key,
static int pop_array(json_object *jso, int flags, json_object *parent_jso, const char *jso_key,
size_t *jso_index, void *userarg) size_t *jso_index, void *userarg)
{ {
(void)emit_object(jso, flags, parent_jso, jso_key, jso_index, userarg); (void)emit_object(jso, flags, parent_jso, jso_key, jso_index, userarg);
@@ -140,10 +127,8 @@ static int pop_array(json_object *jso, int flags,
return JSON_C_VISIT_RETURN_CONTINUE; return JSON_C_VISIT_RETURN_CONTINUE;
} }


static int stop_array(json_object *jso, int flags,
json_object *parent_jso,
const char *jso_key,
size_t *jso_index, void *userarg)
static int stop_array(json_object *jso, int flags, json_object *parent_jso, const char *jso_key,
size_t *jso_index, void *userarg)
{ {
(void)emit_object(jso, flags, parent_jso, jso_key, jso_index, userarg); (void)emit_object(jso, flags, parent_jso, jso_key, jso_index, userarg);
if (jso_index != NULL && (*jso_index == 0)) if (jso_index != NULL && (*jso_index == 0))
@@ -154,15 +139,11 @@ static int stop_array(json_object *jso, int flags,
return JSON_C_VISIT_RETURN_CONTINUE; return JSON_C_VISIT_RETURN_CONTINUE;
} }


static int err_return(json_object *jso, int flags,
json_object *parent_jso,
const char *jso_key,
size_t *jso_index, void *userarg)
static int err_return(json_object *jso, int flags, json_object *parent_jso, const char *jso_key,
size_t *jso_index, void *userarg)
{ {
printf("flags: 0x%x, key: %s, index: %ld, value: %s\n",
flags,
(jso_key ? jso_key : "(null)"),
(jso_index ? (long)*jso_index : -1L),
printf("flags: 0x%x, key: %s, index: %ld, value: %s\n", flags,
(jso_key ? jso_key : "(null)"), (jso_index ? (long)*jso_index : -1L),
json_object_to_json_string(jso)); json_object_to_json_string(jso));
return 100; return 100;
} }

+ 20
- 9
vasprintf_compat.h View File

@@ -18,25 +18,36 @@ static int vasprintf(char **buf, const char *fmt, va_list ap)
int chars; int chars;
char *b; char *b;


if(!buf) { return -1; }
if (!buf)
{
return -1;
}


#ifdef WIN32 #ifdef WIN32
chars = _vscprintf(fmt, ap)+1;
#else /* !defined(WIN32) */
chars = _vscprintf(fmt, ap) + 1;
#else /* !defined(WIN32) */
/* CAW: RAWR! We have to hope to god here that vsnprintf doesn't overwrite /* CAW: RAWR! We have to hope to god here that vsnprintf doesn't overwrite
* our buffer like on some 64bit sun systems.... but hey, its time to move on * our buffer like on some 64bit sun systems.... but hey, its time to move on
*/ */
chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap)+1;
if(chars < 0) { chars *= -1; } /* CAW: old glibc versions have this problem */
chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap) + 1;
if (chars < 0)
{
chars *= -1;
} /* CAW: old glibc versions have this problem */
#endif /* defined(WIN32) */ #endif /* defined(WIN32) */


b = (char*)malloc(sizeof(char)*chars);
if(!b) { return -1; }
b = (char *)malloc(sizeof(char) * chars);
if (!b)
{
return -1;
}


if((chars = vsprintf(b, fmt, ap)) < 0)
if ((chars = vsprintf(b, fmt, ap)) < 0)
{ {
free(b); free(b);
} else {
}
else
{
*buf = b; *buf = b;
} }




Loading…
Cancel
Save