13 Commits
v2.2 ... v2.2.1

Author SHA1 Message Date
Petri Lehtinen
9c6cb42f17 jansson 2.2.1 2011-10-06 21:23:09 +03:00
Petri Lehtinen
ed06777937 Distribute doc/portability.rst 2011-10-06 21:23:09 +03:00
Petri Lehtinen
6362032513 json_load_file: Open the input file in rb mode
For maximum compatibility.
2011-10-04 21:11:31 +03:00
Petri Lehtinen
84f739036d Documentation fixes 2011-10-04 21:04:56 +03:00
Petri Lehtinen
0f358c8eaa doc: Add project status to introduction, add portability chapter
Move the multithreading-and-setlocale documentation to the new
portability chapter.

Fixes GH-36.
2011-10-03 22:42:39 +03:00
Petri Lehtinen
f0d5c04734 Make identifier decoding work under all locales
Replace isxxx() functions from ctype.h with locale-independent macros.

Fixes GH-35.
2011-10-03 21:43:16 +03:00
Petri Lehtinen
fd56deb7dd Use strchr() when searching for a single character 2011-10-03 08:52:30 +03:00
Petri Lehtinen
d7ddbf3661 Make real number encoding and decoding work under all locales
The decimal point '.' is changed to locale's decimal point
before/after JSON conversion to make C standard library's
locale-specific string conversion functions work correctly.

All the tests now call setlocale(LC_ALL, "") on startup to use the
locale set in the environment.

Fixes GH-32.
2011-10-02 21:31:17 +03:00
Petri Lehtinen
b6d0191e51 Implement all other encoding functions using json_dump_callback
This way we can check for JSON_ENCODE_ANY flag in one place only.
2011-09-24 21:10:34 +03:00
Petri Lehtinen
2a70d62251 Merge pull request #33 from bakulf/master
Little fixes
2011-09-20 11:11:55 -07:00
Andrea Marchesini
909874b1b9 scope error. result points to a out-of-score variable. 2011-09-20 13:10:32 +02:00
Andrea Marchesini
ff57dee13d unsed static variable removed 2011-09-20 11:46:29 +02:00
Petri Lehtinen
e4cc77ce52 doc: Clarify the result of 's' format of json_unpack()
Fixes GH-31.
2011-09-12 21:22:20 +03:00
32 changed files with 310 additions and 110 deletions

28
CHANGES
View File

@@ -1,3 +1,31 @@
Version 2.2.1
=============
Released 2011-10-06
* Bug fixes:
- Fix real number encoding and decoding under non-C locales. (#32)
- Fix identifier decoding under non-UTF-8 locales. (#35)
- `json_load_file()`: Open the input file in binary mode for maximum
compatiblity.
* Documentation:
- Clarify the lifecycle of the result of the ``s`` fromat of
`json_unpack()`. (#31)
- Add some portability info. (#36)
- Little clarifications here and there.
* Other:
- Some style fixes, issues detected by static analyzers.
Version 2.2
===========

View File

@@ -1,5 +1,5 @@
AC_PREREQ([2.60])
AC_INIT([jansson], [2.2], [petri@digip.org])
AC_INIT([jansson], [2.2.1], [petri@digip.org])
AM_INIT_AUTOMAKE([1.10 foreign])
@@ -14,6 +14,7 @@ AM_CONDITIONAL([GCC], [test x$GCC = xyes])
# Checks for libraries.
# Checks for header files.
AC_CHECK_HEADERS([locale.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_INT32_T
@@ -34,6 +35,12 @@ esac
AC_SUBST([json_inline])
# Checks for library functions.
AC_CHECK_FUNCS([setlocale localeconv])
case "$ac_cv_header_locale_h$ac_cv_func_localeconv" in
yesyes) json_have_localeconv=1;;
*) json_have_localeconv=0;;
esac
AC_SUBST([json_have_localeconv])
AC_CONFIG_FILES([
jansson.pc

View File

@@ -1,6 +1,6 @@
EXTRA_DIST = conf.py apiref.rst changes.rst conformance.rst \
gettingstarted.rst github_commits.c index.rst tutorial.rst \
upgrading.rst ext/refcounting.py
gettingstarted.rst github_commits.c index.rst portability.rst \
tutorial.rst upgrading.rst ext/refcounting.py
SPHINXBUILD = sphinx-build
SPHINXOPTS = -d _build/doctrees $(SPHINXOPTS_EXTRA)

View File

@@ -703,9 +703,9 @@ can be ORed together to obtain *flags*.
``JSON_INDENT(n)``
Pretty-print the result, using newlines between array and object
items, and indenting with *n* spaces. The valid range for *n* is
between 0 and 32, other values result in an undefined output. If
``JSON_INDENT`` is not used or *n* is 0, no newlines are inserted
between array and object items.
between 0 and 31 (inclusive), other values result in an undefined
output. If ``JSON_INDENT`` is not used or *n* is 0, no newlines are
inserted between array and object items.
``JSON_COMPACT``
This flag enables a compact representation, i.e. sets the separator
@@ -859,6 +859,16 @@ The following functions perform the actual JSON decoding.
filled with information about the error. *flags* is described
above.
This function will start reading the input from whatever position
the input file was, without attempting to seek first. If an error
occurs, the file position will be left indeterminate. On success,
the file position will be at EOF, unless ``JSON_DISABLE_EOF_CHECK``
flag was used. In this case, the file position will be at the first
character after the last ``]`` or ``}`` in the JSON input. This
allows calling :func:`json_loadf()` on the same ``FILE`` object
multiple times, if the input consists of consecutive JSON texts,
possibly separated by whitespace.
.. function:: json_t *json_load_file(const char *path, size_t flags, json_error_t *error)
.. refcounting:: new
@@ -997,7 +1007,9 @@ type whose address should be passed.
``s`` (string) [const char \*]
Convert a JSON string to a pointer to a NULL terminated UTF-8
string.
string. The resulting string is extracted by using
:func:`json_string_value()` internally, so it exists as long as
there are still references to the corresponding JSON string.
``n`` (null)
Expect a JSON null value. Nothing is extracted.
@@ -1189,6 +1201,8 @@ copied in a recursive fashion.
Returns a deep copy of *value*, or *NULL* on error.
.. _apiref-custom-memory-allocation:
Custom Memory Allocation
========================
@@ -1257,5 +1271,5 @@ JSON structures by zeroing all memory when freed::
For more information about the issues of storing sensitive data in
memory, see
http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/protect-secrets.html.
The page also examplains the :func:`guaranteed_memset()` function used
The page also explains the :func:`guaranteed_memset()` function used
in the example and gives a sample implementation for it.

View File

@@ -48,9 +48,9 @@ copyright = u'2009-2011, Petri Lehtinen'
# built documents.
#
# The short X.Y version.
version = '2.2'
version = '2.2.1'
# The full version, including alpha/beta/rc tags.
release = '2.2'
release = version
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

View File

@@ -5,8 +5,7 @@ RFC Conformance
***************
JSON is specified in :rfc:`4627`, *"The application/json Media Type
for JavaScript Object Notation (JSON)"*. This chapter discusses
Jansson's conformance to this specification.
for JavaScript Object Notation (JSON)"*.
Character Encoding
==================

View File

@@ -22,6 +22,11 @@ data. Its main features and design principles are:
Jansson is licensed under the `MIT license`_; see LICENSE in the
source distribution for details.
Jansson is used in production and its API is stable. It works on
numerous platforms, including numerous Unix like systems and Windows.
It's suitable for use on any system, including desktop, server, and
small embedded systems.
.. _`MIT license`: http://www.opensource.org/licenses/mit-license.php
.. _Jansson: http://www.digip.org/jansson/
@@ -36,6 +41,7 @@ Contents
upgrading
tutorial
conformance
portability
apiref
changes

42
doc/portability.rst Normal file
View File

@@ -0,0 +1,42 @@
***********
Portability
***********
Thread safety
-------------
Jansson is thread safe and has no mutable global state. The only
exception are the memory allocation functions, that should be set at
most once, and only on program startup. See
:ref:`apiref-custom-memory-allocation`.
There's no locking performed inside Jansson's code, so a multithreaded
program must perform its own locking if JSON values are shared by
multiple threads. Jansson's reference counting semantics may make this
a bit harder than it seems, as it's possible to have a reference to a
value that's also stored inside a list or object. Modifying the
container (adding or removing values) may trigger concurrent access to
such values, as containers manage the reference count of their
contained values. Bugs involving concurrent incrementing or
decrementing of deference counts may be hard to track.
Locale
------
Jansson works fine under any locale.
However, if the host program is multithreaded and uses ``setlocale()``
to switch the locale in one thread while Jansson is currently encoding
or decoding JSON data in another thread, the result may be wrong or
the program may even crash.
Jansson uses locale specific functions for certain string conversions
in the encoder and decoder, and then converts the locale specific
values to/from the JSON representation. This fails if the locale
changes between the string conversion and the locale-to-JSON
conversion. This can only happen in multithreaded programs that use
``setlocale()``, because ``setlocale()`` switches the locale for all
running threads, not only the thread that calls ``setlocale()``.
If your program uses ``setlocale()`` as described above, consider
using the thread-safe ``uselocale()`` instead.

View File

@@ -12,12 +12,13 @@ libjansson_la_SOURCES = \
pack_unpack.c \
strbuffer.c \
strbuffer.h \
strconv.c \
utf.c \
utf.h \
value.c
libjansson_la_LDFLAGS = \
-export-symbols-regex '^json_' \
-version-info 6:0:2
-version-info 6:1:2
if GCC
# These flags are gcc specific

View File

@@ -196,26 +196,12 @@ static int do_dump(const json_t *json, size_t flags, int depth,
{
char buffer[MAX_REAL_STR_LENGTH];
int size;
double value = json_real_value(json);
size = snprintf(buffer, MAX_REAL_STR_LENGTH, "%.17g",
json_real_value(json));
if(size >= MAX_REAL_STR_LENGTH)
size = jsonp_dtostr(buffer, MAX_REAL_STR_LENGTH, value);
if(size < 0)
return -1;
/* 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(size + 2 >= MAX_REAL_STR_LENGTH) {
/* No space to append ".0" */
return -1;
}
buffer[size] = '.';
buffer[size + 1] = '0';
size += 2;
}
return dump(buffer, size, data);
}
@@ -413,39 +399,26 @@ static int do_dump(const json_t *json, size_t flags, int depth,
}
}
char *json_dumps(const json_t *json, size_t flags)
{
strbuffer_t strbuff;
char *result;
if(!(flags & JSON_ENCODE_ANY)) {
if(!json_is_array(json) && !json_is_object(json))
return NULL;
}
if(strbuffer_init(&strbuff))
return NULL;
if(do_dump(json, flags, 0, dump_to_strbuffer, (void *)&strbuff)) {
strbuffer_close(&strbuff);
return NULL;
}
if(json_dump_callback(json, dump_to_strbuffer, (void *)&strbuff, flags))
result = NULL;
else
result = jsonp_strdup(strbuffer_value(&strbuff));
result = jsonp_strdup(strbuffer_value(&strbuff));
strbuffer_close(&strbuff);
return result;
}
int json_dumpf(const json_t *json, FILE *output, size_t flags)
{
if(!(flags & JSON_ENCODE_ANY)) {
if(!json_is_array(json) && !json_is_object(json))
return -1;
}
return do_dump(json, flags, 0, dump_to_file, (void *)output);
return json_dump_callback(json, dump_to_file, (void *)output, flags);
}
int json_dump_file(const json_t *json, const char *path, size_t flags)

View File

@@ -62,7 +62,6 @@ static size_t primes[] = {
12582917, 25165843, 50331653, 100663319, 201326611, 402653189,
805306457, 1610612741
};
static const size_t num_primes = sizeof(primes) / sizeof(size_t);
static JSON_INLINE size_t num_buckets(hashtable_t *hashtable)
{

View File

@@ -22,10 +22,10 @@ extern "C" {
#define JANSSON_MAJOR_VERSION 2
#define JANSSON_MINOR_VERSION 2
#define JANSSON_MICRO_VERSION 0
#define JANSSON_MICRO_VERSION 1
/* Micro version is omitted if it's 0 */
#define JANSSON_VERSION "2.2"
#define JANSSON_VERSION "2.2.1"
/* Version as a 3-byte hex number, e.g. 0x010201 == 1.2.1. Use this
for numeric comparisons, e.g. #if JANSSON_VERSION_HEX >= ... */

View File

@@ -31,4 +31,8 @@
JSON_INTEGER_IS_LONG_LONG is defined to 1, otherwise to 0. */
#define JSON_INTEGER_IS_LONG_LONG @json_have_long_long@
/* If locale.h and localeconv() are available, define to 1,
otherwise to 0. */
#define JSON_HAVE_LOCALECONV @json_have_localeconv@
#endif

View File

@@ -31,4 +31,8 @@
JSON_INTEGER_IS_LONG_LONG is defined to 1, otherwise to 0. */
#define JSON_INTEGER_IS_LONG_LONG 1
/* If locale.h and localeconv() are available, define to 1,
otherwise to 0. */
#define JSON_HAVE_LOCALECONV 1
#endif

View File

@@ -11,6 +11,7 @@
#include <stddef.h>
#include "jansson.h"
#include "hashtable.h"
#include "strbuffer.h"
#define container_of(ptr_, type_, member_) \
((type_ *)((char *)ptr_ - offsetof(type_, member_)))
@@ -83,6 +84,10 @@ void jsonp_error_set(json_error_t *error, int line, int column,
void jsonp_error_vset(json_error_t *error, int line, int column,
size_t position, 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);
/* Wrappers for custom memory functions */
void* jsonp_malloc(size_t size);
void jsonp_free(void *ptr);

View File

@@ -6,7 +6,6 @@
*/
#define _GNU_SOURCE
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
@@ -32,6 +31,14 @@
#define TOKEN_FALSE 260
#define TOKEN_NULL 261
/* Locale independent versions of isxxx() functions */
#define l_isupper(c) ('A' <= c && c <= 'Z')
#define l_islower(c) ('a' <= c && c <= 'z')
#define l_isalpha(c) (l_isupper(c) || l_islower(c))
#define l_isdigit(c) ('0' <= c && c <= '9')
#define l_isxdigit(c) \
(l_isdigit(c) || 'A' <= c || c <= 'F' || 'a' <= c || c <= 'f')
/* Read one byte from stream, convert to unsigned char, then int, and
return. return EOF on end of file. This corresponds to the
behaviour of fgetc(). */
@@ -69,6 +76,7 @@ static void error_set(json_error_t *error, const lex_t *lex,
{
va_list ap;
char msg_text[JSON_ERROR_TEXT_LENGTH];
char msg_with_context[JSON_ERROR_TEXT_LENGTH];
int line = -1, col = -1;
size_t pos = 0;
@@ -84,7 +92,6 @@ static void error_set(json_error_t *error, const lex_t *lex,
if(lex)
{
const char *saved_text = strbuffer_value(&lex->saved_text);
char msg_with_context[JSON_ERROR_TEXT_LENGTH];
line = lex->stream.line;
col = lex->stream.column;
@@ -268,11 +275,11 @@ static int32_t decode_unicode_escape(const char *str)
for(i = 1; i <= 4; i++) {
char c = str[i];
value <<= 4;
if(isdigit(c))
if(l_isdigit(c))
value += c - '0';
else if(islower(c))
else if(l_islower(c))
value += c - 'a' + 10;
else if(isupper(c))
else if(l_isupper(c))
value += c - 'A' + 10;
else
assert(0);
@@ -317,7 +324,7 @@ static void lex_scan_string(lex_t *lex, json_error_t *error)
if(c == 'u') {
c = lex_get_save(lex, error);
for(i = 0; i < 4; i++) {
if(!isxdigit(c)) {
if(!l_isxdigit(c)) {
error_set(error, lex, "invalid escape");
goto out;
}
@@ -455,14 +462,14 @@ static int lex_scan_number(lex_t *lex, int c, json_error_t *error)
if(c == '0') {
c = lex_get_save(lex, error);
if(isdigit(c)) {
if(l_isdigit(c)) {
lex_unget_unsave(lex, c);
goto out;
}
}
else if(isdigit(c)) {
else if(l_isdigit(c)) {
c = lex_get_save(lex, error);
while(isdigit(c))
while(l_isdigit(c))
c = lex_get_save(lex, error);
}
else {
@@ -496,14 +503,14 @@ static int lex_scan_number(lex_t *lex, int c, json_error_t *error)
if(c == '.') {
c = lex_get(lex, error);
if(!isdigit(c)) {
if(!l_isdigit(c)) {
lex_unget(lex, c);
goto out;
}
lex_save(lex, c);
c = lex_get_save(lex, error);
while(isdigit(c))
while(l_isdigit(c))
c = lex_get_save(lex, error);
}
@@ -512,24 +519,19 @@ static int lex_scan_number(lex_t *lex, int c, json_error_t *error)
if(c == '+' || c == '-')
c = lex_get_save(lex, error);
if(!isdigit(c)) {
if(!l_isdigit(c)) {
lex_unget_unsave(lex, c);
goto out;
}
c = lex_get_save(lex, error);
while(isdigit(c))
while(l_isdigit(c))
c = lex_get_save(lex, error);
}
lex_unget_unsave(lex, c);
saved_text = strbuffer_value(&lex->saved_text);
errno = 0;
value = strtod(saved_text, &end);
assert(end == saved_text + lex->saved_text.length);
if(errno == ERANGE && value != 0) {
if(jsonp_strtod(&lex->saved_text, &value)) {
error_set(error, lex, "real number overflow");
goto out;
}
@@ -575,17 +577,17 @@ static int lex_scan(lex_t *lex, json_error_t *error)
else if(c == '"')
lex_scan_string(lex, error);
else if(isdigit(c) || c == '-') {
else if(l_isdigit(c) || c == '-') {
if(lex_scan_number(lex, c, error))
goto out;
}
else if(isupper(c) || islower(c)) {
else if(l_isalpha(c)) {
/* eat up the whole identifier for clearer error messages */
const char *saved_text;
c = lex_get_save(lex, error);
while(isupper(c) || islower(c))
while(l_isalpha(c))
c = lex_get_save(lex, error);
lex_unget_unsave(lex, c);
@@ -945,7 +947,7 @@ json_t *json_load_file(const char *path, size_t flags, json_error_t *error)
jsonp_error_init(error, path);
fp = fopen(path, "r");
fp = fopen(path, "rb");
if(!fp)
{
error_set(error, NULL, "unable to open %s: %s",

108
src/strconv.c Normal file
View File

@@ -0,0 +1,108 @@
#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;
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 + 2 >= size) {
/* No space to append ".0" */
return -1;
}
buffer[length] = '.';
buffer[length + 1] = '0';
length += 2;
}
return (int)length;
}

View File

@@ -5,12 +5,20 @@
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <jansson.h>
#if HAVE_LOCALE_H
#include <locale.h>
#endif
static int getenv_int(const char *name)
{
char *value, *end;
@@ -55,6 +63,10 @@ int main(int argc, char *argv[])
json_t *json;
json_error_t error;
#if HAVE_SETLOCALE
setlocale(LC_ALL, "");
#endif
if(argc != 1) {
fprintf(stderr, "usage: %s\n", argv[0]);
return 2;

View File

@@ -387,7 +387,7 @@ static void test_circular()
}
int main()
static void run_tests()
{
test_misc();
test_insert();
@@ -395,6 +395,4 @@ int main()
test_clear();
test_extend();
test_circular();
return 0;
}

View File

@@ -307,7 +307,7 @@ static void test_deep_copy_object(void)
json_decref(copy);
}
int main()
static void run_tests()
{
test_copy_simple();
test_deep_copy_simple();
@@ -315,5 +315,4 @@ int main()
test_deep_copy_array();
test_copy_object();
test_deep_copy_object();
return 0;
}

View File

@@ -133,10 +133,9 @@ static void encode_other_than_array_or_object()
}
int main()
static void run_tests()
{
encode_twice();
circular_references();
encode_other_than_array_or_object();
return 0;
}

View File

@@ -26,7 +26,7 @@ static int my_writer(const char *buffer, size_t len, void *data) {
return 0;
}
int main(void)
static void run_tests()
{
struct my_sink s;
json_t *json;
@@ -78,6 +78,4 @@ int main(void)
json_decref(json);
free(dumped_to_string);
free(s.buf);
return EXIT_SUCCESS;
}

View File

@@ -180,11 +180,10 @@ static void test_equal_complex()
/* TODO: There's no negative test case here */
}
int main()
static void run_tests()
{
test_equal_simple();
test_equal_array();
test_equal_object();
test_equal_complex();
return 0;
}

View File

@@ -50,11 +50,9 @@ static void disable_eof_check()
json_decref(json);
}
int main()
static void run_tests()
{
file_not_found();
reject_duplicates();
disable_eof_check();
return 0;
}

View File

@@ -9,7 +9,7 @@
#include <string.h>
#include "util.h"
int main()
static void run_tests()
{
json_t *json;
json_error_t error;
@@ -33,6 +33,4 @@ int main()
if(strcmp(error.text, "']' expected near end of file") != 0) {
fail("json_loadb returned an invalid error message for an unclosed top-level array");
}
return 0;
}

View File

@@ -75,10 +75,8 @@ static void test_secure_funcs(void)
create_and_free_complex_object();
}
int main()
static void run_tests()
{
test_simple();
test_secure_funcs();
return 0;
}

View File

@@ -8,7 +8,7 @@
#include <jansson.h>
#include "util.h"
int main()
static void run_tests()
{
json_t *integer, *real;
int i;
@@ -39,6 +39,4 @@ int main()
json_decref(integer);
json_decref(real);
return 0;
}

View File

@@ -437,7 +437,7 @@ static void test_preserve_order()
json_decref(object);
}
int main()
static void run_tests()
{
test_misc();
test_clear();
@@ -446,6 +446,4 @@ int main()
test_set_nocheck();
test_iterators();
test_preserve_order();
return 0;
}

View File

@@ -11,7 +11,7 @@
#include <stdio.h>
#include "util.h"
int main()
static void run_tests()
{
json_t *value;
int i;
@@ -227,6 +227,4 @@ int main()
if(json_pack_ex(&error, 0, "{s:s}", "foo", "\xff\xff"))
fail("json_pack failed to catch invalid UTF-8 in a string");
check_error("Invalid UTF-8 string", "<args>", 1, 4, 4);
return 0;
}

View File

@@ -10,7 +10,7 @@
#include "util.h"
/* Call the simple functions not covered by other tests of the public API */
int main()
static void run_tests()
{
json_t *value;
@@ -180,6 +180,4 @@ int main()
json_incref(value);
if(value->refcount != (size_t)-1)
fail("refcounting null works incorrectly");
return 0;
}

View File

@@ -11,7 +11,7 @@
#include <stdio.h>
#include "util.h"
int main()
static void run_tests()
{
json_t *j, *j2;
int i1, i2, i3;
@@ -336,6 +336,4 @@ int main()
fail("json_unpack nested array with strict validation failed");
check_error("1 array item(s) left unpacked", "<validation>", 1, 5, 5);
json_decref(j);
return 0;
}

View File

@@ -8,8 +8,16 @@
#ifndef UTIL_H
#define UTIL_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#if HAVE_LOCALE_H
#include <locale.h>
#endif
#include <jansson.h>
#define failhdr fprintf(stderr, "%s:%s:%d: ", __FILE__, __FUNCTION__, __LINE__)
@@ -52,4 +60,15 @@
} \
} while(0)
static void run_tests();
int main() {
#ifdef HAVE_SETLOCALE
setlocale(LC_ALL, "");
#endif
run_tests();
return 0;
}
#endif