parent
5b88cc5ded
commit
17b5fdd94b
@ -905,6 +905,16 @@ can be ORed together to obtain *flags*.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
``JSON_REAL_PRECISION(n)``
|
||||
Output all real numbers with at most *n* digits of precision. The
|
||||
valid range for *n* is between 0 and 31 (inclusive), and other
|
||||
values result in an undefined behavior.
|
||||
|
||||
By default, the precision is 17, to correctly and losslessly encode
|
||||
all IEEE 754 double precision floating point numbers.
|
||||
|
||||
.. versionadded:: 2.7
|
||||
|
||||
The following functions perform the actual JSON encoding. The result
|
||||
is in UTF-8.
|
||||
|
||||
|
10
src/dump.c
10
src/dump.c
@ -22,6 +22,9 @@
|
||||
#define MAX_INTEGER_STR_LENGTH 100
|
||||
#define MAX_REAL_STR_LENGTH 100
|
||||
|
||||
#define FLAGS_TO_INDENT(f) ((f) & 0x1F)
|
||||
#define FLAGS_TO_PRECISION(f) (((f) >> 11) & 0x1F)
|
||||
|
||||
struct object_key {
|
||||
size_t serial;
|
||||
const char *key;
|
||||
@ -45,9 +48,9 @@ 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);
|
||||
int i, ws_count = FLAGS_TO_INDENT(flags);
|
||||
|
||||
if(dump("\n", 1, data))
|
||||
return -1;
|
||||
@ -208,7 +211,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;
|
||||
|
||||
|
@ -259,13 +259,14 @@ json_t *json_load_callback(json_load_callback_t callback, void *data, size_t fla
|
||||
|
||||
/* 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_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_REAL_PRECISION(n) (((n) & 0x1F) << 11)
|
||||
|
||||
typedef int (*json_dump_callback_t)(const char *buffer, size_t size, void *data);
|
||||
|
||||
|
@ -81,7 +81,7 @@ void jsonp_error_vset(json_error_t *error, int line, int column,
|
||||
|
||||
/* 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);
|
||||
|
@ -78,13 +78,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;
|
||||
|
||||
|
@ -39,6 +39,7 @@ struct config {
|
||||
int use_env;
|
||||
int have_hashseed;
|
||||
int hashseed;
|
||||
int precision;
|
||||
} conf;
|
||||
|
||||
#define l_isspace(c) ((c) == ' ' || (c) == '\n' || (c) == '\r' || (c) == '\t')
|
||||
@ -108,6 +109,8 @@ static void read_conf(FILE *conffile)
|
||||
conf.preserve_order = atoi(val);
|
||||
if (!strcmp(line, "JSON_SORT_KEYS"))
|
||||
conf.sort_keys = atoi(val);
|
||||
if (!strcmp(line, "JSON_REAL_PRECISION"))
|
||||
conf.precision = atoi(val);
|
||||
if (!strcmp(line, "STRIP"))
|
||||
conf.strip = atoi(val);
|
||||
if (!strcmp(line, "HASHSEED")) {
|
||||
@ -176,11 +179,10 @@ int use_conf(char *test_path)
|
||||
fclose(conffile);
|
||||
}
|
||||
|
||||
if (conf.indent < 0 || conf.indent > 255) {
|
||||
if (conf.indent < 0 || conf.indent > 31) {
|
||||
fprintf(stderr, "invalid value for JSON_INDENT: %d\n", conf.indent);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (conf.indent)
|
||||
flags |= JSON_INDENT(conf.indent);
|
||||
|
||||
@ -196,6 +198,14 @@ int use_conf(char *test_path)
|
||||
if (conf.sort_keys)
|
||||
flags |= JSON_SORT_KEYS;
|
||||
|
||||
if (conf.precision < 0 || conf.precision > 31) {
|
||||
fprintf(stderr, "invalid value for JSON_REAL_PRECISION: %d\n",
|
||||
conf.precision);
|
||||
return 2;
|
||||
}
|
||||
if (conf.precision)
|
||||
flags |= JSON_REAL_PRECISION(conf.precision);
|
||||
|
||||
if (conf.have_hashseed)
|
||||
json_object_seed(conf.hashseed);
|
||||
|
||||
@ -245,7 +255,7 @@ static int getenv_int(const char *name)
|
||||
|
||||
int use_env()
|
||||
{
|
||||
int indent;
|
||||
int indent, precision;
|
||||
size_t flags = 0;
|
||||
json_t *json;
|
||||
json_error_t error;
|
||||
@ -258,11 +268,10 @@ int use_env()
|
||||
#endif
|
||||
|
||||
indent = getenv_int("JSON_INDENT");
|
||||
if(indent < 0 || indent > 255) {
|
||||
if(indent < 0 || indent > 31) {
|
||||
fprintf(stderr, "invalid value for JSON_INDENT: %d\n", indent);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if(indent > 0)
|
||||
flags |= JSON_INDENT(indent);
|
||||
|
||||
@ -278,9 +287,19 @@ int use_env()
|
||||
if(getenv_int("JSON_SORT_KEYS"))
|
||||
flags |= JSON_SORT_KEYS;
|
||||
|
||||
precision = getenv_int("JSON_REAL_PRECISION");
|
||||
if(precision < 0 || precision > 31) {
|
||||
fprintf(stderr, "invalid value for JSON_REAL_PRECISION: %d\n",
|
||||
precision);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if(getenv("HASHSEED"))
|
||||
json_object_seed(getenv_int("HASHSEED"));
|
||||
|
||||
if(precision > 0)
|
||||
flags |= JSON_REAL_PRECISION(precision);
|
||||
|
||||
if(getenv_int("STRIP")) {
|
||||
/* Load to memory, strip leading and trailing whitespace */
|
||||
size_t size = 0, used = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user