mirror of https://github.com/GOSTSec/sgminer
Con Kolivas
11 years ago
20 changed files with 1267 additions and 466 deletions
@ -1,21 +1,21 @@
@@ -1,21 +1,21 @@
|
||||
EXTRA_DIST = jansson.def |
||||
|
||||
include_HEADERS = jansson.h jansson_config.h |
||||
|
||||
noinst_LIBRARIES = libjansson.a |
||||
|
||||
libjansson_a_SOURCES = \
|
||||
config.h \
|
||||
jansson_config.h \
|
||||
dump.c \
|
||||
error.c \
|
||||
hashtable.c \
|
||||
hashtable.h \
|
||||
jansson.h \
|
||||
jansson_private.h \
|
||||
load.c \
|
||||
memory.c \
|
||||
pack_unpack.c \
|
||||
strbuffer.c \
|
||||
strbuffer.h \
|
||||
strconv.c \
|
||||
utf.c \
|
||||
utf.h \
|
||||
util.h \
|
||||
value.c \
|
||||
memory.c \
|
||||
error.c |
||||
|
||||
value.c |
||||
|
@ -1,73 +0,0 @@
@@ -1,73 +0,0 @@
|
||||
/* config.h. Generated from config.h.in by configure. */ |
||||
/* config.h.in. Generated from configure.ac by autoheader. */ |
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */ |
||||
#define HAVE_DLFCN_H 1 |
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */ |
||||
#define HAVE_INTTYPES_H 1 |
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */ |
||||
#define HAVE_MEMORY_H 1 |
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */ |
||||
#define HAVE_STDINT_H 1 |
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */ |
||||
#define HAVE_STDLIB_H 1 |
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */ |
||||
#define HAVE_STRINGS_H 1 |
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */ |
||||
#define HAVE_STRING_H 1 |
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */ |
||||
#define HAVE_SYS_STAT_H 1 |
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */ |
||||
#define HAVE_SYS_TYPES_H 1 |
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */ |
||||
#define HAVE_UNISTD_H 1 |
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/ |
||||
#define LT_OBJDIR ".libs/" |
||||
|
||||
/* Name of package */ |
||||
#define PACKAGE "jansson" |
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */ |
||||
#define PACKAGE_BUGREPORT "petri@digip.org" |
||||
|
||||
/* Define to the full name of this package. */ |
||||
#define PACKAGE_NAME "jansson" |
||||
|
||||
/* Define to the full name and version of this package. */ |
||||
#define PACKAGE_STRING "jansson 1.3" |
||||
|
||||
/* Define to the one symbol short name of this package. */ |
||||
#define PACKAGE_TARNAME "jansson" |
||||
|
||||
/* Define to the home page for this package. */ |
||||
#define PACKAGE_URL "" |
||||
|
||||
/* Define to the version of this package. */ |
||||
#define PACKAGE_VERSION "1.3" |
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */ |
||||
#define STDC_HEADERS 1 |
||||
|
||||
/* Version number of package */ |
||||
#define VERSION "1.3" |
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */ |
||||
#ifndef __cplusplus |
||||
/* #undef inline */ |
||||
#endif |
||||
|
||||
/* Define to the type of a signed integer type of width exactly 32 bits if
|
||||
such a type exists and the standard includes do not define it. */ |
||||
/* #undef int32_t */ |
@ -0,0 +1,65 @@
@@ -0,0 +1,65 @@
|
||||
LIBRARY "jansson" |
||||
|
||||
EXPORTS |
||||
json_delete |
||||
json_true |
||||
json_false |
||||
json_null |
||||
json_string |
||||
json_string_nocheck |
||||
json_string_value |
||||
json_string_set |
||||
json_string_set_nocheck |
||||
json_integer |
||||
json_integer_value |
||||
json_integer_set |
||||
json_real |
||||
json_real_value |
||||
json_real_set |
||||
json_number_value |
||||
json_array |
||||
json_array_size |
||||
json_array_get |
||||
json_array_set_new |
||||
json_array_append_new |
||||
json_array_insert_new |
||||
json_array_remove |
||||
json_array_clear |
||||
json_array_extend |
||||
json_object |
||||
json_object_size |
||||
json_object_get |
||||
json_object_set_new |
||||
json_object_set_new_nocheck |
||||
json_object_del |
||||
json_object_clear |
||||
json_object_update |
||||
json_object_update_existing |
||||
json_object_update_missing |
||||
json_object_iter |
||||
json_object_iter_at |
||||
json_object_iter_next |
||||
json_object_iter_key |
||||
json_object_iter_value |
||||
json_object_iter_set_new |
||||
json_object_key_to_iter |
||||
json_dumps |
||||
json_dumpf |
||||
json_dump_file |
||||
json_dump_callback |
||||
json_loads |
||||
json_loadb |
||||
json_loadf |
||||
json_load_file |
||||
json_load_callback |
||||
json_equal |
||||
json_copy |
||||
json_deep_copy |
||||
json_pack |
||||
json_pack_ex |
||||
json_vpack_ex |
||||
json_unpack |
||||
json_unpack_ex |
||||
json_vunpack_ex |
||||
json_set_alloc_funcs |
||||
|
@ -0,0 +1,647 @@
@@ -0,0 +1,647 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2012 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 |
||||
* it under the terms of the MIT license. See LICENSE for details. |
||||
*/ |
||||
|
||||
#include <string.h> |
||||
#include "jansson.h" |
||||
#include "jansson_private.h" |
||||
#include "utf.h" |
||||
|
||||
typedef struct { |
||||
const char *start; |
||||
const char *fmt; |
||||
char token; |
||||
json_error_t *error; |
||||
size_t flags; |
||||
int line; |
||||
int column; |
||||
} scanner_t; |
||||
|
||||
static const char *type_names[] = { |
||||
"object", |
||||
"array", |
||||
"string", |
||||
"integer", |
||||
"real", |
||||
"true", |
||||
"false", |
||||
"null" |
||||
}; |
||||
|
||||
#define type_name(x) type_names[json_typeof(x)] |
||||
|
||||
static const char *unpack_value_starters = "{[siIbfFOon"; |
||||
|
||||
|
||||
static void scanner_init(scanner_t *s, json_error_t *error, |
||||
size_t flags, const char *fmt) |
||||
{ |
||||
s->error = error; |
||||
s->flags = flags; |
||||
s->fmt = s->start = fmt; |
||||
s->line = 1; |
||||
s->column = 0; |
||||
} |
||||
|
||||
static void next_token(scanner_t *s) |
||||
{ |
||||
const char *t = s->fmt; |
||||
s->column++; |
||||
|
||||
/* skip space and ignored chars */ |
||||
while(*t == ' ' || *t == '\t' || *t == '\n' || *t == ',' || *t == ':') { |
||||
if(*t == '\n') { |
||||
s->line++; |
||||
s->column = 1; |
||||
} |
||||
else |
||||
s->column++; |
||||
|
||||
t++; |
||||
} |
||||
|
||||
s->token = *t; |
||||
|
||||
t++; |
||||
s->fmt = t; |
||||
} |
||||
|
||||
static void set_error(scanner_t *s, const char *source, const char *fmt, ...) |
||||
{ |
||||
va_list ap; |
||||
size_t pos; |
||||
va_start(ap, fmt); |
||||
|
||||
pos = (size_t)(s->fmt - s->start); |
||||
jsonp_error_vset(s->error, s->line, s->column, pos, fmt, ap); |
||||
|
||||
jsonp_error_set_source(s->error, source); |
||||
|
||||
va_end(ap); |
||||
} |
||||
|
||||
static json_t *pack(scanner_t *s, va_list *ap); |
||||
|
||||
static json_t *pack_object(scanner_t *s, va_list *ap) |
||||
{ |
||||
json_t *object = json_object(); |
||||
next_token(s); |
||||
|
||||
while(s->token != '}') { |
||||
const char *key; |
||||
json_t *value; |
||||
|
||||
if(!s->token) { |
||||
set_error(s, "<format>", "Unexpected end of format string"); |
||||
goto error; |
||||
} |
||||
|
||||
if(s->token != 's') { |
||||
set_error(s, "<format>", "Expected format 's', got '%c'", s->token); |
||||
goto error; |
||||
} |
||||
|
||||
key = va_arg(*ap, const char *); |
||||
if(!key) { |
||||
set_error(s, "<args>", "NULL object key"); |
||||
goto error; |
||||
} |
||||
|
||||
if(!utf8_check_string(key, -1)) { |
||||
set_error(s, "<args>", "Invalid UTF-8 in object key"); |
||||
goto error; |
||||
} |
||||
|
||||
next_token(s); |
||||
|
||||
value = pack(s, ap); |
||||
if(!value) |
||||
goto error; |
||||
|
||||
if(json_object_set_new_nocheck(object, key, value)) { |
||||
set_error(s, "<internal>", "Unable to add key \"%s\"", key); |
||||
goto error; |
||||
} |
||||
|
||||
next_token(s); |
||||
} |
||||
|
||||
return object; |
||||
|
||||
error: |
||||
json_decref(object); |
||||
return NULL; |
||||
} |
||||
|
||||
static json_t *pack_array(scanner_t *s, va_list *ap) |
||||
{ |
||||
json_t *array = json_array(); |
||||
next_token(s); |
||||
|
||||
while(s->token != ']') { |
||||
json_t *value; |
||||
|
||||
if(!s->token) { |
||||
set_error(s, "<format>", "Unexpected end of format string"); |
||||
goto error; |
||||
} |
||||
|
||||
value = pack(s, ap); |
||||
if(!value) |
||||
goto error; |
||||
|
||||
if(json_array_append_new(array, value)) { |
||||
set_error(s, "<internal>", "Unable to append to array"); |
||||
goto error; |
||||
} |
||||
|
||||
next_token(s); |
||||
} |
||||
return array; |
||||
|
||||
error: |
||||
json_decref(array); |
||||
return NULL; |
||||
} |
||||
|
||||
static json_t *pack(scanner_t *s, va_list *ap) |
||||
{ |
||||
switch(s->token) { |
||||
case '{': |
||||
return pack_object(s, ap); |
||||
|
||||
case '[': |
||||
return pack_array(s, ap); |
||||
|
||||
case 's': /* string */ |
||||
{ |
||||
const char *str = va_arg(*ap, const char *); |
||||
if(!str) { |
||||
set_error(s, "<args>", "NULL string argument"); |
||||
return NULL; |
||||
} |
||||
if(!utf8_check_string(str, -1)) { |
||||
set_error(s, "<args>", "Invalid UTF-8 string"); |
||||
return NULL; |
||||
} |
||||
return json_string_nocheck(str); |
||||
} |
||||
|
||||
case 'n': /* null */ |
||||
return json_null(); |
||||
|
||||
case 'b': /* boolean */ |
||||
return va_arg(*ap, int) ? json_true() : json_false(); |
||||
|
||||
case 'i': /* integer from int */ |
||||
return json_integer(va_arg(*ap, int)); |
||||
|
||||
case 'I': /* integer from json_int_t */ |
||||
return json_integer(va_arg(*ap, json_int_t)); |
||||
|
||||
case 'f': /* real */ |
||||
return json_real(va_arg(*ap, double)); |
||||
|
||||
case 'O': /* a json_t object; increments refcount */ |
||||
return json_incref(va_arg(*ap, json_t *)); |
||||
|
||||
case 'o': /* a json_t object; doesn't increment refcount */ |
||||
return va_arg(*ap, json_t *); |
||||
|
||||
default: |
||||
set_error(s, "<format>", "Unexpected format character '%c'", |
||||
s->token); |
||||
return NULL; |
||||
} |
||||
} |
||||
|
||||
static int unpack(scanner_t *s, json_t *root, va_list *ap); |
||||
|
||||
static int unpack_object(scanner_t *s, json_t *root, va_list *ap) |
||||
{ |
||||
int ret = -1; |
||||
int strict = 0; |
||||
|
||||
/* Use a set (emulated by a hashtable) to check that all object
|
||||
keys are accessed. Checking that the correct number of keys |
||||
were accessed is not enough, as the same key can be unpacked |
||||
multiple times. |
||||
*/ |
||||
hashtable_t key_set; |
||||
|
||||
if(hashtable_init(&key_set)) { |
||||
set_error(s, "<internal>", "Out of memory"); |
||||
return -1; |
||||
} |
||||
|
||||
if(root && !json_is_object(root)) { |
||||
set_error(s, "<validation>", "Expected object, got %s", |
||||
type_name(root)); |
||||
goto out; |
||||
} |
||||
next_token(s); |
||||
|
||||
while(s->token != '}') { |
||||
const char *key; |
||||
json_t *value; |
||||
int opt = 0; |
||||
|
||||
if(strict != 0) { |
||||
set_error(s, "<format>", "Expected '}' after '%c', got '%c'", |
||||
(strict == 1 ? '!' : '*'), s->token); |
||||
goto out; |
||||
} |
||||
|
||||
if(!s->token) { |
||||
set_error(s, "<format>", "Unexpected end of format string"); |
||||
goto out; |
||||
} |
||||
|
||||
if(s->token == '!' || s->token == '*') { |
||||
strict = (s->token == '!' ? 1 : -1); |
||||
next_token(s); |
||||
continue; |
||||
} |
||||
|
||||
if(s->token != 's') { |
||||
set_error(s, "<format>", "Expected format 's', got '%c'", s->token); |
||||
goto out; |
||||
} |
||||
|
||||
key = va_arg(*ap, const char *); |
||||
if(!key) { |
||||
set_error(s, "<args>", "NULL object key"); |
||||
goto out; |
||||
} |
||||
|
||||
next_token(s); |
||||
|
||||
if(s->token == '?') { |
||||
opt = 1; |
||||
next_token(s); |
||||
} |
||||
|
||||
if(!root) { |
||||
/* skipping */ |
||||
value = NULL; |
||||
} |
||||
else { |
||||
value = json_object_get(root, key); |
||||
if(!value && !opt) { |
||||
set_error(s, "<validation>", "Object item not found: %s", key); |
||||
goto out; |
||||
} |
||||
} |
||||
|
||||
if(unpack(s, value, ap)) |
||||
goto out; |
||||
|
||||
hashtable_set(&key_set, key, 0, json_null()); |
||||
next_token(s); |
||||
} |
||||
|
||||
if(strict == 0 && (s->flags & JSON_STRICT)) |
||||
strict = 1; |
||||
|
||||
if(root && strict == 1 && key_set.size != json_object_size(root)) { |
||||
long diff = (long)json_object_size(root) - (long)key_set.size; |
||||
set_error(s, "<validation>", "%li object item(s) left unpacked", diff); |
||||
goto out; |
||||
} |
||||
|
||||
ret = 0; |
||||
|
||||
out: |
||||
hashtable_close(&key_set); |
||||
return ret; |
||||
} |
||||
|
||||
static int unpack_array(scanner_t *s, json_t *root, va_list *ap) |
||||
{ |
||||
size_t i = 0; |
||||
int strict = 0; |
||||
|
||||
if(root && !json_is_array(root)) { |
||||
set_error(s, "<validation>", "Expected array, got %s", type_name(root)); |
||||
return -1; |
||||
} |
||||
next_token(s); |
||||
|
||||
while(s->token != ']') { |
||||
json_t *value; |
||||
|
||||
if(strict != 0) { |
||||
set_error(s, "<format>", "Expected ']' after '%c', got '%c'", |
||||
(strict == 1 ? '!' : '*'), |
||||
s->token); |
||||
return -1; |
||||
} |
||||
|
||||
if(!s->token) { |
||||
set_error(s, "<format>", "Unexpected end of format string"); |
||||
return -1; |
||||
} |
||||
|
||||
if(s->token == '!' || s->token == '*') { |
||||
strict = (s->token == '!' ? 1 : -1); |
||||
next_token(s); |
||||
continue; |
||||
} |
||||
|
||||
if(!strchr(unpack_value_starters, s->token)) { |
||||
set_error(s, "<format>", "Unexpected format character '%c'", |
||||
s->token); |
||||
return -1; |
||||
} |
||||
|
||||
if(!root) { |
||||
/* skipping */ |
||||
value = NULL; |
||||
} |
||||
else { |
||||
value = json_array_get(root, i); |
||||
if(!value) { |
||||
set_error(s, "<validation>", "Array index %lu out of range", |
||||
(unsigned long)i); |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
if(unpack(s, value, ap)) |
||||
return -1; |
||||
|
||||
next_token(s); |
||||
i++; |
||||
} |
||||
|
||||
if(strict == 0 && (s->flags & JSON_STRICT)) |
||||
strict = 1; |
||||
|
||||
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); |
||||
return -1; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int unpack(scanner_t *s, json_t *root, va_list *ap) |
||||
{ |
||||
switch(s->token) |
||||
{ |
||||
case '{': |
||||
return unpack_object(s, root, ap); |
||||
|
||||
case '[': |
||||
return unpack_array(s, root, ap); |
||||
|
||||
case 's': |
||||
if(root && !json_is_string(root)) { |
||||
set_error(s, "<validation>", "Expected string, got %s", |
||||
type_name(root)); |
||||
return -1; |
||||
} |
||||
|
||||
if(!(s->flags & JSON_VALIDATE_ONLY)) { |
||||
const char **target; |
||||
|
||||
target = va_arg(*ap, const char **); |
||||
if(!target) { |
||||
set_error(s, "<args>", "NULL string argument"); |
||||
return -1; |
||||
} |
||||
|
||||
if(root) |
||||
*target = json_string_value(root); |
||||
} |
||||
return 0; |
||||
|
||||
case 'i': |
||||
if(root && !json_is_integer(root)) { |
||||
set_error(s, "<validation>", "Expected integer, got %s", |
||||
type_name(root)); |
||||
return -1; |
||||
} |
||||
|
||||
if(!(s->flags & JSON_VALIDATE_ONLY)) { |
||||
int *target = va_arg(*ap, int*); |
||||
if(root) |
||||
*target = (int)json_integer_value(root); |
||||
} |
||||
|
||||
return 0; |
||||
|
||||
case 'I': |
||||
if(root && !json_is_integer(root)) { |
||||
set_error(s, "<validation>", "Expected integer, got %s", |
||||
type_name(root)); |
||||
return -1; |
||||
} |
||||
|
||||
if(!(s->flags & JSON_VALIDATE_ONLY)) { |
||||
json_int_t *target = va_arg(*ap, json_int_t*); |
||||
if(root) |
||||
*target = json_integer_value(root); |
||||
} |
||||
|
||||
return 0; |
||||
|
||||
case 'b': |
||||
if(root && !json_is_boolean(root)) { |
||||
set_error(s, "<validation>", "Expected true or false, got %s", |
||||
type_name(root)); |
||||
return -1; |
||||
} |
||||
|
||||
if(!(s->flags & JSON_VALIDATE_ONLY)) { |
||||
int *target = va_arg(*ap, int*); |
||||
if(root) |
||||
*target = json_is_true(root); |
||||
} |
||||
|
||||
return 0; |
||||
|
||||
case 'f': |
||||
if(root && !json_is_real(root)) { |
||||
set_error(s, "<validation>", "Expected real, got %s", |
||||
type_name(root)); |
||||
return -1; |
||||
} |
||||
|
||||
if(!(s->flags & JSON_VALIDATE_ONLY)) { |
||||
double *target = va_arg(*ap, double*); |
||||
if(root) |
||||
*target = json_real_value(root); |
||||
} |
||||
|
||||
return 0; |
||||
|
||||
case 'F': |
||||
if(root && !json_is_number(root)) { |
||||
set_error(s, "<validation>", "Expected real or integer, got %s", |
||||
type_name(root)); |
||||
return -1; |
||||
} |
||||
|
||||
if(!(s->flags & JSON_VALIDATE_ONLY)) { |
||||
double *target = va_arg(*ap, double*); |
||||
if(root) |
||||
*target = json_number_value(root); |
||||
} |
||||
|
||||
return 0; |
||||
|
||||
case 'O': |
||||
if(root && !(s->flags & JSON_VALIDATE_ONLY)) |
||||
json_incref(root); |
||||
/* Fall through */ |
||||
|
||||
case 'o': |
||||
if(!(s->flags & JSON_VALIDATE_ONLY)) { |
||||
json_t **target = va_arg(*ap, json_t**); |
||||
if(root) |
||||
*target = root; |
||||
} |
||||
|
||||
return 0; |
||||
|
||||
case 'n': |
||||
/* Never assign, just validate */ |
||||
if(root && !json_is_null(root)) { |
||||
set_error(s, "<validation>", "Expected null, got %s", |
||||
type_name(root)); |
||||
return -1; |
||||
} |
||||
return 0; |
||||
|
||||
default: |
||||
set_error(s, "<format>", "Unexpected format character '%c'", |
||||
s->token); |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
json_t *json_vpack_ex(json_error_t *error, size_t flags, |
||||
const char *fmt, va_list ap) |
||||
{ |
||||
scanner_t s; |
||||
va_list ap_copy; |
||||
json_t *value; |
||||
|
||||
if(!fmt || !*fmt) { |
||||
jsonp_error_init(error, "<format>"); |
||||
jsonp_error_set(error, -1, -1, 0, "NULL or empty format string"); |
||||
return NULL; |
||||
} |
||||
jsonp_error_init(error, NULL); |
||||
|
||||
scanner_init(&s, error, flags, fmt); |
||||
next_token(&s); |
||||
|
||||
va_copy(ap_copy, ap); |
||||
value = pack(&s, &ap_copy); |
||||
va_end(ap_copy); |
||||
|
||||
if(!value) |
||||
return NULL; |
||||
|
||||
next_token(&s); |
||||
if(s.token) { |
||||
json_decref(value); |
||||
set_error(&s, "<format>", "Garbage after format string"); |
||||
return NULL; |
||||
} |
||||
|
||||
return value; |
||||
} |
||||
|
||||
json_t *json_pack_ex(json_error_t *error, size_t flags, const char *fmt, ...) |
||||
{ |
||||
json_t *value; |
||||
va_list ap; |
||||
|
||||
va_start(ap, fmt); |
||||
value = json_vpack_ex(error, flags, fmt, ap); |
||||
va_end(ap); |
||||
|
||||
return value; |
||||
} |
||||
|
||||
json_t *json_pack(const char *fmt, ...) |
||||
{ |
||||
json_t *value; |
||||
va_list ap; |
||||
|
||||
va_start(ap, fmt); |
||||
value = json_vpack_ex(NULL, 0, fmt, ap); |
||||
va_end(ap); |
||||
|
||||
return value; |
||||
} |
||||
|
||||
int json_vunpack_ex(json_t *root, json_error_t *error, size_t flags, |
||||
const char *fmt, va_list ap) |
||||
{ |
||||
scanner_t s; |
||||
va_list ap_copy; |
||||
|
||||
if(!root) { |
||||
jsonp_error_init(error, "<root>"); |
||||
jsonp_error_set(error, -1, -1, 0, "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"); |
||||
return -1; |
||||
} |
||||
jsonp_error_init(error, NULL); |
||||
|
||||
scanner_init(&s, error, flags, fmt); |
||||
next_token(&s); |
||||
|
||||
va_copy(ap_copy, ap); |
||||
if(unpack(&s, root, &ap_copy)) { |
||||
va_end(ap_copy); |
||||
return -1; |
||||
} |
||||
va_end(ap_copy); |
||||
|
||||
next_token(&s); |
||||
if(s.token) { |
||||
set_error(&s, "<format>", "Garbage after format string"); |
||||
return -1; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
int json_unpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt, ...) |
||||
{ |
||||
int ret; |
||||
va_list ap; |
||||
|
||||
va_start(ap, fmt); |
||||
ret = json_vunpack_ex(root, error, flags, fmt, ap); |
||||
va_end(ap); |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
int json_unpack(json_t *root, const char *fmt, ...) |
||||
{ |
||||
int ret; |
||||
va_list ap; |
||||
|
||||
va_start(ap, fmt); |
||||
ret = json_vunpack_ex(root, NULL, 0, fmt, ap); |
||||
va_end(ap); |
||||
|
||||
return ret; |
||||
} |
@ -0,0 +1,129 @@
@@ -0,0 +1,129 @@
|
||||
#include <assert.h> |
||||
#include <errno.h> |
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
#include "jansson_private.h" |
||||
#include "strbuffer.h" |
||||
|
||||
#if JSON_HAVE_LOCALECONV |
||||
#include <locale.h> |
||||
|
||||
/*
|
||||
- This code assumes that the decimal separator is exactly one |
||||
character. |
||||
|
||||
- If setlocale() is called by another thread between the call to |
||||
localeconv() and the call to sprintf() or strtod(), the result may |
||||
be wrong. setlocale() is not thread-safe and should not be used |
||||
this way. Multi-threaded programs should use uselocale() instead. |
||||
*/ |
||||
|
||||
static void to_locale(strbuffer_t *strbuffer) |
||||
{ |
||||
const char *point; |
||||
char *pos; |
||||
|
||||
point = localeconv()->decimal_point; |
||||
if(*point == '.') { |
||||
/* No conversion needed */ |
||||
return; |
||||
} |
||||
|
||||
pos = strchr(strbuffer->value, '.'); |
||||
if(pos) |
||||
*pos = *point; |
||||
} |
||||
|
||||
static void from_locale(char *buffer) |
||||
{ |
||||
const char *point; |
||||
char *pos; |
||||
|
||||
point = localeconv()->decimal_point; |
||||
if(*point == '.') { |
||||
/* No conversion needed */ |
||||
return; |
||||
} |
||||
|
||||
pos = strchr(buffer, *point); |
||||
if(pos) |
||||
*pos = '.'; |
||||
} |
||||
#endif |
||||
|
||||
int jsonp_strtod(strbuffer_t *strbuffer, double *out) |
||||
{ |
||||
double value; |
||||
char *end; |
||||
|
||||
#if JSON_HAVE_LOCALECONV |
||||
to_locale(strbuffer); |
||||
#endif |
||||
|
||||
errno = 0; |
||||
value = strtod(strbuffer->value, &end); |
||||
assert(end == strbuffer->value + strbuffer->length); |
||||
|
||||
if(errno == ERANGE && value != 0) { |
||||
/* Overflow */ |
||||
return -1; |
||||
} |
||||
|
||||
*out = value; |
||||
return 0; |
||||
} |
||||
|
||||
int jsonp_dtostr(char *buffer, size_t size, double value) |
||||
{ |
||||
int ret; |
||||
char *start, *end; |
||||
size_t length; |
||||
|
||||
ret = snprintf(buffer, size, "%.17g", value); |
||||
if(ret < 0) |
||||
return -1; |
||||
|
||||
length = (size_t)ret; |
||||
if(length >= size) |
||||
return -1; |
||||
|
||||
#if JSON_HAVE_LOCALECONV |
||||
from_locale(buffer); |
||||
#endif |
||||
|
||||
/* Make sure there's a dot or 'e' in the output. Otherwise
|
||||
a real is converted to an integer when decoding */ |
||||
if(strchr(buffer, '.') == NULL && |
||||
strchr(buffer, 'e') == NULL) |
||||
{ |
||||
if(length + 3 >= size) { |
||||
/* No space to append ".0" */ |
||||
return -1; |
||||
} |
||||
buffer[length] = '.'; |
||||
buffer[length + 1] = '0'; |
||||
buffer[length + 2] = '\0'; |
||||
length += 2; |
||||
} |
||||
|
||||
/* Remove leading '+' from positive exponent. Also remove leading
|
||||
zeros from exponents (added by some printf() implementations) */ |
||||
start = strchr(buffer, 'e'); |
||||
if(start) { |
||||
start++; |
||||
end = start + 1; |
||||
|
||||
if(*start == '-') |
||||
start++; |
||||
|
||||
while(*end == '0') |
||||
end++; |
||||
|
||||
if(end != start) { |
||||
memmove(start, end, length - (size_t)(end - buffer)); |
||||
length -= (size_t)(end - start); |
||||
} |
||||
} |
||||
|
||||
return (int)length; |
||||
} |
Loading…
Reference in new issue