summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Plattner <aplattner@nvidia.com>2014-04-11 10:18:17 -0700
committerAaron Plattner <aplattner@nvidia.com>2014-04-11 10:18:17 -0700
commite3ce465d6a1968f341da16e6c65d3540a301fef2 (patch)
treed6ae9382d163a714082c6fdc40c6b0225c0fdb1f
parent5c353a9cec52c64411343d05a8a87930d6d43579 (diff)
331.67331.67
-rw-r--r--doc/version.mk2
-rw-r--r--samples/version.mk2
-rw-r--r--src/Makefile5
-rw-r--r--src/gtk+-2.x/ctkappprofile.c6
-rw-r--r--src/gtk+-2.x/ctkcolorcorrection.c48
-rw-r--r--src/jansson/dump.c30
-rw-r--r--src/jansson/hashtable.c78
-rw-r--r--src/jansson/hashtable.h5
-rw-r--r--src/jansson/hashtable_seed.c277
-rw-r--r--src/jansson/jansson.h57
-rw-r--r--src/jansson/jansson_config.h47
-rw-r--r--src/jansson/jansson_private.h11
-rw-r--r--src/jansson/jansson_private_config.h57
-rw-r--r--src/jansson/load.c123
-rw-r--r--src/jansson/lookup3.h366
-rw-r--r--src/jansson/memory.c16
-rw-r--r--src/jansson/pack_unpack.c290
-rw-r--r--src/jansson/strbuffer.c11
-rw-r--r--src/jansson/strbuffer.h4
-rw-r--r--src/jansson/strconv.c5
-rw-r--r--src/jansson/utf.c29
-rw-r--r--src/jansson/utf.h34
-rw-r--r--src/jansson/value.c168
-rw-r--r--src/src.mk23
-rw-r--r--src/version.mk2
-rw-r--r--version.mk2
26 files changed, 1406 insertions, 292 deletions
diff --git a/doc/version.mk b/doc/version.mk
index 1012493..bb1a5bc 100644
--- a/doc/version.mk
+++ b/doc/version.mk
@@ -1 +1 @@
-NVIDIA_VERSION = 331.49
+NVIDIA_VERSION = 331.67
diff --git a/samples/version.mk b/samples/version.mk
index 1012493..bb1a5bc 100644
--- a/samples/version.mk
+++ b/samples/version.mk
@@ -1 +1 @@
-NVIDIA_VERSION = 331.49
+NVIDIA_VERSION = 331.67
diff --git a/src/Makefile b/src/Makefile
index 1790b4f..c299491 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -60,7 +60,10 @@ ifndef VDPAU_CFLAGS
endif
ifndef JANSSON_CFLAGS
- JANSSON_CFLAGS = -Wno-cast-qual
+ JANSSON_CFLAGS = -Wno-cast-qual
+ JANSSON_CFLAGS += -Wno-strict-prototypes
+ JANSSON_CFLAGS += -Wno-unused-function
+ JANSSON_CFLAGS += -DHAVE_CONFIG_H
ifeq ($(TARGET_ARCH),armv7l)
JANSSON_CFLAGS += -Wno-unused-but-set-variable
endif
diff --git a/src/gtk+-2.x/ctkappprofile.c b/src/gtk+-2.x/ctkappprofile.c
index 939634b..3bf0e09 100644
--- a/src/gtk+-2.x/ctkappprofile.c
+++ b/src/gtk+-2.x/ctkappprofile.c
@@ -221,11 +221,7 @@ typedef struct _TreeViewColumnTemplate {
const gchar *extended_help_text;
} TreeViewColumnTemplate;
-#if JSON_INTEGER_IS_LONG_LONG
-# define JSON_INTEGER_HEX_FORMAT "llx"
-#else
-# define JSON_INTEGER_HEX_FORMAT "lx"
-#endif
+#define JSON_INTEGER_HEX_FORMAT "llx"
/*
* Function prototypes
diff --git a/src/gtk+-2.x/ctkcolorcorrection.c b/src/gtk+-2.x/ctkcolorcorrection.c
index 6afb93f..5ed46cf 100644
--- a/src/gtk+-2.x/ctkcolorcorrection.c
+++ b/src/gtk+-2.x/ctkcolorcorrection.c
@@ -83,6 +83,8 @@ flush_attribute_channel_values (CtkColorCorrection *, gint, gint);
static void
ctk_color_correction_class_init(CtkColorCorrectionClass *);
+static void ctk_color_correction_finalize(GObject *);
+
static void
apply_parsed_attribute_list(CtkColorCorrection *, ParsedAttribute *);
@@ -158,6 +160,8 @@ static void
ctk_color_correction_class_init(CtkColorCorrectionClass
*ctk_color_correction_class)
{
+ GObjectClass *gobject_class = (GObjectClass *)ctk_color_correction_class;
+
signals[CHANGED] =
g_signal_new("changed",
G_OBJECT_CLASS_TYPE(ctk_color_correction_class),
@@ -166,6 +170,50 @@ ctk_color_correction_class_init(CtkColorCorrectionClass
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
+ gobject_class->finalize = ctk_color_correction_finalize;
+}
+
+
+static void ctk_color_correction_finalize(GObject *object)
+{
+ CtkColorCorrection *ctk_color_correction = CTK_COLOR_CORRECTION(object);
+
+ if (ctk_color_correction->confirm_timer) {
+ /*
+ * This situation comes, if user perform VT-switching
+ * without confirmation of color-correction settings.
+ */
+ gint attr, ch;
+ unsigned int channels = 0;
+ unsigned int attributes = 0;
+
+ /* kill the timer */
+ g_source_remove(ctk_color_correction->confirm_timer);
+ ctk_color_correction->confirm_timer = 0;
+
+ /*
+ * Reset color settings to previous state,
+ * since user did not confirm settings yet.
+ */
+ for (attr = CONTRAST_INDEX; attr <= GAMMA_INDEX; attr++) {
+ for (ch = RED; ch <= ALL_CHANNELS_INDEX; ch++) {
+ /* Check for attribute channel value change. */
+ int index = attr - CONTRAST_INDEX;
+
+ ctk_color_correction->cur_slider_val[index][ch] =
+ ctk_color_correction->prev_slider_val[index][ch];
+
+ attributes |= (1 << attr);
+ channels |= (1 << ch);
+ }
+ }
+
+ NvCtrlSetColorAttributes(ctk_color_correction->handle,
+ ctk_color_correction->cur_slider_val[CONTRAST],
+ ctk_color_correction->cur_slider_val[BRIGHTNESS],
+ ctk_color_correction->cur_slider_val[GAMMA],
+ attributes | channels);
+ }
}
diff --git a/src/jansson/dump.c b/src/jansson/dump.c
index 2c7dee9..7eddd5a 100644
--- a/src/jansson/dump.c
+++ b/src/jansson/dump.c
@@ -1,11 +1,14 @@
/*
- * Copyright (c) 2009-2012 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2014 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.
*/
+#ifndef _GNU_SOURCE
#define _GNU_SOURCE
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -38,7 +41,7 @@ static int dump_to_file(const char *buffer, size_t size, void *data)
}
/* 32 spaces (the maximum indentation size) */
-static char whitespace[] = " ";
+static const char whitespace[] = " ";
static int dump_indent(size_t flags, int depth, int space, json_dump_callback_t dump, void *data)
{
@@ -62,24 +65,25 @@ static int dump_indent(size_t flags, int depth, int space, json_dump_callback_t
return 0;
}
-static int dump_string(const char *str, json_dump_callback_t dump, void *data, size_t flags)
+static int dump_string(const char *str, size_t len, json_dump_callback_t dump, void *data, size_t flags)
{
- const char *pos, *end;
+ const char *pos, *end, *lim;
int32_t codepoint;
if(dump("\"", 1, data))
return -1;
end = pos = str;
+ lim = str + len;
while(1)
{
const char *text;
char seq[13];
int length;
- while(*end)
+ while(end < lim)
{
- end = utf8_iterate(pos, &codepoint);
+ end = utf8_iterate(pos, lim - pos, &codepoint);
if(!end)
return -1;
@@ -123,7 +127,7 @@ static int dump_string(const char *str, json_dump_callback_t dump, void *data, s
/* codepoint is in BMP */
if(codepoint < 0x10000)
{
- sprintf(seq, "\\u%04x", codepoint);
+ sprintf(seq, "\\u%04X", codepoint);
length = 6;
}
@@ -136,7 +140,7 @@ static int dump_string(const char *str, json_dump_callback_t dump, void *data, s
first = 0xD800 | ((codepoint & 0xffc00) >> 10);
last = 0xDC00 | (codepoint & 0x003ff);
- sprintf(seq, "\\u%04x\\u%04x", first, last);
+ sprintf(seq, "\\u%04X\\u%04X", first, last);
length = 12;
}
@@ -171,6 +175,9 @@ static int object_key_compare_serials(const void *key1, const void *key2)
static int do_dump(const json_t *json, size_t flags, int depth,
json_dump_callback_t dump, void *data)
{
+ if(!json)
+ return -1;
+
switch(json_typeof(json)) {
case JSON_NULL:
return dump("null", 4, data);
@@ -209,7 +216,7 @@ static int do_dump(const json_t *json, size_t flags, int depth,
}
case JSON_STRING:
- return dump_string(json_string_value(json), dump, data, flags);
+ return dump_string(json_string_value(json), json_string_length(json), dump, data, flags);
case JSON_ARRAY:
{
@@ -330,7 +337,7 @@ static int do_dump(const json_t *json, size_t flags, int depth,
value = json_object_get(json, key);
assert(value);
- dump_string(key, dump, data, flags);
+ dump_string(key, strlen(key), dump, data, flags);
if(dump(separator, separator_length, data) ||
do_dump(value, flags, depth + 1, dump, data))
{
@@ -366,8 +373,9 @@ static int do_dump(const json_t *json, size_t flags, int depth,
while(iter)
{
void *next = json_object_iter_next((json_t *)json, iter);
+ const char *key = json_object_iter_key(iter);
- dump_string(json_object_iter_key(iter), dump, data, flags);
+ dump_string(key, strlen(key), dump, data, flags);
if(dump(separator, separator_length, data) ||
do_dump(json_object_iter_value(iter), flags, depth + 1,
dump, data))
diff --git a/src/jansson/hashtable.c b/src/jansson/hashtable.c
index bcbaa8c..4c4b565 100644
--- a/src/jansson/hashtable.c
+++ b/src/jansson/hashtable.c
@@ -1,12 +1,21 @@
/*
- * Copyright (c) 2009-2012 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2014 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.
*/
+#if HAVE_CONFIG_H
+#include <jansson_private_config.h>
+#endif
+
#include <stdlib.h>
#include <string.h>
+
+#if HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
#include <jansson_config.h> /* for JSON_INLINE */
#include "jansson_private.h" /* for container_of() */
#include "hashtable.h"
@@ -15,24 +24,13 @@ typedef struct hashtable_list list_t;
typedef struct hashtable_pair pair_t;
typedef struct hashtable_bucket bucket_t;
-#define list_to_pair(list_) container_of(list_, pair_t, list)
-
-/* From http://www.cse.yorku.ca/~oz/hash.html */
-static size_t hash_str(const void *ptr)
-{
- const char *str = (const char *)ptr;
+extern volatile uint32_t hashtable_seed;
- size_t hash = 5381;
- size_t c;
+/* Implementation of the hash function */
+#include "lookup3.h"
- while((c = (size_t)*str))
- {
- hash = ((hash << 5) + hash) + c;
- str++;
- }
-
- return hash;
-}
+#define list_to_pair(list_) container_of(list_, pair_t, list)
+#define hash_str(key) ((size_t)hashlittle((key), strlen(key), hashtable_seed))
static JSON_INLINE void list_init(list_t *list)
{
@@ -74,19 +72,6 @@ static void insert_to_bucket(hashtable_t *hashtable, bucket_t *bucket,
}
}
-static const 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 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 char *key, size_t hash)
{
@@ -120,7 +105,7 @@ static int hashtable_do_del(hashtable_t *hashtable,
bucket_t *bucket;
size_t index;
- index = hash % num_buckets(hashtable);
+ index = hash & hashmask(hashtable->order);
bucket = &hashtable->buckets[index];
pair = hashtable_find_pair(hashtable, bucket, key, hash);
@@ -167,14 +152,14 @@ static int hashtable_do_rehash(hashtable_t *hashtable)
jsonp_free(hashtable->buckets);
- hashtable->num_buckets++;
- new_size = num_buckets(hashtable);
+ hashtable->order++;
+ new_size = hashsize(hashtable->order);
hashtable->buckets = jsonp_malloc(new_size * sizeof(bucket_t));
if(!hashtable->buckets)
return -1;
- for(i = 0; i < num_buckets(hashtable); i++)
+ for(i = 0; i < hashsize(hashtable->order); i++)
{
hashtable->buckets[i].first = hashtable->buckets[i].last =
&hashtable->list;
@@ -199,14 +184,14 @@ int hashtable_init(hashtable_t *hashtable)
size_t i;
hashtable->size = 0;
- hashtable->num_buckets = 0; /* index to primes[] */
- hashtable->buckets = jsonp_malloc(num_buckets(hashtable) * sizeof(bucket_t));
+ hashtable->order = 3;
+ hashtable->buckets = jsonp_malloc(hashsize(hashtable->order) * sizeof(bucket_t));
if(!hashtable->buckets)
return -1;
list_init(&hashtable->list);
- for(i = 0; i < num_buckets(hashtable); i++)
+ for(i = 0; i < hashsize(hashtable->order); i++)
{
hashtable->buckets[i].first = hashtable->buckets[i].last =
&hashtable->list;
@@ -230,12 +215,12 @@ int hashtable_set(hashtable_t *hashtable,
size_t hash, index;
/* rehash if the load ratio exceeds 1 */
- if(hashtable->size >= num_buckets(hashtable))
+ if(hashtable->size >= hashsize(hashtable->order))
if(hashtable_do_rehash(hashtable))
return -1;
hash = hash_str(key);
- index = hash % num_buckets(hashtable);
+ index = hash & hashmask(hashtable->order);
bucket = &hashtable->buckets[index];
pair = hashtable_find_pair(hashtable, bucket, key, hash);
@@ -249,7 +234,14 @@ int hashtable_set(hashtable_t *hashtable,
/* offsetof(...) returns the size of pair_t without the last,
flexible member. This way, the correct amount is
allocated. */
- pair = jsonp_malloc(offsetof(pair_t, key) + strlen(key) + 1);
+
+ size_t len = strlen(key);
+ if(len >= (size_t)-1 - offsetof(pair_t, key)) {
+ /* Avoid an overflow if the key is very long */
+ return -1;
+ }
+
+ pair = jsonp_malloc(offsetof(pair_t, key) + len + 1);
if(!pair)
return -1;
@@ -273,7 +265,7 @@ void *hashtable_get(hashtable_t *hashtable, const char *key)
bucket_t *bucket;
hash = hash_str(key);
- bucket = &hashtable->buckets[hash % num_buckets(hashtable)];
+ bucket = &hashtable->buckets[hash & hashmask(hashtable->order)];
pair = hashtable_find_pair(hashtable, bucket, key, hash);
if(!pair)
@@ -294,7 +286,7 @@ void hashtable_clear(hashtable_t *hashtable)
hashtable_do_clear(hashtable);
- for(i = 0; i < num_buckets(hashtable); i++)
+ for(i = 0; i < hashsize(hashtable->order); i++)
{
hashtable->buckets[i].first = hashtable->buckets[i].last =
&hashtable->list;
@@ -316,7 +308,7 @@ void *hashtable_iter_at(hashtable_t *hashtable, const char *key)
bucket_t *bucket;
hash = hash_str(key);
- bucket = &hashtable->buckets[hash % num_buckets(hashtable)];
+ bucket = &hashtable->buckets[hash & hashmask(hashtable->order)];
pair = hashtable_find_pair(hashtable, bucket, key, hash);
if(!pair)
diff --git a/src/jansson/hashtable.h b/src/jansson/hashtable.h
index de1df26..f54c3fe 100644
--- a/src/jansson/hashtable.h
+++ b/src/jansson/hashtable.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2012 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2014 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.
@@ -32,7 +32,7 @@ struct hashtable_bucket {
typedef struct hashtable {
size_t size;
struct hashtable_bucket *buckets;
- size_t num_buckets; /* index to primes[] */
+ size_t order; /* hashtable has pow(2, order) buckets */
struct hashtable_list list;
} hashtable_t;
@@ -40,6 +40,7 @@ typedef struct hashtable {
#define hashtable_key_to_iter(key_) \
(&(container_of(key_, struct hashtable_pair, key)->list))
+
/**
* hashtable_init - Initialize a hashtable object
*
diff --git a/src/jansson/hashtable_seed.c b/src/jansson/hashtable_seed.c
new file mode 100644
index 0000000..751e0e3
--- /dev/null
+++ b/src/jansson/hashtable_seed.c
@@ -0,0 +1,277 @@
+/* Generate sizeof(uint32_t) bytes of as random data as possible to seed
+ the hash function.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <jansson_private_config.h>
+#endif
+
+#include <stdio.h>
+#include <time.h>
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_SCHED_H
+#include <sched.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#if defined(_WIN32)
+/* For GetModuleHandle(), GetProcAddress() and GetCurrentProcessId() */
+#include <windows.h>
+#endif
+
+#include "jansson.h"
+
+
+static uint32_t buf_to_uint32(char *data) {
+ size_t i;
+ uint32_t result = 0;
+
+ for (i = 0; i < sizeof(uint32_t); i++)
+ result = (result << 8) | (unsigned char)data[i];
+
+ return result;
+}
+
+
+
+/* /dev/urandom */
+#if !defined(_WIN32) && defined(USE_URANDOM)
+static int seed_from_urandom(uint32_t *seed) {
+ /* Use unbuffered I/O if we have open(), close() and read(). Otherwise
+ fall back to fopen() */
+
+ char data[sizeof(uint32_t)];
+ int ok;
+
+#if defined(HAVE_OPEN) && defined(HAVE_CLOSE) && defined(HAVE_READ)
+ int urandom;
+ urandom = open("/dev/urandom", O_RDONLY);
+ if (urandom == -1)
+ return 1;
+
+ ok = read(urandom, data, sizeof(uint32_t)) == sizeof(uint32_t);
+ close(urandom);
+#else
+ FILE *urandom;
+
+ urandom = fopen("/dev/urandom", "rb");
+ if (!urandom)
+ return 1;
+
+ ok = fread(data, 1, sizeof(uint32_t), urandom) == sizeof(uint32_t);
+ fclose(urandom);
+#endif
+
+ if (!ok)
+ return 1;
+
+ *seed = buf_to_uint32(data);
+ return 0;
+}
+#endif
+
+/* Windows Crypto API */
+#if defined(_WIN32) && defined(USE_WINDOWS_CRYPTOAPI)
+#include <wincrypt.h>
+
+typedef BOOL (WINAPI *CRYPTACQUIRECONTEXTA)(HCRYPTPROV *phProv, LPCSTR pszContainer, LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags);
+typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer);
+typedef BOOL (WINAPI *CRYPTRELEASECONTEXT)(HCRYPTPROV hProv, DWORD dwFlags);
+
+static int seed_from_windows_cryptoapi(uint32_t *seed)
+{
+ HINSTANCE hAdvAPI32 = NULL;
+ CRYPTACQUIRECONTEXTA pCryptAcquireContext = NULL;
+ CRYPTGENRANDOM pCryptGenRandom = NULL;
+ CRYPTRELEASECONTEXT pCryptReleaseContext = NULL;
+ HCRYPTPROV hCryptProv = 0;
+ BYTE data[sizeof(uint32_t)];
+ int ok;
+
+ hAdvAPI32 = GetModuleHandle(TEXT("advapi32.dll"));
+ if(hAdvAPI32 == NULL)
+ return 1;
+
+ pCryptAcquireContext = (CRYPTACQUIRECONTEXTA)GetProcAddress(hAdvAPI32, "CryptAcquireContextA");
+ if (!pCryptAcquireContext)
+ return 1;
+
+ pCryptGenRandom = (CRYPTGENRANDOM)GetProcAddress(hAdvAPI32, "CryptGenRandom");
+ if (!pCryptGenRandom)
+ return 1;
+
+ pCryptReleaseContext = (CRYPTRELEASECONTEXT)GetProcAddress(hAdvAPI32, "CryptReleaseContext");
+ if (!pCryptReleaseContext)
+ return 1;
+
+ if (!pCryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
+ return 1;
+
+ ok = pCryptGenRandom(hCryptProv, sizeof(uint32_t), data);
+ pCryptReleaseContext(hCryptProv, 0);
+
+ if (!ok)
+ return 1;
+
+ *seed = buf_to_uint32((char *)data);
+ return 0;
+}
+#endif
+
+/* gettimeofday() and getpid() */
+static int seed_from_timestamp_and_pid(uint32_t *seed) {
+#ifdef HAVE_GETTIMEOFDAY
+ /* XOR of seconds and microseconds */
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ *seed = (uint32_t)tv.tv_sec ^ (uint32_t)tv.tv_usec;
+#else
+ /* Seconds only */
+ *seed = (uint32_t)time(NULL);
+#endif
+
+ /* XOR with PID for more randomness */
+#if defined(_WIN32)
+ *seed ^= (uint32_t)GetCurrentProcessId();
+#elif defined(HAVE_GETPID)
+ *seed ^= (uint32_t)getpid();
+#endif
+
+ return 0;
+}
+
+static uint32_t generate_seed() {
+ uint32_t seed;
+ int done = 0;
+
+#if !defined(_WIN32) && defined(USE_URANDOM)
+ if (!done && seed_from_urandom(&seed) == 0)
+ done = 1;
+#endif
+
+#if defined(_WIN32) && defined(USE_WINDOWS_CRYPTOAPI)
+ if (!done && seed_from_windows_cryptoapi(&seed) == 0)
+ done = 1;
+#endif
+
+ if (!done) {
+ /* Fall back to timestamp and PID if no better randomness is
+ available */
+ seed_from_timestamp_and_pid(&seed);
+ }
+
+ /* Make sure the seed is never zero */
+ if (seed == 0)
+ seed = 1;
+
+ return seed;
+}
+
+
+volatile uint32_t hashtable_seed = 0;
+
+#if defined(HAVE_ATOMIC_BUILTINS) && (defined(HAVE_SCHED_YIELD) || !defined(_WIN32))
+static volatile char seed_initialized = 0;
+
+void json_object_seed(size_t seed) {
+ uint32_t new_seed = (uint32_t)seed;
+
+ if (hashtable_seed == 0) {
+ if (__atomic_test_and_set(&seed_initialized, __ATOMIC_RELAXED) == 0) {
+ /* Do the seeding ourselves */
+ if (new_seed == 0)
+ new_seed = generate_seed();
+
+ __atomic_store_n(&hashtable_seed, new_seed, __ATOMIC_RELEASE);
+ } else {
+ /* Wait for another thread to do the seeding */
+ do {
+#ifdef HAVE_SCHED_YIELD
+ sched_yield();
+#endif
+ } while(__atomic_load_n(&hashtable_seed, __ATOMIC_ACQUIRE) == 0);
+ }
+ }
+}
+#elif defined(HAVE_SYNC_BUILTINS) && (defined(HAVE_SCHED_YIELD) || !defined(_WIN32))
+void json_object_seed(size_t seed) {
+ uint32_t new_seed = (uint32_t)seed;
+
+ if (hashtable_seed == 0) {
+ if (new_seed == 0) {
+ /* Explicit synchronization fences are not supported by the
+ __sync builtins, so every thread getting here has to
+ generate the seed value.
+ */
+ new_seed = generate_seed();
+ }
+
+ do {
+ if (__sync_bool_compare_and_swap(&hashtable_seed, 0, new_seed)) {
+ /* We were the first to seed */
+ break;
+ } else {
+ /* Wait for another thread to do the seeding */
+#ifdef HAVE_SCHED_YIELD
+ sched_yield();
+#endif
+ }
+ } while(hashtable_seed == 0);
+ }
+}
+#elif defined(_WIN32)
+static long seed_initialized = 0;
+void json_object_seed(size_t seed) {
+ uint32_t new_seed = (uint32_t)seed;
+
+ if (hashtable_seed == 0) {
+ if (InterlockedIncrement(&seed_initialized) == 1) {
+ /* Do the seeding ourselves */
+ if (new_seed == 0)
+ new_seed = generate_seed();
+
+ hashtable_seed = new_seed;
+ } else {
+ /* Wait for another thread to do the seeding */
+ do {
+ SwitchToThread();
+ } while (hashtable_seed == 0);
+ }
+ }
+}
+#else
+/* Fall back to a thread-unsafe version */
+void json_object_seed(size_t seed) {
+ uint32_t new_seed = (uint32_t)seed;
+
+ if (hashtable_seed == 0) {
+ if (new_seed == 0)
+ new_seed = generate_seed();
+
+ hashtable_seed = new_seed;
+ }
+}
+#endif
diff --git a/src/jansson/jansson.h b/src/jansson/jansson.h
index 352c6ce..85215f4 100644
--- a/src/jansson/jansson.h
+++ b/src/jansson/jansson.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2012 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2014 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.
@@ -21,11 +21,11 @@ extern "C" {
/* version */
#define JANSSON_MAJOR_VERSION 2
-#define JANSSON_MINOR_VERSION 4
+#define JANSSON_MINOR_VERSION 6
#define JANSSON_MICRO_VERSION 0
/* Micro version is omitted if it's 0 */
-#define JANSSON_VERSION "2.4"
+#define JANSSON_VERSION "2.6"
/* Version as a 3-byte hex number, e.g. 0x010201 == 1.2.1. Use this
for numeric comparisons, e.g. #if JANSSON_VERSION_HEX >= ... */
@@ -47,11 +47,12 @@ typedef enum {
JSON_NULL
} json_type;
-typedef struct {
+typedef struct json_t {
json_type type;
size_t refcount;
} json_t;
+#ifndef JANSSON_USING_CMAKE /* disabled if using cmake */
#if JSON_INTEGER_IS_LONG_LONG
#ifdef _WIN32
#define JSON_INTEGER_FORMAT "I64d"
@@ -63,25 +64,29 @@ typedef long long json_int_t;
#define JSON_INTEGER_FORMAT "ld"
typedef long json_int_t;
#endif /* JSON_INTEGER_IS_LONG_LONG */
+#endif
#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)
-#define json_is_string(json) (json && json_typeof(json) == JSON_STRING)
-#define json_is_integer(json) (json && json_typeof(json) == JSON_INTEGER)
-#define json_is_real(json) (json && json_typeof(json) == JSON_REAL)
+#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_string(json) ((json) && json_typeof(json) == JSON_STRING)
+#define json_is_integer(json) ((json) && json_typeof(json) == JSON_INTEGER)
+#define json_is_real(json) ((json) && json_typeof(json) == JSON_REAL)
#define json_is_number(json) (json_is_integer(json) || json_is_real(json))
-#define json_is_true(json) (json && json_typeof(json) == JSON_TRUE)
-#define json_is_false(json) (json && json_typeof(json) == JSON_FALSE)
+#define json_is_true(json) ((json) && json_typeof(json) == JSON_TRUE)
+#define json_is_false(json) ((json) && json_typeof(json) == JSON_FALSE)
+#define json_boolean_value json_is_true
#define json_is_boolean(json) (json_is_true(json) || json_is_false(json))
-#define json_is_null(json) (json && json_typeof(json) == JSON_NULL)
+#define json_is_null(json) ((json) && json_typeof(json) == JSON_NULL)
/* construction, destruction, reference counting */
json_t *json_object(void);
json_t *json_array(void);
json_t *json_string(const char *value);
+json_t *json_stringn(const char *value, size_t len);
json_t *json_string_nocheck(const char *value);
+json_t *json_stringn_nocheck(const char *value, size_t len);
json_t *json_integer(json_int_t value);
json_t *json_real(double value);
json_t *json_true(void);
@@ -124,6 +129,7 @@ typedef struct {
/* getters, setters, manipulation */
+void json_object_seed(size_t seed);
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);
@@ -146,6 +152,11 @@ int json_object_iter_set_new(json_t *object, void *iter, json_t *value);
key && (value = json_object_iter_value(json_object_key_to_iter(key))); \
key = json_object_iter_key(json_object_iter_next(object, json_object_key_to_iter(key))))
+#define json_array_foreach(array, index, value) \
+ for(index = 0; \
+ index < json_array_size(array) && (value = json_array_get(array, index)); \
+ index++)
+
static JSON_INLINE
int json_object_set(json_t *object, const char *key, json_t *value)
{
@@ -174,9 +185,9 @@ 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, size_t index, json_t *value)
+int json_array_set(json_t *array, size_t ind, json_t *value)
{
- return json_array_set_new(array, index, json_incref(value));
+ return json_array_set_new(array, ind, json_incref(value));
}
static JSON_INLINE
@@ -186,22 +197,24 @@ int json_array_append(json_t *array, json_t *value)
}
static JSON_INLINE
-int json_array_insert(json_t *array, size_t index, json_t *value)
+int json_array_insert(json_t *array, size_t ind, json_t *value)
{
- return json_array_insert_new(array, index, json_incref(value));
+ return json_array_insert_new(array, ind, json_incref(value));
}
const char *json_string_value(const json_t *string);
+size_t json_string_length(const json_t *string);
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_setn(json_t *string, const char *value, size_t len);
int json_string_set_nocheck(json_t *string, const char *value);
+int json_string_setn_nocheck(json_t *string, const char *value, size_t len);
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, ...);
@@ -224,14 +237,16 @@ int json_equal(json_t *value1, json_t *value2);
/* copying */
json_t *json_copy(json_t *value);
-json_t *json_deep_copy(json_t *value);
+json_t *json_deep_copy(const json_t *value);
/* decoding */
-#define JSON_REJECT_DUPLICATES 0x1
-#define JSON_DISABLE_EOF_CHECK 0x2
-#define JSON_DECODE_ANY 0x4
+#define JSON_REJECT_DUPLICATES 0x1
+#define JSON_DISABLE_EOF_CHECK 0x2
+#define JSON_DECODE_ANY 0x4
+#define JSON_DECODE_INT_AS_REAL 0x8
+#define JSON_ALLOW_NUL 0x10
typedef size_t (*json_load_callback_t)(void *buffer, size_t buflen, void *data);
diff --git a/src/jansson/jansson_config.h b/src/jansson/jansson_config.h
index e576cd1..31ad6b3 100644
--- a/src/jansson/jansson_config.h
+++ b/src/jansson/jansson_config.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2012 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2010-2014 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,15 +9,38 @@
* 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.
+ * The CMake system will generate the jansson_config.h file and
+ * copy it to the build and install directories.
*/
#ifndef JANSSON_CONFIG_H
#define JANSSON_CONFIG_H
+/* Define this so that we can disable scattered automake configuration in source files */
+#ifndef JANSSON_USING_CMAKE
+#define JANSSON_USING_CMAKE
+#endif
+
+/* Note: when using cmake, JSON_INTEGER_IS_LONG_LONG is not defined nor used,
+ * as we will also check for __int64 etc types.
+ * (the definition was used in the automake system) */
+
+/* Bring in the cmake-detected defines */
+#define HAVE_STDINT_H 1
+/* #undef HAVE_INTTYPES_H */
+#define HAVE_SYS_TYPES_H 1
+
+/* Include our standard type header for the integer typedef */
+
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#elif defined(HAVE_SYS_TYPES_H)
+# include <sys/types.h>
+#endif
+
+
/* If your compiler supports the inline keyword in C, JSON_INLINE is
defined to `inline', otherwise empty. In C++, the inline is always
supported. */
@@ -27,13 +50,15 @@
#define JSON_INLINE inline
#endif
-/* If your compiler supports the `long long` type and the strtoll()
- library function, JSON_INTEGER_IS_LONG_LONG is defined to 1,
- otherwise to 0. */
-#define JSON_INTEGER_IS_LONG_LONG 1
-/* If locale.h and localeconv() are available, define to 1,
- otherwise to 0. */
+#define json_int_t long long
+#define json_strtoint strtoll
+#define JSON_INTEGER_FORMAT "lld"
+
+
+/* If locale.h and localeconv() are available, define to 1, otherwise to 0. */
#define JSON_HAVE_LOCALECONV 1
+
+
#endif
diff --git a/src/jansson/jansson_private.h b/src/jansson/jansson_private.h
index 7d6d09d..c6f437c 100644
--- a/src/jansson/jansson_private.h
+++ b/src/jansson/jansson_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2012 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2014 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.
@@ -49,6 +49,7 @@ typedef struct {
typedef struct {
json_t json;
char *value;
+ size_t length;
} json_string_t;
typedef struct {
@@ -64,9 +65,13 @@ typedef struct {
#define json_to_object(json_) container_of(json_, json_object_t, json)
#define json_to_array(json_) container_of(json_, json_array_t, json)
#define json_to_string(json_) container_of(json_, json_string_t, json)
-#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)
+/* Create a string by taking ownership of an existing buffer */
+json_t *jsonp_stringn_nocheck_own(const char *value, size_t len);
+
+/* Error message formatting */
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,
@@ -81,7 +86,9 @@ int jsonp_dtostr(char *buffer, size_t size, double value);
/* Wrappers for custom memory functions */
void* jsonp_malloc(size_t size);
void jsonp_free(void *ptr);
+char *jsonp_strndup(const char *str, size_t length);
char *jsonp_strdup(const char *str);
+char *jsonp_strndup(const char *str, size_t len);
/* Windows compatibility */
#ifdef _WIN32
diff --git a/src/jansson/jansson_private_config.h b/src/jansson/jansson_private_config.h
new file mode 100644
index 0000000..cbff15e
--- /dev/null
+++ b/src/jansson/jansson_private_config.h
@@ -0,0 +1,57 @@
+#if defined(NV_LINUX)
+# define HAVE_ENDIAN_H 1
+#endif
+
+/* Prevent value.c from overriding Solaris's builtin isnan() */
+#if defined(NV_SUNOS)
+# define isnan isnan
+#endif
+
+#define HAVE_FCNTL_H 1
+#define HAVE_SCHED_H 1
+#define HAVE_UNISTD_H 1
+#define HAVE_SYS_PARAM_H 1
+#define HAVE_SYS_STAT_H 1
+#define HAVE_SYS_TIME_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_STDINT_H 1
+
+#define HAVE_CLOSE 1
+#define HAVE_GETPID 1
+#define HAVE_GETTIMEOFDAY 1
+#define HAVE_OPEN 1
+#define HAVE_READ 1
+#define HAVE_SCHED_YIELD 1
+
+/* #undef HAVE_SYNC_BUILTINS */
+/* #undef HAVE_ATOMIC_BUILTINS */
+
+#define HAVE_LOCALE_H 1
+#define HAVE_SETLOCALE 1
+
+#define HAVE_INT32_T 1
+#ifndef HAVE_INT32_T
+# define int32_t int32_t
+#endif
+
+#define HAVE_UINT32_T 1
+#ifndef HAVE_UINT32_T
+# define uint32_t uint32_t
+#endif
+
+#define HAVE_SSIZE_T 1
+
+#ifndef HAVE_SSIZE_T
+# define ssize_t
+#endif
+
+#define HAVE_SNPRINTF 1
+
+#ifndef HAVE_SNPRINTF
+# define snprintf snprintf
+#endif
+
+/* #undef HAVE_VSNPRINTF */
+
+#define USE_URANDOM 1
+#define USE_WINDOWS_CRYPTOAPI 1
diff --git a/src/jansson/load.c b/src/jansson/load.c
index d88a704..56c8ee3 100644
--- a/src/jansson/load.c
+++ b/src/jansson/load.c
@@ -1,11 +1,14 @@
/*
- * Copyright (c) 2009-2012 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2014 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.
*/
+#ifndef _GNU_SOURCE
#define _GNU_SOURCE
+#endif
+
#include <errno.h>
#include <limits.h>
#include <stdio.h>
@@ -37,7 +40,7 @@
#define l_isalpha(c) (l_isupper(c) || l_islower(c))
#define l_isdigit(c) ('0' <= (c) && (c) <= '9')
#define l_isxdigit(c) \
- (l_isdigit(c) || 'A' <= (c) || (c) <= 'F' || 'a' <= (c) || (c) <= 'f')
+ (l_isdigit(c) || ('A' <= (c) && (c) <= 'F') || ('a' <= (c) && (c) <= 'f'))
/* Read one byte from stream, convert to unsigned char, then int, and
return. return EOF on end of file. This corresponds to the
@@ -60,7 +63,10 @@ typedef struct {
strbuffer_t saved_text;
int token;
union {
- char *string;
+ struct {
+ char *val;
+ size_t len;
+ } string;
json_int_t integer;
double real;
} value;
@@ -250,9 +256,18 @@ static void lex_unget(lex_t *lex, int c)
static void lex_unget_unsave(lex_t *lex, int c)
{
if(c != STREAM_STATE_EOF && c != STREAM_STATE_ERROR) {
+ /* Since we treat warnings as errors, when assertions are turned
+ * off the "d" variable would be set but never used. Which is
+ * treated as an error by GCC.
+ */
+ #ifndef NDEBUG
char d;
+ #endif
stream_unget(&lex->stream, c);
- d = strbuffer_pop(&lex->saved_text);
+ #ifndef NDEBUG
+ d =
+ #endif
+ strbuffer_pop(&lex->saved_text);
assert(c == d);
}
}
@@ -267,6 +282,13 @@ static void lex_save_cached(lex_t *lex)
}
}
+static void lex_free_string(lex_t *lex)
+{
+ jsonp_free(lex->value.string.val);
+ lex->value.string.val = NULL;
+ lex->value.string.len = 0;
+}
+
/* assumes that str points to 'u' plus at least 4 valid hex digits */
static int32_t decode_unicode_escape(const char *str)
{
@@ -285,7 +307,7 @@ static int32_t decode_unicode_escape(const char *str)
else if(l_isupper(c))
value += c - 'A' + 10;
else
- assert(0);
+ return -1;
}
return value;
@@ -298,7 +320,7 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
char *t;
int i;
- lex->value.string = NULL;
+ lex->value.string.val = NULL;
lex->token = TOKEN_INVALID;
c = lex_get_save(lex, error);
@@ -353,14 +375,12 @@ 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 = jsonp_malloc(lex->saved_text.length + 1);
- if(!lex->value.string) {
+ t = jsonp_malloc(lex->saved_text.length + 1);
+ if(!t) {
/* this is not very nice, since TOKEN_INVALID is returned */
goto out;
}
-
- /* the target */
- t = lex->value.string;
+ lex->value.string.val = t;
/* + 1 to skip the " */
p = strbuffer_value(&lex->saved_text) + 1;
@@ -369,17 +389,24 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
if(*p == '\\') {
p++;
if(*p == 'u') {
- char buffer[4];
- int length;
+ size_t length;
int32_t value;
value = decode_unicode_escape(p);
+ if(value < 0) {
+ error_set(error, lex, "invalid Unicode escape '%.6s'", p - 1);
+ goto out;
+ }
p += 5;
if(0xD800 <= value && value <= 0xDBFF) {
/* surrogate pair */
if(*p == '\\' && *(p + 1) == 'u') {
int32_t value2 = decode_unicode_escape(++p);
+ if(value2 < 0) {
+ error_set(error, lex, "invalid Unicode escape '%.6s'", p - 1);
+ goto out;
+ }
p += 5;
if(0xDC00 <= value2 && value2 <= 0xDFFF) {
@@ -408,16 +435,9 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
error_set(error, lex, "invalid Unicode '\\u%04X'", value);
goto out;
}
- else if(value == 0)
- {
- error_set(error, lex, "\\u0000 is not allowed");
- goto out;
- }
- if(utf8_encode(value, buffer, &length))
+ if(utf8_encode(value, t, &length))
assert(0);
-
- memcpy(t, buffer, length);
t += length;
}
else {
@@ -439,15 +459,17 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
*(t++) = *(p++);
}
*t = '\0';
+ lex->value.string.len = t - lex->value.string.val;
lex->token = TOKEN_STRING;
return;
out:
- jsonp_free(lex->value.string);
+ lex_free_string(lex);
}
+#ifndef JANSSON_USING_CMAKE /* disabled if using cmake */
#if JSON_INTEGER_IS_LONG_LONG
-#ifdef _MSC_VER // Microsoft Visual Studio
+#ifdef _MSC_VER /* Microsoft Visual Studio */
#define json_strtoint _strtoi64
#else
#define json_strtoint strtoll
@@ -455,6 +477,7 @@ out:
#else
#define json_strtoint strtol
#endif
+#endif
static int lex_scan_number(lex_t *lex, int c, json_error_t *error)
{
@@ -557,10 +580,8 @@ static int lex_scan(lex_t *lex, json_error_t *error)
strbuffer_clear(&lex->saved_text);
- if(lex->token == TOKEN_STRING) {
- jsonp_free(lex->value.string);
- lex->value.string = NULL;
- }
+ if(lex->token == TOKEN_STRING)
+ lex_free_string(lex);
c = lex_get(lex, error);
while(c == ' ' || c == '\t' || c == '\n' || c == '\r')
@@ -621,13 +642,14 @@ out:
return lex->token;
}
-static char *lex_steal_string(lex_t *lex)
+static char *lex_steal_string(lex_t *lex, size_t *out_len)
{
char *result = NULL;
- if(lex->token == TOKEN_STRING)
- {
- result = lex->value.string;
- lex->value.string = NULL;
+ if(lex->token == TOKEN_STRING) {
+ result = lex->value.string.val;
+ *out_len = lex->value.string.len;
+ lex->value.string.val = NULL;
+ lex->value.string.len = 0;
}
return result;
}
@@ -645,7 +667,7 @@ static int lex_init(lex_t *lex, get_func get, void *data)
static void lex_close(lex_t *lex)
{
if(lex->token == TOKEN_STRING)
- jsonp_free(lex->value.string);
+ lex_free_string(lex);
strbuffer_close(&lex->saved_text);
}
@@ -666,6 +688,7 @@ static json_t *parse_object(lex_t *lex, size_t flags, json_error_t *error)
while(1) {
char *key;
+ size_t len;
json_t *value;
if(lex->token != TOKEN_STRING) {
@@ -673,9 +696,14 @@ static json_t *parse_object(lex_t *lex, size_t flags, json_error_t *error)
goto error;
}
- key = lex_steal_string(lex);
+ key = lex_steal_string(lex, &len);
if(!key)
return NULL;
+ if (memchr(key, '\0', len)) {
+ jsonp_free(key);
+ error_set(error, lex, "NUL byte in object key not supported");
+ goto error;
+ }
if(flags & JSON_REJECT_DUPLICATES) {
if(json_object_get(object, key)) {
@@ -770,15 +798,38 @@ error:
static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error)
{
json_t *json;
+ double value;
switch(lex->token) {
case TOKEN_STRING: {
- json = json_string_nocheck(lex->value.string);
+ const char *value = lex->value.string.val;
+ size_t len = lex->value.string.len;
+
+ if(!(flags & JSON_ALLOW_NUL)) {
+ if(memchr(value, '\0', len)) {
+ error_set(error, lex, "\\u0000 is not allowed without JSON_ALLOW_NUL");
+ return NULL;
+ }
+ }
+
+ json = jsonp_stringn_nocheck_own(value, len);
+ if(json) {
+ lex->value.string.val = NULL;
+ lex->value.string.len = 0;
+ }
break;
}
case TOKEN_INTEGER: {
- json = json_integer(lex->value.integer);
+ if (flags & JSON_DECODE_INT_AS_REAL) {
+ if(jsonp_strtod(&lex->saved_text, &value)) {
+ error_set(error, lex, "real number overflow");
+ return NULL;
+ }
+ json = json_real(value);
+ } else {
+ json = json_integer(lex->value.integer);
+ }
break;
}
diff --git a/src/jansson/lookup3.h b/src/jansson/lookup3.h
new file mode 100644
index 0000000..8847483
--- /dev/null
+++ b/src/jansson/lookup3.h
@@ -0,0 +1,366 @@
+/*
+-------------------------------------------------------------------------------
+lookup3.c, by Bob Jenkins, May 2006, Public Domain.
+
+These are functions for producing 32-bit hashes for hash table lookup.
+hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
+are externally useful functions. Routines to test the hash are included
+if SELF_TEST is defined. You can use this free for any purpose. It's in
+the public domain. It has no warranty.
+
+You probably want to use hashlittle(). hashlittle() and hashbig()
+hash byte arrays. hashlittle() is is faster than hashbig() on
+little-endian machines. Intel and AMD are little-endian machines.
+On second thought, you probably want hashlittle2(), which is identical to
+hashlittle() except it returns two 32-bit hashes for the price of one.
+You could implement hashbig2() if you wanted but I haven't bothered here.
+
+If you want to find a hash of, say, exactly 7 integers, do
+ a = i1; b = i2; c = i3;
+ mix(a,b,c);
+ a += i4; b += i5; c += i6;
+ mix(a,b,c);
+ a += i7;
+ final(a,b,c);
+then use c as the hash value. If you have a variable length array of
+4-byte integers to hash, use hashword(). If you have a byte array (like
+a character string), use hashlittle(). If you have several byte arrays, or
+a mix of things, see the comments above hashlittle().
+
+Why is this so big? I read 12 bytes at a time into 3 4-byte integers,
+then mix those integers. This is fast (you can do a lot more thorough
+mixing with 12*3 instructions on 3 integers than you can with 3 instructions
+on 1 byte), but shoehorning those bytes into integers efficiently is messy.
+-------------------------------------------------------------------------------
+*/
+
+#include <stdlib.h>
+
+#ifdef HAVE_CONFIG_H
+#include <jansson_private_config.h>
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h> /* defines uint32_t etc */
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h> /* attempt to define endianness */
+#endif
+
+#ifdef HAVE_ENDIAN_H
+# include <endian.h> /* attempt to define endianness */
+#endif
+
+/*
+ * My best guess at if you are big-endian or little-endian. This may
+ * need adjustment.
+ */
+#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
+ __BYTE_ORDER == __LITTLE_ENDIAN) || \
+ (defined(i386) || defined(__i386__) || defined(__i486__) || \
+ defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL))
+# define HASH_LITTLE_ENDIAN 1
+# define HASH_BIG_ENDIAN 0
+#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
+ __BYTE_ORDER == __BIG_ENDIAN) || \
+ (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
+# define HASH_LITTLE_ENDIAN 0
+# define HASH_BIG_ENDIAN 1
+#else
+# define HASH_LITTLE_ENDIAN 0
+# define HASH_BIG_ENDIAN 0
+#endif
+
+#define hashsize(n) ((uint32_t)1<<(n))
+#define hashmask(n) (hashsize(n)-1)
+#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
+
+/*
+-------------------------------------------------------------------------------
+mix -- mix 3 32-bit values reversibly.
+
+This is reversible, so any information in (a,b,c) before mix() is
+still in (a,b,c) after mix().
+
+If four pairs of (a,b,c) inputs are run through mix(), or through
+mix() in reverse, there are at least 32 bits of the output that
+are sometimes the same for one pair and different for another pair.
+This was tested for:
+* pairs that differed by one bit, by two bits, in any combination
+ of top bits of (a,b,c), or in any combination of bottom bits of
+ (a,b,c).
+* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
+ the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
+ is commonly produced by subtraction) look like a single 1-bit
+ difference.
+* the base values were pseudorandom, all zero but one bit set, or
+ all zero plus a counter that starts at zero.
+
+Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that
+satisfy this are
+ 4 6 8 16 19 4
+ 9 15 3 18 27 15
+ 14 9 3 7 17 3
+Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing
+for "differ" defined as + with a one-bit base and a two-bit delta. I
+used http://burtleburtle.net/bob/hash/avalanche.html to choose
+the operations, constants, and arrangements of the variables.
+
+This does not achieve avalanche. There are input bits of (a,b,c)
+that fail to affect some output bits of (a,b,c), especially of a. The
+most thoroughly mixed value is c, but it doesn't really even achieve
+avalanche in c.
+
+This allows some parallelism. Read-after-writes are good at doubling
+the number of bits affected, so the goal of mixing pulls in the opposite
+direction as the goal of parallelism. I did what I could. Rotates
+seem to cost as much as shifts on every machine I could lay my hands
+on, and rotates are much kinder to the top and bottom bits, so I used
+rotates.
+-------------------------------------------------------------------------------
+*/
+#define mix(a,b,c) \
+{ \
+ a -= c; a ^= rot(c, 4); c += b; \
+ b -= a; b ^= rot(a, 6); a += c; \
+ c -= b; c ^= rot(b, 8); b += a; \
+ a -= c; a ^= rot(c,16); c += b; \
+ b -= a; b ^= rot(a,19); a += c; \
+ c -= b; c ^= rot(b, 4); b += a; \
+}
+
+/*
+-------------------------------------------------------------------------------
+final -- final mixing of 3 32-bit values (a,b,c) into c
+
+Pairs of (a,b,c) values differing in only a few bits will usually
+produce values of c that look totally different. This was tested for
+* pairs that differed by one bit, by two bits, in any combination
+ of top bits of (a,b,c), or in any combination of bottom bits of
+ (a,b,c).
+* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
+ the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
+ is commonly produced by subtraction) look like a single 1-bit
+ difference.
+* the base values were pseudorandom, all zero but one bit set, or
+ all zero plus a counter that starts at zero.
+
+These constants passed:
+ 14 11 25 16 4 14 24
+ 12 14 25 16 4 14 24
+and these came close:
+ 4 8 15 26 3 22 24
+ 10 8 15 26 3 22 24
+ 11 8 15 26 3 22 24
+-------------------------------------------------------------------------------
+*/
+#define final(a,b,c) \
+{ \
+ c ^= b; c -= rot(b,14); \
+ a ^= c; a -= rot(c,11); \
+ b ^= a; b -= rot(a,25); \
+ c ^= b; c -= rot(b,16); \
+ a ^= c; a -= rot(c,4); \
+ b ^= a; b -= rot(a,14); \
+ c ^= b; c -= rot(b,24); \
+}
+
+/*
+-------------------------------------------------------------------------------
+hashlittle() -- hash a variable-length key into a 32-bit value
+ k : the key (the unaligned variable-length array of bytes)
+ length : the length of the key, counting by bytes
+ initval : can be any 4-byte value
+Returns a 32-bit value. Every bit of the key affects every bit of
+the return value. Two keys differing by one or two bits will have
+totally different hash values.
+
+The best hash table sizes are powers of 2. There is no need to do
+mod a prime (mod is sooo slow!). If you need less than 32 bits,
+use a bitmask. For example, if you need only 10 bits, do
+ h = (h & hashmask(10));
+In which case, the hash table should have hashsize(10) elements.
+
+If you are hashing n strings (uint8_t **)k, do it like this:
+ for (i=0, h=0; i<n; ++i) h = hashlittle( k[i], len[i], h);
+
+By Bob Jenkins, 2006. bob_jenkins@burtleburtle.net. You may use this
+code any way you wish, private, educational, or commercial. It's free.
+
+Use for hash table lookup, or anything where one collision in 2^^32 is
+acceptable. Do NOT use for cryptographic purposes.
+-------------------------------------------------------------------------------
+*/
+
+static uint32_t hashlittle(const void *key, size_t length, uint32_t initval)
+{
+ uint32_t a,b,c; /* internal state */
+ union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */
+
+ /* Set up the internal state */
+ a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
+
+ u.ptr = key;
+ if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
+ const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
+
+#ifdef VALGRIND
+ const uint8_t *k8;
+#endif
+
+ /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
+ while (length > 12)
+ {
+ a += k[0];
+ b += k[1];
+ c += k[2];
+ mix(a,b,c);
+ length -= 12;
+ k += 3;
+ }
+
+ /*----------------------------- handle the last (probably partial) block */
+ /*
+ * "k[2]&0xffffff" actually reads beyond the end of the string, but
+ * then masks off the part it's not allowed to read. Because the
+ * string is aligned, the masked-off tail is in the same word as the
+ * rest of the string. Every machine with memory protection I've seen
+ * does it on word boundaries, so is OK with this. But VALGRIND will
+ * still catch it and complain. The masking trick does make the hash
+ * noticably faster for short strings (like English words).
+ */
+#ifndef VALGRIND
+
+ switch(length)
+ {
+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
+ case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
+ case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
+ case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
+ case 8 : b+=k[1]; a+=k[0]; break;
+ case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
+ case 6 : b+=k[1]&0xffff; a+=k[0]; break;
+ case 5 : b+=k[1]&0xff; a+=k[0]; break;
+ case 4 : a+=k[0]; break;
+ case 3 : a+=k[0]&0xffffff; break;
+ case 2 : a+=k[0]&0xffff; break;
+ case 1 : a+=k[0]&0xff; break;
+ case 0 : return c; /* zero length strings require no mixing */
+ }
+
+#else /* make valgrind happy */
+
+ k8 = (const uint8_t *)k;
+ switch(length)
+ {
+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
+ case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
+ case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
+ case 9 : c+=k8[8]; /* fall through */
+ case 8 : b+=k[1]; a+=k[0]; break;
+ case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
+ case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
+ case 5 : b+=k8[4]; /* fall through */
+ case 4 : a+=k[0]; break;
+ case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
+ case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
+ case 1 : a+=k8[0]; break;
+ case 0 : return c;
+ }
+
+#endif /* !valgrind */
+
+ } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
+ const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
+ const uint8_t *k8;
+
+ /*--------------- all but last block: aligned reads and different mixing */
+ while (length > 12)
+ {
+ a += k[0] + (((uint32_t)k[1])<<16);
+ b += k[2] + (((uint32_t)k[3])<<16);
+ c += k[4] + (((uint32_t)k[5])<<16);
+ mix(a,b,c);
+ length -= 12;
+ k += 6;
+ }
+
+ /*----------------------------- handle the last (probably partial) block */
+ k8 = (const uint8_t *)k;
+ switch(length)
+ {
+ case 12: c+=k[4]+(((uint32_t)k[5])<<16);
+ b+=k[2]+(((uint32_t)k[3])<<16);
+ a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
+ case 10: c+=k[4];
+ b+=k[2]+(((uint32_t)k[3])<<16);
+ a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 9 : c+=k8[8]; /* fall through */
+ case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
+ a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
+ case 6 : b+=k[2];
+ a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 5 : b+=k8[4]; /* fall through */
+ case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
+ case 2 : a+=k[0];
+ break;
+ case 1 : a+=k8[0];
+ break;
+ case 0 : return c; /* zero length requires no mixing */
+ }
+
+ } else { /* need to read the key one byte at a time */
+ const uint8_t *k = (const uint8_t *)key;
+
+ /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
+ while (length > 12)
+ {
+ a += k[0];
+ a += ((uint32_t)k[1])<<8;
+ a += ((uint32_t)k[2])<<16;
+ a += ((uint32_t)k[3])<<24;
+ b += k[4];
+ b += ((uint32_t)k[5])<<8;
+ b += ((uint32_t)k[6])<<16;
+ b += ((uint32_t)k[7])<<24;
+ c += k[8];
+ c += ((uint32_t)k[9])<<8;
+ c += ((uint32_t)k[10])<<16;
+ c += ((uint32_t)k[11])<<24;
+ mix(a,b,c);
+ length -= 12;
+ k += 12;
+ }
+
+ /*-------------------------------- last block: affect all 32 bits of (c) */
+ switch(length) /* all the case statements fall through */
+ {
+ case 12: c+=((uint32_t)k[11])<<24;
+ case 11: c+=((uint32_t)k[10])<<16;
+ case 10: c+=((uint32_t)k[9])<<8;
+ case 9 : c+=k[8];
+ case 8 : b+=((uint32_t)k[7])<<24;
+ case 7 : b+=((uint32_t)k[6])<<16;
+ case 6 : b+=((uint32_t)k[5])<<8;
+ case 5 : b+=k[4];
+ case 4 : a+=((uint32_t)k[3])<<24;
+ case 3 : a+=((uint32_t)k[2])<<16;
+ case 2 : a+=((uint32_t)k[1])<<8;
+ case 1 : a+=k[0];
+ break;
+ case 0 : return c;
+ }
+ }
+
+ final(a,b,c);
+ return c;
+}
diff --git a/src/jansson/memory.c b/src/jansson/memory.c
index 543ecc4..ca44d6b 100644
--- a/src/jansson/memory.c
+++ b/src/jansson/memory.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2012 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>
* Copyright (c) 2011-2012 Basile Starynkevitch <basile@starynkevitch.net>
*
* Jansson is free software; you can redistribute it and/or modify it
@@ -12,6 +12,10 @@
#include "jansson.h"
#include "jansson_private.h"
+/* C89 allows these to be macros */
+#undef malloc
+#undef free
+
/* memory function pointers */
static json_malloc_t do_malloc = malloc;
static json_free_t do_free = free;
@@ -34,13 +38,19 @@ void jsonp_free(void *ptr)
char *jsonp_strdup(const char *str)
{
+ return jsonp_strndup(str, strlen(str));
+}
+
+char *jsonp_strndup(const char *str, size_t len)
+{
char *new_str;
- new_str = jsonp_malloc(strlen(str) + 1);
+ new_str = jsonp_malloc(len + 1);
if(!new_str)
return NULL;
- strcpy(new_str, str);
+ memcpy(new_str, str, len);
+ new_str[len] = '\0';
return new_str;
}
diff --git a/src/jansson/pack_unpack.c b/src/jansson/pack_unpack.c
index 39db9b8..af381a5 100644
--- a/src/jansson/pack_unpack.c
+++ b/src/jansson/pack_unpack.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2012 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>
* Copyright (c) 2011-2012 Graeme Smecher <graeme.smecher@mail.mcgill.ca>
*
* Jansson is free software; you can redistribute it and/or modify
@@ -12,16 +12,28 @@
#include "utf.h"
typedef struct {
+ int line;
+ int column;
+ size_t pos;
+ char token;
+} token_t;
+
+typedef struct {
const char *start;
const char *fmt;
- char token;
+ token_t prev_token;
+ token_t token;
+ token_t next_token;
json_error_t *error;
size_t flags;
int line;
int column;
+ size_t pos;
} scanner_t;
-static const char *type_names[] = {
+#define token(scanner) ((scanner)->token.token)
+
+static const char * const type_names[] = {
"object",
"array",
"string",
@@ -34,7 +46,7 @@ static const char *type_names[] = {
#define type_name(x) type_names[json_typeof(x)]
-static const char *unpack_value_starters = "{[siIbfFOon";
+static const char unpack_value_starters[] = "{[siIbfFOon";
static void scanner_init(scanner_t *s, json_error_t *error,
@@ -43,14 +55,28 @@ static void scanner_init(scanner_t *s, json_error_t *error,
s->error = error;
s->flags = flags;
s->fmt = s->start = fmt;
+ memset(&s->prev_token, 0, sizeof(token_t));
+ memset(&s->token, 0, sizeof(token_t));
+ memset(&s->next_token, 0, sizeof(token_t));
s->line = 1;
s->column = 0;
+ s->pos = 0;
}
static void next_token(scanner_t *s)
{
- const char *t = s->fmt;
+ const char *t;
+ s->prev_token = s->token;
+
+ if(s->next_token.line) {
+ s->token = s->next_token;
+ s->next_token.line = 0;
+ return;
+ }
+
+ t = s->fmt;
s->column++;
+ s->pos++;
/* skip space and ignored chars */
while(*t == ' ' || *t == '\t' || *t == '\n' || *t == ',' || *t == ':') {
@@ -61,23 +87,32 @@ static void next_token(scanner_t *s)
else
s->column++;
+ s->pos++;
t++;
}
- s->token = *t;
+ s->token.token = *t;
+ s->token.line = s->line;
+ s->token.column = s->column;
+ s->token.pos = s->pos;
t++;
s->fmt = t;
}
+static void prev_token(scanner_t *s)
+{
+ s->next_token = s->token;
+ s->token = s->prev_token;
+}
+
static void set_error(scanner_t *s, const char *source, const char *fmt, ...)
{
va_list ap;
- size_t pos;
va_start(ap, fmt);
- pos = (size_t)(s->fmt - s->start);
- jsonp_error_vset(s->error, s->line, s->column, pos, fmt, ap);
+ jsonp_error_vset(s->error, s->token.line, s->token.column, s->token.pos,
+ fmt, ap);
jsonp_error_set_source(s->error, source);
@@ -86,47 +121,135 @@ static void set_error(scanner_t *s, const char *source, const char *fmt, ...)
static json_t *pack(scanner_t *s, va_list *ap);
+
+/* ours will be set to 1 if jsonp_free() must be called for the result
+ afterwards */
+static char *read_string(scanner_t *s, va_list *ap,
+ const char *purpose, size_t *out_len, int *ours)
+{
+ char t;
+ strbuffer_t strbuff;
+ const char *str;
+ size_t length;
+
+ next_token(s);
+ t = token(s);
+ prev_token(s);
+
+ if(t != '#' && t != '%' && t != '+') {
+ /* Optimize the simple case */
+ str = va_arg(*ap, const char *);
+
+ if(!str) {
+ set_error(s, "<args>", "NULL string argument");
+ return NULL;
+ }
+
+ length = strlen(str);
+
+ if(!utf8_check_string(str, length)) {
+ set_error(s, "<args>", "Invalid UTF-8 %s", purpose);
+ return NULL;
+ }
+
+ *out_len = length;
+ *ours = 0;
+ return (char *)str;
+ }
+
+ strbuffer_init(&strbuff);
+
+ while(1) {
+ str = va_arg(*ap, const char *);
+ if(!str) {
+ set_error(s, "<args>", "NULL string argument");
+ strbuffer_close(&strbuff);
+ return NULL;
+ }
+
+ next_token(s);
+
+ if(token(s) == '#') {
+ length = va_arg(*ap, int);
+ }
+ else if(token(s) == '%') {
+ length = va_arg(*ap, size_t);
+ }
+ else {
+ prev_token(s);
+ length = strlen(str);
+ }
+
+ if(strbuffer_append_bytes(&strbuff, str, length) == -1) {
+ set_error(s, "<internal>", "Out of memory");
+ strbuffer_close(&strbuff);
+ return NULL;
+ }
+
+ next_token(s);
+ if(token(s) != '+') {
+ prev_token(s);
+ break;
+ }
+ }
+
+ if(!utf8_check_string(strbuff.value, strbuff.length)) {
+ set_error(s, "<args>", "Invalid UTF-8 %s", purpose);
+ strbuffer_close(&strbuff);
+ return NULL;
+ }
+
+ *out_len = strbuff.length;
+ *ours = 1;
+ return strbuffer_steal_value(&strbuff);
+}
+
static json_t *pack_object(scanner_t *s, va_list *ap)
{
json_t *object = json_object();
next_token(s);
- while(s->token != '}') {
- const char *key;
+ while(token(s) != '}') {
+ char *key;
+ size_t len;
+ int ours;
json_t *value;
- if(!s->token) {
+ if(!token(s)) {
set_error(s, "<format>", "Unexpected end of format string");
goto error;
}
- if(s->token != 's') {
- set_error(s, "<format>", "Expected format 's', got '%c'", s->token);
- goto error;
- }
-
- key = va_arg(*ap, const char *);
- if(!key) {
- set_error(s, "<args>", "NULL object key");
+ if(token(s) != 's') {
+ set_error(s, "<format>", "Expected format 's', got '%c'", token(s));
goto error;
}
- if(!utf8_check_string(key, -1)) {
- set_error(s, "<args>", "Invalid UTF-8 in object key");
+ key = read_string(s, ap, "object key", &len, &ours);
+ if(!key)
goto error;
- }
next_token(s);
value = pack(s, ap);
- if(!value)
+ if(!value) {
+ if(ours)
+ jsonp_free(key);
+
goto error;
+ }
if(json_object_set_new_nocheck(object, key, value)) {
+ if(ours)
+ jsonp_free(key);
+
set_error(s, "<internal>", "Unable to add key \"%s\"", key);
goto error;
}
+ if(ours)
+ jsonp_free(key);
+
next_token(s);
}
@@ -142,10 +265,10 @@ static json_t *pack_array(scanner_t *s, va_list *ap)
json_t *array = json_array();
next_token(s);
- while(s->token != ']') {
+ while(token(s) != ']') {
json_t *value;
- if(!s->token) {
+ if(!token(s)) {
set_error(s, "<format>", "Unexpected end of format string");
goto error;
}
@@ -170,7 +293,7 @@ error:
static json_t *pack(scanner_t *s, va_list *ap)
{
- switch(s->token) {
+ switch(token(s)) {
case '{':
return pack_object(s, ap);
@@ -179,16 +302,18 @@ static json_t *pack(scanner_t *s, va_list *ap)
case 's': /* string */
{
- const char *str = va_arg(*ap, const char *);
- if(!str) {
- set_error(s, "<args>", "NULL string argument");
- return NULL;
- }
- if(!utf8_check_string(str, -1)) {
- set_error(s, "<args>", "Invalid UTF-8 string");
+ char *str;
+ size_t len;
+ int ours;
+
+ str = read_string(s, ap, "string", &len, &ours);
+ if(!str)
return NULL;
- }
- return json_string_nocheck(str);
+
+ if (ours)
+ return jsonp_stringn_nocheck_own(str, len);
+ else
+ return json_stringn_nocheck(str, len);
}
case 'n': /* null */
@@ -214,7 +339,7 @@ static json_t *pack(scanner_t *s, va_list *ap)
default:
set_error(s, "<format>", "Unexpected format character '%c'",
- s->token);
+ token(s));
return NULL;
}
}
@@ -225,6 +350,7 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
{
int ret = -1;
int strict = 0;
+ int gotopt = 0;
/* Use a set (emulated by a hashtable) to check that all object
keys are accessed. Checking that the correct number of keys
@@ -245,30 +371,30 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
}
next_token(s);
- while(s->token != '}') {
+ while(token(s) != '}') {
const char *key;
json_t *value;
int opt = 0;
if(strict != 0) {
set_error(s, "<format>", "Expected '}' after '%c', got '%c'",
- (strict == 1 ? '!' : '*'), s->token);
+ (strict == 1 ? '!' : '*'), token(s));
goto out;
}
- if(!s->token) {
+ if(!token(s)) {
set_error(s, "<format>", "Unexpected end of format string");
goto out;
}
- if(s->token == '!' || s->token == '*') {
- strict = (s->token == '!' ? 1 : -1);
+ if(token(s) == '!' || token(s) == '*') {
+ strict = (token(s) == '!' ? 1 : -1);
next_token(s);
continue;
}
- if(s->token != 's') {
- set_error(s, "<format>", "Expected format 's', got '%c'", s->token);
+ if(token(s) != 's') {
+ set_error(s, "<format>", "Expected format 's', got '%c'", token(s));
goto out;
}
@@ -280,8 +406,8 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
next_token(s);
- if(s->token == '?') {
- opt = 1;
+ if(token(s) == '?') {
+ opt = gotopt = 1;
next_token(s);
}
@@ -307,10 +433,26 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
if(strict == 0 && (s->flags & JSON_STRICT))
strict = 1;
- if(root && strict == 1 && key_set.size != json_object_size(root)) {
- long diff = (long)json_object_size(root) - (long)key_set.size;
- set_error(s, "<validation>", "%li object item(s) left unpacked", diff);
- goto out;
+ if(root && strict == 1) {
+ /* We need to check that all non optional items have been parsed */
+ const char *key;
+ json_t *value;
+ long unpacked = 0;
+ if (gotopt) {
+ /* We have optional keys, we need to iter on each key */
+ json_object_foreach(root, key, value) {
+ if(!hashtable_get(&key_set, key)) {
+ unpacked++;
+ }
+ }
+ } else {
+ /* No optional keys, we can just compare the number of items */
+ unpacked = (long)json_object_size(root) - (long)key_set.size;
+ }
+ if (unpacked) {
+ set_error(s, "<validation>", "%li object item(s) left unpacked", unpacked);
+ goto out;
+ }
}
ret = 0;
@@ -331,30 +473,30 @@ static int unpack_array(scanner_t *s, json_t *root, va_list *ap)
}
next_token(s);
- while(s->token != ']') {
+ while(token(s) != ']') {
json_t *value;
if(strict != 0) {
set_error(s, "<format>", "Expected ']' after '%c', got '%c'",
(strict == 1 ? '!' : '*'),
- s->token);
+ token(s));
return -1;
}
- if(!s->token) {
+ if(!token(s)) {
set_error(s, "<format>", "Unexpected end of format string");
return -1;
}
- if(s->token == '!' || s->token == '*') {
- strict = (s->token == '!' ? 1 : -1);
+ if(token(s) == '!' || token(s) == '*') {
+ strict = (token(s) == '!' ? 1 : -1);
next_token(s);
continue;
}
- if(!strchr(unpack_value_starters, s->token)) {
+ if(!strchr(unpack_value_starters, token(s))) {
set_error(s, "<format>", "Unexpected format character '%c'",
- s->token);
+ token(s));
return -1;
}
@@ -392,7 +534,7 @@ static int unpack_array(scanner_t *s, json_t *root, va_list *ap)
static int unpack(scanner_t *s, json_t *root, va_list *ap)
{
- switch(s->token)
+ switch(token(s))
{
case '{':
return unpack_object(s, root, ap);
@@ -408,16 +550,32 @@ static int unpack(scanner_t *s, json_t *root, va_list *ap)
}
if(!(s->flags & JSON_VALIDATE_ONLY)) {
- const char **target;
+ const char **str_target;
+ size_t *len_target = NULL;
- target = va_arg(*ap, const char **);
- if(!target) {
+ str_target = va_arg(*ap, const char **);
+ if(!str_target) {
set_error(s, "<args>", "NULL string argument");
return -1;
}
- if(root)
- *target = json_string_value(root);
+ next_token(s);
+
+ if(token(s) == '%') {
+ len_target = va_arg(*ap, size_t *);
+ if(!len_target) {
+ set_error(s, "<args>", "NULL string length argument");
+ return -1;
+ }
+ }
+ else
+ prev_token(s);
+
+ if(root) {
+ *str_target = json_string_value(root);
+ if(len_target)
+ *len_target = json_string_length(root);
+ }
}
return 0;
@@ -521,7 +679,7 @@ static int unpack(scanner_t *s, json_t *root, va_list *ap)
default:
set_error(s, "<format>", "Unexpected format character '%c'",
- s->token);
+ token(s));
return -1;
}
}
@@ -551,7 +709,7 @@ json_t *json_vpack_ex(json_error_t *error, size_t flags,
return NULL;
next_token(&s);
- if(s.token) {
+ if(token(&s)) {
json_decref(value);
set_error(&s, "<format>", "Garbage after format string");
return NULL;
@@ -614,7 +772,7 @@ int json_vunpack_ex(json_t *root, json_error_t *error, size_t flags,
va_end(ap_copy);
next_token(&s);
- if(s.token) {
+ if(token(&s)) {
set_error(&s, "<format>", "Garbage after format string");
return -1;
}
diff --git a/src/jansson/strbuffer.c b/src/jansson/strbuffer.c
index 6d4edd6..b3ddd0e 100644
--- a/src/jansson/strbuffer.c
+++ b/src/jansson/strbuffer.c
@@ -1,11 +1,14 @@
/*
- * Copyright (c) 2009-2012 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2014 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.
*/
+#ifndef _GNU_SOURCE
#define _GNU_SOURCE
+#endif
+
#include <stdlib.h>
#include <string.h>
#include "jansson_private.h"
@@ -31,7 +34,9 @@ int strbuffer_init(strbuffer_t *strbuff)
void strbuffer_close(strbuffer_t *strbuff)
{
- jsonp_free(strbuff->value);
+ if(strbuff->value)
+ jsonp_free(strbuff->value);
+
strbuff->size = 0;
strbuff->length = 0;
strbuff->value = NULL;
@@ -51,7 +56,7 @@ const char *strbuffer_value(const strbuffer_t *strbuff)
char *strbuffer_steal_value(strbuffer_t *strbuff)
{
char *result = strbuff->value;
- strbuffer_init(strbuff);
+ strbuff->value = NULL;
return result;
}
diff --git a/src/jansson/strbuffer.h b/src/jansson/strbuffer.h
index 23f8fff..fc11ec0 100644
--- a/src/jansson/strbuffer.h
+++ b/src/jansson/strbuffer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2012 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2014 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.
@@ -20,6 +20,8 @@ void strbuffer_close(strbuffer_t *strbuff);
void strbuffer_clear(strbuffer_t *strbuff);
const char *strbuffer_value(const strbuffer_t *strbuff);
+
+/* Steal the value and close the strbuffer */
char *strbuffer_steal_value(strbuffer_t *strbuff);
int strbuffer_append(strbuffer_t *strbuff, const char *string);
diff --git a/src/jansson/strconv.c b/src/jansson/strconv.c
index caa9ab8..3a70c6f 100644
--- a/src/jansson/strconv.c
+++ b/src/jansson/strconv.c
@@ -5,6 +5,11 @@
#include "jansson_private.h"
#include "strbuffer.h"
+/* need jansson_private_config.h to get the correct snprintf */
+#ifdef HAVE_CONFIG_H
+#include <jansson_private_config.h>
+#endif
+
#if JSON_HAVE_LOCALECONV
#include <locale.h>
diff --git a/src/jansson/utf.c b/src/jansson/utf.c
index 0359ee2..b56e125 100644
--- a/src/jansson/utf.c
+++ b/src/jansson/utf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2012 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2014 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,7 +8,7 @@
#include <string.h>
#include "utf.h"
-int utf8_encode(int32_t codepoint, char *buffer, int *size)
+int utf8_encode(int32_t codepoint, char *buffer, size_t *size)
{
if(codepoint < 0)
return -1;
@@ -44,7 +44,7 @@ int utf8_encode(int32_t codepoint, char *buffer, int *size)
return 0;
}
-int utf8_check_first(char byte)
+size_t utf8_check_first(char byte)
{
unsigned char u = (unsigned char)byte;
@@ -80,9 +80,9 @@ int utf8_check_first(char byte)
}
}
-int utf8_check_full(const char *buffer, int size, int32_t *codepoint)
+size_t utf8_check_full(const char *buffer, size_t size, int32_t *codepoint)
{
- int i;
+ size_t i;
int32_t value = 0;
unsigned char u = (unsigned char)buffer[0];
@@ -136,12 +136,12 @@ int utf8_check_full(const char *buffer, int size, int32_t *codepoint)
return 1;
}
-const char *utf8_iterate(const char *buffer, int32_t *codepoint)
+const char *utf8_iterate(const char *buffer, size_t bufsize, int32_t *codepoint)
{
- int count;
+ size_t count;
int32_t value;
- if(!*buffer)
+ if(!bufsize)
return buffer;
count = utf8_check_first(buffer[0]);
@@ -152,7 +152,7 @@ const char *utf8_iterate(const char *buffer, int32_t *codepoint)
value = (unsigned char)buffer[0];
else
{
- if(!utf8_check_full(buffer, count, &value))
+ if(count > bufsize || !utf8_check_full(buffer, count, &value))
return NULL;
}
@@ -162,21 +162,18 @@ const char *utf8_iterate(const char *buffer, int32_t *codepoint)
return buffer + count;
}
-int utf8_check_string(const char *string, int length)
+int utf8_check_string(const char *string, size_t length)
{
- int i;
-
- if(length == -1)
- length = strlen(string);
+ size_t i;
for(i = 0; i < length; i++)
{
- int count = utf8_check_first(string[i]);
+ size_t count = utf8_check_first(string[i]);
if(count == 0)
return 0;
else if(count > 1)
{
- if(i + count > length)
+ if(count > length - i)
return 0;
if(!utf8_check_full(&string[i], count, NULL))
diff --git a/src/jansson/utf.h b/src/jansson/utf.h
index 2495cdd..2cebea0 100644
--- a/src/jansson/utf.h
+++ b/src/jansson/utf.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2012 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2014 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,31 +9,19 @@
#define UTF_H
#ifdef HAVE_CONFIG_H
-#include <config.h>
-
-#ifdef HAVE_INTTYPES_H
-/* inttypes.h includes stdint.h in a standard environment, so there's
-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 /* HAVE_INTTYPES_H */
-
-#else /* !HAVE_CONFIG_H */
-#ifdef _WIN32
-typedef int int32_t;
-#else /* !_WIN32 */
-/* Assume a standard environment */
-#include <inttypes.h>
-#endif /* _WIN32 */
+#include <jansson_private_config.h>
+#endif
-#endif /* HAVE_CONFIG_H */
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
-int utf8_encode(int codepoint, char *buffer, int *size);
+int utf8_encode(int32_t codepoint, char *buffer, size_t *size);
-int utf8_check_first(char byte);
-int utf8_check_full(const char *buffer, int size, int32_t *codepoint);
-const char *utf8_iterate(const char *buffer, int32_t *codepoint);
+size_t utf8_check_first(char byte);
+size_t utf8_check_full(const char *buffer, size_t size, int32_t *codepoint);
+const char *utf8_iterate(const char *buffer, size_t size, int32_t *codepoint);
-int utf8_check_string(const char *string, int length);
+int utf8_check_string(const char *string, size_t length);
#endif
diff --git a/src/jansson/value.c b/src/jansson/value.c
index 1a6d902..644bc87 100644
--- a/src/jansson/value.c
+++ b/src/jansson/value.c
@@ -1,17 +1,27 @@
/*
- * Copyright (c) 2009-2012 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2014 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.
*/
+#ifndef _GNU_SOURCE
#define _GNU_SOURCE
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include <jansson_private_config.h>
+#endif
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
#include "jansson.h"
#include "hashtable.h"
#include "jansson_private.h"
@@ -19,12 +29,10 @@
/* Work around nonstandard isnan() and isinf() implementations */
#ifndef isnan
-static JSON_INLINE int jansson_isnan(double x) { return x != x; }
-# define isnan jansson_isnan
+static JSON_INLINE int isnan(double x) { return x != x; }
#endif
#ifndef isinf
-static JSON_INLINE int jansson_isinf(double x) { return !isnan(x) && isnan(x - x); }
-# define isinf jansson_isinf
+static JSON_INLINE int isinf(double x) { return !isnan(x) && isnan(x - x); }
#endif
static JSON_INLINE void json_init(json_t *json, json_type type)
@@ -36,11 +44,19 @@ static JSON_INLINE void json_init(json_t *json, json_type type)
/*** object ***/
+extern volatile uint32_t hashtable_seed;
+
json_t *json_object(void)
{
json_object_t *object = jsonp_malloc(sizeof(json_object_t));
if(!object)
return NULL;
+
+ if (!hashtable_seed) {
+ /* Autoseed */
+ json_object_seed(0);
+ }
+
json_init(&object->json, JSON_OBJECT);
if(hashtable_init(&object->hashtable))
@@ -76,7 +92,7 @@ json_t *json_object_get(const json_t *json, const char *key)
{
json_object_t *object;
- if(!json_is_object(json))
+ if(!key || !json_is_object(json))
return NULL;
object = json_to_object(json);
@@ -108,7 +124,7 @@ int json_object_set_new_nocheck(json_t *json, const char *key, json_t *value)
int json_object_set_new(json_t *json, const char *key, json_t *value)
{
- if(!key || !utf8_check_string(key, -1))
+ if(!key || !utf8_check_string(key, strlen(key)))
{
json_decref(value);
return -1;
@@ -121,7 +137,7 @@ int json_object_del(json_t *json, const char *key)
{
json_object_t *object;
- if(!json_is_object(json))
+ if(!key || !json_is_object(json))
return -1;
object = json_to_object(json);
@@ -292,19 +308,27 @@ static json_t *json_object_copy(json_t *object)
return result;
}
-static json_t *json_object_deep_copy(json_t *object)
+static json_t *json_object_deep_copy(const json_t *object)
{
json_t *result;
-
- const char *key;
- json_t *value;
+ void *iter;
result = json_object();
if(!result)
return NULL;
- json_object_foreach(object, key, value)
+ /* Cannot use json_object_foreach because object has to be cast
+ non-const */
+ iter = json_object_iter((json_t *)object);
+ while(iter) {
+ const char *key;
+ const json_t *value;
+ key = json_object_iter_key(iter);
+ value = json_object_iter_value(iter);
+
json_object_set_new_nocheck(result, key, json_deep_copy(value));
+ iter = json_object_iter_next((json_t *)object, iter);
+ }
return result;
}
@@ -511,7 +535,10 @@ int json_array_remove(json_t *json, size_t index)
json_decref(array->table[index]);
- array_move(array, index, index + 1, array->entries - index);
+ /* If we're removing the last element, nothing has to be moved */
+ if(index < array->entries - 1)
+ array_move(array, index, index + 1, array->entries - index - 1);
+
array->entries--;
return 0;
@@ -592,7 +619,7 @@ static json_t *json_array_copy(json_t *array)
return result;
}
-static json_t *json_array_deep_copy(json_t *array)
+static json_t *json_array_deep_copy(const json_t *array)
{
json_t *result;
size_t i;
@@ -609,33 +636,68 @@ static json_t *json_array_deep_copy(json_t *array)
/*** string ***/
-json_t *json_string_nocheck(const char *value)
+static json_t *string_create(const char *value, size_t len, int own)
{
+ char *v;
json_string_t *string;
if(!value)
return NULL;
+ if(own)
+ v = (char *)value;
+ else {
+ v = jsonp_strndup(value, len);
+ if(!v)
+ return NULL;
+ }
+
string = jsonp_malloc(sizeof(json_string_t));
- if(!string)
+ if(!string) {
+ if(!own)
+ jsonp_free(v);
return NULL;
+ }
json_init(&string->json, JSON_STRING);
+ string->value = v;
+ string->length = len;
+
+ return &string->json;
+}
- string->value = jsonp_strdup(value);
- if(!string->value) {
- jsonp_free(string);
+json_t *json_string_nocheck(const char *value)
+{
+ if(!value)
return NULL;
- }
- return &string->json;
+ return string_create(value, strlen(value), 0);
+}
+
+json_t *json_stringn_nocheck(const char *value, size_t len)
+{
+ return string_create(value, len, 0);
+}
+
+/* this is private; "steal" is not a public API concept */
+json_t *jsonp_stringn_nocheck_own(const char *value, size_t len)
+{
+ return string_create(value, len, 1);
}
json_t *json_string(const char *value)
{
- if(!value || !utf8_check_string(value, -1))
+ if(!value)
+ return NULL;
+
+ return json_stringn(value, strlen(value));
+}
+
+json_t *json_stringn(const char *value, size_t len)
+{
+ if(!value || !utf8_check_string(value, len))
return NULL;
- return json_string_nocheck(value);
+ return json_stringn_nocheck(value, len);
}
const char *json_string_value(const json_t *json)
@@ -646,31 +708,56 @@ const char *json_string_value(const json_t *json)
return json_to_string(json)->value;
}
+size_t json_string_length(const json_t *json)
+{
+ if(!json_is_string(json))
+ return 0;
+
+ return json_to_string(json)->length;
+}
+
int json_string_set_nocheck(json_t *json, const char *value)
{
+ if(!value)
+ return -1;
+
+ return json_string_setn_nocheck(json, value, strlen(value));
+}
+
+int json_string_setn_nocheck(json_t *json, const char *value, size_t len)
+{
char *dup;
json_string_t *string;
if(!json_is_string(json) || !value)
return -1;
- dup = jsonp_strdup(value);
+ dup = jsonp_strndup(value, len);
if(!dup)
return -1;
string = json_to_string(json);
jsonp_free(string->value);
string->value = dup;
+ string->length = len;
return 0;
}
int json_string_set(json_t *json, const char *value)
{
- if(!value || !utf8_check_string(value, -1))
+ if(!value)
return -1;
- return json_string_set_nocheck(json, value);
+ return json_string_setn(json, value, strlen(value));
+}
+
+int json_string_setn(json_t *json, const char *value, size_t len)
+{
+ if(!value || !utf8_check_string(value, len))
+ return -1;
+
+ return json_string_setn_nocheck(json, value, len);
}
static void json_delete_string(json_string_t *string)
@@ -681,12 +768,25 @@ static void json_delete_string(json_string_t *string)
static int json_string_equal(json_t *string1, json_t *string2)
{
- return strcmp(json_string_value(string1), json_string_value(string2)) == 0;
+ json_string_t *s1, *s2;
+
+ if(!json_is_string(string1) || !json_is_string(string2))
+ return 0;
+
+ s1 = json_to_string(string1);
+ s2 = json_to_string(string2);
+ return s1->length == s2->length && !memcmp(s1->value, s2->value, s1->length);
}
-static json_t *json_string_copy(json_t *string)
+static json_t *json_string_copy(const json_t *string)
{
- return json_string_nocheck(json_string_value(string));
+ json_string_t *s;
+
+ if(!json_is_string(string))
+ return NULL;
+
+ s = json_to_string(string);
+ return json_stringn_nocheck(s->value, s->length);
}
@@ -731,7 +831,7 @@ static int json_integer_equal(json_t *integer1, json_t *integer2)
return json_integer_value(integer1) == json_integer_value(integer2);
}
-static json_t *json_integer_copy(json_t *integer)
+static json_t *json_integer_copy(const json_t *integer)
{
return json_integer(json_integer_value(integer));
}
@@ -783,7 +883,7 @@ static int json_real_equal(json_t *real1, json_t *real2)
return json_real_value(real1) == json_real_value(real2);
}
-static json_t *json_real_copy(json_t *real)
+static json_t *json_real_copy(const json_t *real)
{
return json_real(json_real_value(real));
}
@@ -909,7 +1009,7 @@ json_t *json_copy(json_t *json)
return NULL;
}
-json_t *json_deep_copy(json_t *json)
+json_t *json_deep_copy(const json_t *json)
{
if(!json)
return NULL;
@@ -933,7 +1033,7 @@ json_t *json_deep_copy(json_t *json)
return json_real_copy(json);
if(json_is_true(json) || json_is_false(json) || json_is_null(json))
- return json;
+ return (json_t *)json;
return NULL;
}
diff --git a/src/src.mk b/src/src.mk
index 327b41b..1116a21 100644
--- a/src/src.mk
+++ b/src/src.mk
@@ -276,25 +276,28 @@ NVIDIA_SETTINGS_EXTRA_DIST += $(GTK_EXTRA_DIST)
#
# files in the src/jansson directory of nvidia-settings
#
-JANSSON_SRC += jansson/load.c
-JANSSON_SRC += jansson/value.c
-JANSSON_SRC += jansson/pack_unpack.c
-JANSSON_SRC += jansson/utf.c
JANSSON_SRC += jansson/dump.c
-JANSSON_SRC += jansson/strconv.c
-JANSSON_SRC += jansson/strbuffer.c
-JANSSON_SRC += jansson/memory.c
JANSSON_SRC += jansson/error.c
JANSSON_SRC += jansson/hashtable.c
+JANSSON_SRC += jansson/hashtable_seed.c
+JANSSON_SRC += jansson/load.c
+JANSSON_SRC += jansson/memory.c
+JANSSON_SRC += jansson/pack_unpack.c
+JANSSON_SRC += jansson/strbuffer.c
+JANSSON_SRC += jansson/strconv.c
+JANSSON_SRC += jansson/utf.c
+JANSSON_SRC += jansson/value.c
NVIDIA_SETTINGS_SRC += $(JANSSON_SRC)
-JANSSON_EXTRA_DIST += jansson/utf.h
+JANSSON_EXTRA_DIST += jansson/hashtable.h
JANSSON_EXTRA_DIST += jansson/jansson_config.h
-JANSSON_EXTRA_DIST += jansson/strbuffer.h
JANSSON_EXTRA_DIST += jansson/jansson.h
-JANSSON_EXTRA_DIST += jansson/hashtable.h
+JANSSON_EXTRA_DIST += jansson/jansson_private_config.h
JANSSON_EXTRA_DIST += jansson/jansson_private.h
+JANSSON_EXTRA_DIST += jansson/lookup3.h
+JANSSON_EXTRA_DIST += jansson/strbuffer.h
+JANSSON_EXTRA_DIST += jansson/utf.h
NVIDIA_SETTINGS_EXTRA_DIST += $(JANSSON_EXTRA_DIST)
diff --git a/src/version.mk b/src/version.mk
index 1012493..bb1a5bc 100644
--- a/src/version.mk
+++ b/src/version.mk
@@ -1 +1 @@
-NVIDIA_VERSION = 331.49
+NVIDIA_VERSION = 331.67
diff --git a/version.mk b/version.mk
index 1012493..bb1a5bc 100644
--- a/version.mk
+++ b/version.mk
@@ -1 +1 @@
-NVIDIA_VERSION = 331.49
+NVIDIA_VERSION = 331.67