Browse Source

Move to newer jansson library.

Con Kolivas 14 years ago
parent
commit
4de3f32a22

+ 1 - 1
README

@@ -6,7 +6,7 @@ License: GPLv2.  See COPYING for details.
 Dependencies:
 	libcurl			http://curl.haxx.se/libcurl/
 	jansson			http://www.digip.org/jansson/
-	(jansson is included in-tree and an installed one may conflict)
+	(jansson is included in-tree and not necessary)
 	libncurses5-dev (or libpdcurses on WIN32)
 
 Basic *nix build instructions:

+ 4 - 1
compat/jansson/Makefile.am

@@ -3,6 +3,7 @@ noinst_LIBRARIES	= libjansson.a
 
 libjansson_a_SOURCES	= \
 			  config.h		\
+			  jansson_config.h	\
 			  dump.c		\
 			  hashtable.c		\
 			  hashtable.h		\
@@ -14,5 +15,7 @@ libjansson_a_SOURCES	= \
 			  utf.c			\
 			  utf.h			\
 			  util.h		\
-			  value.c
+			  value.c		\
+			  memory.c		\
+			  error.c
 

+ 26 - 21
compat/jansson/dump.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2011 Petri Lehtinen <petri@digip.org>
  *
  * Jansson is free software; you can redistribute it and/or modify
  * it under the terms of the MIT license. See LICENSE for details.
@@ -41,10 +41,10 @@ static int dump_to_file(const char *buffer, int size, void *data)
     return 0;
 }
 
-/* 256 spaces (the maximum indentation size) */
-static char whitespace[] = "                                                                                                                                                                                                                                                                ";
+/* 32 spaces (the maximum indentation size) */
+static char whitespace[] = "                                ";
 
-static int dump_indent(unsigned long flags, int depth, int space, dump_func dump, void *data)
+static int dump_indent(size_t flags, int depth, int space, dump_func dump, void *data)
 {
     if(JSON_INDENT(flags) > 0)
     {
@@ -165,7 +165,7 @@ static int object_key_compare_serials(const void *key1, const void *key2)
            (*(const object_key_t **)key2)->serial;
 }
 
-static int do_dump(const json_t *json, unsigned long flags, int depth,
+static int do_dump(const json_t *json, size_t flags, int depth,
                    dump_func dump, void *data)
 {
     int ascii = flags & JSON_ENSURE_ASCII ? 1 : 0;
@@ -185,7 +185,9 @@ static int do_dump(const json_t *json, unsigned long flags, int depth,
             char buffer[MAX_INTEGER_STR_LENGTH];
             int size;
 
-            size = snprintf(buffer, MAX_INTEGER_STR_LENGTH, "%d", json_integer_value(json));
+            size = snprintf(buffer, MAX_INTEGER_STR_LENGTH,
+                            "%" JSON_INTEGER_FORMAT,
+                            json_integer_value(json));
             if(size >= MAX_INTEGER_STR_LENGTH)
                 return -1;
 
@@ -307,12 +309,11 @@ static int do_dump(const json_t *json, unsigned long flags, int depth,
             if(flags & JSON_SORT_KEYS || flags & JSON_PRESERVE_ORDER)
             {
                 const object_key_t **keys;
-                unsigned int size;
-                unsigned int i;
+                size_t size, i;
                 int (*cmp_func)(const void *, const void *);
 
                 size = json_object_size(json);
-                keys = malloc(size * sizeof(object_key_t *));
+                keys = jsonp_malloc(size * sizeof(object_key_t *));
                 if(!keys)
                     goto object_error;
 
@@ -345,7 +346,7 @@ static int do_dump(const json_t *json, unsigned long flags, int depth,
                     if(dump(separator, separator_length, data) ||
                        do_dump(value, flags, depth + 1, dump, data))
                     {
-                        free(keys);
+                        jsonp_free(keys);
                         goto object_error;
                     }
 
@@ -354,7 +355,7 @@ static int do_dump(const json_t *json, unsigned long flags, int depth,
                         if(dump(",", 1, data) ||
                            dump_indent(flags, depth + 1, 1, dump, data))
                         {
-                            free(keys);
+                            jsonp_free(keys);
                             goto object_error;
                         }
                     }
@@ -362,13 +363,13 @@ static int do_dump(const json_t *json, unsigned long flags, int depth,
                     {
                         if(dump_indent(flags, depth, 0, dump, data))
                         {
-                            free(keys);
+                            jsonp_free(keys);
                             goto object_error;
                         }
                     }
                 }
 
-                free(keys);
+                jsonp_free(keys);
             }
             else
             {
@@ -415,13 +416,15 @@ static int do_dump(const json_t *json, unsigned long flags, int depth,
 }
 
 
-char *json_dumps(const json_t *json, unsigned long flags)
+char *json_dumps(const json_t *json, size_t flags)
 {
     strbuffer_t strbuff;
     char *result;
 
-    if(!json_is_array(json) && !json_is_object(json))
-        return NULL;
+    if(!(flags & JSON_ENCODE_ANY)) {
+        if(!json_is_array(json) && !json_is_object(json))
+           return NULL;
+    }
 
     if(strbuffer_init(&strbuff))
         return NULL;
@@ -431,21 +434,23 @@ char *json_dumps(const json_t *json, unsigned long flags)
         return NULL;
     }
 
-    result = strdup(strbuffer_value(&strbuff));
+    result = jsonp_strdup(strbuffer_value(&strbuff));
     strbuffer_close(&strbuff);
 
     return result;
 }
 
-int json_dumpf(const json_t *json, FILE *output, unsigned long flags)
+int json_dumpf(const json_t *json, FILE *output, size_t flags)
 {
-    if(!json_is_array(json) && !json_is_object(json))
-        return -1;
+    if(!(flags & JSON_ENCODE_ANY)) {
+        if(!json_is_array(json) && !json_is_object(json))
+           return -1;
+    }
 
     return do_dump(json, flags, 0, dump_to_file, (void *)output);
 }
 
-int json_dump_file(const json_t *json, const char *path, unsigned long flags)
+int json_dump_file(const json_t *json, const char *path, size_t flags)
 {
     int result;
 

+ 62 - 0
compat/jansson/error.c

@@ -0,0 +1,62 @@
+#include <string.h>
+#include "jansson_private.h"
+
+void jsonp_error_init(json_error_t *error, const char *source)
+{
+    if(error)
+    {
+        error->text[0] = '\0';
+        error->line = -1;
+        error->column = -1;
+        error->position = 0;
+        if(source)
+            jsonp_error_set_source(error, source);
+        else
+            error->source[0] = '\0';
+    }
+}
+
+void jsonp_error_set_source(json_error_t *error, const char *source)
+{
+    size_t length;
+
+    if(!error || !source)
+        return;
+
+    length = strlen(source);
+    if(length < JSON_ERROR_SOURCE_LENGTH)
+        strcpy(error->source, source);
+    else {
+        size_t extra = length - JSON_ERROR_SOURCE_LENGTH + 4;
+        strcpy(error->source, "...");
+        strcpy(error->source + 3, source + extra);
+    }
+}
+
+void jsonp_error_set(json_error_t *error, int line, int column,
+                     size_t position, const char *msg, ...)
+{
+    va_list ap;
+
+    va_start(ap, msg);
+    jsonp_error_vset(error, line, column, position, msg, ap);
+    va_end(ap);
+}
+
+void jsonp_error_vset(json_error_t *error, int line, int column,
+                      size_t position, const char *msg, va_list ap)
+{
+    if(!error)
+        return;
+
+    if(error->text[0] != '\0') {
+        /* error already set */
+        return;
+    }
+
+    error->line = line;
+    error->column = column;
+    error->position = position;
+
+    vsnprintf(error->text, JSON_ERROR_TEXT_LENGTH, msg, ap);
+}

+ 30 - 33
compat/jansson/hashtable.c

@@ -1,31 +1,28 @@
 /*
- * Copyright (c) 2009, 2010 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2011 Petri Lehtinen <petri@digip.org>
  *
  * This library is free software; you can redistribute it and/or modify
  * it under the terms of the MIT license. See LICENSE for details.
  */
 
-#include <config.h>
-
 #include <stdlib.h>
+#include <jansson_config.h>   /* for JSON_INLINE */
+#include "jansson_private.h"  /* for container_of() */
 #include "hashtable.h"
 
 typedef struct hashtable_list list_t;
 typedef struct hashtable_pair pair_t;
 typedef struct hashtable_bucket bucket_t;
 
-#define container_of(ptr_, type_, member_)                      \
-    ((type_ *)((char *)ptr_ - (size_t)&((type_ *)0)->member_))
-
 #define list_to_pair(list_)  container_of(list_, pair_t, list)
 
-static inline void list_init(list_t *list)
+static JSON_INLINE void list_init(list_t *list)
 {
     list->next = list;
     list->prev = list;
 }
 
-static inline void list_insert(list_t *list, list_t *node)
+static JSON_INLINE void list_insert(list_t *list, list_t *node)
 {
     node->next = list;
     node->prev = list->prev;
@@ -33,13 +30,13 @@ static inline void list_insert(list_t *list, list_t *node)
     list->prev = node;
 }
 
-static inline void list_remove(list_t *list)
+static JSON_INLINE void list_remove(list_t *list)
 {
     list->prev->next = list->next;
     list->next->prev = list->prev;
 }
 
-static inline int bucket_is_empty(hashtable_t *hashtable, bucket_t *bucket)
+static JSON_INLINE int bucket_is_empty(hashtable_t *hashtable, bucket_t *bucket)
 {
     return bucket->first == &hashtable->list && bucket->first == bucket->last;
 }
@@ -59,22 +56,22 @@ static void insert_to_bucket(hashtable_t *hashtable, bucket_t *bucket,
     }
 }
 
-static unsigned int primes[] = {
+static size_t primes[] = {
     5, 13, 23, 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593,
     49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469,
     12582917, 25165843, 50331653, 100663319, 201326611, 402653189,
     805306457, 1610612741
 };
-static const unsigned int num_primes = sizeof(primes) / sizeof(unsigned int);
+static const size_t num_primes = sizeof(primes) / sizeof(size_t);
 
-static inline unsigned int num_buckets(hashtable_t *hashtable)
+static JSON_INLINE size_t num_buckets(hashtable_t *hashtable)
 {
     return primes[hashtable->num_buckets];
 }
 
 
 static pair_t *hashtable_find_pair(hashtable_t *hashtable, bucket_t *bucket,
-                                   const void *key, unsigned int hash)
+                                   const void *key, size_t hash)
 {
     list_t *list;
     pair_t *pair;
@@ -100,11 +97,11 @@ static pair_t *hashtable_find_pair(hashtable_t *hashtable, bucket_t *bucket,
 
 /* returns 0 on success, -1 if key was not found */
 static int hashtable_do_del(hashtable_t *hashtable,
-                            const void *key, unsigned int hash)
+                            const void *key, size_t hash)
 {
     pair_t *pair;
     bucket_t *bucket;
-    unsigned int index;
+    size_t index;
 
     index = hash % num_buckets(hashtable);
     bucket = &hashtable->buckets[index];
@@ -129,7 +126,7 @@ static int hashtable_do_del(hashtable_t *hashtable,
     if(hashtable->free_value)
         hashtable->free_value(pair->value);
 
-    free(pair);
+    jsonp_free(pair);
     hashtable->size--;
 
     return 0;
@@ -148,7 +145,7 @@ static void hashtable_do_clear(hashtable_t *hashtable)
             hashtable->free_key(pair->key);
         if(hashtable->free_value)
             hashtable->free_value(pair->value);
-        free(pair);
+        jsonp_free(pair);
     }
 }
 
@@ -156,14 +153,14 @@ static int hashtable_do_rehash(hashtable_t *hashtable)
 {
     list_t *list, *next;
     pair_t *pair;
-    unsigned int i, index, new_size;
+    size_t i, index, new_size;
 
-    free(hashtable->buckets);
+    jsonp_free(hashtable->buckets);
 
     hashtable->num_buckets++;
     new_size = num_buckets(hashtable);
 
-    hashtable->buckets = malloc(new_size * sizeof(bucket_t));
+    hashtable->buckets = jsonp_malloc(new_size * sizeof(bucket_t));
     if(!hashtable->buckets)
         return -1;
 
@@ -190,13 +187,13 @@ static int hashtable_do_rehash(hashtable_t *hashtable)
 hashtable_t *hashtable_create(key_hash_fn hash_key, key_cmp_fn cmp_keys,
                               free_fn free_key, free_fn free_value)
 {
-    hashtable_t *hashtable = malloc(sizeof(hashtable_t));
+    hashtable_t *hashtable = jsonp_malloc(sizeof(hashtable_t));
     if(!hashtable)
         return NULL;
 
     if(hashtable_init(hashtable, hash_key, cmp_keys, free_key, free_value))
     {
-        free(hashtable);
+        jsonp_free(hashtable);
         return NULL;
     }
 
@@ -206,18 +203,18 @@ hashtable_t *hashtable_create(key_hash_fn hash_key, key_cmp_fn cmp_keys,
 void hashtable_destroy(hashtable_t *hashtable)
 {
     hashtable_close(hashtable);
-    free(hashtable);
+    jsonp_free(hashtable);
 }
 
 int hashtable_init(hashtable_t *hashtable,
                    key_hash_fn hash_key, key_cmp_fn cmp_keys,
                    free_fn free_key, free_fn free_value)
 {
-    unsigned int i;
+    size_t i;
 
     hashtable->size = 0;
     hashtable->num_buckets = 0;  /* index to primes[] */
-    hashtable->buckets = malloc(num_buckets(hashtable) * sizeof(bucket_t));
+    hashtable->buckets = jsonp_malloc(num_buckets(hashtable) * sizeof(bucket_t));
     if(!hashtable->buckets)
         return -1;
 
@@ -240,14 +237,14 @@ int hashtable_init(hashtable_t *hashtable,
 void hashtable_close(hashtable_t *hashtable)
 {
     hashtable_do_clear(hashtable);
-    free(hashtable->buckets);
+    jsonp_free(hashtable->buckets);
 }
 
 int hashtable_set(hashtable_t *hashtable, void *key, void *value)
 {
     pair_t *pair;
     bucket_t *bucket;
-    unsigned int hash, index;
+    size_t hash, index;
 
     /* rehash if the load ratio exceeds 1 */
     if(hashtable->size >= num_buckets(hashtable))
@@ -269,7 +266,7 @@ int hashtable_set(hashtable_t *hashtable, void *key, void *value)
     }
     else
     {
-        pair = malloc(sizeof(pair_t));
+        pair = jsonp_malloc(sizeof(pair_t));
         if(!pair)
             return -1;
 
@@ -288,7 +285,7 @@ int hashtable_set(hashtable_t *hashtable, void *key, void *value)
 void *hashtable_get(hashtable_t *hashtable, const void *key)
 {
     pair_t *pair;
-    unsigned int hash;
+    size_t hash;
     bucket_t *bucket;
 
     hash = hashtable->hash_key(key);
@@ -303,13 +300,13 @@ void *hashtable_get(hashtable_t *hashtable, const void *key)
 
 int hashtable_del(hashtable_t *hashtable, const void *key)
 {
-    unsigned int hash = hashtable->hash_key(key);
+    size_t hash = hashtable->hash_key(key);
     return hashtable_do_del(hashtable, key, hash);
 }
 
 void hashtable_clear(hashtable_t *hashtable)
 {
-    unsigned int i;
+    size_t i;
 
     hashtable_do_clear(hashtable);
 
@@ -331,7 +328,7 @@ void *hashtable_iter(hashtable_t *hashtable)
 void *hashtable_iter_at(hashtable_t *hashtable, const void *key)
 {
     pair_t *pair;
-    unsigned int hash;
+    size_t hash;
     bucket_t *bucket;
 
     hash = hashtable->hash_key(key);

+ 5 - 5
compat/jansson/hashtable.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2011 Petri Lehtinen <petri@digip.org>
  *
  * This library is free software; you can redistribute it and/or modify
  * it under the terms of the MIT license. See LICENSE for details.
@@ -8,7 +8,7 @@
 #ifndef HASHTABLE_H
 #define HASHTABLE_H
 
-typedef unsigned int (*key_hash_fn)(const void *key);
+typedef size_t (*key_hash_fn)(const void *key);
 typedef int (*key_cmp_fn)(const void *key1, const void *key2);
 typedef void (*free_fn)(void *key);
 
@@ -20,7 +20,7 @@ struct hashtable_list {
 struct hashtable_pair {
     void *key;
     void *value;
-    unsigned int hash;
+    size_t hash;
     struct hashtable_list list;
 };
 
@@ -30,9 +30,9 @@ struct hashtable_bucket {
 };
 
 typedef struct hashtable {
-    unsigned int size;
+    size_t size;
     struct hashtable_bucket *buckets;
-    unsigned int num_buckets;  /* index to primes[] */
+    size_t num_buckets;  /* index to primes[] */
     struct hashtable_list list;
 
     key_hash_fn hash_key;

+ 99 - 37
compat/jansson/jansson.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2011 Petri Lehtinen <petri@digip.org>
  *
  * Jansson is free software; you can redistribute it and/or modify
  * it under the terms of the MIT license. See LICENSE for details.
@@ -9,14 +9,31 @@
 #define JANSSON_H
 
 #include <stdio.h>
+#include <stdlib.h>  /* for size_t */
+#include <stdarg.h>
 
-#ifndef __cplusplus
-#define JSON_INLINE inline
-#else
-#define JSON_INLINE inline
+#include <jansson_config.h>
+
+#ifdef __cplusplus
 extern "C" {
 #endif
 
+/* version */
+
+#define JANSSON_MAJOR_VERSION  2
+#define JANSSON_MINOR_VERSION  1
+#define JANSSON_MICRO_VERSION  0
+
+/* Micro version is omitted if it's 0 */
+#define JANSSON_VERSION  "2.1"
+
+/* Version as a 3-byte hex number, e.g. 0x010201 == 1.2.1. Use this
+   for numeric comparisons, e.g. #if JANSSON_VERSION_HEX >= ... */
+#define JANSSON_VERSION_HEX  ((JANSSON_MAJOR_VERSION << 16) |   \
+                              (JANSSON_MINOR_VERSION << 8)  |   \
+                              (JANSSON_MICRO_VERSION << 0))
+
+
 /* types */
 
 typedef enum {
@@ -32,9 +49,17 @@ typedef enum {
 
 typedef struct {
     json_type type;
-    unsigned long refcount;
+    size_t refcount;
 } json_t;
 
+#if JSON_INTEGER_IS_LONG_LONG
+#define JSON_INTEGER_FORMAT "lld"
+typedef long long json_int_t;
+#else
+#define JSON_INTEGER_FORMAT "ld"
+typedef long json_int_t;
+#endif /* JSON_INTEGER_IS_LONG_LONG */
+
 #define json_typeof(json)      ((json)->type)
 #define json_is_object(json)   (json && json_typeof(json) == JSON_OBJECT)
 #define json_is_array(json)    (json && json_typeof(json) == JSON_ARRAY)
@@ -53,7 +78,7 @@ json_t *json_object(void);
 json_t *json_array(void);
 json_t *json_string(const char *value);
 json_t *json_string_nocheck(const char *value);
-json_t *json_integer(int value);
+json_t *json_integer(json_int_t value);
 json_t *json_real(double value);
 json_t *json_true(void);
 json_t *json_false(void);
@@ -62,7 +87,7 @@ json_t *json_null(void);
 static JSON_INLINE
 json_t *json_incref(json_t *json)
 {
-    if(json && json->refcount != (unsigned int)-1)
+    if(json && json->refcount != (size_t)-1)
         ++json->refcount;
     return json;
 }
@@ -73,14 +98,28 @@ void json_delete(json_t *json);
 static JSON_INLINE
 void json_decref(json_t *json)
 {
-    if(json && json->refcount != (unsigned int)-1 && --json->refcount == 0)
+    if(json && json->refcount != (size_t)-1 && --json->refcount == 0)
         json_delete(json);
 }
 
 
+/* error reporting */
+
+#define JSON_ERROR_TEXT_LENGTH    160
+#define JSON_ERROR_SOURCE_LENGTH   80
+
+typedef struct {
+    int line;
+    int column;
+    int position;
+    char source[JSON_ERROR_SOURCE_LENGTH];
+    char text[JSON_ERROR_TEXT_LENGTH];
+} json_error_t;
+
+
 /* getters, setters, manipulation */
 
-unsigned int json_object_size(const json_t *object);
+size_t json_object_size(const json_t *object);
 json_t *json_object_get(const json_t *object, const char *key);
 int json_object_set_new(json_t *object, const char *key, json_t *value);
 int json_object_set_new_nocheck(json_t *object, const char *key, json_t *value);
@@ -106,23 +145,23 @@ int json_object_set_nocheck(json_t *object, const char *key, json_t *value)
     return json_object_set_new_nocheck(object, key, json_incref(value));
 }
 
-static inline
+static JSON_INLINE
 int json_object_iter_set(json_t *object, void *iter, json_t *value)
 {
     return json_object_iter_set_new(object, iter, json_incref(value));
 }
 
-unsigned int json_array_size(const json_t *array);
-json_t *json_array_get(const json_t *array, unsigned int index);
-int json_array_set_new(json_t *array, unsigned int index, json_t *value);
+size_t json_array_size(const json_t *array);
+json_t *json_array_get(const json_t *array, size_t index);
+int json_array_set_new(json_t *array, size_t index, json_t *value);
 int json_array_append_new(json_t *array, json_t *value);
-int json_array_insert_new(json_t *array, unsigned int index, json_t *value);
-int json_array_remove(json_t *array, unsigned int index);
+int json_array_insert_new(json_t *array, size_t index, json_t *value);
+int json_array_remove(json_t *array, size_t index);
 int json_array_clear(json_t *array);
 int json_array_extend(json_t *array, json_t *other);
 
 static JSON_INLINE
-int json_array_set(json_t *array, unsigned int index, json_t *value)
+int json_array_set(json_t *array, size_t index, json_t *value)
 {
     return json_array_set_new(array, index, json_incref(value));
 }
@@ -134,22 +173,36 @@ int json_array_append(json_t *array, json_t *value)
 }
 
 static JSON_INLINE
-int json_array_insert(json_t *array, unsigned int index, json_t *value)
+int json_array_insert(json_t *array, size_t index, json_t *value)
 {
     return json_array_insert_new(array, index, json_incref(value));
 }
 
 const char *json_string_value(const json_t *string);
-int json_integer_value(const json_t *integer);
+json_int_t json_integer_value(const json_t *integer);
 double json_real_value(const json_t *real);
 double json_number_value(const json_t *json);
 
 int json_string_set(json_t *string, const char *value);
 int json_string_set_nocheck(json_t *string, const char *value);
-int json_integer_set(json_t *integer, int value);
+int json_integer_set(json_t *integer, json_int_t value);
 int json_real_set(json_t *real, double value);
 
 
+/* pack, unpack */
+
+json_t *json_pack(const char *fmt, ...);
+json_t *json_pack_ex(json_error_t *error, size_t flags, const char *fmt, ...);
+json_t *json_vpack_ex(json_error_t *error, size_t flags, const char *fmt, va_list ap);
+
+#define JSON_VALIDATE_ONLY  0x1
+#define JSON_STRICT         0x2
+
+int json_unpack(json_t *root, const char *fmt, ...);
+int json_unpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt, ...);
+int json_vunpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt, va_list ap);
+
+
 /* equality */
 
 int json_equal(json_t *value1, json_t *value2);
@@ -161,28 +214,37 @@ json_t *json_copy(json_t *value);
 json_t *json_deep_copy(json_t *value);
 
 
-/* loading, printing */
+/* decoding */
 
-#define JSON_ERROR_TEXT_LENGTH  160
+#define JSON_REJECT_DUPLICATES 0x1
+#define JSON_DISABLE_EOF_CHECK 0x2
+
+json_t *json_loads(const char *input, size_t flags, json_error_t *error);
+json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t *error);
+json_t *json_loadf(FILE *input, size_t flags, json_error_t *error);
+json_t *json_load_file(const char *path, size_t flags, json_error_t *error);
+
+
+/* encoding */
+
+#define JSON_INDENT(n)      (n & 0x1F)
+#define JSON_COMPACT        0x20
+#define JSON_ENSURE_ASCII   0x40
+#define JSON_SORT_KEYS      0x80
+#define JSON_PRESERVE_ORDER 0x100
+#define JSON_ENCODE_ANY     0x200
+
+char *json_dumps(const json_t *json, size_t flags);
+int json_dumpf(const json_t *json, FILE *output, size_t flags);
+int json_dump_file(const json_t *json, const char *path, size_t flags);
 
-typedef struct {
-    char text[JSON_ERROR_TEXT_LENGTH];
-    int line;
-} json_error_t;
 
-json_t *json_loads(const char *input, json_error_t *error);
-json_t *json_loadf(FILE *input, json_error_t *error);
-json_t *json_load_file(const char *path, json_error_t *error);
+/* custom memory allocation */
 
-#define JSON_INDENT(n)      (n & 0xFF)
-#define JSON_COMPACT        0x100
-#define JSON_ENSURE_ASCII   0x200
-#define JSON_SORT_KEYS      0x400
-#define JSON_PRESERVE_ORDER 0x800
+typedef void *(*json_malloc_t)(size_t);
+typedef void (*json_free_t)(void *);
 
-char *json_dumps(const json_t *json, unsigned long flags);
-int json_dumpf(const json_t *json, FILE *output, unsigned long flags);
-int json_dump_file(const json_t *json, const char *path, unsigned long flags);
+void json_set_alloc_funcs(json_malloc_t malloc_fn, json_free_t free_fn);
 
 #ifdef __cplusplus
 }

+ 34 - 0
compat/jansson/jansson_config.h

@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010-2011 Petri Lehtinen <petri@digip.org>
+ *
+ * Jansson is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ *
+ *
+ * This file specifies a part of the site-specific configuration for
+ * Jansson, namely those things that affect the public API in
+ * jansson.h.
+ *
+ * The configure script copies this file to jansson_config.h and
+ * replaces @var@ substitutions by values that fit your system. If you
+ * cannot run the configure script, you can do the value substitution
+ * by hand.
+ */
+
+#ifndef JANSSON_CONFIG_H
+#define JANSSON_CONFIG_H
+
+/* If your compiler supports the inline keyword in C, JSON_INLINE is
+   defined to `inline', otherwise empty. In C++, the inline is always
+   supported. */
+#ifdef __cplusplus
+#define JSON_INLINE inline
+#else
+#define JSON_INLINE inline
+#endif
+
+/* If your compiler supports the `long long` type,
+   JSON_INTEGER_IS_LONG_LONG is defined to 1, otherwise to 0. */
+#define JSON_INTEGER_IS_LONG_LONG 1
+
+#endif

+ 34 - 0
compat/jansson/jansson_config.h.in

@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010-2011 Petri Lehtinen <petri@digip.org>
+ *
+ * Jansson is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+ *
+ *
+ * This file specifies a part of the site-specific configuration for
+ * Jansson, namely those things that affect the public API in
+ * jansson.h.
+ *
+ * The configure script copies this file to jansson_config.h and
+ * replaces @var@ substitutions by values that fit your system. If you
+ * cannot run the configure script, you can do the value substitution
+ * by hand.
+ */
+
+#ifndef JANSSON_CONFIG_H
+#define JANSSON_CONFIG_H
+
+/* If your compiler supports the inline keyword in C, JSON_INLINE is
+   defined to `inline', otherwise empty. In C++, the inline is always
+   supported. */
+#ifdef __cplusplus
+#define JSON_INLINE inline
+#else
+#define JSON_INLINE @json_inline@
+#endif
+
+/* If your compiler supports the `long long` type,
+   JSON_INTEGER_IS_LONG_LONG is defined to 1, otherwise to 0. */
+#define JSON_INTEGER_IS_LONG_LONG @json_have_long_long@
+
+#endif

+ 39 - 8
compat/jansson/jansson_private.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2011 Petri Lehtinen <petri@digip.org>
  *
  * Jansson is free software; you can redistribute it and/or modify
  * it under the terms of the MIT license. See LICENSE for details.
@@ -8,23 +8,39 @@
 #ifndef JANSSON_PRIVATE_H
 #define JANSSON_PRIVATE_H
 
+#include <stddef.h>
 #include "jansson.h"
 #include "hashtable.h"
 
 #define container_of(ptr_, type_, member_)  \
-    ((type_ *)((char *)ptr_ - (size_t)&((type_ *)0)->member_))
+    ((type_ *)((char *)ptr_ - offsetof(type_, member_)))
+
+/* On some platforms, max() may already be defined */
+#ifndef max
+#define max(a, b)  ((a) > (b) ? (a) : (b))
+#endif
+
+/* va_copy is a C99 feature. In C89 implementations, it's sometimes
+   available as __va_copy. If not, memcpy() should do the trick. */
+#ifndef va_copy
+#ifdef __va_copy
+#define va_copy __va_copy
+#else
+#define va_copy(a, b)  memcpy(&(a), &(b), sizeof(va_list))
+#endif
+#endif
 
 typedef struct {
     json_t json;
     hashtable_t hashtable;
-    unsigned long serial;
+    size_t serial;
     int visited;
 } json_object_t;
 
 typedef struct {
     json_t json;
-    unsigned int size;
-    unsigned int entries;
+    size_t size;
+    size_t entries;
     json_t **table;
     int visited;
 } json_array_t;
@@ -41,7 +57,7 @@ typedef struct {
 
 typedef struct {
     json_t json;
-    int value;
+    json_int_t value;
 } json_integer_t;
 
 #define json_to_object(json_)  container_of(json_, json_object_t, json)
@@ -50,11 +66,26 @@ typedef struct {
 #define json_to_real(json_)   container_of(json_, json_real_t, json)
 #define json_to_integer(json_) container_of(json_, json_integer_t, json)
 
+size_t jsonp_hash_str(const void *ptr);
+int jsonp_str_equal(const void *ptr1, const void *ptr2);
+
 typedef struct {
-    unsigned long serial;
-    char key[];
+    size_t serial;
+    char key[1];
 } object_key_t;
 
 const object_key_t *jsonp_object_iter_fullkey(void *iter);
 
+void jsonp_error_init(json_error_t *error, const char *source);
+void jsonp_error_set_source(json_error_t *error, const char *source);
+void jsonp_error_set(json_error_t *error, int line, int column,
+                     size_t position, const char *msg, ...);
+void jsonp_error_vset(json_error_t *error, int line, int column,
+                      size_t position, const char *msg, va_list ap);
+
+/* Wrappers for custom memory functions */
+void* jsonp_malloc(size_t size);
+void jsonp_free(void *ptr);
+char *jsonp_strdup(const char *str);
+
 #endif

+ 243 - 162
compat/jansson/load.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2011 Petri Lehtinen <petri@digip.org>
  *
  * Jansson is free software; you can redistribute it and/or modify
  * it under the terms of the MIT license. See LICENSE for details.
@@ -12,7 +12,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <stdarg.h>
 #include <assert.h>
 
 #include <jansson.h>
@@ -20,6 +19,10 @@
 #include "strbuffer.h"
 #include "utf.h"
 
+#define STREAM_STATE_OK        0
+#define STREAM_STATE_EOF      -1
+#define STREAM_STATE_ERROR    -2
+
 #define TOKEN_INVALID         -1
 #define TOKEN_EOF              0
 #define TOKEN_STRING         256
@@ -29,113 +32,125 @@
 #define TOKEN_FALSE          260
 #define TOKEN_NULL           261
 
-/* read one byte from stream, return EOF on end of file */
+/* Read one byte from stream, convert to unsigned char, then int, and
+   return. return EOF on end of file. This corresponds to the
+   behaviour of fgetc(). */
 typedef int (*get_func)(void *data);
 
-/* return non-zero if end of file has been reached */
-typedef int (*eof_func)(void *data);
-
 typedef struct {
     get_func get;
-    eof_func eof;
     void *data;
-    int stream_pos;
     char buffer[5];
     int buffer_pos;
+    int state;
+    int line;
+    int column, last_column;
+    size_t position;
 } stream_t;
 
-
 typedef struct {
     stream_t stream;
     strbuffer_t saved_text;
     int token;
-    int line, column;
     union {
         char *string;
-        int integer;
+        json_int_t integer;
         double real;
     } value;
 } lex_t;
 
+#define stream_to_lex(stream) container_of(stream, lex_t, stream)
 
-/*** error reporting ***/
 
-static void error_init(json_error_t *error)
-{
-    if(error)
-    {
-        error->text[0] = '\0';
-        error->line = -1;
-    }
-}
+/*** error reporting ***/
 
 static void error_set(json_error_t *error, const lex_t *lex,
                       const char *msg, ...)
 {
     va_list ap;
-    char text[JSON_ERROR_TEXT_LENGTH];
+    char msg_text[JSON_ERROR_TEXT_LENGTH];
+
+    int line = -1, col = -1;
+    size_t pos = 0;
+    const char *result = msg_text;
 
-    if(!error || error->text[0] != '\0') {
-        /* error already set */
+    if(!error)
         return;
-    }
 
     va_start(ap, msg);
-    vsnprintf(text, JSON_ERROR_TEXT_LENGTH, msg, ap);
+    vsnprintf(msg_text, JSON_ERROR_TEXT_LENGTH, msg, ap);
     va_end(ap);
 
     if(lex)
     {
         const char *saved_text = strbuffer_value(&lex->saved_text);
-        error->line = lex->line;
+        char msg_with_context[JSON_ERROR_TEXT_LENGTH];
+
+        line = lex->stream.line;
+        col = lex->stream.column;
+        pos = lex->stream.position;
+
         if(saved_text && saved_text[0])
         {
             if(lex->saved_text.length <= 20) {
-                snprintf(error->text, JSON_ERROR_TEXT_LENGTH,
-                         "%s near '%s'", text, saved_text);
+                snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH,
+                         "%s near '%s'", msg_text, saved_text);
+                result = msg_with_context;
             }
-            else
-                snprintf(error->text, JSON_ERROR_TEXT_LENGTH, "%s", text);
         }
         else
         {
-            snprintf(error->text, JSON_ERROR_TEXT_LENGTH,
-                     "%s near end of file", text);
+            if(lex->stream.state == STREAM_STATE_ERROR) {
+                /* No context for UTF-8 decoding errors */
+                result = msg_text;
+            }
+            else {
+                snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH,
+                         "%s near end of file", msg_text);
+                result = msg_with_context;
+            }
         }
     }
-    else
-    {
-        error->line = -1;
-        snprintf(error->text, JSON_ERROR_TEXT_LENGTH, "%s", text);
-    }
+
+    jsonp_error_set(error, line, col, pos, "%s", result);
 }
 
 
 /*** lexical analyzer ***/
 
 static void
-stream_init(stream_t *stream, get_func get, eof_func eof, void *data)
+stream_init(stream_t *stream, get_func get, void *data)
 {
     stream->get = get;
-    stream->eof = eof;
     stream->data = data;
-    stream->stream_pos = 0;
     stream->buffer[0] = '\0';
     stream->buffer_pos = 0;
+
+    stream->state = STREAM_STATE_OK;
+    stream->line = 1;
+    stream->column = 0;
+    stream->position = 0;
 }
 
-static char stream_get(stream_t *stream, json_error_t *error)
+static int stream_get(stream_t *stream, json_error_t *error)
 {
-    char c;
+    int c;
+
+    if(stream->state != STREAM_STATE_OK)
+        return stream->state;
 
     if(!stream->buffer[stream->buffer_pos])
     {
-        stream->buffer[0] = stream->get(stream->data);
-        stream->buffer_pos = 0;
+        c = stream->get(stream->data);
+        if(c == EOF) {
+            stream->state = STREAM_STATE_EOF;
+            return STREAM_STATE_EOF;
+        }
 
-        c = stream->buffer[0];
+        stream->buffer[0] = c;
+        stream->buffer_pos = 0;
 
-        if((unsigned char)c >= 0x80 && c != (char)EOF)
+        if(0x80 <= c && c <= 0xFF)
         {
             /* multi-byte UTF-8 sequence */
             int i, count;
@@ -152,30 +167,47 @@ static char stream_get(stream_t *stream, json_error_t *error)
             if(!utf8_check_full(stream->buffer, count, NULL))
                 goto out;
 
-            stream->stream_pos += count;
             stream->buffer[count] = '\0';
         }
-        else {
+        else
             stream->buffer[1] = '\0';
-            stream->stream_pos++;
-        }
     }
 
-    return stream->buffer[stream->buffer_pos++];
+    c = stream->buffer[stream->buffer_pos++];
 
-out:
-    error_set(error, NULL, "unable to decode byte 0x%x at position %d",
-              (unsigned char)c, stream->stream_pos);
+    stream->position++;
+    if(c == '\n') {
+        stream->line++;
+        stream->last_column = stream->column;
+        stream->column = 0;
+    }
+    else if(utf8_check_first(c)) {
+        /* track the Unicode character column, so increment only if
+           this is the first character of a UTF-8 sequence */
+        stream->column++;
+    }
 
-    stream->buffer[0] = EOF;
-    stream->buffer[1] = '\0';
-    stream->buffer_pos = 1;
+    return c;
 
-    return EOF;
+out:
+    stream->state = STREAM_STATE_ERROR;
+    error_set(error, stream_to_lex(stream), "unable to decode byte 0x%x", c);
+    return STREAM_STATE_ERROR;
 }
 
-static void stream_unget(stream_t *stream, char c)
+static void stream_unget(stream_t *stream, int c)
 {
+    if(c == STREAM_STATE_EOF || c == STREAM_STATE_ERROR)
+        return;
+
+    stream->position--;
+    if(c == '\n') {
+        stream->line--;
+        stream->column = stream->last_column;
+    }
+    else if(utf8_check_first(c))
+        stream->column--;
+
     assert(stream->buffer_pos > 0);
     stream->buffer_pos--;
     assert(stream->buffer[stream->buffer_pos] == c);
@@ -187,29 +219,32 @@ static int lex_get(lex_t *lex, json_error_t *error)
     return stream_get(&lex->stream, error);
 }
 
-static int lex_eof(lex_t *lex)
-{
-    return lex->stream.eof(lex->stream.data);
-}
-
-static void lex_save(lex_t *lex, char c)
+static void lex_save(lex_t *lex, int c)
 {
     strbuffer_append_byte(&lex->saved_text, c);
 }
 
 static int lex_get_save(lex_t *lex, json_error_t *error)
 {
-    char c = stream_get(&lex->stream, error);
-    lex_save(lex, c);
+    int c = stream_get(&lex->stream, error);
+    if(c != STREAM_STATE_EOF && c != STREAM_STATE_ERROR)
+        lex_save(lex, c);
     return c;
 }
 
-static void lex_unget_unsave(lex_t *lex, char c)
+static void lex_unget(lex_t *lex, int c)
 {
-    char d;
     stream_unget(&lex->stream, c);
-    d = strbuffer_pop(&lex->saved_text);
-    assert(c == d);
+}
+
+static void lex_unget_unsave(lex_t *lex, int c)
+{
+    if(c != STREAM_STATE_EOF && c != STREAM_STATE_ERROR) {
+        char d;
+        stream_unget(&lex->stream, c);
+        d = strbuffer_pop(&lex->saved_text);
+        assert(c == d);
+    }
 }
 
 static void lex_save_cached(lex_t *lex)
@@ -218,6 +253,7 @@ static void lex_save_cached(lex_t *lex)
     {
         lex_save(lex, lex->stream.buffer[lex->stream.buffer_pos]);
         lex->stream.buffer_pos++;
+        lex->stream.position++;
     }
 }
 
@@ -247,7 +283,7 @@ static int32_t decode_unicode_escape(const char *str)
 
 static void lex_scan_string(lex_t *lex, json_error_t *error)
 {
-    char c;
+    int c;
     const char *p;
     char *t;
     int i;
@@ -258,14 +294,15 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
     c = lex_get_save(lex, error);
 
     while(c != '"') {
-        if(c == (char)EOF) {
-            lex_unget_unsave(lex, c);
-            if(lex_eof(lex))
-                error_set(error, lex, "premature end of input");
+        if(c == STREAM_STATE_ERROR)
+            goto out;
+
+        else if(c == STREAM_STATE_EOF) {
+            error_set(error, lex, "premature end of input");
             goto out;
         }
 
-        else if((unsigned char)c <= 0x1F) {
+        else if(0 <= c && c <= 0x1F) {
             /* control character */
             lex_unget_unsave(lex, c);
             if(c == '\n')
@@ -281,7 +318,6 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
                 c = lex_get_save(lex, error);
                 for(i = 0; i < 4; i++) {
                     if(!isxdigit(c)) {
-                        lex_unget_unsave(lex, c);
                         error_set(error, lex, "invalid escape");
                         goto out;
                     }
@@ -292,7 +328,6 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
                     c == 'f' || c == 'n' || c == 'r' || c == 't')
                 c = lex_get_save(lex, error);
             else {
-                lex_unget_unsave(lex, c);
                 error_set(error, lex, "invalid escape");
                 goto out;
             }
@@ -308,7 +343,7 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
          - two \uXXXX escapes (length 12) forming an UTF-16 surrogate pair
            are converted to 4 bytes
     */
-    lex->value.string = malloc(lex->saved_text.length + 1);
+    lex->value.string = jsonp_malloc(lex->saved_text.length + 1);
     if(!lex->value.string) {
         /* this is not very nice, since TOKEN_INVALID is returned */
         goto out;
@@ -398,10 +433,16 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
     return;
 
 out:
-    free(lex->value.string);
+    jsonp_free(lex->value.string);
 }
 
-static int lex_scan_number(lex_t *lex, char c, json_error_t *error)
+#if JSON_INTEGER_IS_LONG_LONG
+#define json_strtoint     strtoll
+#else
+#define json_strtoint     strtol
+#endif
+
+static int lex_scan_number(lex_t *lex, int c, json_error_t *error)
 {
     const char *saved_text;
     char *end;
@@ -425,37 +466,40 @@ static int lex_scan_number(lex_t *lex, char c, json_error_t *error)
             c = lex_get_save(lex, error);
     }
     else {
-      lex_unget_unsave(lex, c);
-      goto out;
+        lex_unget_unsave(lex, c);
+        goto out;
     }
 
     if(c != '.' && c != 'E' && c != 'e') {
-        long value;
+        json_int_t value;
 
         lex_unget_unsave(lex, c);
 
         saved_text = strbuffer_value(&lex->saved_text);
-        value = strtol(saved_text, &end, 10);
-        assert(end == saved_text + lex->saved_text.length);
 
-        if((value == LONG_MAX && errno == ERANGE) || value > INT_MAX) {
-            error_set(error, lex, "too big integer");
-            goto out;
-        }
-        else if((value == LONG_MIN && errno == ERANGE) || value < INT_MIN) {
-            error_set(error, lex, "too big negative integer");
+        errno = 0;
+        value = json_strtoint(saved_text, &end, 10);
+        if(errno == ERANGE) {
+            if(value < 0)
+                error_set(error, lex, "too big negative integer");
+            else
+                error_set(error, lex, "too big integer");
             goto out;
         }
 
+        assert(end == saved_text + lex->saved_text.length);
+
         lex->token = TOKEN_INTEGER;
-        lex->value.integer = (int)value;
+        lex->value.integer = value;
         return 0;
     }
 
     if(c == '.') {
         c = lex_get(lex, error);
-        if(!isdigit(c))
+        if(!isdigit(c)) {
+            lex_unget(lex, c);
             goto out;
+        }
         lex_save(lex, c);
 
         c = lex_get_save(lex, error);
@@ -481,6 +525,7 @@ static int lex_scan_number(lex_t *lex, char c, json_error_t *error)
     lex_unget_unsave(lex, c);
 
     saved_text = strbuffer_value(&lex->saved_text);
+    errno = 0;
     value = strtod(saved_text, &end);
     assert(end == saved_text + lex->saved_text.length);
 
@@ -499,29 +544,26 @@ out:
 
 static int lex_scan(lex_t *lex, json_error_t *error)
 {
-    char c;
+    int c;
 
     strbuffer_clear(&lex->saved_text);
 
     if(lex->token == TOKEN_STRING) {
-        free(lex->value.string);
+        jsonp_free(lex->value.string);
         lex->value.string = NULL;
     }
 
     c = lex_get(lex, error);
     while(c == ' ' || c == '\t' || c == '\n' || c == '\r')
-    {
-        if(c == '\n')
-            lex->line++;
-
         c = lex_get(lex, error);
+
+    if(c == STREAM_STATE_EOF) {
+        lex->token = TOKEN_EOF;
+        goto out;
     }
 
-    if(c == (char)EOF) {
-        if(lex_eof(lex))
-            lex->token = TOKEN_EOF;
-        else
-            lex->token = TOKEN_INVALID;
+    if(c == STREAM_STATE_ERROR) {
+        lex->token = TOKEN_INVALID;
         goto out;
     }
 
@@ -581,31 +623,29 @@ static char *lex_steal_string(lex_t *lex)
     return result;
 }
 
-static int lex_init(lex_t *lex, get_func get, eof_func eof, void *data)
+static int lex_init(lex_t *lex, get_func get, void *data)
 {
-    stream_init(&lex->stream, get, eof, data);
+    stream_init(&lex->stream, get, data);
     if(strbuffer_init(&lex->saved_text))
         return -1;
 
     lex->token = TOKEN_INVALID;
-    lex->line = 1;
-
     return 0;
 }
 
 static void lex_close(lex_t *lex)
 {
     if(lex->token == TOKEN_STRING)
-        free(lex->value.string);
+        jsonp_free(lex->value.string);
     strbuffer_close(&lex->saved_text);
 }
 
 
 /*** parser ***/
 
-static json_t *parse_value(lex_t *lex, json_error_t *error);
+static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error);
 
-static json_t *parse_object(lex_t *lex, json_error_t *error)
+static json_t *parse_object(lex_t *lex, size_t flags, json_error_t *error)
 {
     json_t *object = json_object();
     if(!object)
@@ -628,28 +668,36 @@ static json_t *parse_object(lex_t *lex, json_error_t *error)
         if(!key)
             return NULL;
 
+        if(flags & JSON_REJECT_DUPLICATES) {
+            if(json_object_get(object, key)) {
+                jsonp_free(key);
+                error_set(error, lex, "duplicate object key");
+                goto error;
+            }
+        }
+
         lex_scan(lex, error);
         if(lex->token != ':') {
-            free(key);
+            jsonp_free(key);
             error_set(error, lex, "':' expected");
             goto error;
         }
 
         lex_scan(lex, error);
-        value = parse_value(lex, error);
+        value = parse_value(lex, flags, error);
         if(!value) {
-            free(key);
+            jsonp_free(key);
             goto error;
         }
 
         if(json_object_set_nocheck(object, key, value)) {
-            free(key);
+            jsonp_free(key);
             json_decref(value);
             goto error;
         }
 
         json_decref(value);
-        free(key);
+        jsonp_free(key);
 
         lex_scan(lex, error);
         if(lex->token != ',')
@@ -670,7 +718,7 @@ error:
     return NULL;
 }
 
-static json_t *parse_array(lex_t *lex, json_error_t *error)
+static json_t *parse_array(lex_t *lex, size_t flags, json_error_t *error)
 {
     json_t *array = json_array();
     if(!array)
@@ -681,7 +729,7 @@ static json_t *parse_array(lex_t *lex, json_error_t *error)
         return array;
 
     while(lex->token) {
-        json_t *elem = parse_value(lex, error);
+        json_t *elem = parse_value(lex, flags, error);
         if(!elem)
             goto error;
 
@@ -710,7 +758,7 @@ error:
     return NULL;
 }
 
-static json_t *parse_value(lex_t *lex, json_error_t *error)
+static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error)
 {
     json_t *json;
 
@@ -743,11 +791,11 @@ static json_t *parse_value(lex_t *lex, json_error_t *error)
             break;
 
         case '{':
-            json = parse_object(lex, error);
+            json = parse_object(lex, flags, error);
             break;
 
         case '[':
-            json = parse_array(lex, error);
+            json = parse_array(lex, flags, error);
             break;
 
         case TOKEN_INVALID:
@@ -765,9 +813,9 @@ static json_t *parse_value(lex_t *lex, json_error_t *error)
     return json;
 }
 
-static json_t *parse_json(lex_t *lex, json_error_t *error)
+static json_t *parse_json(lex_t *lex, size_t flags, json_error_t *error)
 {
-    error_init(error);
+    json_t *result;
 
     lex_scan(lex, error);
     if(lex->token != '[' && lex->token != '{') {
@@ -775,7 +823,20 @@ static json_t *parse_json(lex_t *lex, json_error_t *error)
         return NULL;
     }
 
-    return parse_value(lex, error);
+    result = parse_value(lex, flags, error);
+    if(!result)
+        return NULL;
+
+    if(!(flags & JSON_DISABLE_EOF_CHECK)) {
+        lex_scan(lex, error);
+        if(lex->token != TOKEN_EOF) {
+            error_set(error, lex, "end of file expected");
+            json_decref(result);
+            result = NULL;
+        }
+    }
+
+    return result;
 }
 
 typedef struct
@@ -794,75 +855,95 @@ static int string_get(void *data)
     else
     {
         stream->pos++;
-        return c;
+        return (unsigned char)c;
     }
 }
 
-static int string_eof(void *data)
+json_t *json_loads(const char *string, size_t flags, json_error_t *error)
 {
-    string_data_t *stream = (string_data_t *)data;
-    return (stream->data[stream->pos] == '\0');
+    lex_t lex;
+    json_t *result;
+    string_data_t stream_data;
+
+    stream_data.data = string;
+    stream_data.pos = 0;
+
+    if(lex_init(&lex, string_get, (void *)&stream_data))
+        return NULL;
+
+    jsonp_error_init(error, "<string>");
+    result = parse_json(&lex, flags, error);
+
+    lex_close(&lex);
+    return result;
+}
+
+typedef struct
+{
+    const char *data;
+    size_t len;
+    size_t pos;
+} buffer_data_t;
+
+static int buffer_get(void *data)
+{
+    char c;
+    buffer_data_t *stream = data;
+    if(stream->pos >= stream->len)
+      return EOF;
+
+    c = stream->data[stream->pos];
+    stream->pos++;
+    return (unsigned char)c;
 }
 
-json_t *json_loads(const char *string, json_error_t *error)
+json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t *error)
 {
     lex_t lex;
     json_t *result;
+    buffer_data_t stream_data;
 
-    string_data_t stream_data = {
-        .data = string,
-        .pos = 0
-    };
+    stream_data.data = buffer;
+    stream_data.pos = 0;
+    stream_data.len = buflen;
 
-    if(lex_init(&lex, string_get, string_eof, (void *)&stream_data))
+    if(lex_init(&lex, buffer_get, (void *)&stream_data))
         return NULL;
 
-    result = parse_json(&lex, error);
-    if(!result)
-        goto out;
-
-    lex_scan(&lex, error);
-    if(lex.token != TOKEN_EOF) {
-        error_set(error, &lex, "end of file expected");
-        json_decref(result);
-        result = NULL;
-    }
+    jsonp_error_init(error, "<buffer>");
+    result = parse_json(&lex, flags, error);
 
-out:
     lex_close(&lex);
     return result;
 }
 
-json_t *json_loadf(FILE *input, json_error_t *error)
+json_t *json_loadf(FILE *input, size_t flags, json_error_t *error)
 {
     lex_t lex;
+    const char *source;
     json_t *result;
 
-    if(lex_init(&lex, (get_func)fgetc, (eof_func)feof, input))
+    if(lex_init(&lex, (get_func)fgetc, input))
         return NULL;
 
-    result = parse_json(&lex, error);
-    if(!result)
-        goto out;
+    if(input == stdin)
+        source = "<stdin>";
+    else
+        source = "<stream>";
 
-    lex_scan(&lex, error);
-    if(lex.token != TOKEN_EOF) {
-        error_set(error, &lex, "end of file expected");
-        json_decref(result);
-        result = NULL;
-    }
+    jsonp_error_init(error, source);
+    result = parse_json(&lex, flags, error);
 
-out:
     lex_close(&lex);
     return result;
 }
 
-json_t *json_load_file(const char *path, json_error_t *error)
+json_t *json_load_file(const char *path, size_t flags, json_error_t *error)
 {
     json_t *result;
     FILE *fp;
 
-    error_init(error);
+    jsonp_error_init(error, path);
 
     fp = fopen(path, "r");
     if(!fp)
@@ -872,7 +953,7 @@ json_t *json_load_file(const char *path, json_error_t *error)
         return NULL;
     }
 
-    result = json_loadf(fp, error);
+    result = json_loadf(fp, flags, error);
 
     fclose(fp);
     return result;

+ 51 - 0
compat/jansson/memory.c

@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2009-2011 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2011 Basile Starynkevitch  <basile@starynkevitch.net>
+ *
+ * Jansson is free software; you can redistribute it and/or modify it
+ * under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <jansson.h>
+#include "jansson_private.h"
+
+/* memory function pointers */
+static json_malloc_t do_malloc = malloc;
+static json_free_t do_free = free;
+
+void *jsonp_malloc(size_t size)
+{
+    if(!size)
+        return NULL;
+
+    return (*do_malloc)(size);
+}
+
+void jsonp_free(void *ptr)
+{
+    if(!ptr)
+        return;
+
+    (*do_free)(ptr);
+}
+
+char *jsonp_strdup(const char *str)
+{
+    char *new_str;
+
+    new_str = jsonp_malloc(strlen(str) + 1);
+    if(!new_str)
+        return NULL;
+
+    strcpy(new_str, str);
+    return new_str;
+}
+
+void json_set_alloc_funcs(json_malloc_t malloc_fn, json_free_t free_fn)
+{
+    do_malloc = malloc_fn;
+    do_free = free_fn;
+}

+ 17 - 8
compat/jansson/strbuffer.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2011 Petri Lehtinen <petri@digip.org>
  *
  * Jansson is free software; you can redistribute it and/or modify
  * it under the terms of the MIT license. See LICENSE for details.
@@ -8,8 +8,8 @@
 #define _GNU_SOURCE
 #include <stdlib.h>
 #include <string.h>
+#include "jansson_private.h"
 #include "strbuffer.h"
-#include "util.h"
 
 #define STRBUFFER_MIN_SIZE  16
 #define STRBUFFER_FACTOR    2
@@ -19,7 +19,7 @@ int strbuffer_init(strbuffer_t *strbuff)
     strbuff->size = STRBUFFER_MIN_SIZE;
     strbuff->length = 0;
 
-    strbuff->value = malloc(strbuff->size);
+    strbuff->value = jsonp_malloc(strbuff->size);
     if(!strbuff->value)
         return -1;
 
@@ -30,7 +30,7 @@ int strbuffer_init(strbuffer_t *strbuff)
 
 void strbuffer_close(strbuffer_t *strbuff)
 {
-    free(strbuff->value);
+    jsonp_free(strbuff->value);
     strbuff->size = 0;
     strbuff->length = 0;
     strbuff->value = NULL;
@@ -68,12 +68,21 @@ int strbuffer_append_bytes(strbuffer_t *strbuff, const char *data, int size)
 {
     if(strbuff->length + size >= strbuff->size)
     {
-        strbuff->size = max(strbuff->size * STRBUFFER_FACTOR,
-                            strbuff->length + size + 1);
+        size_t new_size;
+        char *new_value;
 
-        strbuff->value = realloc(strbuff->value, strbuff->size);
-        if(!strbuff->value)
+        new_size = max(strbuff->size * STRBUFFER_FACTOR,
+                       strbuff->length + size + 1);
+
+        new_value = jsonp_malloc(new_size);
+        if(!new_value)
             return -1;
+
+        memcpy(new_value, strbuff->value, strbuff->length);
+
+        jsonp_free(strbuff->value);
+        strbuff->value = new_value;
+        strbuff->size = new_size;
     }
 
     memcpy(strbuff->value + strbuff->length, data, size);

+ 1 - 1
compat/jansson/strbuffer.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2011 Petri Lehtinen <petri@digip.org>
  *
  * Jansson is free software; you can redistribute it and/or modify
  * it under the terms of the MIT license. See LICENSE for details.

+ 1 - 1
compat/jansson/utf.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2011 Petri Lehtinen <petri@digip.org>
  *
  * Jansson is free software; you can redistribute it and/or modify
  * it under the terms of the MIT license. See LICENSE for details.

+ 13 - 2
compat/jansson/utf.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2011 Petri Lehtinen <petri@digip.org>
  *
  * Jansson is free software; you can redistribute it and/or modify
  * it under the terms of the MIT license. See LICENSE for details.
@@ -8,6 +8,7 @@
 #ifndef UTF_H
 #define UTF_H
 
+#ifdef HAVE_CONFIG_H
 #include <config.h>
 
 #ifdef HAVE_INTTYPES_H
@@ -15,7 +16,17 @@
 no need to include stdint.h separately. If inttypes.h doesn't define
 int32_t, it's defined in config.h. */
 #include <inttypes.h>
-#endif
+#endif /* HAVE_INTTYPES_H */
+
+#else /* !HAVE_CONFIG_H */
+#ifdef _WIN32
+typedef int int32_t;
+#else /* !_WIN32 */
+/* Assume a standard environment */
+#include <inttypes.h>
+#endif /* _WIN32 */
+
+#endif /* HAVE_CONFIG_H */
 
 int utf8_encode(int codepoint, char *buffer, int *size);
 

+ 85 - 78
compat/jansson/value.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2011 Petri Lehtinen <petri@digip.org>
  *
  * Jansson is free software; you can redistribute it and/or modify
  * it under the terms of the MIT license. See LICENSE for details.
@@ -7,8 +7,7 @@
 
 #define _GNU_SOURCE
 
-#include <config.h>
-
+#include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -16,10 +15,9 @@
 #include "hashtable.h"
 #include "jansson_private.h"
 #include "utf.h"
-#include "util.h"
 
 
-static inline void json_init(json_t *json, json_type type)
+static JSON_INLINE void json_init(json_t *json, json_type type)
 {
     json->type = type;
     json->refcount = 1;
@@ -28,20 +26,15 @@ static inline void json_init(json_t *json, json_type type)
 
 /*** object ***/
 
-/* This macro just returns a pointer that's a few bytes backwards from
-   string. This makes it possible to pass a pointer to object_key_t
-   when only the string inside it is used, without actually creating
-   an object_key_t instance. */
-#define string_to_key(string)  container_of(string, object_key_t, key)
-
-static unsigned int hash_key(const void *ptr)
+/* From http://www.cse.yorku.ca/~oz/hash.html */
+size_t jsonp_hash_str(const void *ptr)
 {
-    const char *str = ((const object_key_t *)ptr)->key;
+    const char *str = (const char *)ptr;
 
-    unsigned int hash = 5381;
-    unsigned int c;
+    size_t hash = 5381;
+    size_t c;
 
-    while((c = (unsigned int)*str))
+    while((c = (size_t)*str))
     {
         hash = ((hash << 5) + hash) + c;
         str++;
@@ -50,10 +43,26 @@ static unsigned int hash_key(const void *ptr)
     return hash;
 }
 
+int jsonp_str_equal(const void *ptr1, const void *ptr2)
+{
+    return strcmp((const char *)ptr1, (const char *)ptr2) == 0;
+}
+
+/* This macro just returns a pointer that's a few bytes backwards from
+   string. This makes it possible to pass a pointer to object_key_t
+   when only the string inside it is used, without actually creating
+   an object_key_t instance. */
+#define string_to_key(string)  container_of(string, object_key_t, key)
+
+static size_t hash_key(const void *ptr)
+{
+    return jsonp_hash_str(((const object_key_t *)ptr)->key);
+}
+
 static int key_equal(const void *ptr1, const void *ptr2)
 {
-    return strcmp(((const object_key_t *)ptr1)->key,
-                  ((const object_key_t *)ptr2)->key) == 0;
+    return jsonp_str_equal(((const object_key_t *)ptr1)->key,
+                           ((const object_key_t *)ptr2)->key);
 }
 
 static void value_decref(void *value)
@@ -63,15 +72,16 @@ static void value_decref(void *value)
 
 json_t *json_object(void)
 {
-    json_object_t *object = malloc(sizeof(json_object_t));
+    json_object_t *object = jsonp_malloc(sizeof(json_object_t));
     if(!object)
         return NULL;
     json_init(&object->json, JSON_OBJECT);
 
-    if(hashtable_init(&object->hashtable, hash_key, key_equal,
-                      free, value_decref))
+    if(hashtable_init(&object->hashtable,
+                      hash_key, key_equal,
+                      jsonp_free, value_decref))
     {
-        free(object);
+        jsonp_free(object);
         return NULL;
     }
 
@@ -84,15 +94,15 @@ json_t *json_object(void)
 static void json_delete_object(json_object_t *object)
 {
     hashtable_close(&object->hashtable);
-    free(object);
+    jsonp_free(object);
 }
 
-unsigned int json_object_size(const json_t *json)
+size_t json_object_size(const json_t *json)
 {
     json_object_t *object;
 
     if(!json_is_object(json))
-        return -1;
+        return 0;
 
     object = json_to_object(json);
     return object->hashtable.size;
@@ -124,9 +134,15 @@ int json_object_set_new_nocheck(json_t *json, const char *key, json_t *value)
     }
     object = json_to_object(json);
 
-    k = malloc(sizeof(object_key_t) + strlen(key) + 1);
+    /* offsetof(...) returns the size of object_key_t without the
+       last, flexible member. This way, the correct amount is
+       allocated. */
+    k = jsonp_malloc(offsetof(object_key_t, key) + strlen(key) + 1);
     if(!k)
+    {
+        json_decref(value);
         return -1;
+    }
 
     k->serial = object->serial++;
     strcpy(k->key, key);
@@ -350,7 +366,7 @@ static json_t *json_object_deep_copy(json_t *object)
 
 json_t *json_array(void)
 {
-    json_array_t *array = malloc(sizeof(json_array_t));
+    json_array_t *array = jsonp_malloc(sizeof(json_array_t));
     if(!array)
         return NULL;
     json_init(&array->json, JSON_ARRAY);
@@ -358,9 +374,9 @@ json_t *json_array(void)
     array->entries = 0;
     array->size = 8;
 
-    array->table = malloc(array->size * sizeof(json_t *));
+    array->table = jsonp_malloc(array->size * sizeof(json_t *));
     if(!array->table) {
-        free(array);
+        jsonp_free(array);
         return NULL;
     }
 
@@ -371,16 +387,16 @@ json_t *json_array(void)
 
 static void json_delete_array(json_array_t *array)
 {
-    unsigned int i;
+    size_t i;
 
     for(i = 0; i < array->entries; i++)
         json_decref(array->table[i]);
 
-    free(array->table);
-    free(array);
+    jsonp_free(array->table);
+    jsonp_free(array);
 }
 
-unsigned int json_array_size(const json_t *json)
+size_t json_array_size(const json_t *json)
 {
     if(!json_is_array(json))
         return 0;
@@ -388,7 +404,7 @@ unsigned int json_array_size(const json_t *json)
     return json_to_array(json)->entries;
 }
 
-json_t *json_array_get(const json_t *json, unsigned int index)
+json_t *json_array_get(const json_t *json, size_t index)
 {
     json_array_t *array;
     if(!json_is_array(json))
@@ -401,7 +417,7 @@ json_t *json_array_get(const json_t *json, unsigned int index)
     return array->table[index];
 }
 
-int json_array_set_new(json_t *json, unsigned int index, json_t *value)
+int json_array_set_new(json_t *json, size_t index, json_t *value)
 {
     json_array_t *array;
 
@@ -427,24 +443,24 @@ int json_array_set_new(json_t *json, unsigned int index, json_t *value)
     return 0;
 }
 
-static void array_move(json_array_t *array, unsigned int dest,
-                       unsigned int src, unsigned int count)
+static void array_move(json_array_t *array, size_t dest,
+                       size_t src, size_t count)
 {
     memmove(&array->table[dest], &array->table[src], count * sizeof(json_t *));
 }
 
-static void array_copy(json_t **dest, unsigned int dpos,
-                       json_t **src, unsigned int spos,
-                       unsigned int count)
+static void array_copy(json_t **dest, size_t dpos,
+                       json_t **src, size_t spos,
+                       size_t count)
 {
     memcpy(&dest[dpos], &src[spos], count * sizeof(json_t *));
 }
 
 static json_t **json_array_grow(json_array_t *array,
-                                unsigned int amount,
+                                size_t amount,
                                 int copy)
 {
-    unsigned int new_size;
+    size_t new_size;
     json_t **old_table, **new_table;
 
     if(array->entries + amount <= array->size)
@@ -453,7 +469,7 @@ static json_t **json_array_grow(json_array_t *array,
     old_table = array->table;
 
     new_size = max(array->size + amount, array->size * 2);
-    new_table = malloc(new_size * sizeof(json_t *));
+    new_table = jsonp_malloc(new_size * sizeof(json_t *));
     if(!new_table)
         return NULL;
 
@@ -462,7 +478,7 @@ static json_t **json_array_grow(json_array_t *array,
 
     if(copy) {
         array_copy(array->table, 0, old_table, 0, array->entries);
-        free(old_table);
+        jsonp_free(old_table);
         return array->table;
     }
 
@@ -494,7 +510,7 @@ int json_array_append_new(json_t *json, json_t *value)
     return 0;
 }
 
-int json_array_insert_new(json_t *json, unsigned int index, json_t *value)
+int json_array_insert_new(json_t *json, size_t index, json_t *value)
 {
     json_array_t *array;
     json_t **old_table;
@@ -523,7 +539,7 @@ int json_array_insert_new(json_t *json, unsigned int index, json_t *value)
         array_copy(array->table, 0, old_table, 0, index);
         array_copy(array->table, index + 1, old_table, index,
                    array->entries - index);
-        free(old_table);
+        jsonp_free(old_table);
     }
     else
         array_move(array, index + 1, index, array->entries - index);
@@ -534,7 +550,7 @@ int json_array_insert_new(json_t *json, unsigned int index, json_t *value)
     return 0;
 }
 
-int json_array_remove(json_t *json, unsigned int index)
+int json_array_remove(json_t *json, size_t index)
 {
     json_array_t *array;
 
@@ -556,7 +572,7 @@ int json_array_remove(json_t *json, unsigned int index)
 int json_array_clear(json_t *json)
 {
     json_array_t *array;
-    unsigned int i;
+    size_t i;
 
     if(!json_is_array(json))
         return -1;
@@ -572,7 +588,7 @@ int json_array_clear(json_t *json)
 int json_array_extend(json_t *json, json_t *other_json)
 {
     json_array_t *array, *other;
-    unsigned int i;
+    size_t i;
 
     if(!json_is_array(json) || !json_is_array(other_json))
         return -1;
@@ -593,7 +609,7 @@ int json_array_extend(json_t *json, json_t *other_json)
 
 static int json_array_equal(json_t *array1, json_t *array2)
 {
-    unsigned int i, size;
+    size_t i, size;
 
     size = json_array_size(array1);
     if(size != json_array_size(array2))
@@ -616,7 +632,7 @@ static int json_array_equal(json_t *array1, json_t *array2)
 static json_t *json_array_copy(json_t *array)
 {
     json_t *result;
-    unsigned int i;
+    size_t i;
 
     result = json_array();
     if(!result)
@@ -631,7 +647,7 @@ static json_t *json_array_copy(json_t *array)
 static json_t *json_array_deep_copy(json_t *array)
 {
     json_t *result;
-    unsigned int i;
+    size_t i;
 
     result = json_array();
     if(!result)
@@ -652,14 +668,14 @@ json_t *json_string_nocheck(const char *value)
     if(!value)
         return NULL;
 
-    string = malloc(sizeof(json_string_t));
+    string = jsonp_malloc(sizeof(json_string_t));
     if(!string)
         return NULL;
     json_init(&string->json, JSON_STRING);
 
-    string->value = strdup(value);
+    string->value = jsonp_strdup(value);
     if(!string->value) {
-        free(string);
+        jsonp_free(string);
         return NULL;
     }
 
@@ -687,12 +703,12 @@ int json_string_set_nocheck(json_t *json, const char *value)
     char *dup;
     json_string_t *string;
 
-    dup = strdup(value);
+    dup = jsonp_strdup(value);
     if(!dup)
         return -1;
 
     string = json_to_string(json);
-    free(string->value);
+    jsonp_free(string->value);
     string->value = dup;
 
     return 0;
@@ -708,8 +724,8 @@ int json_string_set(json_t *json, const char *value)
 
 static void json_delete_string(json_string_t *string)
 {
-    free(string->value);
-    free(string);
+    jsonp_free(string->value);
+    jsonp_free(string);
 }
 
 static int json_string_equal(json_t *string1, json_t *string2)
@@ -725,9 +741,9 @@ static json_t *json_string_copy(json_t *string)
 
 /*** integer ***/
 
-json_t *json_integer(int value)
+json_t *json_integer(json_int_t value)
 {
-    json_integer_t *integer = malloc(sizeof(json_integer_t));
+    json_integer_t *integer = jsonp_malloc(sizeof(json_integer_t));
     if(!integer)
         return NULL;
     json_init(&integer->json, JSON_INTEGER);
@@ -736,7 +752,7 @@ json_t *json_integer(int value)
     return &integer->json;
 }
 
-int json_integer_value(const json_t *json)
+json_int_t json_integer_value(const json_t *json)
 {
     if(!json_is_integer(json))
         return 0;
@@ -744,7 +760,7 @@ int json_integer_value(const json_t *json)
     return json_to_integer(json)->value;
 }
 
-int json_integer_set(json_t *json, int value)
+int json_integer_set(json_t *json, json_int_t value)
 {
     if(!json_is_integer(json))
         return -1;
@@ -756,7 +772,7 @@ int json_integer_set(json_t *json, int value)
 
 static void json_delete_integer(json_integer_t *integer)
 {
-    free(integer);
+    jsonp_free(integer);
 }
 
 static int json_integer_equal(json_t *integer1, json_t *integer2)
@@ -774,7 +790,7 @@ static json_t *json_integer_copy(json_t *integer)
 
 json_t *json_real(double value)
 {
-    json_real_t *real = malloc(sizeof(json_real_t));
+    json_real_t *real = jsonp_malloc(sizeof(json_real_t));
     if(!real)
         return NULL;
     json_init(&real->json, JSON_REAL);
@@ -803,7 +819,7 @@ int json_real_set(json_t *json, double value)
 
 static void json_delete_real(json_real_t *real)
 {
-    free(real);
+    jsonp_free(real);
 }
 
 static int json_real_equal(json_t *real1, json_t *real2)
@@ -834,30 +850,21 @@ double json_number_value(const json_t *json)
 
 json_t *json_true(void)
 {
-    static json_t the_true = {
-        .type = JSON_TRUE,
-        .refcount = (unsigned int)-1
-    };
+    static json_t the_true = {JSON_TRUE, (size_t)-1};
     return &the_true;
 }
 
 
 json_t *json_false(void)
 {
-    static json_t the_false = {
-        .type = JSON_FALSE,
-        .refcount = (unsigned int)-1
-    };
+    static json_t the_false = {JSON_FALSE, (size_t)-1};
     return &the_false;
 }
 
 
 json_t *json_null(void)
 {
-    static json_t the_null = {
-        .type = JSON_NULL,
-        .refcount = (unsigned int)-1
-    };
+    static json_t the_null = {JSON_NULL, (size_t)-1};
     return &the_null;
 }
 

+ 1 - 1
main.c

@@ -421,7 +421,7 @@ static char *load_config(const char *arg, void *unused)
 	json_error_t err;
 	json_t *config;
 
-	config = json_load_file(arg, &err);
+	config = json_load_file(arg, 0, &err);
 	if (!json_is_object(config))
 		return "JSON decode of file failed";