Browse Source

Move to newer jansson library.

nfactor-troky
Con Kolivas 13 years ago
parent
commit
4de3f32a22
  1. 2
      README
  2. 5
      compat/jansson/Makefile.am
  3. 37
      compat/jansson/dump.c
  4. 62
      compat/jansson/error.c
  5. 63
      compat/jansson/hashtable.c
  6. 10
      compat/jansson/hashtable.h
  7. 136
      compat/jansson/jansson.h
  8. 34
      compat/jansson/jansson_config.h
  9. 34
      compat/jansson/jansson_config.h.in
  10. 47
      compat/jansson/jansson_private.h
  11. 383
      compat/jansson/load.c
  12. 51
      compat/jansson/memory.c
  13. 23
      compat/jansson/strbuffer.c
  14. 2
      compat/jansson/strbuffer.h
  15. 2
      compat/jansson/utf.c
  16. 15
      compat/jansson/utf.h
  17. 163
      compat/jansson/value.c
  18. 2
      main.c

2
README

@ -6,7 +6,7 @@ License: GPLv2. See COPYING for details.
Dependencies: Dependencies:
libcurl http://curl.haxx.se/libcurl/ libcurl http://curl.haxx.se/libcurl/
jansson http://www.digip.org/jansson/ 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) libncurses5-dev (or libpdcurses on WIN32)
Basic *nix build instructions: Basic *nix build instructions:

5
compat/jansson/Makefile.am

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

37
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 * Jansson is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details. * 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; return 0;
} }
/* 256 spaces (the maximum indentation size) */ /* 32 spaces (the maximum indentation size) */
static char whitespace[] = " "; 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) 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; (*(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) dump_func dump, void *data)
{ {
int ascii = flags & JSON_ENSURE_ASCII ? 1 : 0; 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]; char buffer[MAX_INTEGER_STR_LENGTH];
int size; 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) if(size >= MAX_INTEGER_STR_LENGTH)
return -1; 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) if(flags & JSON_SORT_KEYS || flags & JSON_PRESERVE_ORDER)
{ {
const object_key_t **keys; const object_key_t **keys;
unsigned int size; size_t size, i;
unsigned int i;
int (*cmp_func)(const void *, const void *); int (*cmp_func)(const void *, const void *);
size = json_object_size(json); size = json_object_size(json);
keys = malloc(size * sizeof(object_key_t *)); keys = jsonp_malloc(size * sizeof(object_key_t *));
if(!keys) if(!keys)
goto object_error; 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) || if(dump(separator, separator_length, data) ||
do_dump(value, flags, depth + 1, dump, data)) do_dump(value, flags, depth + 1, dump, data))
{ {
free(keys); jsonp_free(keys);
goto object_error; goto object_error;
} }
@ -354,7 +355,7 @@ static int do_dump(const json_t *json, unsigned long flags, int depth,
if(dump(",", 1, data) || if(dump(",", 1, data) ||
dump_indent(flags, depth + 1, 1, dump, data)) dump_indent(flags, depth + 1, 1, dump, data))
{ {
free(keys); jsonp_free(keys);
goto object_error; 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)) if(dump_indent(flags, depth, 0, dump, data))
{ {
free(keys); jsonp_free(keys);
goto object_error; goto object_error;
} }
} }
} }
free(keys); jsonp_free(keys);
} }
else 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; strbuffer_t strbuff;
char *result; char *result;
if(!(flags & JSON_ENCODE_ANY)) {
if(!json_is_array(json) && !json_is_object(json)) if(!json_is_array(json) && !json_is_object(json))
return NULL; return NULL;
}
if(strbuffer_init(&strbuff)) if(strbuffer_init(&strbuff))
return NULL; return NULL;
@ -431,21 +434,23 @@ char *json_dumps(const json_t *json, unsigned long flags)
return NULL; return NULL;
} }
result = strdup(strbuffer_value(&strbuff)); result = jsonp_strdup(strbuffer_value(&strbuff));
strbuffer_close(&strbuff); strbuffer_close(&strbuff);
return result; 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(!(flags & JSON_ENCODE_ANY)) {
if(!json_is_array(json) && !json_is_object(json)) if(!json_is_array(json) && !json_is_object(json))
return -1; return -1;
}
return do_dump(json, flags, 0, dump_to_file, (void *)output); 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; int result;

62
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);
}

63
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 * This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
*/ */
#include <config.h>
#include <stdlib.h> #include <stdlib.h>
#include <jansson_config.h> /* for JSON_INLINE */
#include "jansson_private.h" /* for container_of() */
#include "hashtable.h" #include "hashtable.h"
typedef struct hashtable_list list_t; typedef struct hashtable_list list_t;
typedef struct hashtable_pair pair_t; typedef struct hashtable_pair pair_t;
typedef struct hashtable_bucket bucket_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) #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->next = list;
list->prev = 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->next = list;
node->prev = list->prev; node->prev = list->prev;
@ -33,13 +30,13 @@ static inline void list_insert(list_t *list, list_t *node)
list->prev = 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->prev->next = list->next;
list->next->prev = list->prev; 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; 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, 5, 13, 23, 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593,
49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469, 49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469,
12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 12582917, 25165843, 50331653, 100663319, 201326611, 402653189,
805306457, 1610612741 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]; return primes[hashtable->num_buckets];
} }
static pair_t *hashtable_find_pair(hashtable_t *hashtable, bucket_t *bucket, 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; list_t *list;
pair_t *pair; 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 */ /* returns 0 on success, -1 if key was not found */
static int hashtable_do_del(hashtable_t *hashtable, static int hashtable_do_del(hashtable_t *hashtable,
const void *key, unsigned int hash) const void *key, size_t hash)
{ {
pair_t *pair; pair_t *pair;
bucket_t *bucket; bucket_t *bucket;
unsigned int index; size_t index;
index = hash % num_buckets(hashtable); index = hash % num_buckets(hashtable);
bucket = &hashtable->buckets[index]; bucket = &hashtable->buckets[index];
@ -129,7 +126,7 @@ static int hashtable_do_del(hashtable_t *hashtable,
if(hashtable->free_value) if(hashtable->free_value)
hashtable->free_value(pair->value); hashtable->free_value(pair->value);
free(pair); jsonp_free(pair);
hashtable->size--; hashtable->size--;
return 0; return 0;
@ -148,7 +145,7 @@ static void hashtable_do_clear(hashtable_t *hashtable)
hashtable->free_key(pair->key); hashtable->free_key(pair->key);
if(hashtable->free_value) if(hashtable->free_value)
hashtable->free_value(pair->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; list_t *list, *next;
pair_t *pair; 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++; hashtable->num_buckets++;
new_size = num_buckets(hashtable); 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) if(!hashtable->buckets)
return -1; 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, hashtable_t *hashtable_create(key_hash_fn hash_key, key_cmp_fn cmp_keys,
free_fn free_key, free_fn free_value) 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) if(!hashtable)
return NULL; return NULL;
if(hashtable_init(hashtable, hash_key, cmp_keys, free_key, free_value)) if(hashtable_init(hashtable, hash_key, cmp_keys, free_key, free_value))
{ {
free(hashtable); jsonp_free(hashtable);
return NULL; 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) void hashtable_destroy(hashtable_t *hashtable)
{ {
hashtable_close(hashtable); hashtable_close(hashtable);
free(hashtable); jsonp_free(hashtable);
} }
int hashtable_init(hashtable_t *hashtable, int hashtable_init(hashtable_t *hashtable,
key_hash_fn hash_key, key_cmp_fn cmp_keys, key_hash_fn hash_key, key_cmp_fn cmp_keys,
free_fn free_key, free_fn free_value) free_fn free_key, free_fn free_value)
{ {
unsigned int i; size_t i;
hashtable->size = 0; hashtable->size = 0;
hashtable->num_buckets = 0; /* index to primes[] */ 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) if(!hashtable->buckets)
return -1; return -1;
@ -240,14 +237,14 @@ int hashtable_init(hashtable_t *hashtable,
void hashtable_close(hashtable_t *hashtable) void hashtable_close(hashtable_t *hashtable)
{ {
hashtable_do_clear(hashtable); hashtable_do_clear(hashtable);
free(hashtable->buckets); jsonp_free(hashtable->buckets);
} }
int hashtable_set(hashtable_t *hashtable, void *key, void *value) int hashtable_set(hashtable_t *hashtable, void *key, void *value)
{ {
pair_t *pair; pair_t *pair;
bucket_t *bucket; bucket_t *bucket;
unsigned int hash, index; size_t hash, index;
/* rehash if the load ratio exceeds 1 */ /* rehash if the load ratio exceeds 1 */
if(hashtable->size >= num_buckets(hashtable)) if(hashtable->size >= num_buckets(hashtable))
@ -269,7 +266,7 @@ int hashtable_set(hashtable_t *hashtable, void *key, void *value)
} }
else else
{ {
pair = malloc(sizeof(pair_t)); pair = jsonp_malloc(sizeof(pair_t));
if(!pair) if(!pair)
return -1; 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) void *hashtable_get(hashtable_t *hashtable, const void *key)
{ {
pair_t *pair; pair_t *pair;
unsigned int hash; size_t hash;
bucket_t *bucket; bucket_t *bucket;
hash = hashtable->hash_key(key); 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) 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); return hashtable_do_del(hashtable, key, hash);
} }
void hashtable_clear(hashtable_t *hashtable) void hashtable_clear(hashtable_t *hashtable)
{ {
unsigned int i; size_t i;
hashtable_do_clear(hashtable); hashtable_do_clear(hashtable);
@ -331,7 +328,7 @@ void *hashtable_iter(hashtable_t *hashtable)
void *hashtable_iter_at(hashtable_t *hashtable, const void *key) void *hashtable_iter_at(hashtable_t *hashtable, const void *key)
{ {
pair_t *pair; pair_t *pair;
unsigned int hash; size_t hash;
bucket_t *bucket; bucket_t *bucket;
hash = hashtable->hash_key(key); hash = hashtable->hash_key(key);

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

136
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 * Jansson is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
@ -9,14 +9,31 @@
#define JANSSON_H #define JANSSON_H
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> /* for size_t */
#include <stdarg.h>
#ifndef __cplusplus #include <jansson_config.h>
#define JSON_INLINE inline
#else #ifdef __cplusplus
#define JSON_INLINE inline
extern "C" { extern "C" {
#endif #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 */ /* types */
typedef enum { typedef enum {
@ -32,9 +49,17 @@ typedef enum {
typedef struct { typedef struct {
json_type type; json_type type;
unsigned long refcount; size_t refcount;
} json_t; } 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_typeof(json) ((json)->type)
#define json_is_object(json) (json && json_typeof(json) == JSON_OBJECT) #define json_is_object(json) (json && json_typeof(json) == JSON_OBJECT)
#define json_is_array(json) (json && json_typeof(json) == JSON_ARRAY) #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_array(void);
json_t *json_string(const char *value); json_t *json_string(const char *value);
json_t *json_string_nocheck(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_real(double value);
json_t *json_true(void); json_t *json_true(void);
json_t *json_false(void); json_t *json_false(void);
@ -62,7 +87,7 @@ json_t *json_null(void);
static JSON_INLINE static JSON_INLINE
json_t *json_incref(json_t *json) json_t *json_incref(json_t *json)
{ {
if(json && json->refcount != (unsigned int)-1) if(json && json->refcount != (size_t)-1)
++json->refcount; ++json->refcount;
return json; return json;
} }
@ -73,14 +98,28 @@ void json_delete(json_t *json);
static JSON_INLINE static JSON_INLINE
void json_decref(json_t *json) 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); 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 */ /* 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); 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(json_t *object, const char *key, json_t *value);
int json_object_set_new_nocheck(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)); 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) int json_object_iter_set(json_t *object, void *iter, json_t *value)
{ {
return json_object_iter_set_new(object, iter, json_incref(value)); return json_object_iter_set_new(object, iter, json_incref(value));
} }
unsigned int json_array_size(const json_t *array); size_t json_array_size(const json_t *array);
json_t *json_array_get(const json_t *array, unsigned int index); json_t *json_array_get(const json_t *array, size_t index);
int json_array_set_new(json_t *array, unsigned int index, json_t *value); 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_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_insert_new(json_t *array, size_t index, json_t *value);
int json_array_remove(json_t *array, unsigned int index); int json_array_remove(json_t *array, size_t index);
int json_array_clear(json_t *array); int json_array_clear(json_t *array);
int json_array_extend(json_t *array, json_t *other); int json_array_extend(json_t *array, json_t *other);
static JSON_INLINE 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)); 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 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)); return json_array_insert_new(array, index, json_incref(value));
} }
const char *json_string_value(const json_t *string); 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_real_value(const json_t *real);
double json_number_value(const json_t *json); double json_number_value(const json_t *json);
int json_string_set(json_t *string, const char *value); int json_string_set(json_t *string, const char *value);
int json_string_set_nocheck(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); 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 */ /* equality */
int json_equal(json_t *value1, json_t *value2); 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); 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); /* custom memory allocation */
json_t *json_loadf(FILE *input, json_error_t *error);
json_t *json_load_file(const char *path, json_error_t *error);
#define JSON_INDENT(n) (n & 0xFF) typedef void *(*json_malloc_t)(size_t);
#define JSON_COMPACT 0x100 typedef void (*json_free_t)(void *);
#define JSON_ENSURE_ASCII 0x200
#define JSON_SORT_KEYS 0x400
#define JSON_PRESERVE_ORDER 0x800
char *json_dumps(const json_t *json, unsigned long flags); void json_set_alloc_funcs(json_malloc_t malloc_fn, json_free_t free_fn);
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);
#ifdef __cplusplus #ifdef __cplusplus
} }

34
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
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

47
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 * Jansson is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
@ -8,23 +8,39 @@
#ifndef JANSSON_PRIVATE_H #ifndef JANSSON_PRIVATE_H
#define JANSSON_PRIVATE_H #define JANSSON_PRIVATE_H
#include <stddef.h>
#include "jansson.h" #include "jansson.h"
#include "hashtable.h" #include "hashtable.h"
#define container_of(ptr_, type_, member_) \ #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 { typedef struct {
json_t json; json_t json;
hashtable_t hashtable; hashtable_t hashtable;
unsigned long serial; size_t serial;
int visited; int visited;
} json_object_t; } json_object_t;
typedef struct { typedef struct {
json_t json; json_t json;
unsigned int size; size_t size;
unsigned int entries; size_t entries;
json_t **table; json_t **table;
int visited; int visited;
} json_array_t; } json_array_t;
@ -41,7 +57,7 @@ typedef struct {
typedef struct { typedef struct {
json_t json; json_t json;
int value; json_int_t value;
} json_integer_t; } json_integer_t;
#define json_to_object(json_) container_of(json_, json_object_t, json) #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_real(json_) container_of(json_, json_real_t, json)
#define json_to_integer(json_) container_of(json_, json_integer_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 { typedef struct {
unsigned long serial; size_t serial;
char key[]; char key[1];
} object_key_t; } object_key_t;
const object_key_t *jsonp_object_iter_fullkey(void *iter); 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 #endif

383
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 * Jansson is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
@ -12,7 +12,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdarg.h>
#include <assert.h> #include <assert.h>
#include <jansson.h> #include <jansson.h>
@ -20,6 +19,10 @@
#include "strbuffer.h" #include "strbuffer.h"
#include "utf.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_INVALID -1
#define TOKEN_EOF 0 #define TOKEN_EOF 0
#define TOKEN_STRING 256 #define TOKEN_STRING 256
@ -29,113 +32,125 @@
#define TOKEN_FALSE 260 #define TOKEN_FALSE 260
#define TOKEN_NULL 261 #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); typedef int (*get_func)(void *data);
/* return non-zero if end of file has been reached */
typedef int (*eof_func)(void *data);
typedef struct { typedef struct {
get_func get; get_func get;
eof_func eof;
void *data; void *data;
int stream_pos;
char buffer[5]; char buffer[5];
int buffer_pos; int buffer_pos;
int state;
int line;
int column, last_column;
size_t position;
} stream_t; } stream_t;
typedef struct { typedef struct {
stream_t stream; stream_t stream;
strbuffer_t saved_text; strbuffer_t saved_text;
int token; int token;
int line, column;
union { union {
char *string; char *string;
int integer; json_int_t integer;
double real; double real;
} value; } value;
} lex_t; } lex_t;
#define stream_to_lex(stream) container_of(stream, lex_t, stream)
/*** error reporting ***/
static void error_init(json_error_t *error) /*** error reporting ***/
{
if(error)
{
error->text[0] = '\0';
error->line = -1;
}
}
static void error_set(json_error_t *error, const lex_t *lex, static void error_set(json_error_t *error, const lex_t *lex,
const char *msg, ...) const char *msg, ...)
{ {
va_list ap; 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') { if(!error)
/* error already set */
return; return;
}
va_start(ap, msg); va_start(ap, msg);
vsnprintf(text, JSON_ERROR_TEXT_LENGTH, msg, ap); vsnprintf(msg_text, JSON_ERROR_TEXT_LENGTH, msg, ap);
va_end(ap); va_end(ap);
if(lex) if(lex)
{ {
const char *saved_text = strbuffer_value(&lex->saved_text); 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(saved_text && saved_text[0])
{ {
if(lex->saved_text.length <= 20) { if(lex->saved_text.length <= 20) {
snprintf(error->text, JSON_ERROR_TEXT_LENGTH, snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH,
"%s near '%s'", text, saved_text); "%s near '%s'", msg_text, saved_text);
result = msg_with_context;
} }
else
snprintf(error->text, JSON_ERROR_TEXT_LENGTH, "%s", text);
} }
else else
{ {
snprintf(error->text, JSON_ERROR_TEXT_LENGTH, if(lex->stream.state == STREAM_STATE_ERROR) {
"%s near end of file", text); /* 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 ***/ /*** lexical analyzer ***/
static void 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->get = get;
stream->eof = eof;
stream->data = data; stream->data = data;
stream->stream_pos = 0;
stream->buffer[0] = '\0'; stream->buffer[0] = '\0';
stream->buffer_pos = 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]) if(!stream->buffer[stream->buffer_pos])
{ {
stream->buffer[0] = stream->get(stream->data); c = stream->get(stream->data);
stream->buffer_pos = 0; 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 */ /* multi-byte UTF-8 sequence */
int i, count; 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)) if(!utf8_check_full(stream->buffer, count, NULL))
goto out; goto out;
stream->stream_pos += count;
stream->buffer[count] = '\0'; stream->buffer[count] = '\0';
} }
else { else
stream->buffer[1] = '\0'; stream->buffer[1] = '\0';
stream->stream_pos++;
} }
c = stream->buffer[stream->buffer_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++;
} }
return stream->buffer[stream->buffer_pos++]; return c;
out: out:
error_set(error, NULL, "unable to decode byte 0x%x at position %d", stream->state = STREAM_STATE_ERROR;
(unsigned char)c, stream->stream_pos); error_set(error, stream_to_lex(stream), "unable to decode byte 0x%x", c);
return STREAM_STATE_ERROR;
}
stream->buffer[0] = EOF; static void stream_unget(stream_t *stream, int c)
stream->buffer[1] = '\0'; {
stream->buffer_pos = 1; if(c == STREAM_STATE_EOF || c == STREAM_STATE_ERROR)
return;
return EOF; stream->position--;
if(c == '\n') {
stream->line--;
stream->column = stream->last_column;
} }
else if(utf8_check_first(c))
stream->column--;
static void stream_unget(stream_t *stream, char c)
{
assert(stream->buffer_pos > 0); assert(stream->buffer_pos > 0);
stream->buffer_pos--; stream->buffer_pos--;
assert(stream->buffer[stream->buffer_pos] == c); assert(stream->buffer[stream->buffer_pos] == c);
@ -187,30 +219,33 @@ static int lex_get(lex_t *lex, json_error_t *error)
return stream_get(&lex->stream, error); return stream_get(&lex->stream, error);
} }
static int lex_eof(lex_t *lex) static void lex_save(lex_t *lex, int c)
{
return lex->stream.eof(lex->stream.data);
}
static void lex_save(lex_t *lex, char c)
{ {
strbuffer_append_byte(&lex->saved_text, c); strbuffer_append_byte(&lex->saved_text, c);
} }
static int lex_get_save(lex_t *lex, json_error_t *error) static int lex_get_save(lex_t *lex, json_error_t *error)
{ {
char c = stream_get(&lex->stream, error); int c = stream_get(&lex->stream, error);
if(c != STREAM_STATE_EOF && c != STREAM_STATE_ERROR)
lex_save(lex, c); lex_save(lex, c);
return c; return c;
} }
static void lex_unget_unsave(lex_t *lex, char c) static void lex_unget(lex_t *lex, int c)
{
stream_unget(&lex->stream, c);
}
static void lex_unget_unsave(lex_t *lex, int c)
{ {
if(c != STREAM_STATE_EOF && c != STREAM_STATE_ERROR) {
char d; char d;
stream_unget(&lex->stream, c); stream_unget(&lex->stream, c);
d = strbuffer_pop(&lex->saved_text); d = strbuffer_pop(&lex->saved_text);
assert(c == d); assert(c == d);
} }
}
static void lex_save_cached(lex_t *lex) 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_save(lex, lex->stream.buffer[lex->stream.buffer_pos]);
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) static void lex_scan_string(lex_t *lex, json_error_t *error)
{ {
char c; int c;
const char *p; const char *p;
char *t; char *t;
int i; int i;
@ -258,14 +294,15 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
c = lex_get_save(lex, error); c = lex_get_save(lex, error);
while(c != '"') { while(c != '"') {
if(c == (char)EOF) { if(c == STREAM_STATE_ERROR)
lex_unget_unsave(lex, c); goto out;
if(lex_eof(lex))
else if(c == STREAM_STATE_EOF) {
error_set(error, lex, "premature end of input"); error_set(error, lex, "premature end of input");
goto out; goto out;
} }
else if((unsigned char)c <= 0x1F) { else if(0 <= c && c <= 0x1F) {
/* control character */ /* control character */
lex_unget_unsave(lex, c); lex_unget_unsave(lex, c);
if(c == '\n') 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); c = lex_get_save(lex, error);
for(i = 0; i < 4; i++) { for(i = 0; i < 4; i++) {
if(!isxdigit(c)) { if(!isxdigit(c)) {
lex_unget_unsave(lex, c);
error_set(error, lex, "invalid escape"); error_set(error, lex, "invalid escape");
goto out; 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 == 'f' || c == 'n' || c == 'r' || c == 't')
c = lex_get_save(lex, error); c = lex_get_save(lex, error);
else { else {
lex_unget_unsave(lex, c);
error_set(error, lex, "invalid escape"); error_set(error, lex, "invalid escape");
goto out; 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 - two \uXXXX escapes (length 12) forming an UTF-16 surrogate pair
are converted to 4 bytes 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) { if(!lex->value.string) {
/* this is not very nice, since TOKEN_INVALID is returned */ /* this is not very nice, since TOKEN_INVALID is returned */
goto out; goto out;
@ -398,10 +433,16 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
return; return;
out: 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; const char *saved_text;
char *end; char *end;
@ -430,32 +471,35 @@ static int lex_scan_number(lex_t *lex, char c, json_error_t *error)
} }
if(c != '.' && c != 'E' && c != 'e') { if(c != '.' && c != 'E' && c != 'e') {
long value; json_int_t value;
lex_unget_unsave(lex, c); lex_unget_unsave(lex, c);
saved_text = strbuffer_value(&lex->saved_text); 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) { errno = 0;
error_set(error, lex, "too big integer"); value = json_strtoint(saved_text, &end, 10);
goto out; if(errno == ERANGE) {
} if(value < 0)
else if((value == LONG_MIN && errno == ERANGE) || value < INT_MIN) {
error_set(error, lex, "too big negative integer"); error_set(error, lex, "too big negative integer");
else
error_set(error, lex, "too big integer");
goto out; goto out;
} }
assert(end == saved_text + lex->saved_text.length);
lex->token = TOKEN_INTEGER; lex->token = TOKEN_INTEGER;
lex->value.integer = (int)value; lex->value.integer = value;
return 0; return 0;
} }
if(c == '.') { if(c == '.') {
c = lex_get(lex, error); c = lex_get(lex, error);
if(!isdigit(c)) if(!isdigit(c)) {
lex_unget(lex, c);
goto out; goto out;
}
lex_save(lex, c); lex_save(lex, c);
c = lex_get_save(lex, error); 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); lex_unget_unsave(lex, c);
saved_text = strbuffer_value(&lex->saved_text); saved_text = strbuffer_value(&lex->saved_text);
errno = 0;
value = strtod(saved_text, &end); value = strtod(saved_text, &end);
assert(end == saved_text + lex->saved_text.length); assert(end == saved_text + lex->saved_text.length);
@ -499,28 +544,25 @@ out:
static int lex_scan(lex_t *lex, json_error_t *error) static int lex_scan(lex_t *lex, json_error_t *error)
{ {
char c; int c;
strbuffer_clear(&lex->saved_text); strbuffer_clear(&lex->saved_text);
if(lex->token == TOKEN_STRING) { if(lex->token == TOKEN_STRING) {
free(lex->value.string); jsonp_free(lex->value.string);
lex->value.string = NULL; lex->value.string = NULL;
} }
c = lex_get(lex, error); c = lex_get(lex, error);
while(c == ' ' || c == '\t' || c == '\n' || c == '\r') while(c == ' ' || c == '\t' || c == '\n' || c == '\r')
{
if(c == '\n')
lex->line++;
c = lex_get(lex, error); c = lex_get(lex, error);
}
if(c == (char)EOF) { if(c == STREAM_STATE_EOF) {
if(lex_eof(lex))
lex->token = TOKEN_EOF; lex->token = TOKEN_EOF;
else goto out;
}
if(c == STREAM_STATE_ERROR) {
lex->token = TOKEN_INVALID; lex->token = TOKEN_INVALID;
goto out; goto out;
} }
@ -581,31 +623,29 @@ static char *lex_steal_string(lex_t *lex)
return result; 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)) if(strbuffer_init(&lex->saved_text))
return -1; return -1;
lex->token = TOKEN_INVALID; lex->token = TOKEN_INVALID;
lex->line = 1;
return 0; return 0;
} }
static void lex_close(lex_t *lex) static void lex_close(lex_t *lex)
{ {
if(lex->token == TOKEN_STRING) if(lex->token == TOKEN_STRING)
free(lex->value.string); jsonp_free(lex->value.string);
strbuffer_close(&lex->saved_text); strbuffer_close(&lex->saved_text);
} }
/*** parser ***/ /*** 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(); json_t *object = json_object();
if(!object) if(!object)
@ -628,28 +668,36 @@ static json_t *parse_object(lex_t *lex, json_error_t *error)
if(!key) if(!key)
return NULL; 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); lex_scan(lex, error);
if(lex->token != ':') { if(lex->token != ':') {
free(key); jsonp_free(key);
error_set(error, lex, "':' expected"); error_set(error, lex, "':' expected");
goto error; goto error;
} }
lex_scan(lex, error); lex_scan(lex, error);
value = parse_value(lex, error); value = parse_value(lex, flags, error);
if(!value) { if(!value) {
free(key); jsonp_free(key);
goto error; goto error;
} }
if(json_object_set_nocheck(object, key, value)) { if(json_object_set_nocheck(object, key, value)) {
free(key); jsonp_free(key);
json_decref(value); json_decref(value);
goto error; goto error;
} }
json_decref(value); json_decref(value);
free(key); jsonp_free(key);
lex_scan(lex, error); lex_scan(lex, error);
if(lex->token != ',') if(lex->token != ',')
@ -670,7 +718,7 @@ error:
return NULL; 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(); json_t *array = json_array();
if(!array) if(!array)
@ -681,7 +729,7 @@ static json_t *parse_array(lex_t *lex, json_error_t *error)
return array; return array;
while(lex->token) { while(lex->token) {
json_t *elem = parse_value(lex, error); json_t *elem = parse_value(lex, flags, error);
if(!elem) if(!elem)
goto error; goto error;
@ -710,7 +758,7 @@ error:
return NULL; 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; json_t *json;
@ -743,11 +791,11 @@ static json_t *parse_value(lex_t *lex, json_error_t *error)
break; break;
case '{': case '{':
json = parse_object(lex, error); json = parse_object(lex, flags, error);
break; break;
case '[': case '[':
json = parse_array(lex, error); json = parse_array(lex, flags, error);
break; break;
case TOKEN_INVALID: case TOKEN_INVALID:
@ -765,9 +813,9 @@ static json_t *parse_value(lex_t *lex, json_error_t *error)
return json; 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); lex_scan(lex, error);
if(lex->token != '[' && lex->token != '{') { if(lex->token != '[' && lex->token != '{') {
@ -775,7 +823,20 @@ static json_t *parse_json(lex_t *lex, json_error_t *error)
return NULL; 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 typedef struct
@ -794,75 +855,95 @@ static int string_get(void *data)
else else
{ {
stream->pos++; 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; lex_t lex;
return (stream->data[stream->pos] == '\0'); 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;
} }
json_t *json_loads(const char *string, json_error_t *error) 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_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t *error)
{ {
lex_t lex; lex_t lex;
json_t *result; json_t *result;
buffer_data_t stream_data;
string_data_t stream_data = { stream_data.data = buffer;
.data = string, stream_data.pos = 0;
.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; return NULL;
result = parse_json(&lex, error); jsonp_error_init(error, "<buffer>");
if(!result) result = parse_json(&lex, flags, error);
goto out;
lex_scan(&lex, error);
if(lex.token != TOKEN_EOF) {
error_set(error, &lex, "end of file expected");
json_decref(result);
result = NULL;
}
out:
lex_close(&lex); lex_close(&lex);
return result; 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; lex_t lex;
const char *source;
json_t *result; json_t *result;
if(lex_init(&lex, (get_func)fgetc, (eof_func)feof, input)) if(lex_init(&lex, (get_func)fgetc, input))
return NULL; return NULL;
result = parse_json(&lex, error); if(input == stdin)
if(!result) source = "<stdin>";
goto out; else
source = "<stream>";
lex_scan(&lex, error); jsonp_error_init(error, source);
if(lex.token != TOKEN_EOF) { result = parse_json(&lex, flags, error);
error_set(error, &lex, "end of file expected");
json_decref(result);
result = NULL;
}
out:
lex_close(&lex); lex_close(&lex);
return result; 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; json_t *result;
FILE *fp; FILE *fp;
error_init(error); jsonp_error_init(error, path);
fp = fopen(path, "r"); fp = fopen(path, "r");
if(!fp) if(!fp)
@ -872,7 +953,7 @@ json_t *json_load_file(const char *path, json_error_t *error)
return NULL; return NULL;
} }
result = json_loadf(fp, error); result = json_loadf(fp, flags, error);
fclose(fp); fclose(fp);
return result; return result;

51
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;
}

23
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 * Jansson is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
@ -8,8 +8,8 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "jansson_private.h"
#include "strbuffer.h" #include "strbuffer.h"
#include "util.h"
#define STRBUFFER_MIN_SIZE 16 #define STRBUFFER_MIN_SIZE 16
#define STRBUFFER_FACTOR 2 #define STRBUFFER_FACTOR 2
@ -19,7 +19,7 @@ int strbuffer_init(strbuffer_t *strbuff)
strbuff->size = STRBUFFER_MIN_SIZE; strbuff->size = STRBUFFER_MIN_SIZE;
strbuff->length = 0; strbuff->length = 0;
strbuff->value = malloc(strbuff->size); strbuff->value = jsonp_malloc(strbuff->size);
if(!strbuff->value) if(!strbuff->value)
return -1; return -1;
@ -30,7 +30,7 @@ int strbuffer_init(strbuffer_t *strbuff)
void strbuffer_close(strbuffer_t *strbuff) void strbuffer_close(strbuffer_t *strbuff)
{ {
free(strbuff->value); jsonp_free(strbuff->value);
strbuff->size = 0; strbuff->size = 0;
strbuff->length = 0; strbuff->length = 0;
strbuff->value = NULL; 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) if(strbuff->length + size >= strbuff->size)
{ {
strbuff->size = max(strbuff->size * STRBUFFER_FACTOR, size_t new_size;
char *new_value;
new_size = max(strbuff->size * STRBUFFER_FACTOR,
strbuff->length + size + 1); strbuff->length + size + 1);
strbuff->value = realloc(strbuff->value, strbuff->size); new_value = jsonp_malloc(new_size);
if(!strbuff->value) if(!new_value)
return -1; 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); memcpy(strbuff->value + strbuff->length, data, size);

2
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 * Jansson is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.

2
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 * Jansson is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.

15
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 * Jansson is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
@ -8,6 +8,7 @@
#ifndef UTF_H #ifndef UTF_H
#define UTF_H #define UTF_H
#ifdef HAVE_CONFIG_H
#include <config.h> #include <config.h>
#ifdef HAVE_INTTYPES_H #ifdef HAVE_INTTYPES_H
@ -15,7 +16,17 @@
no need to include stdint.h separately. If inttypes.h doesn't define no need to include stdint.h separately. If inttypes.h doesn't define
int32_t, it's defined in config.h. */ int32_t, it's defined in config.h. */
#include <inttypes.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); int utf8_encode(int codepoint, char *buffer, int *size);

163
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 * Jansson is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details. * it under the terms of the MIT license. See LICENSE for details.
@ -7,8 +7,7 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include <config.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -16,10 +15,9 @@
#include "hashtable.h" #include "hashtable.h"
#include "jansson_private.h" #include "jansson_private.h"
#include "utf.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->type = type;
json->refcount = 1; json->refcount = 1;
@ -28,20 +26,15 @@ static inline void json_init(json_t *json, json_type type)
/*** object ***/ /*** object ***/
/* This macro just returns a pointer that's a few bytes backwards from /* From http://www.cse.yorku.ca/~oz/hash.html */
string. This makes it possible to pass a pointer to object_key_t size_t jsonp_hash_str(const void *ptr)
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)
{ {
const char *str = ((const object_key_t *)ptr)->key; const char *str = (const char *)ptr;
unsigned int hash = 5381; size_t hash = 5381;
unsigned int c; size_t c;
while((c = (unsigned int)*str)) while((c = (size_t)*str))
{ {
hash = ((hash << 5) + hash) + c; hash = ((hash << 5) + hash) + c;
str++; str++;
@ -50,10 +43,26 @@ static unsigned int hash_key(const void *ptr)
return hash; 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) static int key_equal(const void *ptr1, const void *ptr2)
{ {
return strcmp(((const object_key_t *)ptr1)->key, return jsonp_str_equal(((const object_key_t *)ptr1)->key,
((const object_key_t *)ptr2)->key) == 0; ((const object_key_t *)ptr2)->key);
} }
static void value_decref(void *value) static void value_decref(void *value)
@ -63,15 +72,16 @@ static void value_decref(void *value)
json_t *json_object(void) 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) if(!object)
return NULL; return NULL;
json_init(&object->json, JSON_OBJECT); json_init(&object->json, JSON_OBJECT);
if(hashtable_init(&object->hashtable, hash_key, key_equal, if(hashtable_init(&object->hashtable,
free, value_decref)) hash_key, key_equal,
jsonp_free, value_decref))
{ {
free(object); jsonp_free(object);
return NULL; return NULL;
} }
@ -84,15 +94,15 @@ json_t *json_object(void)
static void json_delete_object(json_object_t *object) static void json_delete_object(json_object_t *object)
{ {
hashtable_close(&object->hashtable); 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; json_object_t *object;
if(!json_is_object(json)) if(!json_is_object(json))
return -1; return 0;
object = json_to_object(json); object = json_to_object(json);
return object->hashtable.size; 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); 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) if(!k)
{
json_decref(value);
return -1; return -1;
}
k->serial = object->serial++; k->serial = object->serial++;
strcpy(k->key, key); strcpy(k->key, key);
@ -350,7 +366,7 @@ static json_t *json_object_deep_copy(json_t *object)
json_t *json_array(void) 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) if(!array)
return NULL; return NULL;
json_init(&array->json, JSON_ARRAY); json_init(&array->json, JSON_ARRAY);
@ -358,9 +374,9 @@ json_t *json_array(void)
array->entries = 0; array->entries = 0;
array->size = 8; array->size = 8;
array->table = malloc(array->size * sizeof(json_t *)); array->table = jsonp_malloc(array->size * sizeof(json_t *));
if(!array->table) { if(!array->table) {
free(array); jsonp_free(array);
return NULL; return NULL;
} }
@ -371,16 +387,16 @@ json_t *json_array(void)
static void json_delete_array(json_array_t *array) static void json_delete_array(json_array_t *array)
{ {
unsigned int i; size_t i;
for(i = 0; i < array->entries; i++) for(i = 0; i < array->entries; i++)
json_decref(array->table[i]); json_decref(array->table[i]);
free(array->table); jsonp_free(array->table);
free(array); 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)) if(!json_is_array(json))
return 0; return 0;
@ -388,7 +404,7 @@ unsigned int json_array_size(const json_t *json)
return json_to_array(json)->entries; 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; json_array_t *array;
if(!json_is_array(json)) 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]; 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; json_array_t *array;
@ -427,24 +443,24 @@ int json_array_set_new(json_t *json, unsigned int index, json_t *value)
return 0; return 0;
} }
static void array_move(json_array_t *array, unsigned int dest, static void array_move(json_array_t *array, size_t dest,
unsigned int src, unsigned int count) size_t src, size_t count)
{ {
memmove(&array->table[dest], &array->table[src], count * sizeof(json_t *)); memmove(&array->table[dest], &array->table[src], count * sizeof(json_t *));
} }
static void array_copy(json_t **dest, unsigned int dpos, static void array_copy(json_t **dest, size_t dpos,
json_t **src, unsigned int spos, json_t **src, size_t spos,
unsigned int count) size_t count)
{ {
memcpy(&dest[dpos], &src[spos], count * sizeof(json_t *)); memcpy(&dest[dpos], &src[spos], count * sizeof(json_t *));
} }
static json_t **json_array_grow(json_array_t *array, static json_t **json_array_grow(json_array_t *array,
unsigned int amount, size_t amount,
int copy) int copy)
{ {
unsigned int new_size; size_t new_size;
json_t **old_table, **new_table; json_t **old_table, **new_table;
if(array->entries + amount <= array->size) if(array->entries + amount <= array->size)
@ -453,7 +469,7 @@ static json_t **json_array_grow(json_array_t *array,
old_table = array->table; old_table = array->table;
new_size = max(array->size + amount, array->size * 2); 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) if(!new_table)
return NULL; return NULL;
@ -462,7 +478,7 @@ static json_t **json_array_grow(json_array_t *array,
if(copy) { if(copy) {
array_copy(array->table, 0, old_table, 0, array->entries); array_copy(array->table, 0, old_table, 0, array->entries);
free(old_table); jsonp_free(old_table);
return array->table; return array->table;
} }
@ -494,7 +510,7 @@ int json_array_append_new(json_t *json, json_t *value)
return 0; 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_array_t *array;
json_t **old_table; 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, 0, old_table, 0, index);
array_copy(array->table, index + 1, old_table, index, array_copy(array->table, index + 1, old_table, index,
array->entries - index); array->entries - index);
free(old_table); jsonp_free(old_table);
} }
else else
array_move(array, index + 1, index, array->entries - index); 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; 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; 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) int json_array_clear(json_t *json)
{ {
json_array_t *array; json_array_t *array;
unsigned int i; size_t i;
if(!json_is_array(json)) if(!json_is_array(json))
return -1; return -1;
@ -572,7 +588,7 @@ int json_array_clear(json_t *json)
int json_array_extend(json_t *json, json_t *other_json) int json_array_extend(json_t *json, json_t *other_json)
{ {
json_array_t *array, *other; json_array_t *array, *other;
unsigned int i; size_t i;
if(!json_is_array(json) || !json_is_array(other_json)) if(!json_is_array(json) || !json_is_array(other_json))
return -1; 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) static int json_array_equal(json_t *array1, json_t *array2)
{ {
unsigned int i, size; size_t i, size;
size = json_array_size(array1); size = json_array_size(array1);
if(size != json_array_size(array2)) 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) static json_t *json_array_copy(json_t *array)
{ {
json_t *result; json_t *result;
unsigned int i; size_t i;
result = json_array(); result = json_array();
if(!result) 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) static json_t *json_array_deep_copy(json_t *array)
{ {
json_t *result; json_t *result;
unsigned int i; size_t i;
result = json_array(); result = json_array();
if(!result) if(!result)
@ -652,14 +668,14 @@ json_t *json_string_nocheck(const char *value)
if(!value) if(!value)
return NULL; return NULL;
string = malloc(sizeof(json_string_t)); string = jsonp_malloc(sizeof(json_string_t));
if(!string) if(!string)
return NULL; return NULL;
json_init(&string->json, JSON_STRING); json_init(&string->json, JSON_STRING);
string->value = strdup(value); string->value = jsonp_strdup(value);
if(!string->value) { if(!string->value) {
free(string); jsonp_free(string);
return NULL; return NULL;
} }
@ -687,12 +703,12 @@ int json_string_set_nocheck(json_t *json, const char *value)
char *dup; char *dup;
json_string_t *string; json_string_t *string;
dup = strdup(value); dup = jsonp_strdup(value);
if(!dup) if(!dup)
return -1; return -1;
string = json_to_string(json); string = json_to_string(json);
free(string->value); jsonp_free(string->value);
string->value = dup; string->value = dup;
return 0; 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) static void json_delete_string(json_string_t *string)
{ {
free(string->value); jsonp_free(string->value);
free(string); jsonp_free(string);
} }
static int json_string_equal(json_t *string1, json_t *string2) 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 ***/ /*** 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) if(!integer)
return NULL; return NULL;
json_init(&integer->json, JSON_INTEGER); json_init(&integer->json, JSON_INTEGER);
@ -736,7 +752,7 @@ json_t *json_integer(int value)
return &integer->json; 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)) if(!json_is_integer(json))
return 0; return 0;
@ -744,7 +760,7 @@ int json_integer_value(const json_t *json)
return json_to_integer(json)->value; 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)) if(!json_is_integer(json))
return -1; return -1;
@ -756,7 +772,7 @@ int json_integer_set(json_t *json, int value)
static void json_delete_integer(json_integer_t *integer) 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) 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_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) if(!real)
return NULL; return NULL;
json_init(&real->json, JSON_REAL); 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) 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) 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) json_t *json_true(void)
{ {
static json_t the_true = { static json_t the_true = {JSON_TRUE, (size_t)-1};
.type = JSON_TRUE,
.refcount = (unsigned int)-1
};
return &the_true; return &the_true;
} }
json_t *json_false(void) json_t *json_false(void)
{ {
static json_t the_false = { static json_t the_false = {JSON_FALSE, (size_t)-1};
.type = JSON_FALSE,
.refcount = (unsigned int)-1
};
return &the_false; return &the_false;
} }
json_t *json_null(void) json_t *json_null(void)
{ {
static json_t the_null = { static json_t the_null = {JSON_NULL, (size_t)-1};
.type = JSON_NULL,
.refcount = (unsigned int)-1
};
return &the_null; return &the_null;
} }

2
main.c

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

Loading…
Cancel
Save