Merge branch 'rebased_cmake_patch' of git://github.com/JoakimSoderberg/jansson

This commit is contained in:
Petri Lehtinen 2013-03-14 21:46:27 +02:00
commit 70f663db29
17 changed files with 788 additions and 51 deletions

384
CMakeLists.txt Normal file
View File

@ -0,0 +1,384 @@
# Notes:
#
# Author: Paul Harris, June 2012
# Additions: Joakim Soderberg, Febuary 2013
#
# Supports: building static/shared, release/debug/etc, can also build html docs
# and some of the tests.
# Note that its designed for out-of-tree builds, so it will not pollute your
# source tree.
#
# TODO 1: Finish implementing tests. api tests are working, but the valgrind
# variants are not flagging problems.
#
# TODO 2: There is a check_exports script that would try and incorporate.
#
# TODO 3: Consolidate version numbers, currently the version number is written
# into: * cmake (here) * autotools (the configure) * source code header files.
# Should not be written directly into header files, autotools/cmake can do
# that job.
#
# Brief intro on how to use cmake:
# > mkdir build (somewhere - we do out-of-tree builds)
# > use cmake, ccmake, or cmake-gui to configure the project. for linux, you
# can only choose one variant: release,debug,etc... and static or shared.
# >> example:
# >> cd build
# >> ccmake -i ../path_to_jansson_dir
# >> inside, configure your options. press C until there are no lines
# with * next to them.
# >> note, I like to configure the 'install' path to ../install, so I get
# self-contained clean installs I can point other projects to.
# >> press G to 'generate' the project files.
# >> make (to build the project)
# >> make install
# >> make test (to run the tests, if you enabled them)
#
# Brief description on how it works:
# There is a small heirachy of CMakeLists.txt files which define how the
# project is built.
# Header file detection etc is done, and the results are written into config.h
# and jansson_config.h, which are generated from the corresponding
# config.h.cmake and jansson_config.h.cmake template files.
# The generated header files end up in the build directory - not in
# the source directory.
# The rest is down to the usual make process.
cmake_minimum_required (VERSION 2.8)
# required for exports? cmake_minimum_required (VERSION 2.8.6)
project (jansson C)
# Options
OPTION (BUILD_SHARED_LIBS "Build shared libraries." OFF)
# Set some nicer output dirs.
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
# This is how I thought it should go
# set (JANSSON_VERSION "2.3.1")
# set (JANSSON_SOVERSION 2)
# This is what is required to match the same numbers as automake's
set (JANSSON_VERSION "4.3.1")
set (JANSSON_SOVERSION 4)
# for CheckFunctionKeywords
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include (CheckFunctionExists)
include (CheckFunctionKeywords)
include (CheckIncludeFiles)
include (CheckTypeSize)
# Turn off Microsofts "security" warnings.
if (MSVC)
add_definitions( "/W3 /D_CRT_SECURE_NO_WARNINGS /wd4005 /wd4996 /nologo" )
endif()
# Check for the int-type includes
check_include_files (sys/types.h HAVE_SYS_TYPES_H)
check_include_files (inttypes.h HAVE_INTTYPES_H)
check_include_files (stdint.h HAVE_STDINT_H)
# Check our 64 bit integer sizes
check_type_size (__int64 __INT64)
check_type_size (int64_t INT64_T)
check_type_size ("long long" LONG_LONG_INT)
# Check our 32 bit integer sizes
check_type_size (int32_t INT32_T)
check_type_size (__int32 __INT32)
check_type_size ("long" LONG_INT)
check_type_size ("int" INT)
if (HAVE_INT32_T)
set (JSON_INT32 int32_t)
elseif (HAVE___INT32)
set (JSON_INT32 __int32)
elseif (HAVE_LONG AND (${LONG_INT} EQUAL 4))
set (JSON_INT32 long)
elseif (HAVE_INT AND (${INT} EQUAL 4))
set (JSON_INT32 int)
else ()
message (FATAL_ERROR "Could not detect a valid 32 bit integer type")
endif ()
# Check for ssize_t and SSIZE_T existance.
check_type_size(ssize_t SSIZE_T)
check_type_size(SSIZE_T UPPERCASE_SSIZE_T)
if(NOT HAVE_SSIZE_T)
if(HAVE_UPPERCASE_SSIZE_T)
set(JSON_SSIZE SSIZE_T)
else()
set(JSON_SSIZE int)
endif()
endif()
set(CMAKE_EXTRA_INCLUDE_FILES "")
# Check for all the variants of strtoll
check_function_exists (strtoll HAVE_STRTOLL)
check_function_exists (strtoq HAVE_STRTOQ)
check_function_exists (_strtoi64 HAVE__STRTOI64)
# Figure out what variant we should use
if (HAVE_STRTOLL)
set (JSON_STRTOINT strtoll)
elseif (HAVE_STRTOQ)
set (JSON_STRTOINT strtoq)
elseif (HAVE__STRTOI64)
set (JSON_STRTOINT _strtoi64)
else ()
# fallback to strtol (32 bit)
# this will set all the required variables
set (JSON_STRTOINT strtol)
set (JSON_INT_T long)
set (JSON_INTEGER_FORMAT "\"ld\"")
endif ()
# if we haven't defined JSON_INT_T, then we have a 64 bit conversion function.
# detect what to use for the 64 bit type.
# Note: I will prefer long long if I can get it, as that is what the automake system aimed for.
if (NOT DEFINED JSON_INT_T)
if (HAVE_LONG_LONG_INT AND (${LONG_LONG_INT} EQUAL 8))
set (JSON_INT_T "long long")
elseif (HAVE_INT64_T)
set (JSON_INT_T int64_t)
elseif (HAVE___INT64)
set (JSON_INT_T __int64)
else ()
message (FATAL_ERROR "Could not detect 64 bit type, although I detected the strtoll equivalent")
endif ()
# Apparently, Borland BCC and MSVC wants I64d,
# Borland BCC could also accept LD
# and gcc wants ldd,
# I am not sure what cygwin will want, so I will assume I64d
if (WIN32) # matches both msvc and cygwin
set (JSON_INTEGER_FORMAT "\"I64d\"")
else ()
set (JSON_INTEGER_FORMAT "\"lld\"")
endif ()
endif ()
# If locale.h and localeconv() are available, define to 1, otherwise to 0.
check_include_files (locale.h HAVE_LOCALE_H)
check_function_exists (localeconv HAVE_LOCALECONV)
if (HAVE_LOCALECONV AND HAVE_LOCALE_H)
set (JSON_HAVE_LOCALECONV 1)
else ()
set (JSON_HAVE_LOCALECONV 0)
endif ()
# check if we have setlocale
check_function_exists (setlocale HAVE_SETLOCALE)
# Check what the inline keyword is.
# Note that the original JSON_INLINE was always set to just 'inline', so this goes further.
check_function_keywords("inline")
check_function_keywords("__inline")
check_function_keywords("__inline__")
if (HAVE_INLINE)
set (JSON_INLINE inline)
elseif (HAVE___INLINE)
set (JSON_INLINE __inline)
elseif (HAVE___INLINE__)
set (JSON_INLINE __inline__)
else (HAVE_INLINE)
# no inline on this platform
set (JSON_INLINE)
endif (HAVE_INLINE)
# Find our snprintf
check_function_exists (snprintf HAVE_SNPRINTF)
check_function_exists (_snprintf HAVE__SNPRINTF)
if (HAVE_SNPRINTF)
set (JSON_SNPRINTF snprintf)
elseif (HAVE__SNPRINTF)
set (JSON_SNPRINTF _snprintf)
endif ()
# configure the public config file
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/cmake/jansson_config.h.cmake
${CMAKE_CURRENT_BINARY_DIR}/include/jansson_config.h)
# Copy the jansson.h file to the public include folder
file (COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/jansson.h
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/include/)
# configure the private config file
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/cmake/config.h.cmake
${CMAKE_CURRENT_BINARY_DIR}/private_include/config.h)
# and tell the source code to include it
add_definitions (-DHAVE_CONFIG_H)
include_directories (${CMAKE_CURRENT_BINARY_DIR}/include)
include_directories (${CMAKE_CURRENT_BINARY_DIR}/private_include)
# Add the lib sources.
file (GLOB C_FILES src/*.c)
if (BUILD_SHARED_LIBS)
add_library (jansson SHARED ${C_FILES} src/jansson.def)
set_target_properties (jansson PROPERTIES
VERSION ${JANSSON_VERSION}
SOVERSION ${JANSSON_SOVERSION})
else ()
add_library (jansson ${C_FILES})
endif ()
# LIBRARY for linux
# RUNTIME for windows (when building shared)
install (TARGETS jansson
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
)
install (FILES
${CMAKE_CURRENT_BINARY_DIR}/include/jansson_config.h
${CMAKE_CURRENT_SOURCE_DIR}/src/jansson.h
DESTINATION include)
# For building Documentation (uses Sphinx)
OPTION (BUILD_DOCS "Build documentation (uses python-sphinx)." OFF)
if (BUILD_DOCS)
find_package(Sphinx REQUIRED)
# configured documentation tools and intermediate build results
set(BINARY_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/_build")
# Sphinx cache with pickled ReST documents
set(SPHINX_CACHE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_doctrees")
# HTML output directory
set(SPHINX_HTML_DIR "${CMAKE_CURRENT_BINARY_DIR}/html")
# CMake could be used to build the conf.py file too,
# eg it could automatically write the version of the program or change the theme.
# if(NOT DEFINED SPHINX_THEME)
# set(SPHINX_THEME default)
# endif()
#
# if(NOT DEFINED SPHINX_THEME_DIR)
# set(SPHINX_THEME_DIR)
# endif()
#
# configure_file(
# "${CMAKE_CURRENT_SOURCE_DIR}/conf.py.in"
# "${BINARY_BUILD_DIR}/conf.py"
# @ONLY)
add_custom_target(jansson_docs ALL
${SPHINX_EXECUTABLE}
# -q # Enable for quiet mode
-b html
-d "${SPHINX_CACHE_DIR}"
# -c "${BINARY_BUILD_DIR}" # enable if using cmake-generated conf.py
"${CMAKE_CURRENT_SOURCE_DIR}/doc"
"${SPHINX_HTML_DIR}"
COMMENT "Building HTML documentation with Sphinx")
message (STATUS "Documentation has been built in ${SPHINX_HTML_DIR}")
endif ()
OPTION (WITHOUT_TESTS "Don't build tests ('make test' to execute tests)" OFF)
if (NOT WITHOUT_TESTS)
OPTION (TEST_WITH_VALGRIND "Enable valgrind tests." OFF)
ENABLE_TESTING()
if (TEST_WITH_VALGRIND)
# TODO: Add FindValgrind.cmake instead of having a hardcoded path.
# enable valgrind
set(CMAKE_MEMORYCHECK_COMMAND valgrind)
set(CMAKE_MEMORYCHECK_COMMAND_OPTIONS
"--leak-check=full --show-reachable=yes --track-origins=yes -q")
set(MEMCHECK_COMMAND
"${CMAKE_MEMORYCHECK_COMMAND} ${CMAKE_MEMORYCHECK_COMMAND_OPTIONS}")
separate_arguments(MEMCHECK_COMMAND)
endif ()
#
# Test suites.
#
if (CMAKE_COMPILER_IS_GNUCC)
add_definitions(-Wall -Wextra -Wdeclaration-after-statement -Werror)
endif ()
set(api_tests
test_array
test_copy
test_dump
test_dump_callback
test_equal
test_load
test_loadb
test_number
test_object
test_pack
test_simple
test_unpack)
# Doing arithmetic on void pointers is not allowed by Microsofts compiler
# such as secure_malloc and secure_free is doing, so exclude it for now.
if (NOT MSVC)
list(APPEND api_tests test_memory_funcs)
endif()
# Helper macro for building and linking a test program.
macro(build_testprog name dir)
add_executable(${name} ${dir}/${name}.c)
add_dependencies(${name} jansson)
target_link_libraries(${name} jansson)
endmacro(build_testprog)
# Create executables and tests/valgrind tests for API tests.
foreach (test ${api_tests})
build_testprog(${test} ${PROJECT_SOURCE_DIR}/test/suites/api)
add_test(${test} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${test})
if (TEST_WITH_VALGRIND)
add_test(memcheck_${test} ${MEMCHECK_COMMAND}
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${test})
endif ()
endforeach ()
# Test harness for the suites tests.
build_testprog(json_process ${PROJECT_SOURCE_DIR}/test/bin)
set(SUITES encoding-flags valid invalid invalid-unicode)
foreach (SUITE ${SUITES})
file(GLOB TESTDIRS ${jansson_SOURCE_DIR}/test/suites/${SUITE}/*)
foreach (TESTDIR ${TESTDIRS})
if (IS_DIRECTORY ${TESTDIR})
get_filename_component(TNAME ${TESTDIR} NAME)
add_test(${SUITE}__${TNAME}
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/json_process ${TESTDIR})
endif ()
endforeach ()
endforeach ()
endif ()

View File

@ -0,0 +1,15 @@
include(CheckCSourceCompiles)
macro(check_function_keywords _wordlist)
set(${_result} "")
foreach(flag ${_wordlist})
string(REGEX REPLACE "[-+/ ()]" "_" flagname "${flag}")
string(TOUPPER "${flagname}" flagname)
set(have_flag "HAVE_${flagname}")
check_c_source_compiles("${flag} void func(); void func() { } int main() { func(); return 0; }" ${have_flag})
if(${have_flag} AND NOT ${_result})
set(${_result} "${flag}")
# break()
endif(${have_flag} AND NOT ${_result})
endforeach(flag)
endmacro(check_function_keywords)

16
cmake/FindSphinx.cmake Normal file
View File

@ -0,0 +1,16 @@
find_program(SPHINX_EXECUTABLE NAMES sphinx-build
HINTS
$ENV{SPHINX_DIR}
PATH_SUFFIXES bin
DOC "Sphinx documentation generator"
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Sphinx DEFAULT_MSG
SPHINX_EXECUTABLE
)
mark_as_advanced(
  SPHINX_EXECUTABLE
)

45
cmake/config.h.cmake Normal file
View File

@ -0,0 +1,45 @@
/* Reduced down to the defines that are actually used in the code */
/* Define to 1 if you have the <inttypes.h> (and friends) header file. */
#cmakedefine HAVE_INTTYPES_H 1
#cmakedefine HAVE_STDINT_H 1
#cmakedefine HAVE_SYS_TYPES_H 1
/* We must include this here, as in (eg) utf.h it will want to use
the integer type, which in MSVC2010 will be in stdint.h
(there is no inttypes.h in MSVC2010) */
#if defined(HAVE_STDINT_H)
# include <stdint.h>
#elif defined(HAVE_INTTYPES_H)
# include <inttypes.h>
#elif defined(HAVE_SYS_TYPES_H)
# include <sys/types.h>
#endif
/* Define to 1 if you have the <locale.h> header file. */
#cmakedefine HAVE_LOCALE_H 1
/* Define to 1 if you have the 'setlocale' function. */
#cmakedefine HAVE_SETLOCALE 1
/* 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. */
#cmakedefine HAVE_INT32_T 1
#ifndef HAVE_INT32_T
# define int32_t @JSON_INT32@
#endif
#cmakedefine HAVE_SSIZE_T 1
#ifndef HAVE_SSIZE_T
# define ssize_t @JSON_SSIZE@
#endif
#cmakedefine HAVE_SNPRINTF 1
#ifndef HAVE_SNPRINTF
# define snprintf @JSON_SNPRINTF@
#endif
#cmakedefine HAVE_VSNPRINTF

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2010-2012 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.
*
*
* This file specifies a part of the site-specific configuration for
* Jansson, namely those things that affect the public API in
* jansson.h.
*
* The CMake system will generate the jansson_config.h file and
* copy it to the build and install directories.
*/
#ifndef JANSSON_CONFIG_H
#define JANSSON_CONFIG_H
/* Define this so that we can disable scattered automake configuration in source files */
#define JANSSON_USING_CMAKE
/* Note: when using cmake, JSON_INTEGER_IS_LONG_LONG is not defined nor used,
* as we will also check for __int64 etc types.
* (the definition was used in the automake system) */
/* Bring in the cmake-detected defines */
#cmakedefine HAVE_STDINT_H 1
#cmakedefine HAVE_INTTYPES_H 1
#cmakedefine HAVE_SYS_TYPES_H 1
/* Include our standard type header for the integer typedef */
#if defined(HAVE_STDINT_H)
# include <stdint.h>
#elif defined(HAVE_INTTYPES_H)
# include <inttypes.h>
#elif defined(HAVE_SYS_TYPES_H)
# include <sys/types.h>
#endif
/* If your compiler supports the inline keyword in C, JSON_INLINE is
defined to `inline', otherwise empty. In C++, the inline is always
supported. */
#ifdef __cplusplus
#define JSON_INLINE inline
#else
#define JSON_INLINE @JSON_INLINE@
#endif
#define json_int_t @JSON_INT_T@
#define json_strtoint @JSON_STRTOINT@
#define JSON_INTEGER_FORMAT @JSON_INTEGER_FORMAT@
/* If locale.h and localeconv() are available, define to 1, otherwise to 0. */
#define JSON_HAVE_LOCALECONV @JSON_HAVE_LOCALECONV@
#endif

View File

@ -52,6 +52,7 @@ typedef struct json_t {
size_t refcount;
} json_t;
#ifndef JANSSON_USING_CMAKE /* disabled if using cmake */
#if JSON_INTEGER_IS_LONG_LONG
#ifdef _WIN32
#define JSON_INTEGER_FORMAT "I64d"
@ -63,6 +64,7 @@ typedef long long json_int_t;
#define JSON_INTEGER_FORMAT "ld"
typedef long json_int_t;
#endif /* JSON_INTEGER_IS_LONG_LONG */
#endif
#define json_typeof(json) ((json)->type)
#define json_is_object(json) (json && json_typeof(json) == JSON_OBJECT)

View File

@ -446,6 +446,7 @@ out:
jsonp_free(lex->value.string);
}
#ifndef JANSSON_USING_CMAKE /* disabled if using cmake */
#if JSON_INTEGER_IS_LONG_LONG
#ifdef _MSC_VER /* Microsoft Visual Studio */
#define json_strtoint _strtoi64
@ -455,6 +456,7 @@ out:
#else
#define json_strtoint strtol
#endif
#endif
static int lex_scan_number(lex_t *lex, int c, json_error_t *error)
{

View File

@ -5,6 +5,11 @@
#include "jansson_private.h"
#include "strbuffer.h"
/* need config.h to get the correct snprintf */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#if JSON_HAVE_LOCALECONV
#include <locale.h>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009-2012 Petri Lehtinen <petri@digip.org>
* Copyright (c) 2009-2013 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.
@ -15,22 +15,213 @@
#include <ctype.h>
#include <jansson.h>
#if HAVE_LOCALE_H
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif
#endif
#if _WIN32
#include <io.h> /* for _setmode() */
#include <fcntl.h> /* for _O_BINARY */
static const char dir_sep = '\\';
#else
static const char dir_sep = '/';
#endif
struct config {
int indent;
int compact;
int preserve_order;
int ensure_ascii;
int sort_keys;
int strip;
int use_env;
} conf;
#define l_isspace(c) ((c) == ' ' || (c) == '\n' || (c) == '\r' || (c) == '\t')
/* Return a pointer to the first non-whitespace character of str.
Modifies str so that all trailing whitespace characters are
replaced by '\0'. */
static const char *strip(char *str)
{
size_t length;
char *result = str;
while (*result && l_isspace(*result))
result++;
length = strlen(result);
if (length == 0)
return result;
while (l_isspace(result[length - 1]))
result[--length] = '\0';
return result;
}
static char *loadfile(FILE *file)
{
long fsize, ret;
char *buf;
fseek(file, 0, SEEK_END);
fsize = ftell(file);
fseek(file, 0, SEEK_SET);
buf = malloc(fsize+1);
ret = fread(buf, 1, fsize, file);
if (ret != fsize)
exit(1);
buf[fsize] = '\0';
return buf;
}
static void read_conf(FILE *conffile)
{
char *buffer, *line, *val;
buffer = loadfile(conffile);
line = strtok(buffer, "\r\n");
while (line) {
val = strchr(line, '=');
if (!val) {
printf("invalid configuration line\n");
break;
}
*val++ = '\0';
if (!strcmp(line, "JSON_INDENT"))
conf.indent = atoi(val);
if (!strcmp(line, "JSON_COMPACT"))
conf.compact = atoi(val);
if (!strcmp(line, "JSON_ENSURE_ASCII"))
conf.ensure_ascii = atoi(val);
if (!strcmp(line, "JSON_PRESERVE_ORDER"))
conf.preserve_order = atoi(val);
if (!strcmp(line, "JSON_SORT_KEYS"))
conf.sort_keys = atoi(val);
if (!strcmp(line, "STRIP"))
conf.strip = atoi(val);
line = strtok(NULL, "\r\n");
}
free(buffer);
}
static int cmpfile(const char *str, const char *path, const char *fname)
{
char filename[1024], *buffer;
int ret;
FILE *file;
sprintf(filename, "%s%c%s", path, dir_sep, fname);
file = fopen(filename, "rb");
if (!file) {
if (conf.strip)
strcat(filename, ".strip");
else
strcat(filename, ".normal");
file = fopen(filename, "rb");
}
if (!file) {
printf("Error: test result file could not be opened.\n");
exit(1);
}
buffer = loadfile(file);
if (strcmp(buffer, str) != 0)
ret = 1;
else
ret = 0;
free(buffer);
fclose(file);
return ret;
}
int use_conf(char *test_path)
{
int ret;
size_t flags = 0;
char filename[1024], errstr[1024];
char *buffer;
FILE *infile, *conffile;
json_t *json;
json_error_t error;
sprintf(filename, "%s%cinput", test_path, dir_sep);
if (!(infile = fopen(filename, "rb"))) {
fprintf(stderr, "Could not open \"%s\"\n", filename);
return 2;
}
sprintf(filename, "%s%cenv", test_path, dir_sep);
conffile = fopen(filename, "rb");
if (conffile) {
read_conf(conffile);
fclose(conffile);
}
if (conf.indent < 0 || conf.indent > 255) {
fprintf(stderr, "invalid value for JSON_INDENT: %d\n", conf.indent);
return 2;
}
if (conf.indent)
flags |= JSON_INDENT(conf.indent);
if (conf.compact)
flags |= JSON_COMPACT;
if (conf.ensure_ascii)
flags |= JSON_ENSURE_ASCII;
if (conf.preserve_order)
flags |= JSON_PRESERVE_ORDER;
if (conf.sort_keys)
flags |= JSON_SORT_KEYS;
if (conf.strip) {
/* Load to memory, strip leading and trailing whitespace */
buffer = loadfile(infile);
json = json_loads(strip(buffer), 0, &error);
free(buffer);
}
else
json = json_loadf(infile, 0, &error);
fclose(infile);
if (!json) {
sprintf(errstr, "%d %d %d\n%s\n",
error.line, error.column, error.position,
error.text);
ret = cmpfile(errstr, test_path, "error");
return ret;
}
buffer = json_dumps(json, flags);
ret = cmpfile(buffer, test_path, "output");
free(buffer);
json_decref(json);
return ret;
}
static int getenv_int(const char *name)
{
char *value, *end;
long result;
value = getenv(name);
if(!value)
return 0;
@ -42,49 +233,19 @@ static int getenv_int(const char *name)
return (int)result;
}
/* Return a pointer to the first non-whitespace character of str.
Modifies str so that all trailing whitespace characters are
replaced by '\0'. */
static const char *strip(char *str)
int use_env()
{
size_t length;
char *result = str;
while(*result && l_isspace(*result))
result++;
length = strlen(result);
if(length == 0)
return result;
while(l_isspace(result[length - 1]))
result[--length] = '\0';
return result;
}
int main(int argc, char *argv[])
{
int indent = 0;
int indent;
size_t flags = 0;
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;
}
#ifdef _WIN32
#ifdef _WIN32
/* On Windows, set stdout and stderr to binary mode to avoid
outputting DOS line terminators */
_setmode(_fileno(stdout), _O_BINARY);
_setmode(_fileno(stderr), _O_BINARY);
#endif
#endif
indent = getenv_int("JSON_INDENT");
if(indent < 0 || indent > 255) {
@ -103,10 +264,10 @@ int main(int argc, char *argv[])
if(getenv_int("JSON_PRESERVE_ORDER"))
flags |= JSON_PRESERVE_ORDER;
if(getenv_int("JSON_SORT_KEYS"))
flags |= JSON_SORT_KEYS;
flags |= JSON_SORT_KEYS;
if(getenv_int("STRIP")) {
/* Load to memory, strip leading and trailing whitespace */
size_t size = 0, used = 0;
@ -129,7 +290,7 @@ int main(int argc, char *argv[])
}
used += count;
}
json = json_loads(strip(buffer), 0, &error);
free(buffer);
}
@ -138,13 +299,50 @@ int main(int argc, char *argv[])
if(!json) {
fprintf(stderr, "%d %d %d\n%s\n",
error.line, error.column, error.position,
error.text);
error.line, error.column,
error.position, error.text);
return 1;
}
json_dumpf(json, stdout, flags);
json_decref(json);
return 0;
}
int main(int argc, char *argv[])
{
int i;
char *test_path = NULL;
#ifdef HAVE_SETLOCALE
setlocale(LC_ALL, "");
#endif
if (argc < 2) {
goto usage;
}
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "--strip"))
conf.strip = 1;
else if (!strcmp(argv[i], "--env"))
conf.use_env = 1;
else
test_path = argv[i];
}
if (conf.use_env)
return use_env();
else
{
if (!test_path)
goto usage;
return use_conf(test_path);
}
usage:
fprintf(stderr, "argc =%d\n", argc);
fprintf(stderr, "usage: %s [--strip] [--env] test_dir\n", argv[0]);
return 2;
}

2
test/suites/.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
api/ text=auto
* text eol=lf

View File

@ -12,7 +12,7 @@
static void run_tests()
{
json_t *integer, *real;
int i;
json_int_t i;
double d;
integer = json_integer(5);

View File

@ -6,6 +6,12 @@
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <jansson_config.h>
#include <string.h>
#include <jansson.h>
#include <stdio.h>
@ -20,7 +26,6 @@ static void run_tests()
/*
* Simple, valid json_pack cases
*/
/* true */
value = json_pack("b", 1);
if(!json_is_true(value))

View File

@ -14,7 +14,7 @@ run_test() {
if [ -f $test_path/env ]; then
. $test_path/env
fi
$json_process <$test_path/input >$test_log/stdout 2>$test_log/stderr
$json_process --env <$test_path/input >$test_log/stdout 2>$test_log/stderr
)
valgrind_check $test_log/stderr || return 1
cmp -s $test_path/output $test_log/stdout

View File

@ -10,7 +10,7 @@ is_test() {
}
run_test() {
$json_process <$test_path/input >$test_log/stdout 2>$test_log/stderr
$json_process --env <$test_path/input >$test_log/stdout 2>$test_log/stderr
valgrind_check $test_log/stderr || return 1
cmp -s $test_path/error $test_log/stderr
}

View File

@ -20,7 +20,7 @@ do_run() {
strip=1
fi
STRIP=$strip $json_process \
STRIP=$strip $json_process --env \
<$test_path/input >$test_log/stdout$s 2>$test_log/stderr$s
valgrind_check $test_log/stderr$s || return 1

View File

@ -0,0 +1 @@
JSON_SORT_KEYS=1

View File

@ -19,7 +19,7 @@ do_run() {
strip=0
[ "$variant" = "strip" ] && strip=1
STRIP=$strip $json_process \
STRIP=$strip $json_process --env \
<$test_path/input >$test_log/stdout$s 2>$test_log/stderr$s
valgrind_check $test_log/stderr$s || return 1