summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Plattner <aplattner@nvidia.com>2019-04-23 11:11:51 -0700
committerAaron Plattner <aplattner@nvidia.com>2019-04-23 11:11:51 -0700
commit6750128dd06d682d260355d49692ceda2f352ef4 (patch)
treeb63b1dc0b41509e0c56585338c0b87109f5f2b04
parentf2a3b63791beb6b5a7e509de457c690a96667395 (diff)
430.09430.09
-rw-r--r--doc/version.mk2
-rw-r--r--samples/version.mk2
-rw-r--r--src/XF86Config-parser/Generate.c10
-rw-r--r--src/gtk+-2.x/ctkappprofile.c4
-rw-r--r--src/gtk+-2.x/ctkframelock.c4
-rw-r--r--src/gtk+-2.x/ctkgridlicense.c15
-rw-r--r--src/gtk+-2.x/ctkscale.c2
-rw-r--r--src/gtk+-2.x/ctkvdpau.c8
-rw-r--r--src/jansson/dump.c212
-rw-r--r--src/jansson/error.c21
-rw-r--r--src/jansson/hashtable.c56
-rw-r--r--src/jansson/hashtable.h25
-rw-r--r--src/jansson/hashtable_seed.c6
-rw-r--r--src/jansson/jansson.h137
-rw-r--r--src/jansson/jansson_config.h12
-rw-r--r--src/jansson/jansson_private.h38
-rw-r--r--src/jansson/jansson_private_config.h20
-rw-r--r--src/jansson/load.c208
-rw-r--r--src/jansson/lookup3.h39
-rw-r--r--src/jansson/memory.c10
-rw-r--r--src/jansson/pack_unpack.c333
-rw-r--r--src/jansson/strbuffer.c7
-rw-r--r--src/jansson/strbuffer.h7
-rw-r--r--src/jansson/strconv.c17
-rw-r--r--src/jansson/utf.c2
-rw-r--r--src/jansson/utf.h2
-rw-r--r--src/jansson/value.c227
-rw-r--r--src/libXNVCtrl/version.mk2
-rw-r--r--src/nvml.h64
-rw-r--r--src/version.h2
-rw-r--r--src/version.mk2
-rw-r--r--version.mk2
32 files changed, 973 insertions, 525 deletions
diff --git a/doc/version.mk b/doc/version.mk
index 6942222..5e94d96 100644
--- a/doc/version.mk
+++ b/doc/version.mk
@@ -1 +1 @@
-NVIDIA_VERSION = 418.56
+NVIDIA_VERSION = 430.09
diff --git a/samples/version.mk b/samples/version.mk
index 6942222..5e94d96 100644
--- a/samples/version.mk
+++ b/samples/version.mk
@@ -1 +1 @@
-NVIDIA_VERSION = 418.56
+NVIDIA_VERSION = 430.09
diff --git a/src/XF86Config-parser/Generate.c b/src/XF86Config-parser/Generate.c
index 1f8ffca..b446558 100644
--- a/src/XF86Config-parser/Generate.c
+++ b/src/XF86Config-parser/Generate.c
@@ -426,16 +426,6 @@ XConfigMonitorPtr xconfigAddMonitor(XConfigPtr config, int count)
monitor->vendor = xconfigStrdup("Unknown"); /* XXX */
monitor->modelname = xconfigStrdup("Unknown"); /* XXX */
- /* XXX check EDID for freq ranges */
-
- monitor->n_hsync = 1;
- monitor->hsync[0].lo = 28.0;
- monitor->hsync[0].hi = 33.0;
-
- monitor->n_vrefresh = 1;
- monitor->vrefresh[0].lo = 43.0;
- monitor->vrefresh[0].hi = 72.0;
-
monitor->options = NULL;
xconfigAddNewOption(&monitor->options, "DPMS", NULL);
diff --git a/src/gtk+-2.x/ctkappprofile.c b/src/gtk+-2.x/ctkappprofile.c
index b070f02..b6253d7 100644
--- a/src/gtk+-2.x/ctkappprofile.c
+++ b/src/gtk+-2.x/ctkappprofile.c
@@ -2030,7 +2030,7 @@ static EditRuleDialog* edit_rule_dialog_new(CtkAppProfile *ctk_app_profile)
dialog->parent = GTK_WIDGET(ctk_app_profile);
dialog->top_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_window_set_modal(GTK_WINDOW(dialog->top_window), TRUE);
+ gtk_window_set_modal(GTK_WINDOW(dialog->top_window), FALSE);
g_signal_connect(G_OBJECT(dialog->top_window), "delete-event",
G_CALLBACK(edit_rule_dialog_handle_delete), dialog);
@@ -2996,7 +2996,7 @@ static EditProfileDialog *edit_profile_dialog_new(CtkAppProfile *ctk_app_profile
dialog->setting_toolbar_help_data = NULL;
dialog->bottom_help_data = NULL;
- gtk_window_set_modal(GTK_WINDOW(dialog->top_window), TRUE);
+ gtk_window_set_modal(GTK_WINDOW(dialog->top_window), FALSE);
g_signal_connect(G_OBJECT(dialog->top_window), "delete-event",
G_CALLBACK(edit_profile_dialog_handle_delete), dialog);
diff --git a/src/gtk+-2.x/ctkframelock.c b/src/gtk+-2.x/ctkframelock.c
index 6f51e23..12bd8ff 100644
--- a/src/gtk+-2.x/ctkframelock.c
+++ b/src/gtk+-2.x/ctkframelock.c
@@ -4328,7 +4328,7 @@ static void display_state_received(GObject *object,
if (!display_entry ||
!display_entry->data ||
- !display_entry->data_type != ENTRY_DATA_DISPLAY) {
+ display_entry->data_type != ENTRY_DATA_DISPLAY) {
return;
}
@@ -4383,7 +4383,7 @@ static void gpu_state_received(GObject *object,
if (!gpu_entry ||
!gpu_entry->data ||
- !gpu_entry->data_type != ENTRY_DATA_GPU) {
+ gpu_entry->data_type != ENTRY_DATA_GPU) {
return;
}
diff --git a/src/gtk+-2.x/ctkgridlicense.c b/src/gtk+-2.x/ctkgridlicense.c
index 4280b08..2d36867 100644
--- a/src/gtk+-2.x/ctkgridlicense.c
+++ b/src/gtk+-2.x/ctkgridlicense.c
@@ -119,7 +119,7 @@ static gboolean allow_digits(GtkWidget *widget, GdkEvent *event, gpointer user_d
static gboolean enable_disable_ui_controls(GtkWidget *widget, GdkEvent *event, gpointer user_data);
static void update_gui_from_griddconfig(gpointer user_data);
static gboolean licenseStateQueryFailed = FALSE;
-static void get_licensed_feature_information(gpointer user_data);
+static void get_licensable_feature_information(gpointer user_data);
static gboolean is_restart_required(gpointer user_data);
static gboolean queryLicensedFeatureCode = TRUE;
int64_t licensedFeatureCode = NV_GRID_LICENSE_FEATURE_TYPE_VAPP;
@@ -843,7 +843,7 @@ static gboolean update_manage_grid_license_state_info(gpointer user_data)
break;
}
if (queryLicensedFeatureCode == TRUE) {
- get_licensed_feature_information(ctk_manage_grid_license);
+ get_licensable_feature_information(ctk_manage_grid_license);
queryLicensedFeatureCode = FALSE;
}
}
@@ -1080,9 +1080,9 @@ static void apply_clicked(GtkWidget *widget, gpointer user_data)
}
/*
- * get_licensed_feature_information() - Get the details of the feature that is licensed on this system.
+ * get_licensable_feature_information() - Get the details of the supported licensable features on the system.
*/
-static void get_licensed_feature_information(gpointer user_data)
+static void get_licensable_feature_information(gpointer user_data)
{
CtkManageGridLicense *ctk_manage_grid_license = CTK_MANAGE_GRID_LICENSE(user_data);
nvmlGridLicensableFeatures_t *gridLicensableFeatures;
@@ -1107,6 +1107,11 @@ static void get_licensed_feature_information(gpointer user_data)
licensedFeatureCode = gridLicensableFeatures->gridLicensableFeatures[i].featureCode;
break;
}
+ else if (gridLicensableFeatures->gridLicensableFeatures[i].featureState == 0 &&
+ gridLicensableFeatures->gridLicensableFeatures[i].featureCode == NVML_GRID_LICENSE_FEATURE_CODE_VWORKSTATION)
+ {
+ break;
+ }
}
nvfree(gridLicensableFeatures);
}
@@ -1558,7 +1563,7 @@ GtkWidget* ctk_manage_grid_license_new(CtrlTarget *target,
gtk_box_set_spacing(GTK_BOX(ctk_manage_grid_license), 5);
- get_licensed_feature_information(ctk_manage_grid_license);
+ get_licensable_feature_information(ctk_manage_grid_license);
/* banner */
diff --git a/src/gtk+-2.x/ctkscale.c b/src/gtk+-2.x/ctkscale.c
index 5ba439d..f44cf9e 100644
--- a/src/gtk+-2.x/ctkscale.c
+++ b/src/gtk+-2.x/ctkscale.c
@@ -298,7 +298,7 @@ GtkWidget* ctk_scale_new(GtkAdjustment *gtk_adjustment,
gtk_scale_set_draw_value(GTK_SCALE(ctk_scale->gtk_scale), FALSE);
- gtk_scale_set_digits(GTK_SCALE(ctk_scale->gtk_scale), 0);
+ gtk_scale_set_digits(GTK_SCALE(ctk_scale->gtk_scale), 6);
gtk_box_pack_start(GTK_BOX(hbox), ctk_scale->gtk_scale, TRUE, TRUE, 3);
diff --git a/src/gtk+-2.x/ctkvdpau.c b/src/gtk+-2.x/ctkvdpau.c
index 58b756d..64f2d28 100644
--- a/src/gtk+-2.x/ctkvdpau.c
+++ b/src/gtk+-2.x/ctkvdpau.c
@@ -284,6 +284,12 @@ static const Desc ycbcr_types[] = {
{"YUYV", VDP_YCBCR_FORMAT_YUYV, 0},
{"Y8U8V8A8", VDP_YCBCR_FORMAT_Y8U8V8A8, 0},
{"V8U8Y8A8", VDP_YCBCR_FORMAT_V8U8Y8A8, 0},
+#ifdef VDP_YCBCR_FORMAT_Y_UV_444
+ {"Y_UV_444", VDP_YCBCR_FORMAT_Y_UV_444, 0},
+ {"Y_U_V_444", VDP_YCBCR_FORMAT_Y_U_V_444, 0},
+#else
+#warning "Update libvdpau to version 1.2"
+#endif
};
static const size_t ycbcr_type_count = sizeof(ycbcr_types)/sizeof(Desc);
@@ -644,8 +650,8 @@ static int queryDecoderCaps(CtkVDPAU *ctk_vdpau, VdpDevice device,
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
gtk_table_attach(GTK_TABLE(table), label, 4, 5, count+3, count+4,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
+ count++;
}
- count++;
}
return 0;
} /* queryDecoderCaps() */
diff --git a/src/jansson/dump.c b/src/jansson/dump.c
index 7eddd5a..89802c6 100644
--- a/src/jansson/dump.c
+++ b/src/jansson/dump.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2016 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,22 +9,30 @@
#define _GNU_SOURCE
#endif
+#include "jansson_private.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
#include "jansson.h"
-#include "jansson_private.h"
#include "strbuffer.h"
#include "utf.h"
#define MAX_INTEGER_STR_LENGTH 100
#define MAX_REAL_STR_LENGTH 100
-struct object_key {
- size_t serial;
- const char *key;
+#define FLAGS_TO_INDENT(f) ((f) & 0x1F)
+#define FLAGS_TO_PRECISION(f) (((f) >> 11) & 0x1F)
+
+struct buffer {
+ const size_t size;
+ size_t used;
+ char *data;
};
static int dump_to_strbuffer(const char *buffer, size_t size, void *data)
@@ -32,6 +40,17 @@ static int dump_to_strbuffer(const char *buffer, size_t size, void *data)
return strbuffer_append_bytes((strbuffer_t *)data, buffer, size);
}
+static int dump_to_buffer(const char *buffer, size_t size, void *data)
+{
+ struct buffer *buf = (struct buffer *)data;
+
+ if(buf->used + size <= buf->size)
+ memcpy(&buf->data[buf->used], buffer, size);
+
+ buf->used += size;
+ return 0;
+}
+
static int dump_to_file(const char *buffer, size_t size, void *data)
{
FILE *dest = (FILE *)data;
@@ -40,22 +59,36 @@ static int dump_to_file(const char *buffer, size_t size, void *data)
return 0;
}
+static int dump_to_fd(const char *buffer, size_t size, void *data)
+{
+#ifdef HAVE_UNISTD_H
+ int *dest = (int *)data;
+ if(write(*dest, buffer, size) == (ssize_t)size)
+ return 0;
+#endif
+ return -1;
+}
+
/* 32 spaces (the maximum indentation size) */
static const char whitespace[] = " ";
static int dump_indent(size_t flags, int depth, int space, json_dump_callback_t dump, void *data)
{
- if(JSON_INDENT(flags) > 0)
+ if(FLAGS_TO_INDENT(flags) > 0)
{
- int i, ws_count = JSON_INDENT(flags);
+ unsigned int ws_count = FLAGS_TO_INDENT(flags), n_spaces = depth * ws_count;
if(dump("\n", 1, data))
return -1;
- for(i = 0; i < depth; i++)
+ while(n_spaces > 0)
{
- if(dump(whitespace, ws_count, data))
+ int cur_n = n_spaces < sizeof whitespace - 1 ? n_spaces : sizeof whitespace - 1;
+
+ if(dump(whitespace, cur_n, data))
return -1;
+
+ n_spaces -= cur_n;
}
}
else if(space && !(flags & JSON_COMPACT))
@@ -68,7 +101,7 @@ static int dump_indent(size_t flags, int depth, int space, json_dump_callback_t
static int dump_string(const char *str, size_t len, json_dump_callback_t dump, void *data, size_t flags)
{
const char *pos, *end, *lim;
- int32_t codepoint;
+ int32_t codepoint = 0;
if(dump("\"", 1, data))
return -1;
@@ -127,7 +160,7 @@ static int dump_string(const char *str, size_t len, json_dump_callback_t dump, v
/* codepoint is in BMP */
if(codepoint < 0x10000)
{
- sprintf(seq, "\\u%04X", codepoint);
+ snprintf(seq, sizeof(seq), "\\u%04X", (unsigned int)codepoint);
length = 6;
}
@@ -140,7 +173,7 @@ static int dump_string(const char *str, size_t len, json_dump_callback_t dump, v
first = 0xD800 | ((codepoint & 0xffc00) >> 10);
last = 0xDC00 | (codepoint & 0x003ff);
- sprintf(seq, "\\u%04X\\u%04X", first, last);
+ snprintf(seq, sizeof(seq), "\\u%04X\\u%04X", (unsigned int)first, (unsigned int)last);
length = 12;
}
@@ -158,23 +191,27 @@ static int dump_string(const char *str, size_t len, json_dump_callback_t dump, v
return dump("\"", 1, data);
}
-static int object_key_compare_keys(const void *key1, const void *key2)
+static int compare_keys(const void *key1, const void *key2)
{
- return strcmp(((const struct object_key *)key1)->key,
- ((const struct object_key *)key2)->key);
+ return strcmp(*(const char **)key1, *(const char **)key2);
}
-static int object_key_compare_serials(const void *key1, const void *key2)
+static int loop_check(hashtable_t *parents, const json_t *json, char *key, size_t key_size)
{
- size_t a = ((const struct object_key *)key1)->serial;
- size_t b = ((const struct object_key *)key2)->serial;
+ snprintf(key, key_size, "%p", json);
+ if (hashtable_get(parents, key))
+ return -1;
- return a < b ? -1 : a == b ? 0 : 1;
+ return hashtable_set(parents, key, json_null());
}
static int do_dump(const json_t *json, size_t flags, int depth,
- json_dump_callback_t dump, void *data)
+ hashtable_t *parents, json_dump_callback_t dump, void *data)
{
+ int embed = flags & JSON_EMBED;
+
+ flags &= ~JSON_EMBED;
+
if(!json)
return -1;
@@ -208,7 +245,8 @@ static int do_dump(const json_t *json, size_t flags, int depth,
int size;
double value = json_real_value(json);
- size = jsonp_dtostr(buffer, MAX_REAL_STR_LENGTH, value);
+ size = jsonp_dtostr(buffer, MAX_REAL_STR_LENGTH, value,
+ FLAGS_TO_PRECISION(flags));
if(size < 0)
return -1;
@@ -220,59 +258,55 @@ static int do_dump(const json_t *json, size_t flags, int depth,
case JSON_ARRAY:
{
- int i;
- int n;
- json_array_t *array;
+ size_t n;
+ size_t i;
+ /* Space for "0x", double the sizeof a pointer for the hex and a terminator. */
+ char key[2 + (sizeof(json) * 2) + 1];
/* detect circular references */
- array = json_to_array(json);
- if(array->visited)
- goto array_error;
- array->visited = 1;
+ if (loop_check(parents, json, key, sizeof(key)))
+ return -1;
n = json_array_size(json);
- if(dump("[", 1, data))
- goto array_error;
+ if(!embed && dump("[", 1, data))
+ return -1;
if(n == 0) {
- array->visited = 0;
- return dump("]", 1, data);
+ hashtable_del(parents, key);
+ return embed ? 0 : dump("]", 1, data);
}
if(dump_indent(flags, depth + 1, 0, dump, data))
- goto array_error;
+ return -1;
for(i = 0; i < n; ++i) {
if(do_dump(json_array_get(json, i), flags, depth + 1,
- dump, data))
- goto array_error;
+ parents, dump, data))
+ return -1;
if(i < n - 1)
{
if(dump(",", 1, data) ||
dump_indent(flags, depth + 1, 1, dump, data))
- goto array_error;
+ return -1;
}
else
{
if(dump_indent(flags, depth, 0, dump, data))
- goto array_error;
+ return -1;
}
}
- array->visited = 0;
- return dump("]", 1, data);
-
- array_error:
- array->visited = 0;
- return -1;
+ hashtable_del(parents, key);
+ return embed ? 0 : dump("]", 1, data);
}
case JSON_OBJECT:
{
- json_object_t *object;
void *iter;
const char *separator;
int separator_length;
+ /* Space for "0x", double the sizeof a pointer for the hex and a terminator. */
+ char loop_key[2 + (sizeof(json) * 2) + 1];
if(flags & JSON_COMPACT) {
separator = ":";
@@ -284,65 +318,56 @@ static int do_dump(const json_t *json, size_t flags, int depth,
}
/* detect circular references */
- object = json_to_object(json);
- if(object->visited)
- goto object_error;
- object->visited = 1;
+ if (loop_check(parents, json, loop_key, sizeof(loop_key)))
+ return -1;
iter = json_object_iter((json_t *)json);
- if(dump("{", 1, data))
- goto object_error;
+ if(!embed && dump("{", 1, data))
+ return -1;
if(!iter) {
- object->visited = 0;
- return dump("}", 1, data);
+ hashtable_del(parents, loop_key);
+ return embed ? 0 : dump("}", 1, data);
}
if(dump_indent(flags, depth + 1, 0, dump, data))
- goto object_error;
+ return -1;
- if(flags & JSON_SORT_KEYS || flags & JSON_PRESERVE_ORDER)
+ if(flags & JSON_SORT_KEYS)
{
- struct object_key *keys;
+ const char **keys;
size_t size, i;
- int (*cmp_func)(const void *, const void *);
size = json_object_size(json);
- keys = jsonp_malloc(size * sizeof(struct object_key));
+ keys = jsonp_malloc(size * sizeof(const char *));
if(!keys)
- goto object_error;
+ return -1;
i = 0;
while(iter)
{
- keys[i].serial = hashtable_iter_serial(iter);
- keys[i].key = json_object_iter_key(iter);
+ keys[i] = json_object_iter_key(iter);
iter = json_object_iter_next((json_t *)json, iter);
i++;
}
assert(i == size);
- if(flags & JSON_SORT_KEYS)
- cmp_func = object_key_compare_keys;
- else
- cmp_func = object_key_compare_serials;
-
- qsort(keys, size, sizeof(struct object_key), cmp_func);
+ qsort(keys, size, sizeof(const char *), compare_keys);
for(i = 0; i < size; i++)
{
const char *key;
json_t *value;
- key = keys[i].key;
+ key = keys[i];
value = json_object_get(json, key);
assert(value);
dump_string(key, strlen(key), dump, data, flags);
if(dump(separator, separator_length, data) ||
- do_dump(value, flags, depth + 1, dump, data))
+ do_dump(value, flags, depth + 1, parents, dump, data))
{
jsonp_free(keys);
- goto object_error;
+ return -1;
}
if(i < size - 1)
@@ -351,7 +376,7 @@ static int do_dump(const json_t *json, size_t flags, int depth,
dump_indent(flags, depth + 1, 1, dump, data))
{
jsonp_free(keys);
- goto object_error;
+ return -1;
}
}
else
@@ -359,7 +384,7 @@ static int do_dump(const json_t *json, size_t flags, int depth,
if(dump_indent(flags, depth, 0, dump, data))
{
jsonp_free(keys);
- goto object_error;
+ return -1;
}
}
}
@@ -378,31 +403,27 @@ static int do_dump(const json_t *json, size_t flags, int depth,
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))
- goto object_error;
+ parents, dump, data))
+ return -1;
if(next)
{
if(dump(",", 1, data) ||
dump_indent(flags, depth + 1, 1, dump, data))
- goto object_error;
+ return -1;
}
else
{
if(dump_indent(flags, depth, 0, dump, data))
- goto object_error;
+ return -1;
}
iter = next;
}
}
- object->visited = 0;
- return dump("}", 1, data);
-
- object_error:
- object->visited = 0;
- return -1;
+ hashtable_del(parents, loop_key);
+ return embed ? 0 : dump("}", 1, data);
}
default:
@@ -428,11 +449,26 @@ char *json_dumps(const json_t *json, size_t flags)
return result;
}
+size_t json_dumpb(const json_t *json, char *buffer, size_t size, size_t flags)
+{
+ struct buffer buf = { size, 0, buffer };
+
+ if(json_dump_callback(json, dump_to_buffer, (void *)&buf, flags))
+ return 0;
+
+ return buf.used;
+}
+
int json_dumpf(const json_t *json, FILE *output, size_t flags)
{
return json_dump_callback(json, dump_to_file, (void *)output, flags);
}
+int json_dumpfd(const json_t *json, int output, size_t flags)
+{
+ return json_dump_callback(json, dump_to_fd, (void *)&output, flags);
+}
+
int json_dump_file(const json_t *json, const char *path, size_t flags)
{
int result;
@@ -443,16 +479,26 @@ int json_dump_file(const json_t *json, const char *path, size_t flags)
result = json_dumpf(json, output, flags);
- fclose(output);
+ if(fclose(output) != 0)
+ return -1;
+
return result;
}
int json_dump_callback(const json_t *json, json_dump_callback_t callback, void *data, size_t flags)
{
+ int res;
+ hashtable_t parents_set;
+
if(!(flags & JSON_ENCODE_ANY)) {
if(!json_is_array(json) && !json_is_object(json))
return -1;
}
- return do_dump(json, flags, 0, callback, data);
+ if (hashtable_init(&parents_set))
+ return -1;
+ res = do_dump(json, flags, 0, &parents_set, callback, data);
+ hashtable_close(&parents_set);
+
+ return res;
}
diff --git a/src/jansson/error.c b/src/jansson/error.c
index a544a59..f5da6b9 100644
--- a/src/jansson/error.c
+++ b/src/jansson/error.c
@@ -25,26 +25,28 @@ void jsonp_error_set_source(json_error_t *error, const char *source)
length = strlen(source);
if(length < JSON_ERROR_SOURCE_LENGTH)
- strcpy(error->source, source);
+ strncpy(error->source, source, length + 1);
else {
size_t extra = length - JSON_ERROR_SOURCE_LENGTH + 4;
- strcpy(error->source, "...");
- strcpy(error->source + 3, source + extra);
+ memcpy(error->source, "...", 3);
+ strncpy(error->source + 3, source + extra, length - extra + 1);
}
}
void jsonp_error_set(json_error_t *error, int line, int column,
- size_t position, const char *msg, ...)
+ size_t position, enum json_error_code code,
+ const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
- jsonp_error_vset(error, line, column, position, msg, ap);
+ jsonp_error_vset(error, line, column, position, code, 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)
+ size_t position, enum json_error_code code,
+ const char *msg, va_list ap)
{
if(!error)
return;
@@ -56,8 +58,9 @@ void jsonp_error_vset(json_error_t *error, int line, int column,
error->line = line;
error->column = column;
- error->position = position;
+ error->position = (int)position;
- vsnprintf(error->text, JSON_ERROR_TEXT_LENGTH, msg, ap);
- error->text[JSON_ERROR_TEXT_LENGTH - 1] = '\0';
+ vsnprintf(error->text, JSON_ERROR_TEXT_LENGTH - 1, msg, ap);
+ error->text[JSON_ERROR_TEXT_LENGTH - 2] = '\0';
+ error->text[JSON_ERROR_TEXT_LENGTH - 1] = code;
}
diff --git a/src/jansson/hashtable.c b/src/jansson/hashtable.c
index 4c4b565..c819319 100644
--- a/src/jansson/hashtable.c
+++ b/src/jansson/hashtable.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2016 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.
@@ -20,6 +20,10 @@
#include "jansson_private.h" /* for container_of() */
#include "hashtable.h"
+#ifndef INITIAL_HASHTABLE_ORDER
+#define INITIAL_HASHTABLE_ORDER 3
+#endif
+
typedef struct hashtable_list list_t;
typedef struct hashtable_pair pair_t;
typedef struct hashtable_bucket bucket_t;
@@ -30,6 +34,7 @@ extern volatile uint32_t hashtable_seed;
#include "lookup3.h"
#define list_to_pair(list_) container_of(list_, pair_t, list)
+#define ordered_list_to_pair(list_) container_of(list_, pair_t, ordered_list)
#define hash_str(key) ((size_t)hashlittle((key), strlen(key), hashtable_seed))
static JSON_INLINE void list_init(list_t *list)
@@ -122,6 +127,7 @@ static int hashtable_do_del(hashtable_t *hashtable,
bucket->last = pair->list.prev;
list_remove(&pair->list);
+ list_remove(&pair->ordered_list);
json_decref(pair->value);
jsonp_free(pair);
@@ -148,17 +154,20 @@ static int hashtable_do_rehash(hashtable_t *hashtable)
{
list_t *list, *next;
pair_t *pair;
- size_t i, index, new_size;
+ size_t i, index, new_size, new_order;
+ struct hashtable_bucket *new_buckets;
- jsonp_free(hashtable->buckets);
+ new_order = hashtable->order + 1;
+ new_size = hashsize(new_order);
- hashtable->order++;
- new_size = hashsize(hashtable->order);
-
- hashtable->buckets = jsonp_malloc(new_size * sizeof(bucket_t));
- if(!hashtable->buckets)
+ new_buckets = jsonp_malloc(new_size * sizeof(bucket_t));
+ if(!new_buckets)
return -1;
+ jsonp_free(hashtable->buckets);
+ hashtable->buckets = new_buckets;
+ hashtable->order = new_order;
+
for(i = 0; i < hashsize(hashtable->order); i++)
{
hashtable->buckets[i].first = hashtable->buckets[i].last =
@@ -184,12 +193,13 @@ int hashtable_init(hashtable_t *hashtable)
size_t i;
hashtable->size = 0;
- hashtable->order = 3;
+ hashtable->order = INITIAL_HASHTABLE_ORDER;
hashtable->buckets = jsonp_malloc(hashsize(hashtable->order) * sizeof(bucket_t));
if(!hashtable->buckets)
return -1;
list_init(&hashtable->list);
+ list_init(&hashtable->ordered_list);
for(i = 0; i < hashsize(hashtable->order); i++)
{
@@ -206,9 +216,7 @@ void hashtable_close(hashtable_t *hashtable)
jsonp_free(hashtable->buckets);
}
-int hashtable_set(hashtable_t *hashtable,
- const char *key, size_t serial,
- json_t *value)
+int hashtable_set(hashtable_t *hashtable, const char *key, json_t *value)
{
pair_t *pair;
bucket_t *bucket;
@@ -246,12 +254,13 @@ int hashtable_set(hashtable_t *hashtable,
return -1;
pair->hash = hash;
- pair->serial = serial;
- strcpy(pair->key, key);
+ strncpy(pair->key, key, len + 1);
pair->value = value;
list_init(&pair->list);
+ list_init(&pair->ordered_list);
insert_to_bucket(hashtable, bucket, &pair->list);
+ list_insert(&hashtable->ordered_list, &pair->ordered_list);
hashtable->size++;
}
@@ -293,12 +302,13 @@ void hashtable_clear(hashtable_t *hashtable)
}
list_init(&hashtable->list);
+ list_init(&hashtable->ordered_list);
hashtable->size = 0;
}
void *hashtable_iter(hashtable_t *hashtable)
{
- return hashtable_iter_next(hashtable, &hashtable->list);
+ return hashtable_iter_next(hashtable, &hashtable->ordered_list);
}
void *hashtable_iter_at(hashtable_t *hashtable, const char *key)
@@ -314,38 +324,32 @@ void *hashtable_iter_at(hashtable_t *hashtable, const char *key)
if(!pair)
return NULL;
- return &pair->list;
+ return &pair->ordered_list;
}
void *hashtable_iter_next(hashtable_t *hashtable, void *iter)
{
list_t *list = (list_t *)iter;
- if(list->next == &hashtable->list)
+ if(list->next == &hashtable->ordered_list)
return NULL;
return list->next;
}
void *hashtable_iter_key(void *iter)
{
- pair_t *pair = list_to_pair((list_t *)iter);
+ pair_t *pair = ordered_list_to_pair((list_t *)iter);
return pair->key;
}
-size_t hashtable_iter_serial(void *iter)
-{
- pair_t *pair = list_to_pair((list_t *)iter);
- return pair->serial;
-}
-
void *hashtable_iter_value(void *iter)
{
- pair_t *pair = list_to_pair((list_t *)iter);
+ pair_t *pair = ordered_list_to_pair((list_t *)iter);
return pair->value;
}
void hashtable_iter_set(void *iter, json_t *value)
{
- pair_t *pair = list_to_pair((list_t *)iter);
+ pair_t *pair = ordered_list_to_pair((list_t *)iter);
json_decref(pair->value);
pair->value = value;
diff --git a/src/jansson/hashtable.h b/src/jansson/hashtable.h
index f54c3fe..c112834 100644
--- a/src/jansson/hashtable.h
+++ b/src/jansson/hashtable.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -8,6 +8,9 @@
#ifndef HASHTABLE_H
#define HASHTABLE_H
+#include <stdlib.h>
+#include "jansson.h"
+
struct hashtable_list {
struct hashtable_list *prev;
struct hashtable_list *next;
@@ -17,10 +20,10 @@ struct hashtable_list {
key-value pair. In this case, it just encodes some extra data,
too */
struct hashtable_pair {
- size_t hash;
struct hashtable_list list;
+ struct hashtable_list ordered_list;
+ size_t hash;
json_t *value;
- size_t serial;
char key[1];
};
@@ -34,11 +37,12 @@ typedef struct hashtable {
struct hashtable_bucket *buckets;
size_t order; /* hashtable has pow(2, order) buckets */
struct hashtable_list list;
+ struct hashtable_list ordered_list;
} hashtable_t;
#define hashtable_key_to_iter(key_) \
- (&(container_of(key_, struct hashtable_pair, key)->list))
+ (&(container_of(key_, struct hashtable_pair, key)->ordered_list))
/**
@@ -51,7 +55,7 @@ typedef struct hashtable {
*
* Returns 0 on success, -1 on error (out of memory).
*/
-int hashtable_init(hashtable_t *hashtable);
+int hashtable_init(hashtable_t *hashtable) JANSSON_ATTRS(warn_unused_result);
/**
* hashtable_close - Release all resources used by a hashtable object
@@ -77,9 +81,7 @@ void hashtable_close(hashtable_t *hashtable);
*
* Returns 0 on success, -1 on failure (out of memory).
*/
-int hashtable_set(hashtable_t *hashtable,
- const char *key, size_t serial,
- json_t *value);
+int hashtable_set(hashtable_t *hashtable, const char *key, json_t *value);
/**
* hashtable_get - Get a value associated with a key
@@ -157,13 +159,6 @@ void *hashtable_iter_next(hashtable_t *hashtable, void *iter);
void *hashtable_iter_key(void *iter);
/**
- * hashtable_iter_serial - Retrieve the serial number pointed to by an iterator
- *
- * @iter: The iterator
- */
-size_t hashtable_iter_serial(void *iter);
-
-/**
* hashtable_iter_value - Retrieve the value pointed by an iterator
*
* @iter: The iterator
diff --git a/src/jansson/hashtable_seed.c b/src/jansson/hashtable_seed.c
index 751e0e3..540358a 100644
--- a/src/jansson/hashtable_seed.c
+++ b/src/jansson/hashtable_seed.c
@@ -164,16 +164,16 @@ static int seed_from_timestamp_and_pid(uint32_t *seed) {
}
static uint32_t generate_seed() {
- uint32_t seed;
+ uint32_t seed = 0;
int done = 0;
#if !defined(_WIN32) && defined(USE_URANDOM)
- if (!done && seed_from_urandom(&seed) == 0)
+ if (seed_from_urandom(&seed) == 0)
done = 1;
#endif
#if defined(_WIN32) && defined(USE_WINDOWS_CRYPTOAPI)
- if (!done && seed_from_windows_cryptoapi(&seed) == 0)
+ if (seed_from_windows_cryptoapi(&seed) == 0)
done = 1;
#endif
diff --git a/src/jansson/jansson.h b/src/jansson/jansson.h
index 85215f4..e4e73e2 100644
--- a/src/jansson/jansson.h
+++ b/src/jansson/jansson.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
*
* Jansson is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -12,7 +12,7 @@
#include <stdlib.h> /* for size_t */
#include <stdarg.h>
-#include <jansson_config.h>
+#include "jansson_config.h"
#ifdef __cplusplus
extern "C" {
@@ -21,11 +21,11 @@ extern "C" {
/* version */
#define JANSSON_MAJOR_VERSION 2
-#define JANSSON_MINOR_VERSION 6
+#define JANSSON_MINOR_VERSION 12
#define JANSSON_MICRO_VERSION 0
/* Micro version is omitted if it's 0 */
-#define JANSSON_VERSION "2.6"
+#define JANSSON_VERSION "2.12"
/* Version as a 3-byte hex number, e.g. 0x010201 == 1.2.1. Use this
for numeric comparisons, e.g. #if JANSSON_VERSION_HEX >= ... */
@@ -33,6 +33,17 @@ extern "C" {
(JANSSON_MINOR_VERSION << 8) | \
(JANSSON_MICRO_VERSION << 0))
+/* If __atomic or __sync builtins are available the library is thread
+ * safe for all read-only functions plus reference counting. */
+#if JSON_HAVE_ATOMIC_BUILTINS || JSON_HAVE_SYNC_BUILTINS
+#define JANSSON_THREAD_SAFE_REFCOUNT 1
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+#define JANSSON_ATTRS(...) __attribute__((__VA_ARGS__))
+#else
+#define JANSSON_ATTRS(...)
+#endif
/* types */
@@ -49,7 +60,7 @@ typedef enum {
typedef struct json_t {
json_type type;
- size_t refcount;
+ volatile size_t refcount;
} json_t;
#ifndef JANSSON_USING_CMAKE /* disabled if using cmake */
@@ -94,11 +105,23 @@ json_t *json_false(void);
#define json_boolean(val) ((val) ? json_true() : json_false())
json_t *json_null(void);
+/* do not call JSON_INTERNAL_INCREF or JSON_INTERNAL_DECREF directly */
+#if JSON_HAVE_ATOMIC_BUILTINS
+#define JSON_INTERNAL_INCREF(json) __atomic_add_fetch(&json->refcount, 1, __ATOMIC_ACQUIRE)
+#define JSON_INTERNAL_DECREF(json) __atomic_sub_fetch(&json->refcount, 1, __ATOMIC_RELEASE)
+#elif JSON_HAVE_SYNC_BUILTINS
+#define JSON_INTERNAL_INCREF(json) __sync_add_and_fetch(&json->refcount, 1)
+#define JSON_INTERNAL_DECREF(json) __sync_sub_and_fetch(&json->refcount, 1)
+#else
+#define JSON_INTERNAL_INCREF(json) (++json->refcount)
+#define JSON_INTERNAL_DECREF(json) (--json->refcount)
+#endif
+
static JSON_INLINE
json_t *json_incref(json_t *json)
{
if(json && json->refcount != (size_t)-1)
- ++json->refcount;
+ JSON_INTERNAL_INCREF(json);
return json;
}
@@ -108,17 +131,30 @@ void json_delete(json_t *json);
static JSON_INLINE
void json_decref(json_t *json)
{
- if(json && json->refcount != (size_t)-1 && --json->refcount == 0)
+ if(json && json->refcount != (size_t)-1 && JSON_INTERNAL_DECREF(json) == 0)
json_delete(json);
}
+#if defined(__GNUC__) || defined(__clang__)
+static JSON_INLINE
+void json_decrefp(json_t **json)
+{
+ if(json) {
+ json_decref(*json);
+ *json = NULL;
+ }
+}
+
+#define json_auto_t json_t __attribute__((cleanup(json_decrefp)))
+#endif
+
/* error reporting */
#define JSON_ERROR_TEXT_LENGTH 160
#define JSON_ERROR_SOURCE_LENGTH 80
-typedef struct {
+typedef struct json_error_t {
int line;
int column;
int position;
@@ -126,12 +162,36 @@ typedef struct {
char text[JSON_ERROR_TEXT_LENGTH];
} json_error_t;
+enum json_error_code {
+ json_error_unknown,
+ json_error_out_of_memory,
+ json_error_stack_overflow,
+ json_error_cannot_open_file,
+ json_error_invalid_argument,
+ json_error_invalid_utf8,
+ json_error_premature_end_of_input,
+ json_error_end_of_input_expected,
+ json_error_invalid_syntax,
+ json_error_invalid_format,
+ json_error_wrong_type,
+ json_error_null_character,
+ json_error_null_value,
+ json_error_null_byte_in_key,
+ json_error_duplicate_key,
+ json_error_numeric_overflow,
+ json_error_item_not_found,
+ json_error_index_out_of_range
+};
+
+static JSON_INLINE enum json_error_code json_error_code(const json_error_t *e) {
+ return (enum json_error_code)e->text[JSON_ERROR_TEXT_LENGTH - 1];
+}
/* 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);
+json_t *json_object_get(const json_t *object, const char *key) JANSSON_ATTRS(warn_unused_result);
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_del(json_t *object, const char *key);
@@ -152,6 +212,13 @@ 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_object_foreach_safe(object, n, key, value) \
+ for(key = json_object_iter_key(json_object_iter(object)), \
+ n = json_object_iter_next(object, json_object_key_to_iter(key)); \
+ key && (value = json_object_iter_value(json_object_key_to_iter(key))); \
+ key = json_object_iter_key(n), \
+ n = 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)); \
@@ -176,7 +243,7 @@ int json_object_iter_set(json_t *object, void *iter, json_t *value)
}
size_t json_array_size(const json_t *array);
-json_t *json_array_get(const json_t *array, size_t index);
+json_t *json_array_get(const json_t *array, size_t index) JANSSON_ATTRS(warn_unused_result);
int json_array_set_new(json_t *array, size_t index, json_t *value);
int json_array_append_new(json_t *array, json_t *value);
int json_array_insert_new(json_t *array, size_t index, json_t *value);
@@ -217,9 +284,9 @@ 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);
+json_t *json_pack(const char *fmt, ...) JANSSON_ATTRS(warn_unused_result);
+json_t *json_pack_ex(json_error_t *error, size_t flags, const char *fmt, ...) JANSSON_ATTRS(warn_unused_result);
+json_t *json_vpack_ex(json_error_t *error, size_t flags, const char *fmt, va_list ap) JANSSON_ATTRS(warn_unused_result);
#define JSON_VALIDATE_ONLY 0x1
#define JSON_STRICT 0x2
@@ -228,16 +295,21 @@ 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);
+/* sprintf */
+
+json_t *json_sprintf(const char *fmt, ...) JANSSON_ATTRS(warn_unused_result, format(printf, 1, 2));
+json_t *json_vsprintf(const char *fmt, va_list ap) JANSSON_ATTRS(warn_unused_result, format(printf, 1, 0));
+
/* equality */
-int json_equal(json_t *value1, json_t *value2);
+int json_equal(const json_t *value1, const json_t *value2);
/* copying */
-json_t *json_copy(json_t *value);
-json_t *json_deep_copy(const json_t *value);
+json_t *json_copy(json_t *value) JANSSON_ATTRS(warn_unused_result);
+json_t *json_deep_copy(const json_t *value) JANSSON_ATTRS(warn_unused_result);
/* decoding */
@@ -250,27 +322,33 @@ json_t *json_deep_copy(const json_t *value);
typedef size_t (*json_load_callback_t)(void *buffer, size_t buflen, void *data);
-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);
-json_t *json_load_callback(json_load_callback_t callback, void *data, size_t flags, json_error_t *error);
+json_t *json_loads(const char *input, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result);
+json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result);
+json_t *json_loadf(FILE *input, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result);
+json_t *json_loadfd(int input, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result);
+json_t *json_load_file(const char *path, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result);
+json_t *json_load_callback(json_load_callback_t callback, void *data, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result);
/* 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
-#define JSON_ESCAPE_SLASH 0x400
+#define JSON_MAX_INDENT 0x1F
+#define JSON_INDENT(n) ((n) & JSON_MAX_INDENT)
+#define JSON_COMPACT 0x20
+#define JSON_ENSURE_ASCII 0x40
+#define JSON_SORT_KEYS 0x80
+#define JSON_PRESERVE_ORDER 0x100
+#define JSON_ENCODE_ANY 0x200
+#define JSON_ESCAPE_SLASH 0x400
+#define JSON_REAL_PRECISION(n) (((n) & 0x1F) << 11)
+#define JSON_EMBED 0x10000
typedef int (*json_dump_callback_t)(const char *buffer, size_t size, void *data);
-char *json_dumps(const json_t *json, size_t flags);
+char *json_dumps(const json_t *json, size_t flags) JANSSON_ATTRS(warn_unused_result);
+size_t json_dumpb(const json_t *json, char *buffer, size_t size, size_t flags);
int json_dumpf(const json_t *json, FILE *output, size_t flags);
+int json_dumpfd(const json_t *json, int output, size_t flags);
int json_dump_file(const json_t *json, const char *path, size_t flags);
int json_dump_callback(const json_t *json, json_dump_callback_t callback, void *data, size_t flags);
@@ -280,6 +358,7 @@ typedef void *(*json_malloc_t)(size_t);
typedef void (*json_free_t)(void *);
void json_set_alloc_funcs(json_malloc_t malloc_fn, json_free_t free_fn);
+void json_get_alloc_funcs(json_malloc_t *malloc_fn, json_free_t *free_fn);
#ifdef __cplusplus
}
diff --git a/src/jansson/jansson_config.h b/src/jansson/jansson_config.h
index 31ad6b3..b397f20 100644
--- a/src/jansson/jansson_config.h
+++ b/src/jansson/jansson_config.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2014 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2010-2016 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.
@@ -59,6 +59,16 @@
/* If locale.h and localeconv() are available, define to 1, otherwise to 0. */
#define JSON_HAVE_LOCALECONV 1
+/* If __atomic builtins are available they will be used to manage
+ reference counts of json_t. */
+#define JSON_HAVE_ATOMIC_BUILTINS 0
+/* If __atomic builtins are not available we try using __sync builtins
+ to manage reference counts of json_t. */
+#define JSON_HAVE_SYNC_BUILTINS 0
+
+/* Maximum recursion depth for parsing JSON input.
+ This limits the depth of e.g. array-within-array constructions. */
+#define JSON_PARSER_MAX_DEPTH 2048
#endif
diff --git a/src/jansson/jansson_private.h b/src/jansson/jansson_private.h
index c6f437c..bf86c57 100644
--- a/src/jansson/jansson_private.h
+++ b/src/jansson/jansson_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
*
* Jansson is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -8,6 +8,7 @@
#ifndef JANSSON_PRIVATE_H
#define JANSSON_PRIVATE_H
+#include "jansson_private_config.h"
#include <stddef.h>
#include "jansson.h"
#include "hashtable.h"
@@ -34,8 +35,6 @@
typedef struct {
json_t json;
hashtable_t hashtable;
- size_t serial;
- int visited;
} json_object_t;
typedef struct {
@@ -43,7 +42,6 @@ typedef struct {
size_t size;
size_t entries;
json_t **table;
- int visited;
} json_array_t;
typedef struct {
@@ -75,25 +73,37 @@ json_t *jsonp_stringn_nocheck_own(const char *value, size_t len);
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, ...);
+ size_t position, enum json_error_code code,
+ const char *msg, ...);
void jsonp_error_vset(json_error_t *error, int line, int column,
- size_t position, const char *msg, va_list ap);
+ size_t position, enum json_error_code code,
+ const char *msg, va_list ap);
/* Locale independent string<->double conversions */
int jsonp_strtod(strbuffer_t *strbuffer, double *out);
-int jsonp_dtostr(char *buffer, size_t size, double value);
+int jsonp_dtostr(char *buffer, size_t size, double value, int prec);
/* Wrappers for custom memory functions */
-void* jsonp_malloc(size_t size);
+void* jsonp_malloc(size_t size) JANSSON_ATTRS(warn_unused_result);
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);
+char *jsonp_strndup(const char *str, size_t length) JANSSON_ATTRS(warn_unused_result);
+char *jsonp_strdup(const char *str) JANSSON_ATTRS(warn_unused_result);
+char *jsonp_strndup(const char *str, size_t len) JANSSON_ATTRS(warn_unused_result);
+
/* Windows compatibility */
-#ifdef _WIN32
-#define snprintf _snprintf
-#define vsnprintf _vsnprintf
+#if defined(_WIN32) || defined(WIN32)
+# if defined(_MSC_VER) /* MS compiller */
+# if (_MSC_VER < 1900) && !defined(snprintf) /* snprintf not defined yet & not introduced */
+# define snprintf _snprintf
+# endif
+# if (_MSC_VER < 1500) && !defined(vsnprintf) /* vsnprintf not defined yet & not introduced */
+# define vsnprintf(b,c,f,a) _vsnprintf(b,c,f,a)
+# endif
+# else /* Other Windows compiller, old definition */
+# define snprintf _snprintf
+# define vsnprintf _vsnprintf
+# endif
#endif
#endif
diff --git a/src/jansson/jansson_private_config.h b/src/jansson/jansson_private_config.h
index cbff15e..6b51bc0 100644
--- a/src/jansson/jansson_private_config.h
+++ b/src/jansson/jansson_private_config.h
@@ -39,19 +39,23 @@
# define uint32_t uint32_t
#endif
-#define HAVE_SSIZE_T 1
+#define HAVE_UINT16_T 1
+#ifndef HAVE_UINT16_T
+# define uint16_t uint16_t
+#endif
-#ifndef HAVE_SSIZE_T
-# define ssize_t
+#define HAVE_UINT8_T 1
+#ifndef HAVE_UINT8_T
+# define uint8_t uint8_t
#endif
-#define HAVE_SNPRINTF 1
+#define HAVE_SSIZE_T 1
-#ifndef HAVE_SNPRINTF
-# define snprintf snprintf
+#ifndef HAVE_SSIZE_T
+# define ssize_t
#endif
-/* #undef HAVE_VSNPRINTF */
-
#define USE_URANDOM 1
#define USE_WINDOWS_CRYPTOAPI 1
+
+#define INITIAL_HASHTABLE_ORDER 3
diff --git a/src/jansson/load.c b/src/jansson/load.c
index 56c8ee3..8700919 100644
--- a/src/jansson/load.c
+++ b/src/jansson/load.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2016 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,19 @@
#define _GNU_SOURCE
#endif
+#include "jansson_private.h"
+
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
#include "jansson.h"
-#include "jansson_private.h"
#include "strbuffer.h"
#include "utf.h"
@@ -61,6 +65,8 @@ typedef struct {
typedef struct {
stream_t stream;
strbuffer_t saved_text;
+ size_t flags;
+ size_t depth;
int token;
union {
struct {
@@ -78,6 +84,7 @@ typedef struct {
/*** error reporting ***/
static void error_set(json_error_t *error, const lex_t *lex,
+ enum json_error_code code,
const char *msg, ...)
{
va_list ap;
@@ -115,6 +122,10 @@ static void error_set(json_error_t *error, const lex_t *lex,
}
else
{
+ if(code == json_error_invalid_syntax) {
+ /* More specific error code for premature end of file. */
+ code = json_error_premature_end_of_input;
+ }
if(lex->stream.state == STREAM_STATE_ERROR) {
/* No context for UTF-8 decoding errors */
result = msg_text;
@@ -128,7 +139,7 @@ static void error_set(json_error_t *error, const lex_t *lex,
}
}
- jsonp_error_set(error, line, col, pos, "%s", result);
+ jsonp_error_set(error, line, col, pos, code, "%s", result);
}
@@ -169,7 +180,7 @@ static int stream_get(stream_t *stream, json_error_t *error)
if(0x80 <= c && c <= 0xFF)
{
/* multi-byte UTF-8 sequence */
- int i, count;
+ size_t i, count;
count = utf8_check_first(c);
if(!count)
@@ -207,7 +218,7 @@ static int stream_get(stream_t *stream, json_error_t *error)
out:
stream->state = STREAM_STATE_ERROR;
- error_set(error, stream_to_lex(stream), "unable to decode byte 0x%x", c);
+ error_set(error, stream_to_lex(stream), json_error_invalid_utf8, "unable to decode byte 0x%x", c);
return STREAM_STATE_ERROR;
}
@@ -265,7 +276,7 @@ static void lex_unget_unsave(lex_t *lex, int c)
#endif
stream_unget(&lex->stream, c);
#ifndef NDEBUG
- d =
+ d =
#endif
strbuffer_pop(&lex->saved_text);
assert(c == d);
@@ -330,7 +341,7 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
goto out;
else if(c == STREAM_STATE_EOF) {
- error_set(error, lex, "premature end of input");
+ error_set(error, lex, json_error_premature_end_of_input, "premature end of input");
goto out;
}
@@ -338,9 +349,9 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
/* control character */
lex_unget_unsave(lex, c);
if(c == '\n')
- error_set(error, lex, "unexpected newline", c);
+ error_set(error, lex, json_error_invalid_syntax, "unexpected newline");
else
- error_set(error, lex, "control character 0x%x", c);
+ error_set(error, lex, json_error_invalid_syntax, "control character 0x%x", c);
goto out;
}
@@ -350,7 +361,7 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
c = lex_get_save(lex, error);
for(i = 0; i < 4; i++) {
if(!l_isxdigit(c)) {
- error_set(error, lex, "invalid escape");
+ error_set(error, lex, json_error_invalid_syntax, "invalid escape");
goto out;
}
c = lex_get_save(lex, error);
@@ -360,7 +371,7 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
c == 'f' || c == 'n' || c == 'r' || c == 't')
c = lex_get_save(lex, error);
else {
- error_set(error, lex, "invalid escape");
+ error_set(error, lex, json_error_invalid_syntax, "invalid escape");
goto out;
}
}
@@ -394,7 +405,7 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
value = decode_unicode_escape(p);
if(value < 0) {
- error_set(error, lex, "invalid Unicode escape '%.6s'", p - 1);
+ error_set(error, lex, json_error_invalid_syntax, "invalid Unicode escape '%.6s'", p - 1);
goto out;
}
p += 5;
@@ -404,7 +415,7 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
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);
+ error_set(error, lex, json_error_invalid_syntax, "invalid Unicode escape '%.6s'", p - 1);
goto out;
}
p += 5;
@@ -419,6 +430,7 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
else {
/* invalid second surrogate */
error_set(error, lex,
+ json_error_invalid_syntax,
"invalid Unicode '\\u%04X\\u%04X'",
value, value2);
goto out;
@@ -426,13 +438,13 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
}
else {
/* no second surrogate */
- error_set(error, lex, "invalid Unicode '\\u%04X'",
+ error_set(error, lex, json_error_invalid_syntax, "invalid Unicode '\\u%04X'",
value);
goto out;
}
}
else if(0xDC00 <= value && value <= 0xDFFF) {
- error_set(error, lex, "invalid Unicode '\\u%04X'", value);
+ error_set(error, lex, json_error_invalid_syntax, "invalid Unicode '\\u%04X'", value);
goto out;
}
@@ -483,7 +495,7 @@ static int lex_scan_number(lex_t *lex, int c, json_error_t *error)
{
const char *saved_text;
char *end;
- double value;
+ double doubleval;
lex->token = TOKEN_INVALID;
@@ -498,36 +510,38 @@ static int lex_scan_number(lex_t *lex, int c, json_error_t *error)
}
}
else if(l_isdigit(c)) {
- c = lex_get_save(lex, error);
- while(l_isdigit(c))
+ do
c = lex_get_save(lex, error);
+ while(l_isdigit(c));
}
else {
lex_unget_unsave(lex, c);
goto out;
}
- if(c != '.' && c != 'E' && c != 'e') {
- json_int_t value;
+ if(!(lex->flags & JSON_DECODE_INT_AS_REAL) &&
+ c != '.' && c != 'E' && c != 'e')
+ {
+ json_int_t intval;
lex_unget_unsave(lex, c);
saved_text = strbuffer_value(&lex->saved_text);
errno = 0;
- value = json_strtoint(saved_text, &end, 10);
+ intval = json_strtoint(saved_text, &end, 10);
if(errno == ERANGE) {
- if(value < 0)
- error_set(error, lex, "too big negative integer");
+ if(intval < 0)
+ error_set(error, lex, json_error_numeric_overflow, "too big negative integer");
else
- error_set(error, lex, "too big integer");
+ error_set(error, lex, json_error_numeric_overflow, "too big integer");
goto out;
}
assert(end == saved_text + lex->saved_text.length);
lex->token = TOKEN_INTEGER;
- lex->value.integer = value;
+ lex->value.integer = intval;
return 0;
}
@@ -539,9 +553,9 @@ static int lex_scan_number(lex_t *lex, int c, json_error_t *error)
}
lex_save(lex, c);
- c = lex_get_save(lex, error);
- while(l_isdigit(c))
+ do
c = lex_get_save(lex, error);
+ while(l_isdigit(c));
}
if(c == 'E' || c == 'e') {
@@ -554,20 +568,20 @@ static int lex_scan_number(lex_t *lex, int c, json_error_t *error)
goto out;
}
- c = lex_get_save(lex, error);
- while(l_isdigit(c))
+ do
c = lex_get_save(lex, error);
+ while(l_isdigit(c));
}
lex_unget_unsave(lex, c);
- if(jsonp_strtod(&lex->saved_text, &value)) {
- error_set(error, lex, "real number overflow");
+ if(jsonp_strtod(&lex->saved_text, &doubleval)) {
+ error_set(error, lex, json_error_numeric_overflow, "real number overflow");
goto out;
}
lex->token = TOKEN_REAL;
- lex->value.real = value;
+ lex->value.real = doubleval;
return 0;
out:
@@ -583,9 +597,9 @@ static int lex_scan(lex_t *lex, json_error_t *error)
if(lex->token == TOKEN_STRING)
lex_free_string(lex);
- c = lex_get(lex, error);
- while(c == ' ' || c == '\t' || c == '\n' || c == '\r')
+ do
c = lex_get(lex, error);
+ while(c == ' ' || c == '\t' || c == '\n' || c == '\r');
if(c == STREAM_STATE_EOF) {
lex->token = TOKEN_EOF;
@@ -614,9 +628,9 @@ static int lex_scan(lex_t *lex, json_error_t *error)
/* eat up the whole identifier for clearer error messages */
const char *saved_text;
- c = lex_get_save(lex, error);
- while(l_isalpha(c))
+ do
c = lex_get_save(lex, error);
+ while(l_isalpha(c));
lex_unget_unsave(lex, c);
saved_text = strbuffer_value(&lex->saved_text);
@@ -654,12 +668,13 @@ static char *lex_steal_string(lex_t *lex, size_t *out_len)
return result;
}
-static int lex_init(lex_t *lex, get_func get, void *data)
+static int lex_init(lex_t *lex, get_func get, size_t flags, void *data)
{
stream_init(&lex->stream, get, data);
if(strbuffer_init(&lex->saved_text))
return -1;
+ lex->flags = flags;
lex->token = TOKEN_INVALID;
return 0;
}
@@ -692,7 +707,7 @@ static json_t *parse_object(lex_t *lex, size_t flags, json_error_t *error)
json_t *value;
if(lex->token != TOKEN_STRING) {
- error_set(error, lex, "string or '}' expected");
+ error_set(error, lex, json_error_invalid_syntax, "string or '}' expected");
goto error;
}
@@ -701,14 +716,14 @@ static json_t *parse_object(lex_t *lex, size_t flags, json_error_t *error)
return NULL;
if (memchr(key, '\0', len)) {
jsonp_free(key);
- error_set(error, lex, "NUL byte in object key not supported");
+ error_set(error, lex, json_error_null_byte_in_key, "NUL byte in object key not supported");
goto error;
}
if(flags & JSON_REJECT_DUPLICATES) {
if(json_object_get(object, key)) {
jsonp_free(key);
- error_set(error, lex, "duplicate object key");
+ error_set(error, lex, json_error_duplicate_key, "duplicate object key");
goto error;
}
}
@@ -716,7 +731,7 @@ static json_t *parse_object(lex_t *lex, size_t flags, json_error_t *error)
lex_scan(lex, error);
if(lex->token != ':') {
jsonp_free(key);
- error_set(error, lex, "':' expected");
+ error_set(error, lex, json_error_invalid_syntax, "':' expected");
goto error;
}
@@ -727,13 +742,11 @@ static json_t *parse_object(lex_t *lex, size_t flags, json_error_t *error)
goto error;
}
- if(json_object_set_nocheck(object, key, value)) {
+ if(json_object_set_new_nocheck(object, key, value)) {
jsonp_free(key);
- json_decref(value);
goto error;
}
- json_decref(value);
jsonp_free(key);
lex_scan(lex, error);
@@ -744,7 +757,7 @@ static json_t *parse_object(lex_t *lex, size_t flags, json_error_t *error)
}
if(lex->token != '}') {
- error_set(error, lex, "'}' expected");
+ error_set(error, lex, json_error_invalid_syntax, "'}' expected");
goto error;
}
@@ -770,11 +783,9 @@ static json_t *parse_array(lex_t *lex, size_t flags, json_error_t *error)
if(!elem)
goto error;
- if(json_array_append(array, elem)) {
- json_decref(elem);
+ if(json_array_append_new(array, elem)) {
goto error;
}
- json_decref(elem);
lex_scan(lex, error);
if(lex->token != ',')
@@ -784,7 +795,7 @@ static json_t *parse_array(lex_t *lex, size_t flags, json_error_t *error)
}
if(lex->token != ']') {
- error_set(error, lex, "']' expected");
+ error_set(error, lex, json_error_invalid_syntax, "']' expected");
goto error;
}
@@ -798,7 +809,12 @@ error:
static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error)
{
json_t *json;
- double value;
+
+ lex->depth++;
+ if(lex->depth > JSON_PARSER_MAX_DEPTH) {
+ error_set(error, lex, json_error_stack_overflow, "maximum parsing depth reached");
+ return NULL;
+ }
switch(lex->token) {
case TOKEN_STRING: {
@@ -807,29 +823,19 @@ static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error)
if(!(flags & JSON_ALLOW_NUL)) {
if(memchr(value, '\0', len)) {
- error_set(error, lex, "\\u0000 is not allowed without JSON_ALLOW_NUL");
+ error_set(error, lex, json_error_null_character, "\\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;
- }
+ lex->value.string.val = NULL;
+ lex->value.string.len = 0;
break;
}
case TOKEN_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);
- }
+ json = json_integer(lex->value.integer);
break;
}
@@ -859,17 +865,18 @@ static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error)
break;
case TOKEN_INVALID:
- error_set(error, lex, "invalid token");
+ error_set(error, lex, json_error_invalid_syntax, "invalid token");
return NULL;
default:
- error_set(error, lex, "unexpected token");
+ error_set(error, lex, json_error_invalid_syntax, "unexpected token");
return NULL;
}
if(!json)
return NULL;
+ lex->depth--;
return json;
}
@@ -877,10 +884,12 @@ static json_t *parse_json(lex_t *lex, size_t flags, json_error_t *error)
{
json_t *result;
+ lex->depth = 0;
+
lex_scan(lex, error);
if(!(flags & JSON_DECODE_ANY)) {
if(lex->token != '[' && lex->token != '{') {
- error_set(error, lex, "'[' or '{' expected");
+ error_set(error, lex, json_error_invalid_syntax, "'[' or '{' expected");
return NULL;
}
}
@@ -892,7 +901,7 @@ static json_t *parse_json(lex_t *lex, size_t flags, json_error_t *error)
if(!(flags & JSON_DISABLE_EOF_CHECK)) {
lex_scan(lex, error);
if(lex->token != TOKEN_EOF) {
- error_set(error, lex, "end of file expected");
+ error_set(error, lex, json_error_end_of_input_expected, "end of file expected");
json_decref(result);
return NULL;
}
@@ -900,7 +909,7 @@ static json_t *parse_json(lex_t *lex, size_t flags, json_error_t *error)
if(error) {
/* Save the position even though there was no error */
- error->position = lex->stream.position;
+ error->position = (int)lex->stream.position;
}
return result;
@@ -909,7 +918,7 @@ static json_t *parse_json(lex_t *lex, size_t flags, json_error_t *error)
typedef struct
{
const char *data;
- int pos;
+ size_t pos;
} string_data_t;
static int string_get(void *data)
@@ -935,14 +944,14 @@ json_t *json_loads(const char *string, size_t flags, json_error_t *error)
jsonp_error_init(error, "<string>");
if (string == NULL) {
- error_set(error, NULL, "wrong arguments");
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
return NULL;
}
stream_data.data = string;
stream_data.pos = 0;
- if(lex_init(&lex, string_get, (void *)&stream_data))
+ if(lex_init(&lex, string_get, flags, (void *)&stream_data))
return NULL;
result = parse_json(&lex, flags, error);
@@ -979,7 +988,7 @@ json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t
jsonp_error_init(error, "<buffer>");
if (buffer == NULL) {
- error_set(error, NULL, "wrong arguments");
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
return NULL;
}
@@ -987,7 +996,7 @@ json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t
stream_data.pos = 0;
stream_data.len = buflen;
- if(lex_init(&lex, buffer_get, (void *)&stream_data))
+ if(lex_init(&lex, buffer_get, flags, (void *)&stream_data))
return NULL;
result = parse_json(&lex, flags, error);
@@ -1010,11 +1019,50 @@ json_t *json_loadf(FILE *input, size_t flags, json_error_t *error)
jsonp_error_init(error, source);
if (input == NULL) {
- error_set(error, NULL, "wrong arguments");
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
+ return NULL;
+ }
+
+ if(lex_init(&lex, (get_func)fgetc, flags, input))
+ return NULL;
+
+ result = parse_json(&lex, flags, error);
+
+ lex_close(&lex);
+ return result;
+}
+
+static int fd_get_func(int *fd)
+{
+#ifdef HAVE_UNISTD_H
+ uint8_t c;
+ if (read(*fd, &c, 1) == 1)
+ return c;
+#endif
+ return EOF;
+}
+
+json_t *json_loadfd(int input, size_t flags, json_error_t *error)
+{
+ lex_t lex;
+ const char *source;
+ json_t *result;
+
+#ifdef HAVE_UNISTD_H
+ if(input == STDIN_FILENO)
+ source = "<stdin>";
+ else
+#endif
+ source = "<stream>";
+
+ jsonp_error_init(error, source);
+
+ if (input < 0) {
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
return NULL;
}
- if(lex_init(&lex, (get_func)fgetc, input))
+ if(lex_init(&lex, (get_func)fd_get_func, flags, &input))
return NULL;
result = parse_json(&lex, flags, error);
@@ -1031,14 +1079,14 @@ json_t *json_load_file(const char *path, size_t flags, json_error_t *error)
jsonp_error_init(error, path);
if (path == NULL) {
- error_set(error, NULL, "wrong arguments");
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
return NULL;
}
fp = fopen(path, "rb");
if(!fp)
{
- error_set(error, NULL, "unable to open %s: %s",
+ error_set(error, NULL, json_error_cannot_open_file, "unable to open %s: %s",
path, strerror(errno));
return NULL;
}
@@ -1091,11 +1139,11 @@ json_t *json_load_callback(json_load_callback_t callback, void *arg, size_t flag
jsonp_error_init(error, "<callback>");
if (callback == NULL) {
- error_set(error, NULL, "wrong arguments");
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
return NULL;
}
- if(lex_init(&lex, (get_func)callback_get, &stream_data))
+ if(lex_init(&lex, (get_func)callback_get, flags, &stream_data))
return NULL;
result = parse_json(&lex, flags, error);
diff --git a/src/jansson/lookup3.h b/src/jansson/lookup3.h
index 8847483..2fe4c25 100644
--- a/src/jansson/lookup3.h
+++ b/src/jansson/lookup3.h
@@ -205,7 +205,22 @@ static uint32_t hashlittle(const void *key, size_t length, uint32_t initval)
if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
+/* Detect Valgrind or AddressSanitizer */
#ifdef VALGRIND
+# define NO_MASKING_TRICK 1
+#else
+# if defined(__has_feature) /* Clang */
+# if __has_feature(address_sanitizer) /* is ASAN enabled? */
+# define NO_MASKING_TRICK 1
+# endif
+# else
+# if defined(__SANITIZE_ADDRESS__) /* GCC 4.8.x, is ASAN enabled? */
+# define NO_MASKING_TRICK 1
+# endif
+# endif
+#endif
+
+#ifdef NO_MASKING_TRICK
const uint8_t *k8;
#endif
@@ -230,7 +245,7 @@ static uint32_t hashlittle(const void *key, size_t length, uint32_t initval)
* still catch it and complain. The masking trick does make the hash
* noticably faster for short strings (like English words).
*/
-#ifndef VALGRIND
+#ifndef NO_MASKING_TRICK
switch(length)
{
@@ -344,17 +359,17 @@ static uint32_t hashlittle(const void *key, size_t length, uint32_t initval)
/*-------------------------------- 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 12: c+=((uint32_t)k[11])<<24; /* fall through */
+ case 11: c+=((uint32_t)k[10])<<16; /* fall through */
+ case 10: c+=((uint32_t)k[9])<<8; /* fall through */
+ case 9 : c+=k[8]; /* fall through */
+ case 8 : b+=((uint32_t)k[7])<<24; /* fall through */
+ case 7 : b+=((uint32_t)k[6])<<16; /* fall through */
+ case 6 : b+=((uint32_t)k[5])<<8; /* fall through */
+ case 5 : b+=k[4]; /* fall through */
+ case 4 : a+=((uint32_t)k[3])<<24; /* fall through */
+ case 3 : a+=((uint32_t)k[2])<<16; /* fall through */
+ case 2 : a+=((uint32_t)k[1])<<8; /* fall through */
case 1 : a+=k[0];
break;
case 0 : return c;
diff --git a/src/jansson/memory.c b/src/jansson/memory.c
index ca44d6b..a2be5d2 100644
--- a/src/jansson/memory.c
+++ b/src/jansson/memory.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2016 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
@@ -59,3 +59,11 @@ void json_set_alloc_funcs(json_malloc_t malloc_fn, json_free_t free_fn)
do_malloc = malloc_fn;
do_free = free_fn;
}
+
+void json_get_alloc_funcs(json_malloc_t *malloc_fn, json_free_t *free_fn)
+{
+ if (malloc_fn)
+ *malloc_fn = do_malloc;
+ if (free_fn)
+ *free_fn = do_free;
+}
diff --git a/src/jansson/pack_unpack.c b/src/jansson/pack_unpack.c
index af381a5..3b99776 100644
--- a/src/jansson/pack_unpack.c
+++ b/src/jansson/pack_unpack.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2016 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
@@ -29,6 +29,7 @@ typedef struct {
int line;
int column;
size_t pos;
+ int has_error;
} scanner_t;
#define token(scanner) ((scanner)->token.token)
@@ -48,7 +49,6 @@ static const char * const type_names[] = {
static const char unpack_value_starters[] = "{[siIbfFOon";
-
static void scanner_init(scanner_t *s, json_error_t *error,
size_t flags, const char *fmt)
{
@@ -61,6 +61,7 @@ static void scanner_init(scanner_t *s, json_error_t *error,
s->line = 1;
s->column = 0;
s->pos = 0;
+ s->has_error = 0;
}
static void next_token(scanner_t *s)
@@ -74,6 +75,9 @@ static void next_token(scanner_t *s)
return;
}
+ if (!token(s) && !*s->fmt)
+ return;
+
t = s->fmt;
s->column++;
s->pos++;
@@ -96,7 +100,7 @@ static void next_token(scanner_t *s)
s->token.column = s->column;
s->token.pos = s->pos;
- t++;
+ if (*t) t++;
s->fmt = t;
}
@@ -106,13 +110,14 @@ static void prev_token(scanner_t *s)
s->token = s->prev_token;
}
-static void set_error(scanner_t *s, const char *source, const char *fmt, ...)
+static void set_error(scanner_t *s, const char *source, enum json_error_code code,
+ const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
jsonp_error_vset(s->error, s->token.line, s->token.column, s->token.pos,
- fmt, ap);
+ code, fmt, ap);
jsonp_error_set_source(s->error, source);
@@ -125,7 +130,7 @@ 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)
+ const char *purpose, size_t *out_len, int *ours, int optional)
{
char t;
strbuffer_t strbuff;
@@ -136,35 +141,46 @@ static char *read_string(scanner_t *s, va_list *ap,
t = token(s);
prev_token(s);
+ *ours = 0;
if(t != '#' && t != '%' && t != '+') {
/* Optimize the simple case */
str = va_arg(*ap, const char *);
if(!str) {
- set_error(s, "<args>", "NULL string argument");
+ if (!optional) {
+ set_error(s, "<args>", json_error_null_value, "NULL %s", purpose);
+ s->has_error = 1;
+ }
return NULL;
}
length = strlen(str);
if(!utf8_check_string(str, length)) {
- set_error(s, "<args>", "Invalid UTF-8 %s", purpose);
+ set_error(s, "<args>", json_error_invalid_utf8, "Invalid UTF-8 %s", purpose);
+ s->has_error = 1;
return NULL;
}
*out_len = length;
- *ours = 0;
return (char *)str;
+ } else if (optional) {
+ set_error(s, "<format>", json_error_invalid_format, "Cannot use '%c' on optional strings", t);
+ s->has_error = 1;
+
+ return NULL;
}
- strbuffer_init(&strbuff);
+ if(strbuffer_init(&strbuff)) {
+ set_error(s, "<internal>", json_error_out_of_memory, "Out of memory");
+ s->has_error = 1;
+ }
while(1) {
str = va_arg(*ap, const char *);
if(!str) {
- set_error(s, "<args>", "NULL string argument");
- strbuffer_close(&strbuff);
- return NULL;
+ set_error(s, "<args>", json_error_null_value, "NULL %s", purpose);
+ s->has_error = 1;
}
next_token(s);
@@ -177,13 +193,12 @@ static char *read_string(scanner_t *s, va_list *ap,
}
else {
prev_token(s);
- length = strlen(str);
+ length = s->has_error ? 0 : strlen(str);
}
- if(strbuffer_append_bytes(&strbuff, str, length) == -1) {
- set_error(s, "<internal>", "Out of memory");
- strbuffer_close(&strbuff);
- return NULL;
+ if(!s->has_error && strbuffer_append_bytes(&strbuff, str, length) == -1) {
+ set_error(s, "<internal>", json_error_out_of_memory, "Out of memory");
+ s->has_error = 1;
}
next_token(s);
@@ -193,9 +208,15 @@ static char *read_string(scanner_t *s, va_list *ap,
}
}
+ if(s->has_error) {
+ strbuffer_close(&strbuff);
+ return NULL;
+ }
+
if(!utf8_check_string(strbuff.value, strbuff.length)) {
- set_error(s, "<args>", "Invalid UTF-8 %s", purpose);
+ set_error(s, "<args>", json_error_invalid_utf8, "Invalid UTF-8 %s", purpose);
strbuffer_close(&strbuff);
+ s->has_error = 1;
return NULL;
}
@@ -214,37 +235,46 @@ static json_t *pack_object(scanner_t *s, va_list *ap)
size_t len;
int ours;
json_t *value;
+ char valueOptional;
if(!token(s)) {
- set_error(s, "<format>", "Unexpected end of format string");
+ set_error(s, "<format>", json_error_invalid_format, "Unexpected end of format string");
goto error;
}
if(token(s) != 's') {
- set_error(s, "<format>", "Expected format 's', got '%c'", token(s));
+ set_error(s, "<format>", json_error_invalid_format, "Expected format 's', got '%c'", token(s));
goto error;
}
- key = read_string(s, ap, "object key", &len, &ours);
- if(!key)
- goto error;
+ key = read_string(s, ap, "object key", &len, &ours, 0);
+
+ next_token(s);
next_token(s);
+ valueOptional = token(s);
+ prev_token(s);
value = pack(s, ap);
if(!value) {
if(ours)
jsonp_free(key);
- goto error;
+ if(valueOptional != '*') {
+ set_error(s, "<args>", json_error_null_value, "NULL object value");
+ s->has_error = 1;
+ }
+
+ next_token(s);
+ continue;
}
- if(json_object_set_new_nocheck(object, key, value)) {
- if(ours)
- jsonp_free(key);
+ if(s->has_error)
+ json_decref(value);
- set_error(s, "<internal>", "Unable to add key \"%s\"", key);
- goto error;
+ if(!s->has_error && json_object_set_new_nocheck(object, key, value)) {
+ set_error(s, "<internal>", json_error_out_of_memory, "Unable to add key \"%s\"", key);
+ s->has_error = 1;
}
if(ours)
@@ -253,7 +283,8 @@ static json_t *pack_object(scanner_t *s, va_list *ap)
next_token(s);
}
- return object;
+ if(!s->has_error)
+ return object;
error:
json_decref(object);
@@ -267,30 +298,143 @@ static json_t *pack_array(scanner_t *s, va_list *ap)
while(token(s) != ']') {
json_t *value;
+ char valueOptional;
if(!token(s)) {
- set_error(s, "<format>", "Unexpected end of format string");
+ set_error(s, "<format>", json_error_invalid_format, "Unexpected end of format string");
+ /* Format string errors are unrecoverable. */
goto error;
}
+ next_token(s);
+ valueOptional = token(s);
+ prev_token(s);
+
value = pack(s, ap);
- if(!value)
- goto error;
+ if(!value) {
+ if(valueOptional != '*') {
+ s->has_error = 1;
+ }
- if(json_array_append_new(array, value)) {
- set_error(s, "<internal>", "Unable to append to array");
- goto error;
+ next_token(s);
+ continue;
+ }
+
+ if(s->has_error)
+ json_decref(value);
+
+ if(!s->has_error && json_array_append_new(array, value)) {
+ set_error(s, "<internal>", json_error_out_of_memory, "Unable to append to array");
+ s->has_error = 1;
}
next_token(s);
}
- return array;
+
+ if(!s->has_error)
+ return array;
error:
json_decref(array);
return NULL;
}
+static json_t *pack_string(scanner_t *s, va_list *ap)
+{
+ char *str;
+ char t;
+ size_t len;
+ int ours;
+ int optional;
+
+ next_token(s);
+ t = token(s);
+ optional = t == '?' || t == '*';
+ if (!optional)
+ prev_token(s);
+
+ str = read_string(s, ap, "string", &len, &ours, optional);
+
+ if (!str)
+ return t == '?' && !s->has_error ? json_null() : NULL;
+
+ if (s->has_error) {
+ /* It's impossible to reach this point if ours != 0, do not free str. */
+ return NULL;
+ }
+
+ if (ours)
+ return jsonp_stringn_nocheck_own(str, len);
+
+ return json_stringn_nocheck(str, len);
+}
+
+static json_t *pack_object_inter(scanner_t *s, va_list *ap, int need_incref)
+{
+ json_t *json;
+ char ntoken;
+
+ next_token(s);
+ ntoken = token(s);
+
+ if (ntoken != '?' && ntoken != '*')
+ prev_token(s);
+
+ json = va_arg(*ap, json_t *);
+
+ if (json)
+ return need_incref ? json_incref(json) : json;
+
+ switch (ntoken) {
+ case '?':
+ return json_null();
+ case '*':
+ return NULL;
+ default:
+ break;
+ }
+
+ set_error(s, "<args>", json_error_null_value, "NULL object");
+ s->has_error = 1;
+ return NULL;
+}
+
+static json_t *pack_integer(scanner_t *s, json_int_t value)
+{
+ json_t *json = json_integer(value);
+
+ if (!json) {
+ set_error(s, "<internal>", json_error_out_of_memory, "Out of memory");
+ s->has_error = 1;
+ }
+
+ return json;
+}
+
+static json_t *pack_real(scanner_t *s, double value)
+{
+ /* Allocate without setting value so we can identify OOM error. */
+ json_t *json = json_real(0.0);
+
+ if (!json) {
+ set_error(s, "<internal>", json_error_out_of_memory, "Out of memory");
+ s->has_error = 1;
+
+ return NULL;
+ }
+
+ if (json_real_set(json, value)) {
+ json_decref(json);
+
+ set_error(s, "<args>", json_error_numeric_overflow, "Invalid floating point value");
+ s->has_error = 1;
+
+ return NULL;
+ }
+
+ return json;
+}
+
static json_t *pack(scanner_t *s, va_list *ap)
{
switch(token(s)) {
@@ -301,20 +445,7 @@ static json_t *pack(scanner_t *s, va_list *ap)
return pack_array(s, ap);
case 's': /* string */
- {
- char *str;
- size_t len;
- int ours;
-
- str = read_string(s, ap, "string", &len, &ours);
- if(!str)
- return NULL;
-
- if (ours)
- return jsonp_stringn_nocheck_own(str, len);
- else
- return json_stringn_nocheck(str, len);
- }
+ return pack_string(s, ap);
case 'n': /* null */
return json_null();
@@ -323,23 +454,24 @@ static json_t *pack(scanner_t *s, va_list *ap)
return va_arg(*ap, int) ? json_true() : json_false();
case 'i': /* integer from int */
- return json_integer(va_arg(*ap, int));
+ return pack_integer(s, va_arg(*ap, int));
case 'I': /* integer from json_int_t */
- return json_integer(va_arg(*ap, json_int_t));
+ return pack_integer(s, va_arg(*ap, json_int_t));
case 'f': /* real */
- return json_real(va_arg(*ap, double));
+ return pack_real(s, va_arg(*ap, double));
case 'O': /* a json_t object; increments refcount */
- return json_incref(va_arg(*ap, json_t *));
+ return pack_object_inter(s, ap, 1);
case 'o': /* a json_t object; doesn't increment refcount */
- return va_arg(*ap, json_t *);
+ return pack_object_inter(s, ap, 0);
default:
- set_error(s, "<format>", "Unexpected format character '%c'",
+ set_error(s, "<format>", json_error_invalid_format, "Unexpected format character '%c'",
token(s));
+ s->has_error = 1;
return NULL;
}
}
@@ -360,12 +492,12 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
hashtable_t key_set;
if(hashtable_init(&key_set)) {
- set_error(s, "<internal>", "Out of memory");
+ set_error(s, "<internal>", json_error_out_of_memory, "Out of memory");
return -1;
}
if(root && !json_is_object(root)) {
- set_error(s, "<validation>", "Expected object, got %s",
+ set_error(s, "<validation>", json_error_wrong_type, "Expected object, got %s",
type_name(root));
goto out;
}
@@ -377,13 +509,13 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
int opt = 0;
if(strict != 0) {
- set_error(s, "<format>", "Expected '}' after '%c', got '%c'",
+ set_error(s, "<format>", json_error_invalid_format, "Expected '}' after '%c', got '%c'",
(strict == 1 ? '!' : '*'), token(s));
goto out;
}
if(!token(s)) {
- set_error(s, "<format>", "Unexpected end of format string");
+ set_error(s, "<format>", json_error_invalid_format, "Unexpected end of format string");
goto out;
}
@@ -394,13 +526,13 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
}
if(token(s) != 's') {
- set_error(s, "<format>", "Expected format 's', got '%c'", token(s));
+ set_error(s, "<format>", json_error_invalid_format, "Expected format 's', got '%c'", token(s));
goto out;
}
key = va_arg(*ap, const char *);
if(!key) {
- set_error(s, "<args>", "NULL object key");
+ set_error(s, "<args>", json_error_null_value, "NULL object key");
goto out;
}
@@ -418,7 +550,7 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
else {
value = json_object_get(root, key);
if(!value && !opt) {
- set_error(s, "<validation>", "Object item not found: %s", key);
+ set_error(s, "<validation>", json_error_item_not_found, "Object item not found: %s", key);
goto out;
}
}
@@ -426,7 +558,7 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
if(unpack(s, value, ap))
goto out;
- hashtable_set(&key_set, key, 0, json_null());
+ hashtable_set(&key_set, key, json_null());
next_token(s);
}
@@ -436,21 +568,35 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap)
if(root && strict == 1) {
/* We need to check that all non optional items have been parsed */
const char *key;
+ /* keys_res is 1 for uninitialized, 0 for success, -1 for error. */
+ int keys_res = 1;
+ strbuffer_t unrecognized_keys;
json_t *value;
long unpacked = 0;
- if (gotopt) {
- /* We have optional keys, we need to iter on each key */
+
+ if (gotopt || json_object_size(root) != key_set.size) {
json_object_foreach(root, key, value) {
if(!hashtable_get(&key_set, key)) {
unpacked++;
+
+ /* Save unrecognized keys for the error message */
+ if (keys_res == 1) {
+ keys_res = strbuffer_init(&unrecognized_keys);
+ } else if (!keys_res) {
+ keys_res = strbuffer_append_bytes(&unrecognized_keys, ", ", 2);
+ }
+
+ if (!keys_res)
+ keys_res = strbuffer_append_bytes(&unrecognized_keys, key, strlen(key));
}
}
- } 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);
+ set_error(s, "<validation>", json_error_end_of_input_expected,
+ "%li object item(s) left unpacked: %s",
+ unpacked,
+ keys_res ? "<unknown>" : strbuffer_value(&unrecognized_keys));
+ strbuffer_close(&unrecognized_keys);
goto out;
}
}
@@ -468,7 +614,7 @@ static int unpack_array(scanner_t *s, json_t *root, va_list *ap)
int strict = 0;
if(root && !json_is_array(root)) {
- set_error(s, "<validation>", "Expected array, got %s", type_name(root));
+ set_error(s, "<validation>", json_error_wrong_type, "Expected array, got %s", type_name(root));
return -1;
}
next_token(s);
@@ -477,14 +623,14 @@ static int unpack_array(scanner_t *s, json_t *root, va_list *ap)
json_t *value;
if(strict != 0) {
- set_error(s, "<format>", "Expected ']' after '%c', got '%c'",
+ set_error(s, "<format>", json_error_invalid_format, "Expected ']' after '%c', got '%c'",
(strict == 1 ? '!' : '*'),
token(s));
return -1;
}
if(!token(s)) {
- set_error(s, "<format>", "Unexpected end of format string");
+ set_error(s, "<format>", json_error_invalid_format, "Unexpected end of format string");
return -1;
}
@@ -495,7 +641,7 @@ static int unpack_array(scanner_t *s, json_t *root, va_list *ap)
}
if(!strchr(unpack_value_starters, token(s))) {
- set_error(s, "<format>", "Unexpected format character '%c'",
+ set_error(s, "<format>", json_error_invalid_format, "Unexpected format character '%c'",
token(s));
return -1;
}
@@ -507,7 +653,7 @@ static int unpack_array(scanner_t *s, json_t *root, va_list *ap)
else {
value = json_array_get(root, i);
if(!value) {
- set_error(s, "<validation>", "Array index %lu out of range",
+ set_error(s, "<validation>", json_error_index_out_of_range, "Array index %lu out of range",
(unsigned long)i);
return -1;
}
@@ -525,7 +671,7 @@ static int unpack_array(scanner_t *s, json_t *root, va_list *ap)
if(root && strict == 1 && i != json_array_size(root)) {
long diff = (long)json_array_size(root) - (long)i;
- set_error(s, "<validation>", "%li array item(s) left unpacked", diff);
+ set_error(s, "<validation>", json_error_end_of_input_expected, "%li array item(s) left unpacked", diff);
return -1;
}
@@ -544,7 +690,7 @@ static int unpack(scanner_t *s, json_t *root, va_list *ap)
case 's':
if(root && !json_is_string(root)) {
- set_error(s, "<validation>", "Expected string, got %s",
+ set_error(s, "<validation>", json_error_wrong_type, "Expected string, got %s",
type_name(root));
return -1;
}
@@ -555,7 +701,7 @@ static int unpack(scanner_t *s, json_t *root, va_list *ap)
str_target = va_arg(*ap, const char **);
if(!str_target) {
- set_error(s, "<args>", "NULL string argument");
+ set_error(s, "<args>", json_error_null_value, "NULL string argument");
return -1;
}
@@ -564,7 +710,7 @@ static int unpack(scanner_t *s, json_t *root, va_list *ap)
if(token(s) == '%') {
len_target = va_arg(*ap, size_t *);
if(!len_target) {
- set_error(s, "<args>", "NULL string length argument");
+ set_error(s, "<args>", json_error_null_value, "NULL string length argument");
return -1;
}
}
@@ -581,7 +727,7 @@ static int unpack(scanner_t *s, json_t *root, va_list *ap)
case 'i':
if(root && !json_is_integer(root)) {
- set_error(s, "<validation>", "Expected integer, got %s",
+ set_error(s, "<validation>", json_error_wrong_type, "Expected integer, got %s",
type_name(root));
return -1;
}
@@ -596,7 +742,7 @@ static int unpack(scanner_t *s, json_t *root, va_list *ap)
case 'I':
if(root && !json_is_integer(root)) {
- set_error(s, "<validation>", "Expected integer, got %s",
+ set_error(s, "<validation>", json_error_wrong_type, "Expected integer, got %s",
type_name(root));
return -1;
}
@@ -611,7 +757,7 @@ static int unpack(scanner_t *s, json_t *root, va_list *ap)
case 'b':
if(root && !json_is_boolean(root)) {
- set_error(s, "<validation>", "Expected true or false, got %s",
+ set_error(s, "<validation>", json_error_wrong_type, "Expected true or false, got %s",
type_name(root));
return -1;
}
@@ -626,7 +772,7 @@ static int unpack(scanner_t *s, json_t *root, va_list *ap)
case 'f':
if(root && !json_is_real(root)) {
- set_error(s, "<validation>", "Expected real, got %s",
+ set_error(s, "<validation>", json_error_wrong_type, "Expected real, got %s",
type_name(root));
return -1;
}
@@ -641,7 +787,7 @@ static int unpack(scanner_t *s, json_t *root, va_list *ap)
case 'F':
if(root && !json_is_number(root)) {
- set_error(s, "<validation>", "Expected real or integer, got %s",
+ set_error(s, "<validation>", json_error_wrong_type, "Expected real or integer, got %s",
type_name(root));
return -1;
}
@@ -671,14 +817,14 @@ static int unpack(scanner_t *s, json_t *root, va_list *ap)
case 'n':
/* Never assign, just validate */
if(root && !json_is_null(root)) {
- set_error(s, "<validation>", "Expected null, got %s",
+ set_error(s, "<validation>", json_error_wrong_type, "Expected null, got %s",
type_name(root));
return -1;
}
return 0;
default:
- set_error(s, "<format>", "Unexpected format character '%c'",
+ set_error(s, "<format>", json_error_invalid_format, "Unexpected format character '%c'",
token(s));
return -1;
}
@@ -693,7 +839,7 @@ json_t *json_vpack_ex(json_error_t *error, size_t flags,
if(!fmt || !*fmt) {
jsonp_error_init(error, "<format>");
- jsonp_error_set(error, -1, -1, 0, "NULL or empty format string");
+ jsonp_error_set(error, -1, -1, 0, json_error_invalid_argument, "NULL or empty format string");
return NULL;
}
jsonp_error_init(error, NULL);
@@ -705,13 +851,14 @@ json_t *json_vpack_ex(json_error_t *error, size_t flags,
value = pack(&s, &ap_copy);
va_end(ap_copy);
+ /* This will cover all situations where s.has_error is true */
if(!value)
return NULL;
next_token(&s);
if(token(&s)) {
json_decref(value);
- set_error(&s, "<format>", "Garbage after format string");
+ set_error(&s, "<format>", json_error_invalid_format, "Garbage after format string");
return NULL;
}
@@ -750,13 +897,13 @@ int json_vunpack_ex(json_t *root, json_error_t *error, size_t flags,
if(!root) {
jsonp_error_init(error, "<root>");
- jsonp_error_set(error, -1, -1, 0, "NULL root value");
+ jsonp_error_set(error, -1, -1, 0, json_error_null_value, "NULL root value");
return -1;
}
if(!fmt || !*fmt) {
jsonp_error_init(error, "<format>");
- jsonp_error_set(error, -1, -1, 0, "NULL or empty format string");
+ jsonp_error_set(error, -1, -1, 0, json_error_invalid_argument, "NULL or empty format string");
return -1;
}
jsonp_error_init(error, NULL);
@@ -773,7 +920,7 @@ int json_vunpack_ex(json_t *root, json_error_t *error, size_t flags,
next_token(&s);
if(token(&s)) {
- set_error(&s, "<format>", "Garbage after format string");
+ set_error(&s, "<format>", json_error_invalid_format, "Garbage after format string");
return -1;
}
diff --git a/src/jansson/strbuffer.c b/src/jansson/strbuffer.c
index b3ddd0e..5e8c003 100644
--- a/src/jansson/strbuffer.c
+++ b/src/jansson/strbuffer.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2016 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.
@@ -60,11 +60,6 @@ char *strbuffer_steal_value(strbuffer_t *strbuff)
return result;
}
-int strbuffer_append(strbuffer_t *strbuff, const char *string)
-{
- return strbuffer_append_bytes(strbuff, string, strlen(string));
-}
-
int strbuffer_append_byte(strbuffer_t *strbuff, char byte)
{
return strbuffer_append_bytes(strbuff, &byte, 1);
diff --git a/src/jansson/strbuffer.h b/src/jansson/strbuffer.h
index fc11ec0..a0276d4 100644
--- a/src/jansson/strbuffer.h
+++ b/src/jansson/strbuffer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2016 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,13 +8,15 @@
#ifndef STRBUFFER_H
#define STRBUFFER_H
+#include <stdlib.h>
+
typedef struct {
char *value;
size_t length; /* bytes used */
size_t size; /* bytes allocated */
} strbuffer_t;
-int strbuffer_init(strbuffer_t *strbuff);
+int strbuffer_init(strbuffer_t *strbuff) JANSSON_ATTRS(warn_unused_result);
void strbuffer_close(strbuffer_t *strbuff);
void strbuffer_clear(strbuffer_t *strbuff);
@@ -24,7 +26,6 @@ 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);
int strbuffer_append_byte(strbuffer_t *strbuff, char byte);
int strbuffer_append_bytes(strbuffer_t *strbuff, const char *data, size_t size);
diff --git a/src/jansson/strconv.c b/src/jansson/strconv.c
index 3a70c6f..1cce56c 100644
--- a/src/jansson/strconv.c
+++ b/src/jansson/strconv.c
@@ -2,6 +2,10 @@
#include <errno.h>
#include <stdio.h>
#include <string.h>
+#include <math.h>
+#ifdef __MINGW32__
+#undef __NO_ISOCEXT /* ensure stdlib.h will declare prototypes for mingw own 'strtod' replacement, called '__strtod' */
+#endif
#include "jansson_private.h"
#include "strbuffer.h"
@@ -10,6 +14,10 @@
#include <jansson_private_config.h>
#endif
+#ifdef __MINGW32__
+#define strtod __strtod
+#endif
+
#if JSON_HAVE_LOCALECONV
#include <locale.h>
@@ -69,7 +77,7 @@ int jsonp_strtod(strbuffer_t *strbuffer, double *out)
value = strtod(strbuffer->value, &end);
assert(end == strbuffer->value + strbuffer->length);
- if(errno == ERANGE && value != 0) {
+ if((value == __builtin_huge_val() || value == -__builtin_huge_val()) && errno == ERANGE) {
/* Overflow */
return -1;
}
@@ -78,13 +86,16 @@ int jsonp_strtod(strbuffer_t *strbuffer, double *out)
return 0;
}
-int jsonp_dtostr(char *buffer, size_t size, double value)
+int jsonp_dtostr(char *buffer, size_t size, double value, int precision)
{
int ret;
char *start, *end;
size_t length;
- ret = snprintf(buffer, size, "%.17g", value);
+ if (precision == 0)
+ precision = 17;
+
+ ret = snprintf(buffer, size, "%.*g", precision, value);
if(ret < 0)
return -1;
diff --git a/src/jansson/utf.c b/src/jansson/utf.c
index b56e125..be966cb 100644
--- a/src/jansson/utf.c
+++ b/src/jansson/utf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2016 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.
diff --git a/src/jansson/utf.h b/src/jansson/utf.h
index 2cebea0..e182df7 100644
--- a/src/jansson/utf.h
+++ b/src/jansson/utf.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2016 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.
diff --git a/src/jansson/value.c b/src/jansson/value.c
index 644bc87..3f964a0 100644
--- a/src/jansson/value.c
+++ b/src/jansson/value.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>
+ * Copyright (c) 2009-2016 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.
@@ -29,8 +29,10 @@
/* Work around nonstandard isnan() and isinf() implementations */
#ifndef isnan
+#ifndef __sun
static JSON_INLINE int isnan(double x) { return x != x; }
#endif
+#endif
#ifndef isinf
static JSON_INLINE int isinf(double x) { return !isnan(x) && isnan(x - x); }
#endif
@@ -65,9 +67,6 @@ json_t *json_object(void)
return NULL;
}
- object->serial = 0;
- object->visited = 0;
-
return &object->json;
}
@@ -113,7 +112,7 @@ int json_object_set_new_nocheck(json_t *json, const char *key, json_t *value)
}
object = json_to_object(json);
- if(hashtable_set(&object->hashtable, key, object->serial++, value))
+ if(hashtable_set(&object->hashtable, key, value))
{
json_decref(value);
return -1;
@@ -152,9 +151,7 @@ int json_object_clear(json_t *json)
return -1;
object = json_to_object(json);
-
hashtable_clear(&object->hashtable);
- object->serial = 0;
return 0;
}
@@ -259,7 +256,10 @@ json_t *json_object_iter_value(void *iter)
int json_object_iter_set_new(json_t *json, void *iter, json_t *value)
{
if(!json_is_object(json) || !iter || !value)
+ {
+ json_decref(value);
return -1;
+ }
hashtable_iter_set(iter, value);
return 0;
@@ -273,15 +273,15 @@ void *json_object_key_to_iter(const char *key)
return hashtable_key_to_iter(key);
}
-static int json_object_equal(json_t *object1, json_t *object2)
+static int json_object_equal(const json_t *object1, const json_t *object2)
{
const char *key;
- json_t *value1, *value2;
+ const json_t *value1, *value2;
if(json_object_size(object1) != json_object_size(object2))
return 0;
- json_object_foreach(object1, key, value1) {
+ json_object_foreach((json_t *)object1, key, value1) {
value2 = json_object_get(object2, key);
if(!json_equal(value1, value2))
@@ -352,8 +352,6 @@ json_t *json_array(void)
return NULL;
}
- array->visited = 0;
-
return &array->json;
}
@@ -582,7 +580,7 @@ int json_array_extend(json_t *json, json_t *other_json)
return 0;
}
-static int json_array_equal(json_t *array1, json_t *array2)
+static int json_array_equal(const json_t *array1, const json_t *array2)
{
size_t i, size;
@@ -654,8 +652,7 @@ static json_t *string_create(const char *value, size_t len, int own)
string = jsonp_malloc(sizeof(json_string_t));
if(!string) {
- if(!own)
- jsonp_free(v);
+ jsonp_free(v);
return NULL;
}
json_init(&string->json, JSON_STRING);
@@ -766,13 +763,10 @@ static void json_delete_string(json_string_t *string)
jsonp_free(string);
}
-static int json_string_equal(json_t *string1, json_t *string2)
+static int json_string_equal(const json_t *string1, const json_t *string2)
{
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);
@@ -782,13 +776,51 @@ static json_t *json_string_copy(const json_t *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);
}
+json_t *json_vsprintf(const char *fmt, va_list ap) {
+ json_t *json = NULL;
+ int length;
+ char *buf;
+ va_list aq;
+ va_copy(aq, ap);
+
+ length = vsnprintf(NULL, 0, fmt, ap);
+ if (length == 0) {
+ json = json_string("");
+ goto out;
+ }
+
+ buf = jsonp_malloc(length + 1);
+ if (!buf)
+ goto out;
+
+ vsnprintf(buf, length + 1, fmt, aq);
+ if (!utf8_check_string(buf, length)) {
+ jsonp_free(buf);
+ goto out;
+ }
+
+ json = jsonp_stringn_nocheck_own(buf, length);
+
+out:
+ va_end(aq);
+ return json;
+}
+
+json_t *json_sprintf(const char *fmt, ...) {
+ json_t *result;
+ va_list ap;
+
+ va_start(ap, fmt);
+ result = json_vsprintf(fmt, ap);
+ va_end(ap);
+
+ return result;
+}
+
/*** integer ***/
@@ -826,7 +858,7 @@ static void json_delete_integer(json_integer_t *integer)
jsonp_free(integer);
}
-static int json_integer_equal(json_t *integer1, json_t *integer2)
+static int json_integer_equal(const json_t *integer1, const json_t *integer2)
{
return json_integer_value(integer1) == json_integer_value(integer2);
}
@@ -878,7 +910,7 @@ static void json_delete_real(json_real_t *real)
jsonp_free(real);
}
-static int json_real_equal(json_t *real1, json_t *real2)
+static int json_real_equal(const json_t *real1, const json_t *real2)
{
return json_real_value(real1) == json_real_value(real2);
}
@@ -929,20 +961,28 @@ json_t *json_null(void)
void json_delete(json_t *json)
{
- if(json_is_object(json))
- json_delete_object(json_to_object(json));
-
- else if(json_is_array(json))
- json_delete_array(json_to_array(json));
-
- else if(json_is_string(json))
- json_delete_string(json_to_string(json));
-
- else if(json_is_integer(json))
- json_delete_integer(json_to_integer(json));
-
- else if(json_is_real(json))
- json_delete_real(json_to_real(json));
+ if (!json)
+ return;
+
+ switch(json_typeof(json)) {
+ case JSON_OBJECT:
+ json_delete_object(json_to_object(json));
+ break;
+ case JSON_ARRAY:
+ json_delete_array(json_to_array(json));
+ break;
+ case JSON_STRING:
+ json_delete_string(json_to_string(json));
+ break;
+ case JSON_INTEGER:
+ json_delete_integer(json_to_integer(json));
+ break;
+ case JSON_REAL:
+ json_delete_real(json_to_real(json));
+ break;
+ default:
+ return;
+ }
/* json_delete is not called for true, false or null */
}
@@ -950,7 +990,7 @@ void json_delete(json_t *json)
/*** equality ***/
-int json_equal(json_t *json1, json_t *json2)
+int json_equal(const json_t *json1, const json_t *json2)
{
if(!json1 || !json2)
return 0;
@@ -962,22 +1002,20 @@ int json_equal(json_t *json1, json_t *json2)
if(json1 == json2)
return 1;
- if(json_is_object(json1))
- return json_object_equal(json1, json2);
-
- if(json_is_array(json1))
- return json_array_equal(json1, json2);
-
- if(json_is_string(json1))
- return json_string_equal(json1, json2);
-
- if(json_is_integer(json1))
- return json_integer_equal(json1, json2);
-
- if(json_is_real(json1))
- return json_real_equal(json1, json2);
-
- return 0;
+ switch(json_typeof(json1)) {
+ case JSON_OBJECT:
+ return json_object_equal(json1, json2);
+ case JSON_ARRAY:
+ return json_array_equal(json1, json2);
+ case JSON_STRING:
+ return json_string_equal(json1, json2);
+ case JSON_INTEGER:
+ return json_integer_equal(json1, json2);
+ case JSON_REAL:
+ return json_real_equal(json1, json2);
+ default:
+ return 0;
+ }
}
@@ -988,25 +1026,24 @@ json_t *json_copy(json_t *json)
if(!json)
return NULL;
- if(json_is_object(json))
- return json_object_copy(json);
-
- if(json_is_array(json))
- return json_array_copy(json);
-
- if(json_is_string(json))
- return json_string_copy(json);
-
- if(json_is_integer(json))
- return json_integer_copy(json);
-
- if(json_is_real(json))
- return json_real_copy(json);
-
- if(json_is_true(json) || json_is_false(json) || json_is_null(json))
- return json;
-
- return NULL;
+ switch(json_typeof(json)) {
+ case JSON_OBJECT:
+ return json_object_copy(json);
+ case JSON_ARRAY:
+ return json_array_copy(json);
+ case JSON_STRING:
+ return json_string_copy(json);
+ case JSON_INTEGER:
+ return json_integer_copy(json);
+ case JSON_REAL:
+ return json_real_copy(json);
+ case JSON_TRUE:
+ case JSON_FALSE:
+ case JSON_NULL:
+ return json;
+ default:
+ return NULL;
+ }
}
json_t *json_deep_copy(const json_t *json)
@@ -1014,26 +1051,24 @@ json_t *json_deep_copy(const json_t *json)
if(!json)
return NULL;
- if(json_is_object(json))
- return json_object_deep_copy(json);
-
- if(json_is_array(json))
- return json_array_deep_copy(json);
-
- /* for the rest of the types, deep copying doesn't differ from
- shallow copying */
-
- if(json_is_string(json))
- return json_string_copy(json);
-
- if(json_is_integer(json))
- return json_integer_copy(json);
-
- if(json_is_real(json))
- return json_real_copy(json);
-
- if(json_is_true(json) || json_is_false(json) || json_is_null(json))
- return (json_t *)json;
-
- return NULL;
+ switch(json_typeof(json)) {
+ case JSON_OBJECT:
+ return json_object_deep_copy(json);
+ case JSON_ARRAY:
+ return json_array_deep_copy(json);
+ /* for the rest of the types, deep copying doesn't differ from
+ shallow copying */
+ case JSON_STRING:
+ return json_string_copy(json);
+ case JSON_INTEGER:
+ return json_integer_copy(json);
+ case JSON_REAL:
+ return json_real_copy(json);
+ case JSON_TRUE:
+ case JSON_FALSE:
+ case JSON_NULL:
+ return (json_t *)json;
+ default:
+ return NULL;
+ }
}
diff --git a/src/libXNVCtrl/version.mk b/src/libXNVCtrl/version.mk
index 6942222..5e94d96 100644
--- a/src/libXNVCtrl/version.mk
+++ b/src/libXNVCtrl/version.mk
@@ -1 +1 @@
-NVIDIA_VERSION = 418.56
+NVIDIA_VERSION = 430.09
diff --git a/src/nvml.h b/src/nvml.h
index f0230bd..4ba6170 100644
--- a/src/nvml.h
+++ b/src/nvml.h
@@ -243,7 +243,7 @@ typedef enum nvmlNvLinkUtilizationCountUnits_enum
NVML_NVLINK_COUNTER_UNIT_CYCLES = 0, // count by cycles
NVML_NVLINK_COUNTER_UNIT_PACKETS = 1, // count by packets
NVML_NVLINK_COUNTER_UNIT_BYTES = 2, // count by bytes
-
+ NVML_NVLINK_COUNTER_UNIT_RESERVED = 3, // count reserved for internal use
// this must be last
NVML_NVLINK_COUNTER_UNIT_COUNT
} nvmlNvLinkUtilizationCountUnits_t;
@@ -5767,6 +5767,22 @@ nvmlReturn_t DECLDIR nvmlVgpuInstanceGetType(nvmlVgpuInstance_t vgpuInstance, nv
nvmlReturn_t DECLDIR nvmlVgpuInstanceGetFrameRateLimit(nvmlVgpuInstance_t vgpuInstance, unsigned int *frameRateLimit);
/**
+ * Retrieve the current ECC mode of vGPU instance.
+ *
+ * @param vgpuInstance The identifier of the target vGPU instance
+ * @param eccMode Reference in which to return the current ECC mode
+ *
+ * @return
+ * - \ref NVML_SUCCESS if the vgpuInstance's ECC mode has been successfully retrieved
+ * - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized
+ * - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuInstance is 0, or \a mode is NULL
+ * - \ref NVML_ERROR_NOT_FOUND if \a vgpuInstance does not match a valid active vGPU instance on the system
+ * - \ref NVML_ERROR_NOT_SUPPORTED if the vGPU doesn't support this feature
+ * - \ref NVML_ERROR_UNKNOWN on any unexpected error
+ */
+nvmlReturn_t DECLDIR nvmlVgpuInstanceGetEccMode(nvmlVgpuInstance_t vgpuInstance, nvmlEnableState_t *eccMode);
+
+/**
* Retrieve the encoder capacity of a vGPU instance, as a percentage of maximum encoder capacity with valid values in the range 0-100.
*
* For Maxwell &tm; or newer fully supported devices.
@@ -6056,11 +6072,11 @@ nvmlReturn_t DECLDIR nvmlDeviceGetProcessUtilization(nvmlDevice_t device, nvmlPr
*
* For Maxwell &tm; or newer fully supported devices.
*
- * @param vgpuInstance The identifier of the target vGPU VM
+ * @param vgpuInstance The identifier of the target vGPU instance
* @param mode Reference in which to return the current accounting mode
*
- * @return
- * - \ref NVML_SUCCESS if the mode has been successfully retrieved
+ * @return
+ * - \ref NVML_SUCCESS if the mode has been successfully retrieved
* - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized
* - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuInstance is 0, or \a mode is NULL
* - \ref NVML_ERROR_NOT_FOUND if \a vgpuInstance does not match a valid active vGPU instance on the system
@@ -6070,24 +6086,24 @@ nvmlReturn_t DECLDIR nvmlDeviceGetProcessUtilization(nvmlDevice_t device, nvmlPr
nvmlReturn_t DECLDIR nvmlVgpuInstanceGetAccountingMode(nvmlVgpuInstance_t vgpuInstance, nvmlEnableState_t *mode);
/**
- * Queries list of processes running on vGPU that can be queried for accounting stats. The list of processes
+ * Queries list of processes running on vGPU that can be queried for accounting stats. The list of processes
* returned can be in running or terminated state.
*
* For Maxwell &tm; or newer fully supported devices.
- *
+ *
* To just query the maximum number of processes that can be queried, call this function with *count = 0 and
* pids=NULL. The return code will be NVML_ERROR_INSUFFICIENT_SIZE, or NVML_SUCCESS if list is empty.
- *
+ *
* For more details see \ref nvmlVgpuInstanceGetAccountingStats.
*
* @note In case of PID collision some processes might not be accessible before the circular buffer is full.
*
- * @param vgpuInstance The identifier of the target vGPU VM
+ * @param vgpuInstance The identifier of the target vGPU instance
* @param count Reference in which to provide the \a pids array size, and
* to return the number of elements ready to be queried
* @param pids Reference in which to return list of process ids
- *
- * @return
+ *
+ * @return
* - \ref NVML_SUCCESS if pids were successfully retrieved
* - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized
* - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuInstance is 0, or \a count is NULL
@@ -6104,10 +6120,10 @@ nvmlReturn_t DECLDIR nvmlVgpuInstanceGetAccountingPids(nvmlVgpuInstance_t vgpuIn
* Queries process's accounting stats.
*
* For Maxwell &tm; or newer fully supported devices.
- *
+ *
* Accounting stats capture GPU utilization and other statistics across the lifetime of a process, and
* can be queried during life time of the process or after its termination.
- * The time field in \ref nvmlAccountingStats_t is reported as 0 during the lifetime of the process and
+ * The time field in \ref nvmlAccountingStats_t is reported as 0 during the lifetime of the process and
* updated to actual running time after its termination.
* Accounting stats are kept in a circular buffer, newly created processes overwrite information about old
* processes.
@@ -6120,11 +6136,11 @@ nvmlReturn_t DECLDIR nvmlVgpuInstanceGetAccountingPids(nvmlVgpuInstance_t vgpuIn
* queried since they don't contribute to GPU utilization.
* @note In case of pid collision stats of only the latest process (that terminated last) will be reported
*
- * @param vgpuInstance The identifier of the target vGPU VM
+ * @param vgpuInstance The identifier of the target vGPU instance
* @param pid Process Id of the target process to query stats for
* @param stats Reference in which to return the process's accounting stats
*
- * @return
+ * @return
* - \ref NVML_SUCCESS if stats have been successfully retrieved
* - \ref NVML_ERROR_UNINITIALIZED if the library has not been successfully initialized
* - \ref NVML_ERROR_INVALID_ARGUMENT if \a vgpuInstance is 0, or \a stats is NULL
@@ -6292,6 +6308,26 @@ nvmlReturn_t DECLDIR nvmlDeviceGetVgpuMetadata(nvmlDevice_t device, nvmlVgpuPgpu
*/
nvmlReturn_t DECLDIR nvmlGetVgpuCompatibility(nvmlVgpuMetadata_t *vgpuMetadata, nvmlVgpuPgpuMetadata_t *pgpuMetadata, nvmlVgpuPgpuCompatibility_t *compatibilityInfo);
+/**
+ * Returns the properties of the physical GPU indicated by the device in an ascii-encoded string format.
+ *
+ * The caller passes in a buffer via \a pgpuMetadata, with the size of the buffer in \a bufferSize. If the
+ * string is too large to fit in the supplied buffer, the function returns NVML_ERROR_INSUFFICIENT_SIZE with the size needed
+ * in \a bufferSize.
+ *
+ * @param device The identifier of the target device
+ * @param pgpuMetadata Pointer to caller-supplied buffer into which \a pgpuMetadata is written
+ * @param bufferSize Pointer to size of \a pgpuMetadata buffer
+ *
+ * @return
+ * - \ref NVML_SUCCESS GPU metadata structure was successfully returned
+ * - \ref NVML_ERROR_INSUFFICIENT_SIZE \a pgpuMetadata buffer is too small, required size is returned in \a bufferSize
+ * - \ref NVML_ERROR_INVALID_ARGUMENT if \a bufferSize is NULL or \a device is invalid; if \a pgpuMetadata is NULL and the value of \a bufferSize is not 0.
+ * - \ref NVML_ERROR_NOT_SUPPORTED if vGPU is not supported by the system
+ * - \ref NVML_ERROR_UNKNOWN on any unexpected error
+ */
+nvmlReturn_t DECLDIR nvmlDeviceGetPgpuMetadataString(nvmlDevice_t device, char *pgpuMetadata, unsigned int *bufferSize);
+
/*
* Virtual GPU (vGPU) version
*
diff --git a/src/version.h b/src/version.h
index dcde6d6..68e698d 100644
--- a/src/version.h
+++ b/src/version.h
@@ -1 +1 @@
-#define NVIDIA_VERSION "418.56"
+#define NVIDIA_VERSION "430.09"
diff --git a/src/version.mk b/src/version.mk
index 6942222..5e94d96 100644
--- a/src/version.mk
+++ b/src/version.mk
@@ -1 +1 @@
-NVIDIA_VERSION = 418.56
+NVIDIA_VERSION = 430.09
diff --git a/version.mk b/version.mk
index 6942222..5e94d96 100644
--- a/version.mk
+++ b/version.mk
@@ -1 +1 @@
-NVIDIA_VERSION = 418.56
+NVIDIA_VERSION = 430.09