mirror of
https://github.com/etlegacy/etlegacy-libs.git
synced 2025-04-19 04:41:11 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
22a4fb3268
3615 changed files with 1228343 additions and 7094 deletions
118
CMakeLists.txt
118
CMakeLists.txt
|
@ -4,31 +4,39 @@ include(CheckIncludeFile)
|
|||
set(LIBS_BINARYDIR_DIR ${PROJECT_BINARY_DIR}/libs)
|
||||
set(LIBS_DOWNLOAD_DIR ${PROJECT_BINARY_DIR}/downloads)
|
||||
|
||||
if(BUNDLED_OPENSSL)
|
||||
find_program(NASM_EXECUTABLE nasm)
|
||||
if(NOT NASM_EXECUTABLE)
|
||||
message(FATAL_ERROR "NASM not found")
|
||||
endif()
|
||||
|
||||
FIND_PACKAGE(perl REQUIRED)
|
||||
if(NOT PERL_FOUND)
|
||||
message(FATAL_ERROR "Perl not found")
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
if(64BITS)
|
||||
set(openssl_plat VC-WIN64)
|
||||
# set(curl_plat x64)
|
||||
else()
|
||||
set(openssl_plat VC-WIN32)
|
||||
# set(curl_plat x86)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
# note/FIXME/clarify:
|
||||
# when features are disabled this script is still
|
||||
# adding the related targets? F.e. LUA_FEATURE is Off and BUNDLED_LUA On
|
||||
# see usage of BUNDLED_LUA below (BUNDLED_OPENSSL, BUNDLED OPENAL ...)
|
||||
|
||||
#CMAKE_DEBUG_POSTFIX
|
||||
|
||||
if(WIN32)
|
||||
|
||||
# moved for now until linux BUNDLED_OPENSSL is done
|
||||
if(BUNDLED_OPENSSL)
|
||||
find_program(NASM_EXECUTABLE nasm)
|
||||
if(NOT NASM_EXECUTABLE)
|
||||
message(FATAL_ERROR "NASM not found")
|
||||
endif()
|
||||
|
||||
# FIXME: there is no findPerl cmake script in project?! (at least for *NIX)
|
||||
FIND_PACKAGE(perl REQUIRED)
|
||||
if(NOT PERL_FOUND)
|
||||
message(FATAL_ERROR "Perl not found")
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
if(64BITS)
|
||||
set(openssl_plat VC-WIN64)
|
||||
# set(curl_plat x64)
|
||||
else()
|
||||
set(openssl_plat VC-WIN32)
|
||||
# set(curl_plat x86)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
# Build bundled JPEG library
|
||||
#-----------------------------------------------------------------
|
||||
|
@ -181,7 +189,7 @@ if(WIN32)
|
|||
|
||||
if(VSTUDIO)
|
||||
set(CURL_BUNDLED_LIBRARY optimized "${binary_dir}/lib/Release/libcurl${CMAKE_STATIC_LIBRARY_SUFFIX}" debug "${binary_dir}/lib/Debug/libcurl-d${CMAKE_STATIC_LIBRARY_SUFFIX}")
|
||||
elseif(MINGW)
|
||||
elseif(MINGW OR NMAKE_BUILD)
|
||||
set(CURL_BUNDLED_LIBRARY optimized "${binary_dir}/lib/libcurl${CMAKE_STATIC_LIBRARY_SUFFIX}" debug "${binary_dir}/lib/libcurl-d${CMAKE_STATIC_LIBRARY_SUFFIX}")
|
||||
else(VSTUDIO)
|
||||
set(CURL_BUNDLED_LIBRARY "${binary_dir}/libcurl${CMAKE_STATIC_LIBRARY_SUFFIX}")
|
||||
|
@ -401,11 +409,52 @@ elseif(UNIX)
|
|||
endif()
|
||||
endif(CROSS_COMPILE32)
|
||||
|
||||
if (BUNDLED_OPENSSL AND (BUILD_CLIENT OR BUILD_SERVER))
|
||||
# FIXME: check flags
|
||||
if(CROSS_COMPILE32)
|
||||
if(APPLE)
|
||||
SET(OPENSSL_BUILD ./Configure darwin-i386-cc ${CROSS_COMPILE32_FLAGS})
|
||||
else()
|
||||
SET(OPENSSL_BUILD ./Configure linux-x86 ${CROSS_COMPILE32_FLAGS})
|
||||
endif()
|
||||
else(CROSS_COMPILE32)
|
||||
if(APPLE)
|
||||
SET(OPENSSL_BUILD ./Configure darwin64-x86_64-cc ${CROSS_COMPILE32_FLAGS})
|
||||
else()
|
||||
#SET(OPENSSL_BUILD ./Configure linux-x86_64 ${CROSS_COMPILE32_FLAGS})
|
||||
# better use ./config here?! (..and not the CROSS_COMPILE32_FLAGS?!)
|
||||
SET(OPENSSL_BUILD ./Configure ${CROSS_COMPILE32_FLAGS})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# FIXME:
|
||||
# check all the locations of the files (runtime files?!)
|
||||
# and enable ssl in CURL
|
||||
ExternalProject_Add(
|
||||
bundled_openssl
|
||||
SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/openssl
|
||||
CONFIGURE_COMMAND ${OPENSSL_BUILD} --prefix=${CMAKE_CURRENT_BINARY_DIR}/libs/openssl
|
||||
--openssldir=${CMAKE_CURRENT_BINARY_DIR}/libs/openssl
|
||||
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/libs/openssl
|
||||
BUILD_COMMAND make
|
||||
INSTALL_COMMAND make install
|
||||
BUILD_IN_SOURCE 1
|
||||
)
|
||||
|
||||
# also generates libcrypto.a
|
||||
set(OPENSSL_BUNDLED_LIBRARIES "${CMAKE_CURRENT_BINARY_DIR}/libs/openssl/lib/libssl.a")
|
||||
set(OPENSSL_BUNDLED_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/libs/openssl/include")
|
||||
|
||||
endif()
|
||||
|
||||
#-----------------------------------------------------------------
|
||||
# Build bundled cURL library
|
||||
#-----------------------------------------------------------------
|
||||
if(BUNDLED_CURL AND (BUILD_CLIENT OR BUILD_SERVER))
|
||||
|
||||
# FIXME: add openssl lib to project
|
||||
# set --with-ssl / remove --without-ssl
|
||||
|
||||
ExternalProject_Add(
|
||||
bundled_curl
|
||||
SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/curl
|
||||
|
@ -416,7 +465,7 @@ elseif(UNIX)
|
|||
--enable-proxy --disable-dict --disable-telnet
|
||||
--disable-tftp --disable-pop3 --disable-imap
|
||||
--disable-smb --disable-smtp --disable-gopher
|
||||
--without-ssl --without-libssh2 --without-nghttp2
|
||||
--without-libssh2 --without-nghttp2
|
||||
--without-gssapi --with-zlib --without-brotli
|
||||
--disable-ares --enable-threaded-resolver
|
||||
--enable-ipv6 --enable-unix-sockets
|
||||
|
@ -424,6 +473,7 @@ elseif(UNIX)
|
|||
--disable-sspi --enable-libgcc
|
||||
--without-libmetalink --without-libpsl
|
||||
--without-librtmp ${CROSS_COMPILE32_FLAGS}
|
||||
--without-ssl
|
||||
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/libs/curl
|
||||
BUILD_COMMAND make
|
||||
INSTALL_COMMAND make install
|
||||
|
@ -483,11 +533,21 @@ elseif(UNIX)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_LIST_DIR}/lua/src/liblua.a
|
||||
COMMAND make clean || true
|
||||
COMMAND ${CROSS_COMPILE32_FLAGS} make ${LUA_MAKE_TARGET}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/lua/src
|
||||
)
|
||||
# MacOS X requires a different flag order to succeed,
|
||||
# but io.popen support requires the initial order
|
||||
if(NOT CMAKE_SYSTEM MATCHES "Darwin")
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_LIST_DIR}/lua/src/liblua.a
|
||||
COMMAND make clean || true
|
||||
COMMAND ${CROSS_COMPILE32_FLAGS} make ${LUA_MAKE_TARGET}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/lua/src
|
||||
)
|
||||
else()
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_LIST_DIR}/lua/src/liblua.a
|
||||
COMMAND make clean || true
|
||||
COMMAND make ${LUA_MAKE_TARGET} CFLAGS=-mmacosx-version-min=10.7\ -O3\ -m32\ -DLUA_USE_MACOSX LDFLAGS=-mmacosx-version-min=10.7\ -m32
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/lua/src
|
||||
)
|
||||
endif()
|
||||
|
||||
set(LUA_BUNDLED_LIBRARIES "${CMAKE_CURRENT_LIST_DIR}/lua/src/liblua.a")
|
||||
set(LUA_BUNDLED_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/lua/src")
|
||||
|
@ -710,7 +770,7 @@ endif()
|
|||
#-----------------------------------------------------------------
|
||||
# Build bundled SQLITE3 library
|
||||
#-----------------------------------------------------------------
|
||||
if(BUNDLED_SQLITE3 AND (BUILD_CLIENT OR BUILD_SERVER))
|
||||
if(BUNDLED_SQLITE3 AND (BUILD_CLIENT OR BUILD_SERVER OR BUILD_MOD))
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/sqlite3/CMakeLists.txt)
|
||||
set(SQLITE3_BUNDLED_LIBRARIES bundled_sqlite3)
|
||||
set(SQLITE3_BUNDLED_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/sqlite3/src")
|
||||
|
|
302
jansson/CHANGES
302
jansson/CHANGES
|
@ -1,34 +1,322 @@
|
|||
Version 2.7 (in development)
|
||||
============================
|
||||
Version 2.12
|
||||
|
||||
Released XXXX-XX-XX
|
||||
Released 2018-11-25
|
||||
|
||||
* Bug fixes:
|
||||
|
||||
- Fix error message in `json_pack()` for NULL object (#409).
|
||||
|
||||
- Avoid invalid memory read in `json_pack()` (#421).
|
||||
|
||||
- Call va_end after va_copy in `json_vsprintf()` (#427).
|
||||
|
||||
- Improve handling of formats with '?' and '*' in `json_pack()` (#438).
|
||||
|
||||
- Remove inappropriate `jsonp_free()` which caused segmentation fault in
|
||||
error handling (#444).
|
||||
|
||||
* Build:
|
||||
|
||||
- Add function attributes for GCC and CLANG to provide warnings on improper
|
||||
use of jansson routines (#404).
|
||||
|
||||
- Many CMake fixes (#408, #412, #415).
|
||||
|
||||
- Enable -Bsymbolic-functions linker flag whenever possible.
|
||||
|
||||
- Resolve various compiler warnings (#423, #430, #435, #436).
|
||||
|
||||
- Fix code coverage ignored paths (#439).
|
||||
|
||||
* Other:
|
||||
|
||||
- Test coverage improvements (#398, #400).
|
||||
|
||||
- Add VS 2017 to appveyor, update Visual Studio documentation (#417).
|
||||
|
||||
- Update copyright for 2018 (#424).
|
||||
|
||||
- Update install instructions in README (#401).
|
||||
|
||||
Version 2.11
|
||||
============
|
||||
|
||||
Released 2018-02-09
|
||||
|
||||
* New features:
|
||||
|
||||
- Add `json_pack()` format specifiers s*, o* and O* for values that
|
||||
can be omitted if null (#339).
|
||||
|
||||
- Add `json_error_code()` to retrieve numeric error codes (#365, #380,
|
||||
#381).
|
||||
|
||||
- Enable thread safety for `json_dump()` on all systems. Enable thread
|
||||
safe `json_decref()` and `json_incref()` for modern compilers (#389).
|
||||
|
||||
- Add `json_sprintf()` and `json_vsprintf()` (#393).
|
||||
|
||||
* Bug Fixes:
|
||||
|
||||
- Fix incorrect report of success from `json_dump_file()` when an error
|
||||
is returned by `fclose()` (#359).
|
||||
|
||||
- Make json_equal() const-correct (#344).
|
||||
|
||||
- Fix incomplete stealing of references by `json_pack()` (#374).
|
||||
|
||||
* Build:
|
||||
|
||||
- Work around gcc's -Wimplicit-fallthrough.
|
||||
|
||||
- Fix CMake detection of `sys/types.h` header (#375).
|
||||
|
||||
- Fix `jansson.pc` generated by CMake to be more consistent with the one
|
||||
generated using GNU Autotools (#368).
|
||||
|
||||
* Other:
|
||||
|
||||
- Miscellaneous documentation fixes (#356, #378, #395).
|
||||
|
||||
- Remove unnecessary reference actions from parsers (#377).
|
||||
|
||||
Version 2.10
|
||||
============
|
||||
|
||||
Released 2017-03-02
|
||||
|
||||
* New features:
|
||||
|
||||
- Add JSON_EMBED encoding flag allowing arrays and objects to be encoded
|
||||
into existing streams (#329).
|
||||
|
||||
- Add `json_dumpb()` function for dumping to a pre-allocated buffer (#328).
|
||||
|
||||
- Add `json_dumpfd()` and `json_loadfd()` functions for dumping to streaming
|
||||
file descriptors (#328).
|
||||
|
||||
- Add support for parsing buffers larger than 2GB (#309).
|
||||
|
||||
* Build:
|
||||
|
||||
- Fix CMake build when LONG_LONG_INT is defined as "" (#321)
|
||||
|
||||
* Other:
|
||||
|
||||
- Internal code cleanup (#311, #314)
|
||||
|
||||
Version 2.9
|
||||
===========
|
||||
|
||||
Released 2016-09-18
|
||||
|
||||
* New features:
|
||||
|
||||
- Add ``json_auto_t`` to automatically decref a value that goes out
|
||||
of scope. Available only on GCC and Clang. (#301)
|
||||
|
||||
* Build:
|
||||
|
||||
- Fix CMake build (at least on Linux) by removing conflicting
|
||||
jansson_config.h from the distribution (#306)
|
||||
|
||||
- Change CMake install target generation to be optional (#305)
|
||||
|
||||
* Documentation:
|
||||
|
||||
- Small documentation fixes.
|
||||
|
||||
|
||||
Version 2.8
|
||||
===========
|
||||
|
||||
Released 2016-08-30
|
||||
|
||||
* New features:
|
||||
|
||||
- Always preserve insertion order of object items.
|
||||
`json_object_iter()` and friends, `json_object_foreach()` and
|
||||
`json_dumps()` and friends now always work in the insertion order of
|
||||
object items (#293).
|
||||
|
||||
- Add `json_object_foreach_safe()` macro that allows
|
||||
`json_object_del()` calls during iteration (#230).
|
||||
|
||||
- Add `json_get_alloc_funcs()` to allow reading the allocation
|
||||
functions set by `json_set_alloc_funcs()` (#262, #264).
|
||||
|
||||
- Add `json_pack()` format specifiers s?, o? and O? for values that
|
||||
can be null (#261, #270).
|
||||
|
||||
* Bug fixes:
|
||||
|
||||
- Fix a crash when parsing inputs consisting of very deeply nested
|
||||
arrays or objects (#282, #284).
|
||||
|
||||
- Never convert numbers to integers in the parser when
|
||||
JSON_DECODE_INT_AS_REAL is set. This fixes error messages for
|
||||
overflowing numbers when JSON_DECODE_INT_AS_REAL is set (#212).
|
||||
|
||||
- Fix a use-after-free in `json_pack()` error handling.
|
||||
|
||||
- Fix subnormal number parsing on mingw32.
|
||||
|
||||
- Handle out-of-memory situations gracefully in the hashtable
|
||||
implementation (#298).
|
||||
|
||||
* Build:
|
||||
|
||||
- Fix build with CMake on all versions of Visual Studio up to 2015
|
||||
(#262, #289).
|
||||
|
||||
- Fix pkgconfig libdir when using CMake (#268).
|
||||
|
||||
- Fix CMake config for static CRT builds on Windows (#206).
|
||||
|
||||
- Fix warnings on LLVM 6.0 targeting iOS arm64 (#208).
|
||||
|
||||
- Add coverlls.io support via Travis for a nice test coverage badge
|
||||
(#211).
|
||||
|
||||
- Don't expect ``jansson_config.h`` to be in the compiler's include
|
||||
path (#209).
|
||||
|
||||
- Add a build-time option to set initial hashtable size (#213).
|
||||
|
||||
- Use snprintf and strncpy in place of sprintf and strcpy to silence
|
||||
linker warnings on OpenBSD (#233).
|
||||
|
||||
* Documentation:
|
||||
|
||||
- Fix various typos in documentation, and a broken link (#258).
|
||||
|
||||
- Add an example program in ``examples/`` (#214, #217).
|
||||
|
||||
- Fix building of documentation man pages (#207).
|
||||
|
||||
- Document the fact that copying objects doesn't preserve the
|
||||
insertion order of keys (#237).
|
||||
|
||||
* Tests:
|
||||
|
||||
- Don't use the nonstandard __FUNCTION__ macro in tests.
|
||||
|
||||
- Use expr instead of $((...)) in shell scripts for Solaris 10
|
||||
compatibility.
|
||||
|
||||
- Disable Visual Studio warning C4756 when triggered deliberately in
|
||||
tests (#216).
|
||||
|
||||
- Other minor fixes (#221, #248).
|
||||
|
||||
* Other changes:
|
||||
|
||||
- List all unrecognized object keys when strict unpacking fails
|
||||
(#263).
|
||||
|
||||
- Alter the order of the members of the hashtable_pair struct for
|
||||
easier debugging.
|
||||
|
||||
- Minor performance improvement to `json_dump()` and friends (#234).
|
||||
|
||||
- Minor style fixes (#255, #257).
|
||||
|
||||
|
||||
Version 2.7
|
||||
===========
|
||||
|
||||
Released 2014-10-02
|
||||
|
||||
* New features:
|
||||
|
||||
- `json_pack()` and friends: Add format specifiers ``s%`` and ``+%``
|
||||
for a size_t string length.
|
||||
for a size_t string length (#141).
|
||||
|
||||
- `json_unpack()` and friends: Add format specifier ``s%`` for
|
||||
unpacking the string length along with the string itself.
|
||||
unpacking the string length along with the string itself (#141).
|
||||
|
||||
- Add length-aware string constructors `json_stringn()` and
|
||||
`json_stringn_nocheck()`, length-aware string mutators
|
||||
`json_string_setn()` and `json_string_setn_nocheck()`, and a
|
||||
function for getting string's length `json_string_length()`.
|
||||
function for getting string's length `json_string_length()` (#141,
|
||||
#143).
|
||||
|
||||
- Support ``\u0000`` escapes in the decoder. The support can be
|
||||
enabled by using the ``JSON_ALLOW_NUL`` decoding flag.
|
||||
enabled by using the ``JSON_ALLOW_NUL`` decoding flag (#141).
|
||||
|
||||
- Add `json_boolean_value()` as an alias for `json_is_true()`
|
||||
(#146).
|
||||
|
||||
- Add JSON_REAL_PRECISION encoding flag/macro for controlling real
|
||||
number precision (#178).
|
||||
|
||||
- Define the maximum indentation as JSON_MAX_INDENT (#191).
|
||||
|
||||
* Bug fixes:
|
||||
|
||||
- Some malformed ``\uNNNN`` escapes could crash the decoder with an
|
||||
assertion failure.
|
||||
|
||||
- Avoid integer overflows with very long strings in UTF-8 decoder and
|
||||
hashtable.
|
||||
|
||||
- Check for *NULL* key in `json_object_get()` and
|
||||
`json_object_del()` (#151).
|
||||
|
||||
- Enhance hashtable seeding on Windows (#162).
|
||||
|
||||
- `json_unpack()`: Allow mixing JSON_STRICT with optional keys
|
||||
(#162, #163).
|
||||
|
||||
- Fix int/int32 mismatch (#142).
|
||||
|
||||
- Parse subnormal numbers correctly (#202).
|
||||
|
||||
* Build:
|
||||
|
||||
- Remove VS2010 build files. CMake should be used on Windows instead
|
||||
(#165).
|
||||
|
||||
- Fix CMake build flags for MinGW (#193).
|
||||
|
||||
- Add CMake config files for find_package. Rename config.h to
|
||||
jansson_private_config.h (#157, #159).
|
||||
|
||||
- Make Valgrind checks work with CMake (#160).
|
||||
|
||||
- Fix feature checks to use correct __ATOMIC flags.
|
||||
|
||||
- Fix CMake checks for uint16_t and uint8_t support (#177).
|
||||
|
||||
- Make Jansson build on SmartOS/Solaris (#171).
|
||||
|
||||
- Work around a GCC bug on Solaris (#175).
|
||||
|
||||
- Fix autoreconf on Debian (#182).
|
||||
|
||||
- Don't use GNU make specific export for global AM_CFLAGS (#203,
|
||||
#204).
|
||||
|
||||
- Fix building on Android using the supplied Android.mk (#166,
|
||||
#174).
|
||||
|
||||
- Android.mk: Add -DHAVE_STDINT_H to LOCAL_CFLAGS (#200).
|
||||
|
||||
* Documentation:
|
||||
|
||||
- Document JANSSON_BUILD_SHARED_LIBS CMake option (#187).
|
||||
|
||||
* Tests:
|
||||
|
||||
- Close file handles correctly (#198).
|
||||
|
||||
* Other changes:
|
||||
|
||||
- ``\uNNNN`` escapes are now encoded in upper case for better
|
||||
readability.
|
||||
|
||||
- Enable usage of AddressSanitizer (#180).
|
||||
|
||||
|
||||
Version 2.6
|
||||
===========
|
||||
|
|
|
@ -46,9 +46,8 @@
|
|||
|
||||
|
||||
|
||||
cmake_minimum_required (VERSION 2.8)
|
||||
# required for exports? cmake_minimum_required (VERSION 2.8.6)
|
||||
project (jansson C)
|
||||
cmake_minimum_required (VERSION 3.1)
|
||||
project(jansson C)
|
||||
|
||||
# Options
|
||||
option(JANSSON_BUILD_SHARED_LIBS "Build shared libraries." OFF)
|
||||
|
@ -61,27 +60,35 @@ if (MSVC)
|
|||
option(JANSSON_STATIC_CRT "Link the static CRT libraries" OFF )
|
||||
endif ()
|
||||
|
||||
option(JANSSON_EXAMPLES "Compile example applications" ON)
|
||||
|
||||
if (UNIX)
|
||||
option(JANSSON_COVERAGE "(GCC Only! Requires gcov/lcov to be installed). Include target for doing coverage analysis for the test suite. Note that -DCMAKE_BUILD_TYPE=Debug must be set" OFF)
|
||||
option(JANSSON_COVERALLS "Generate coverage info for Coveralls" OFF)
|
||||
option(JANSSON_COVERALLS_UPLOAD "Upload coverage info to Coveralls (Only works via Travis)" ON)
|
||||
endif ()
|
||||
|
||||
# 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)
|
||||
set(JANSSON_TEMP_DIR ${PROJECT_BINARY_DIR}/tmp)
|
||||
|
||||
# Give the debug version a different postfix for windows,
|
||||
# so both the debug and release version can be built in the
|
||||
# same build-tree on Windows (MSVC).
|
||||
if (WIN32)
|
||||
if (WIN32 AND NOT CMAKE_DEBUG_POSTFIX)
|
||||
set(CMAKE_DEBUG_POSTFIX "_d")
|
||||
else (WIN32)
|
||||
endif (WIN32)
|
||||
endif()
|
||||
|
||||
# This is how I thought it should go
|
||||
# set (JANSSON_VERSION "2.3.1")
|
||||
# set (JANSSON_SOVERSION 2)
|
||||
|
||||
set(JANSSON_DISPLAY_VERSION "2.6")
|
||||
set(JANSSON_DISPLAY_VERSION "2.12")
|
||||
|
||||
# This is what is required to match the same numbers as automake's
|
||||
set(JANSSON_VERSION "4.6.0")
|
||||
set(JANSSON_VERSION "4.11.1")
|
||||
set(JANSSON_SOVERSION 4)
|
||||
|
||||
# for CheckFunctionKeywords
|
||||
|
@ -101,11 +108,21 @@ if (MSVC)
|
|||
set(CMAKE_C_FLAGS_RELEASE "/MT")
|
||||
set(CMAKE_C_FLAGS_DEBUG "/MTd")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
if (NOT WIN32 AND (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX))
|
||||
set(CMAKE_C_FLAGS "-fPIC")
|
||||
message("C compiler: ${CMAKE_C_COMPILER_ID}")
|
||||
|
||||
# Coverage only works with GCC for a debug build.
|
||||
if (JANSSON_COVERALLS)
|
||||
set(JANSSON_COVERAGE ON)
|
||||
endif()
|
||||
|
||||
if (JANSSON_COVERAGE)
|
||||
include(CodeCoverage)
|
||||
include(Coveralls)
|
||||
|
||||
# This adds coverage arguments to gcc/clang.
|
||||
coveralls_turn_on_coverage()
|
||||
endif()
|
||||
|
||||
check_include_files (endian.h HAVE_ENDIAN_H)
|
||||
|
@ -115,7 +132,7 @@ check_include_files (unistd.h HAVE_UNISTD_H)
|
|||
check_include_files (sys/param.h HAVE_SYS_PARAM_H)
|
||||
check_include_files (sys/stat.h HAVE_SYS_STAT_H)
|
||||
check_include_files (sys/time.h HAVE_SYS_TIME_H)
|
||||
check_include_files (sys/time.h HAVE_SYS_TYPES_H)
|
||||
check_include_files (sys/types.h HAVE_SYS_TYPES_H)
|
||||
|
||||
check_function_exists (close HAVE_CLOSE)
|
||||
check_function_exists (getpid HAVE_GETPID)
|
||||
|
@ -141,9 +158,9 @@ if (HAVE_INT32_T)
|
|||
set (JSON_INT32 int32_t)
|
||||
elseif (HAVE___INT32)
|
||||
set (JSON_INT32 __int32)
|
||||
elseif (HAVE_LONG_INT AND (${LONG_INT} EQUAL 4))
|
||||
elseif (HAVE_LONG_INT AND (LONG_INT EQUAL 4))
|
||||
set (JSON_INT32 long)
|
||||
elseif (HAVE_INT AND (${INT} EQUAL 4))
|
||||
elseif (HAVE_INT AND (INT EQUAL 4))
|
||||
set (JSON_INT32 int)
|
||||
else ()
|
||||
message (FATAL_ERROR "Could not detect a valid 32-bit integer type")
|
||||
|
@ -159,12 +176,12 @@ if (HAVE_UINT32_T)
|
|||
set (JSON_UINT32 uint32_t)
|
||||
elseif (HAVE___UINT32)
|
||||
set (JSON_UINT32 __uint32)
|
||||
elseif (HAVE_UNSIGNED_LONG_INT AND (${UNSIGNED_LONG_INT} EQUAL 4))
|
||||
elseif (HAVE_UNSIGNED_LONG_INT AND (UNSIGNED_LONG_INT EQUAL 4))
|
||||
set (JSON_UINT32 "unsigned long")
|
||||
elseif (HAVE_UNSIGNED_INT AND (${UNSIGNED_INT} EQUAL 4))
|
||||
elseif (HAVE_UNSIGNED_INT AND (UNSIGNED_INT EQUAL 4))
|
||||
set (JSON_UINT32 "unsigned int")
|
||||
else ()
|
||||
message (FATAL_ERROR "Could not detect a valid unsigned 32-bit integer type")
|
||||
message (FATAL_ERROR "Could not detect a valid unsigned 32-bit integer type")
|
||||
endif ()
|
||||
|
||||
check_type_size (uint16_t UINT16_T)
|
||||
|
@ -173,12 +190,12 @@ if (HAVE_UINT16_T)
|
|||
set (JSON_UINT16 uint16_t)
|
||||
elseif (HAVE___UINT16)
|
||||
set (JSON_UINT16 __uint16)
|
||||
elseif (HAVE_UNSIGNED_INT AND (${UNSIGNED_INT} EQUAL 2))
|
||||
elseif (HAVE_UNSIGNED_INT AND (UNSIGNED_INT EQUAL 2))
|
||||
set (JSON_UINT16 "unsigned int")
|
||||
elseif (HAVE_UNSIGNED_SHORT AND (${UNSIGNED_SHORT} EQUAL 2))
|
||||
elseif (HAVE_UNSIGNED_SHORT AND (UNSIGNED_SHORT EQUAL 2))
|
||||
set (JSON_UINT16 "unsigned short")
|
||||
else ()
|
||||
message (FATAL_ERROR "Could not detect a valid unsigned 16-bit integer type")
|
||||
message (FATAL_ERROR "Could not detect a valid unsigned 16-bit integer type")
|
||||
endif ()
|
||||
|
||||
check_type_size (uint8_t UINT8_T)
|
||||
|
@ -227,7 +244,7 @@ endif ()
|
|||
# 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))
|
||||
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)
|
||||
|
@ -280,31 +297,22 @@ else()
|
|||
set (JSON_INLINE)
|
||||
endif()
|
||||
|
||||
# Find our snprintf
|
||||
check_function_exists (snprintf HAVE_SNPRINTF)
|
||||
check_function_exists (_snprintf HAVE__SNPRINTF)
|
||||
check_c_source_compiles ("int main() { unsigned long val; __sync_bool_compare_and_swap(&val, 0, 1); __sync_add_and_fetch(&val, 1); __sync_sub_and_fetch(&val, 1); return 0; } " HAVE_SYNC_BUILTINS)
|
||||
check_c_source_compiles ("int main() { char l; unsigned long v; __atomic_test_and_set(&l, __ATOMIC_RELAXED); __atomic_store_n(&v, 1, __ATOMIC_RELEASE); __atomic_load_n(&v, __ATOMIC_ACQUIRE); __atomic_add_fetch(&v, 1, __ATOMIC_ACQUIRE); __atomic_sub_fetch(&v, 1, __ATOMIC_RELEASE); return 0; }" HAVE_ATOMIC_BUILTINS)
|
||||
|
||||
if (HAVE_SNPRINTF)
|
||||
set(JSON_SNPRINTF snprintf)
|
||||
elseif (HAVE__SNPRINTF)
|
||||
set(JSON_SNPRINTF _snprintf)
|
||||
endif ()
|
||||
if (HAVE_SYNC_BUILTINS)
|
||||
set(JSON_HAVE_SYNC_BUILTINS 1)
|
||||
else()
|
||||
set(JSON_HAVE_SYNC_BUILTINS 0)
|
||||
endif()
|
||||
|
||||
check_c_source_compiles ("int main() { unsigned long val; __sync_bool_compare_and_swap(&val, 0, 1); return 0; } " HAVE_SYNC_BUILTINS)
|
||||
check_c_source_compiles ("int main() { char l; unsigned long v; __atomic_test_and_set(&l, __ATOMIC_RELAXED); __atomic_store_n(&v, 1, __ATOMIC_RELEASE); __atomic_load_n(&v, __ATOMIC_ACQUIRE); return 0; }" HAVE_ATOMIC_BUILTINS)
|
||||
if (HAVE_ATOMIC_BUILTINS)
|
||||
set(JSON_HAVE_ATOMIC_BUILTINS 1)
|
||||
else()
|
||||
set(JSON_HAVE_ATOMIC_BUILTINS 0)
|
||||
endif()
|
||||
|
||||
# Create pkg-conf file.
|
||||
# (We use the same files as ./configure does, so we
|
||||
# have to defined the same variables used there).
|
||||
if(NOT DEFINED CMAKE_INSTALL_LIBDIR)
|
||||
set(CMAKE_INSTALL_LIBDIR lib)
|
||||
endif(NOT DEFINED CMAKE_INSTALL_LIBDIR)
|
||||
set(prefix ${CMAKE_INSTALL_PREFIX})
|
||||
set(exec_prefix ${CMAKE_INSTALL_PREFIX})
|
||||
set(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
|
||||
set(VERSION ${JANSSON_DISPLAY_VERSION})
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/jansson.pc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/jansson.pc @ONLY)
|
||||
set (JANSSON_INITIAL_HASHTABLE_ORDER 3 CACHE STRING "Number of buckets new object hashtables contain is 2 raised to this power. The default is 3, so empty hashtables contain 2^3 = 8 buckets.")
|
||||
|
||||
# configure the public config file
|
||||
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/cmake/jansson_config.h.cmake
|
||||
|
@ -355,12 +363,18 @@ if(JANSSON_BUILD_SHARED_LIBS)
|
|||
VERSION ${JANSSON_VERSION}
|
||||
SOVERSION ${JANSSON_SOVERSION})
|
||||
else()
|
||||
add_library(jansson
|
||||
add_library(jansson STATIC
|
||||
${JANSSON_SRC}
|
||||
${JANSSON_HDR_PRIVATE}
|
||||
${JANSSON_HDR_PUBLIC})
|
||||
set_target_properties(jansson PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE true)
|
||||
endif()
|
||||
|
||||
if (JANSSON_EXAMPLES)
|
||||
add_executable(simple_parse "${CMAKE_CURRENT_SOURCE_DIR}/examples/simple_parse.c")
|
||||
target_link_libraries(simple_parse jansson)
|
||||
endif()
|
||||
|
||||
# For building Documentation (uses Sphinx)
|
||||
option(JANSSON_BUILD_DOCS "Build documentation (uses python-sphinx)." ON)
|
||||
|
@ -481,15 +495,18 @@ if (NOT JANSSON_WITHOUT_TESTS)
|
|||
set(api_tests
|
||||
test_array
|
||||
test_copy
|
||||
test_chaos
|
||||
test_dump
|
||||
test_dump_callback
|
||||
test_equal
|
||||
test_load
|
||||
test_loadb
|
||||
test_load_callback
|
||||
test_number
|
||||
test_object
|
||||
test_pack
|
||||
test_simple
|
||||
test_sprintf
|
||||
test_unpack)
|
||||
|
||||
# Doing arithmetic on void pointers is not allowed by Microsofts compiler
|
||||
|
@ -507,29 +524,31 @@ if (NOT JANSSON_WITHOUT_TESTS)
|
|||
|
||||
# Create executables and tests/valgrind tests for API tests.
|
||||
foreach (test ${api_tests})
|
||||
build_testprog(${test} ${PROJECT_SOURCE_DIR}/test/suites/api)
|
||||
build_testprog(${test} ${CMAKE_CURRENT_SOURCE_DIR}/test/suites/api)
|
||||
|
||||
if (JANSSON_TEST_WITH_VALGRIND)
|
||||
add_test(memcheck__${test}
|
||||
${MEMCHECK_COMMAND} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${test})
|
||||
${MEMCHECK_COMMAND} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${test}
|
||||
WORKING_DIRECTORY ${JANSSON_TEMP_DIR})
|
||||
else()
|
||||
add_test(${test} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${test})
|
||||
add_test(${test}
|
||||
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${test}
|
||||
WORKING_DIRECTORY ${JANSSON_TEMP_DIR})
|
||||
endif ()
|
||||
endforeach ()
|
||||
|
||||
# Test harness for the suites tests.
|
||||
build_testprog(json_process ${PROJECT_SOURCE_DIR}/test/bin)
|
||||
build_testprog(json_process ${CMAKE_CURRENT_SOURCE_DIR}/test/bin)
|
||||
|
||||
set(SUITE_TEST_CMD ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/json_process)
|
||||
set(SUITES encoding-flags valid invalid invalid-unicode)
|
||||
foreach (SUITE ${SUITES})
|
||||
file(GLOB TESTDIRS ${jansson_SOURCE_DIR}/test/suites/${SUITE}/*)
|
||||
file(GLOB TESTDIRS test/suites/${SUITE}/*)
|
||||
|
||||
foreach (TESTDIR ${TESTDIRS})
|
||||
if (IS_DIRECTORY ${TESTDIR})
|
||||
get_filename_component(TNAME ${TESTDIR} NAME)
|
||||
|
||||
set(SUITE_TEST_CMD ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/json_process)
|
||||
|
||||
if (JANSSON_TEST_WITH_VALGRIND)
|
||||
add_test(memcheck__${SUITE}__${TNAME}
|
||||
${MEMCHECK_COMMAND} ${SUITE_TEST_CMD} ${TESTDIR})
|
||||
|
@ -551,6 +570,21 @@ if (NOT JANSSON_WITHOUT_TESTS)
|
|||
endforeach ()
|
||||
endforeach ()
|
||||
|
||||
if (JANSSON_COVERAGE)
|
||||
setup_target_for_coverage(
|
||||
coverage # Coverage make target "make coverage".
|
||||
coverage # Name of output directory.
|
||||
make # Name of test runner executable.
|
||||
test) # Arguments to the test runner above (make test).
|
||||
|
||||
if (JANSSON_COVERALLS)
|
||||
set(COVERAGE_SRCS ${JANSSON_SRC})
|
||||
coveralls_setup("${COVERAGE_SRCS}" ${JANSSON_COVERALLS_UPLOAD})
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Enable using "make check" just like the autotools project.
|
||||
# By default cmake creates a target "make test"
|
||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND}
|
||||
DEPENDS json_process ${api_tests})
|
||||
endif ()
|
||||
|
@ -572,87 +606,78 @@ endif()
|
|||
|
||||
set(JANSSON_INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files")
|
||||
|
||||
# Make sure the paths are absolute.
|
||||
foreach(p LIB BIN INCLUDE CMAKE)
|
||||
set(var JANSSON_INSTALL_${p}_DIR)
|
||||
if(NOT IS_ABSOLUTE "${${var}}")
|
||||
set(${var} "${CMAKE_INSTALL_PREFIX}/${${var}}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Export targets (This is used for other CMake projects to easily find the libraries and include files).
|
||||
export(TARGETS jansson
|
||||
FILE "${PROJECT_BINARY_DIR}/JanssonTargets.cmake")
|
||||
export(PACKAGE jansson)
|
||||
|
||||
# Generate the config file for the build-tree.
|
||||
set(JANSSON__INCLUDE_DIRS
|
||||
"${PROJECT_SOURCE_DIR}/include"
|
||||
"${PROJECT_BINARY_DIR}/include")
|
||||
set(JANSSON_INCLUDE_DIRS ${JANSSON__INCLUDE_DIRS} CACHE PATH "Jansson include directories")
|
||||
configure_file(${PROJECT_SOURCE_DIR}/cmake/JanssonConfig.cmake.in
|
||||
${PROJECT_BINARY_DIR}/JanssonConfig.cmake
|
||||
@ONLY)
|
||||
|
||||
# Generate the config file for the installation tree.
|
||||
file(RELATIVE_PATH
|
||||
REL_INCLUDE_DIR
|
||||
"${JANSSON_INSTALL_CMAKE_DIR}"
|
||||
"${JANSSON_INSTALL_INCLUDE_DIR}") # Calculate the relative directory from the Cmake dir.
|
||||
|
||||
# Note the EVENT_CMAKE_DIR is defined in JanssonConfig.cmake.in,
|
||||
# we escape it here so it's evaluated when it is included instead
|
||||
# so that the include dirs are given relative to where the
|
||||
# config file is located.
|
||||
set(JANSSON__INCLUDE_DIRS
|
||||
"\${JANSSON_CMAKE_DIR}/${REL_INCLUDE_DIR}")
|
||||
configure_file(${PROJECT_SOURCE_DIR}/cmake/JanssonConfig.cmake.in
|
||||
${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/JanssonConfig.cmake
|
||||
@ONLY)
|
||||
|
||||
# Generate version info for both build-tree and install-tree.
|
||||
configure_file(${PROJECT_SOURCE_DIR}/cmake/JanssonConfigVersion.cmake.in
|
||||
${PROJECT_BINARY_DIR}/JanssonConfigVersion.cmake
|
||||
@ONLY)
|
||||
|
||||
# Define the public headers.
|
||||
set_target_properties(jansson PROPERTIES PUBLIC_HEADER "${JANSSON_HDR_PUBLIC}")
|
||||
#TODO: fix this.
|
||||
|
||||
# Create pkg-conf file.
|
||||
# (We use the same files as ./configure does, so we
|
||||
# have to defined the same variables used there).
|
||||
set(prefix ${CMAKE_INSTALL_PREFIX})
|
||||
set(exec_prefix ${CMAKE_INSTALL_PREFIX})
|
||||
set(libdir ${CMAKE_INSTALL_PREFIX}/${JANSSON_INSTALL_LIB_DIR})
|
||||
set(exec_prefix "\${prefix}")
|
||||
set(libdir "\${exec_prefix}/${JANSSON_INSTALL_LIB_DIR}")
|
||||
set(includedir "\${prefix}/${JANSSON_INSTALL_INCLUDE_DIR}")
|
||||
set(VERSION ${JANSSON_DISPLAY_VERSION})
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/jansson.pc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/jansson.pc @ONLY)
|
||||
|
||||
# Make sure the paths are relative.
|
||||
foreach(p LIB BIN INCLUDE CMAKE)
|
||||
set(var JANSSON_INSTALL_${p}_DIR)
|
||||
endforeach()
|
||||
|
||||
# Generate the config file for the build-tree.
|
||||
set(JANSSON__INCLUDE_DIRS
|
||||
"${PROJECT_BINARY_DIR}/include"
|
||||
"${PROJECT_BINARY_DIR}/include")
|
||||
set(JANSSON_INCLUDE_DIRS ${JANSSON__INCLUDE_DIRS} CACHE PATH "Jansson include directories")
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/janssonConfig.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/janssonConfig.cmake
|
||||
@ONLY)
|
||||
|
||||
|
||||
# Generate the config file for the installation tree.
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
write_basic_package_version_file(
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/cmake/janssonConfigVersion.cmake"
|
||||
VERSION ${JANSSON_VERSION}
|
||||
COMPATIBILITY ExactVersion
|
||||
)
|
||||
|
||||
configure_package_config_file(
|
||||
"cmake/janssonConfig.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/cmake/janssonConfig.cmake"
|
||||
INSTALL_DESTINATION "${JANSSON_INSTALL_CMAKE_DIR}"
|
||||
)
|
||||
|
||||
#
|
||||
# Install targets.
|
||||
#
|
||||
install(TARGETS jansson
|
||||
EXPORT JanssonTargets
|
||||
LIBRARY DESTINATION "${JANSSON_INSTALL_LIB_DIR}" COMPONENT lib
|
||||
ARCHIVE DESTINATION "${JANSSON_INSTALL_LIB_DIR}" COMPONENT lib
|
||||
RUNTIME DESTINATION "${JANSSON_INSTALL_BIN_DIR}" COMPONENT lib # Windows DLLs
|
||||
PUBLIC_HEADER DESTINATION "${JANSSON_INSTALL_INCLUDE_DIR}" COMPONENT dev)
|
||||
option(JANSSON_INSTALL "Generate installation target" ON)
|
||||
if (JANSSON_INSTALL)
|
||||
install(TARGETS jansson
|
||||
EXPORT janssonTargets
|
||||
LIBRARY DESTINATION "lib"
|
||||
ARCHIVE DESTINATION "lib"
|
||||
RUNTIME DESTINATION "bin"
|
||||
INCLUDES DESTINATION "include")
|
||||
|
||||
# Install the pkg-config.
|
||||
install (FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/jansson.pc
|
||||
DESTINATION ${JANSSON_INSTALL_LIB_DIR}/pkgconfig COMPONENT dev)
|
||||
install(FILES ${JANSSON_HDR_PUBLIC}
|
||||
DESTINATION "include")
|
||||
|
||||
# Install the configs.
|
||||
install(FILES
|
||||
${PROJECT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/JanssonConfig.cmake
|
||||
${PROJECT_BINARY_DIR}/JanssonConfigVersion.cmake
|
||||
DESTINATION "${JANSSON_INSTALL_CMAKE_DIR}" COMPONENT dev)
|
||||
# Install the pkg-config.
|
||||
install(FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/jansson.pc
|
||||
DESTINATION lib/pkgconfig)
|
||||
|
||||
# Install exports for the install-tree.
|
||||
install(EXPORT JanssonTargets
|
||||
DESTINATION "${JANSSON_INSTALL_CMAKE_DIR}" COMPONENT dev)
|
||||
# Install the configs.
|
||||
install(FILES
|
||||
${PROJECT_BINARY_DIR}/cmake/janssonConfig.cmake
|
||||
${PROJECT_BINARY_DIR}/cmake/janssonConfigVersion.cmake
|
||||
DESTINATION "${JANSSON_INSTALL_CMAKE_DIR}")
|
||||
|
||||
# Install exports for the install-tree.
|
||||
install(EXPORT janssonTargets
|
||||
NAMESPACE jansson::
|
||||
DESTINATION "${JANSSON_INSTALL_CMAKE_DIR}")
|
||||
endif()
|
||||
|
||||
# For use when simply using add_library from a parent project to build jansson.
|
||||
set(JANSSON_LIBRARIES jansson CACHE STRING "Jansson libraries")
|
||||
set(JANSSON_LIBRARIES jansson CACHE STRING "jansson libraries")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>
|
||||
Copyright (c) 2009-2018 Petri Lehtinen <petri@digip.org>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
EXTRA_DIST = CHANGES LICENSE README.rst CMakeLists.txt cmake
|
||||
EXTRA_DIST = CHANGES LICENSE README.rst CMakeLists.txt cmake android examples
|
||||
SUBDIRS = doc src test
|
||||
|
||||
# "make distcheck" builds the dvi target, so use it to check that the
|
||||
|
@ -8,8 +8,3 @@ dvi:
|
|||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = jansson.pc
|
||||
|
||||
if GCC
|
||||
# These flags are gcc specific
|
||||
export AM_CFLAGS = -Wall -Wextra -Wdeclaration-after-statement
|
||||
endif
|
||||
|
|
|
@ -2,15 +2,20 @@ Jansson README
|
|||
==============
|
||||
|
||||
.. image:: https://travis-ci.org/akheron/jansson.png
|
||||
:alt: Build status
|
||||
:target: https://travis-ci.org/akheron/jansson
|
||||
|
||||
.. image:: https://ci.appveyor.com/api/projects/status/lmhkkc4q8cwc65ko
|
||||
:target: https://ci.appveyor.com/project/akheron/jansson
|
||||
|
||||
.. image:: https://coveralls.io/repos/akheron/jansson/badge.png?branch=master
|
||||
:target: https://coveralls.io/r/akheron/jansson?branch=master
|
||||
|
||||
Jansson_ is a C library for encoding, decoding and manipulating JSON
|
||||
data. Its main features and design principles are:
|
||||
|
||||
- Simple and intuitive API and data model
|
||||
|
||||
- Comprehensive documentation
|
||||
- `Comprehensive documentation`_
|
||||
|
||||
- No dependencies on other libraries
|
||||
|
||||
|
@ -25,8 +30,8 @@ source distribution for details.
|
|||
Compilation and Installation
|
||||
----------------------------
|
||||
|
||||
If you obtained a source tarball, just use the standard autotools
|
||||
commands::
|
||||
If you obtained a `source tarball`_ from the "Releases" section of the main
|
||||
site just use the standard autotools commands::
|
||||
|
||||
$ ./configure
|
||||
$ make
|
||||
|
@ -46,8 +51,7 @@ use autoreconf::
|
|||
Documentation
|
||||
-------------
|
||||
|
||||
Prebuilt HTML documentation is available at
|
||||
http://www.digip.org/jansson/doc/.
|
||||
Documentation is available at http://jansson.readthedocs.io/en/latest/.
|
||||
|
||||
The documentation source is in the ``doc/`` subdirectory. To generate
|
||||
HTML documentation, invoke::
|
||||
|
@ -59,5 +63,7 @@ Then, point your browser to ``doc/_build/html/index.html``. Sphinx_
|
|||
|
||||
|
||||
.. _Jansson: http://www.digip.org/jansson/
|
||||
.. _`Comprehensive documentation`: http://jansson.readthedocs.io/en/latest/
|
||||
.. _`MIT license`: http://www.opensource.org/licenses/mit-license.php
|
||||
.. _`source tarball`: http://www.digip.org/jansson#releases
|
||||
.. _Sphinx: http://sphinx.pocoo.org/
|
||||
|
|
|
@ -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.
|
||||
|
@ -36,4 +36,8 @@
|
|||
otherwise to 0. */
|
||||
#define JSON_HAVE_LOCALECONV 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
|
||||
|
|
163
jansson/cmake/CodeCoverage.cmake
Normal file
163
jansson/cmake/CodeCoverage.cmake
Normal file
|
@ -0,0 +1,163 @@
|
|||
#
|
||||
# Boost Software License - Version 1.0 - August 17th, 2003
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person or organization
|
||||
# obtaining a copy of the software and accompanying documentation covered by
|
||||
# this license (the "Software") to use, reproduce, display, distribute,
|
||||
# execute, and transmit the Software, and to prepare derivative works of the
|
||||
# Software, and to permit third-parties to whom the Software is furnished to
|
||||
# do so, all subject to the following:
|
||||
#
|
||||
# The copyright notices in the Software and this entire statement, including
|
||||
# the above license grant, this restriction and the following disclaimer,
|
||||
# must be included in all copies of the Software, in whole or in part, and
|
||||
# all derivative works of the Software, unless such copies or derivative
|
||||
# works are solely in the form of machine-executable object code generated by
|
||||
# a source language processor.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
# SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
# FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
# DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# 2012-01-31, Lars Bilke
|
||||
# - Enable Code Coverage
|
||||
#
|
||||
# 2013-09-17, Joakim Söderberg
|
||||
# - Added support for Clang.
|
||||
# - Some additional usage instructions.
|
||||
#
|
||||
# USAGE:
|
||||
# 1. Copy this file into your cmake modules path.
|
||||
#
|
||||
# 2. Add the following line to your CMakeLists.txt:
|
||||
# INCLUDE(CodeCoverage)
|
||||
#
|
||||
# 3. Set compiler flags to turn off optimization and enable coverage:
|
||||
# SET(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
|
||||
# SET(CMAKE_C_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
|
||||
#
|
||||
# 3. Use the function SETUP_TARGET_FOR_COVERAGE to create a custom make target
|
||||
# which runs your test executable and produces a lcov code coverage report:
|
||||
# Example:
|
||||
# SETUP_TARGET_FOR_COVERAGE(
|
||||
# my_coverage_target # Name for custom target.
|
||||
# test_driver # Name of the test driver executable that runs the tests.
|
||||
# # NOTE! This should always have a ZERO as exit code
|
||||
# # otherwise the coverage generation will not complete.
|
||||
# coverage # Name of output directory.
|
||||
# )
|
||||
#
|
||||
# 4. Build a Debug build:
|
||||
# cmake -DCMAKE_BUILD_TYPE=Debug ..
|
||||
# make
|
||||
# make my_coverage_target
|
||||
#
|
||||
#
|
||||
|
||||
# Check prereqs
|
||||
FIND_PROGRAM( GCOV_PATH gcov )
|
||||
FIND_PROGRAM( LCOV_PATH lcov )
|
||||
FIND_PROGRAM( GENHTML_PATH genhtml )
|
||||
FIND_PROGRAM( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/tests)
|
||||
|
||||
IF(NOT GCOV_PATH)
|
||||
MESSAGE(FATAL_ERROR "gcov not found! Aborting...")
|
||||
ENDIF() # NOT GCOV_PATH
|
||||
|
||||
IF(NOT (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUCC))
|
||||
# Clang version 3.0.0 and greater now supports gcov as well.
|
||||
MESSAGE(WARNING "Compiler is not GNU gcc! Clang Version 3.0.0 and greater supports gcov as well, but older versions don't.")
|
||||
|
||||
IF(NOT ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang"))
|
||||
MESSAGE(FATAL_ERROR "Compiler is not GNU gcc or Clang! Aborting...")
|
||||
ENDIF()
|
||||
ENDIF() # NOT CMAKE_COMPILER_IS_GNUCXX
|
||||
|
||||
IF ( NOT CMAKE_BUILD_TYPE STREQUAL "Debug" )
|
||||
MESSAGE( WARNING "Code coverage results with an optimized (non-Debug) build may be misleading" )
|
||||
ENDIF() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug"
|
||||
|
||||
|
||||
# Param _targetname The name of new the custom make target
|
||||
# Param _outputname lcov output is generated as _outputname.info
|
||||
# HTML report is generated in _outputname/index.html
|
||||
# Param _testrunner The name of the target which runs the tests.
|
||||
# MUST return ZERO always, even on errors.
|
||||
# If not, no coverage report will be created!
|
||||
# Optional fourth parameter is passed as arguments to _testrunner
|
||||
# Pass them in list form, e.g.: "-j;2" for -j 2
|
||||
FUNCTION(SETUP_TARGET_FOR_COVERAGE _targetname _outputname _testrunner)
|
||||
|
||||
IF(NOT LCOV_PATH)
|
||||
MESSAGE(FATAL_ERROR "lcov not found! Aborting...")
|
||||
ENDIF() # NOT LCOV_PATH
|
||||
|
||||
IF(NOT GENHTML_PATH)
|
||||
MESSAGE(FATAL_ERROR "genhtml not found! Aborting...")
|
||||
ENDIF() # NOT GENHTML_PATH
|
||||
|
||||
# Setup target
|
||||
ADD_CUSTOM_TARGET(${_targetname}
|
||||
|
||||
# Cleanup lcov
|
||||
${LCOV_PATH} --directory . --zerocounters
|
||||
|
||||
# Run tests
|
||||
COMMAND ${_testrunner} ${ARGV3}
|
||||
|
||||
# Capturing lcov counters and generating report
|
||||
COMMAND ${LCOV_PATH} --directory . --capture --output-file ${_outputname}.info --rc lcov_branch_coverage=1
|
||||
COMMAND ${LCOV_PATH} --remove ${_outputname}.info '*/build/include/*' '*/test/*' '/usr/include/*' --output-file ${_outputname}.info.cleaned --rc lcov_branch_coverage=1
|
||||
COMMAND ${GENHTML_PATH} --branch-coverage -o ${_outputname} ${_outputname}.info.cleaned
|
||||
COMMAND ${CMAKE_COMMAND} -E remove ${_outputname}.info ${_outputname}.info.cleaned
|
||||
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
|
||||
)
|
||||
|
||||
# Show info where to find the report
|
||||
ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD
|
||||
COMMAND ;
|
||||
COMMENT "Open ./${_outputname}/index.html in your browser to view the coverage report."
|
||||
)
|
||||
|
||||
ENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE
|
||||
|
||||
# Param _targetname The name of new the custom make target
|
||||
# Param _testrunner The name of the target which runs the tests
|
||||
# Param _outputname cobertura output is generated as _outputname.xml
|
||||
# Optional fourth parameter is passed as arguments to _testrunner
|
||||
# Pass them in list form, e.g.: "-j;2" for -j 2
|
||||
FUNCTION(SETUP_TARGET_FOR_COVERAGE_COBERTURA _targetname _testrunner _outputname)
|
||||
|
||||
IF(NOT PYTHON_EXECUTABLE)
|
||||
MESSAGE(FATAL_ERROR "Python not found! Aborting...")
|
||||
ENDIF() # NOT PYTHON_EXECUTABLE
|
||||
|
||||
IF(NOT GCOVR_PATH)
|
||||
MESSAGE(FATAL_ERROR "gcovr not found! Aborting...")
|
||||
ENDIF() # NOT GCOVR_PATH
|
||||
|
||||
ADD_CUSTOM_TARGET(${_targetname}
|
||||
|
||||
# Run tests
|
||||
${_testrunner} ${ARGV3}
|
||||
|
||||
# Running gcovr
|
||||
COMMAND ${GCOVR_PATH} -x -r ${CMAKE_SOURCE_DIR} -e '${CMAKE_SOURCE_DIR}/tests/' -o ${_outputname}.xml
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT "Running gcovr to produce Cobertura code coverage report."
|
||||
)
|
||||
|
||||
# Show info where to find the report
|
||||
ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD
|
||||
COMMAND ;
|
||||
COMMENT "Cobertura code coverage report saved in ${_outputname}.xml."
|
||||
)
|
||||
|
||||
ENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE_COBERTURA
|
||||
|
111
jansson/cmake/Coveralls.cmake
Normal file
111
jansson/cmake/Coveralls.cmake
Normal file
|
@ -0,0 +1,111 @@
|
|||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# Copyright (C) 2014 Joakim Söderberg <joakim.soderberg@gmail.com>
|
||||
#
|
||||
|
||||
|
||||
#
|
||||
# Param _COVERAGE_SRCS A list of source files that coverage should be collected for.
|
||||
# Param _COVERALLS_UPLOAD Upload the result to coveralls?
|
||||
#
|
||||
function(coveralls_setup _COVERAGE_SRCS _COVERALLS_UPLOAD)
|
||||
# When passing a CMake list to an external process, the list
|
||||
# will be converted from the format "1;2;3" to "1 2 3".
|
||||
# This means the script we're calling won't see it as a list
|
||||
# of sources, but rather just one long path. We remedy this
|
||||
# by replacing ";" with "*" and then reversing that in the script
|
||||
# that we're calling.
|
||||
# http://cmake.3232098.n2.nabble.com/Passing-a-CMake-list-quot-as-is-quot-to-a-custom-target-td6505681.html
|
||||
set(COVERAGE_SRCS_TMP ${_COVERAGE_SRCS})
|
||||
set(COVERAGE_SRCS "")
|
||||
foreach (COVERAGE_SRC ${COVERAGE_SRCS_TMP})
|
||||
set(COVERAGE_SRCS "${COVERAGE_SRCS}*${COVERAGE_SRC}")
|
||||
endforeach()
|
||||
|
||||
#message("Coverage sources: ${COVERAGE_SRCS}")
|
||||
set(COVERALLS_FILE ${PROJECT_BINARY_DIR}/coveralls.json)
|
||||
|
||||
add_custom_target(coveralls_generate
|
||||
|
||||
# Zero the coverage counters.
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-P "${PROJECT_SOURCE_DIR}/cmake/CoverallsClear.cmake"
|
||||
|
||||
# Run regress tests.
|
||||
COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure
|
||||
|
||||
# Generate Gcov and translate it into coveralls JSON.
|
||||
# We do this by executing an external CMake script.
|
||||
# (We don't want this to run at CMake generation time, but after compilation and everything has run).
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DCOVERAGE_SRCS="${COVERAGE_SRCS}" # TODO: This is passed like: "a b c", not "a;b;c"
|
||||
-DCOVERALLS_OUTPUT_FILE="${COVERALLS_FILE}"
|
||||
-DCOV_PATH="${PROJECT_BINARY_DIR}"
|
||||
-DPROJECT_ROOT="${PROJECT_SOURCE_DIR}"
|
||||
-P "${PROJECT_SOURCE_DIR}/cmake/CoverallsGenerateGcov.cmake"
|
||||
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||
COMMENT "Generating coveralls output..."
|
||||
)
|
||||
|
||||
if (_COVERALLS_UPLOAD)
|
||||
message("COVERALLS UPLOAD: ON")
|
||||
|
||||
find_program(CURL_EXECUTABLE curl)
|
||||
|
||||
if (NOT CURL_EXECUTABLE)
|
||||
message(FATAL_ERROR "Coveralls: curl not found! Aborting")
|
||||
endif()
|
||||
|
||||
add_custom_target(coveralls_upload
|
||||
# Upload the JSON to coveralls.
|
||||
COMMAND ${CURL_EXECUTABLE}
|
||||
-S -F json_file=@${COVERALLS_FILE}
|
||||
https://coveralls.io/api/v1/jobs
|
||||
|
||||
DEPENDS coveralls_generate
|
||||
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||
COMMENT "Uploading coveralls output...")
|
||||
|
||||
add_custom_target(coveralls DEPENDS coveralls_upload)
|
||||
else()
|
||||
message("COVERALLS UPLOAD: OFF")
|
||||
add_custom_target(coveralls DEPENDS coveralls_generate)
|
||||
endif()
|
||||
|
||||
endfunction()
|
||||
|
||||
macro(coveralls_turn_on_coverage)
|
||||
if(NOT (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
|
||||
AND (NOT "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang"))
|
||||
message(FATAL_ERROR "Coveralls: Compiler ${CMAKE_C_COMPILER_ID} is not GNU gcc! Aborting... You can set this on the command line using CC=/usr/bin/gcc CXX=/usr/bin/g++ cmake <options> ..")
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
message(FATAL_ERROR "Coveralls: Code coverage results with an optimised (non-Debug) build may be misleading! Add -DCMAKE_BUILD_TYPE=Debug")
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
|
||||
endmacro()
|
||||
|
||||
|
||||
|
24
jansson/cmake/CoverallsClear.cmake
Normal file
24
jansson/cmake/CoverallsClear.cmake
Normal file
|
@ -0,0 +1,24 @@
|
|||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# Copyright (C) 2014 Joakim Söderberg <joakim.soderberg@gmail.com>
|
||||
#
|
||||
|
||||
file(REMOVE_RECURSE ${PROJECT_BINARY_DIR}/*.gcda)
|
||||
|
380
jansson/cmake/CoverallsGenerateGcov.cmake
Normal file
380
jansson/cmake/CoverallsGenerateGcov.cmake
Normal file
|
@ -0,0 +1,380 @@
|
|||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# Copyright (C) 2014 Joakim Söderberg <joakim.soderberg@gmail.com>
|
||||
#
|
||||
# This is intended to be run by a custom target in a CMake project like this.
|
||||
# 0. Compile program with coverage support.
|
||||
# 1. Clear coverage data. (Recursively delete *.gcda in build dir)
|
||||
# 2. Run the unit tests.
|
||||
# 3. Run this script specifying which source files the coverage should be performed on.
|
||||
#
|
||||
# This script will then use gcov to generate .gcov files in the directory specified
|
||||
# via the COV_PATH var. This should probably be the same as your cmake build dir.
|
||||
#
|
||||
# It then parses the .gcov files to convert them into the Coveralls JSON format:
|
||||
# https://coveralls.io/docs/api
|
||||
#
|
||||
# Example for running as standalone CMake script from the command line:
|
||||
# (Note it is important the -P is at the end...)
|
||||
# $ cmake -DCOV_PATH=$(pwd)
|
||||
# -DCOVERAGE_SRCS="catcierge_rfid.c;catcierge_timer.c"
|
||||
# -P ../cmake/CoverallsGcovUpload.cmake
|
||||
#
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
|
||||
|
||||
#
|
||||
# Make sure we have the needed arguments.
|
||||
#
|
||||
if (NOT COVERALLS_OUTPUT_FILE)
|
||||
message(FATAL_ERROR "Coveralls: No coveralls output file specified. Please set COVERALLS_OUTPUT_FILE")
|
||||
endif()
|
||||
|
||||
if (NOT COV_PATH)
|
||||
message(FATAL_ERROR "Coveralls: Missing coverage directory path where gcov files will be generated. Please set COV_PATH")
|
||||
endif()
|
||||
|
||||
if (NOT COVERAGE_SRCS)
|
||||
message(FATAL_ERROR "Coveralls: Missing the list of source files that we should get the coverage data for COVERAGE_SRCS")
|
||||
endif()
|
||||
|
||||
if (NOT PROJECT_ROOT)
|
||||
message(FATAL_ERROR "Coveralls: Missing PROJECT_ROOT.")
|
||||
endif()
|
||||
|
||||
# Since it's not possible to pass a CMake list properly in the
|
||||
# "1;2;3" format to an external process, we have replaced the
|
||||
# ";" with "*", so reverse that here so we get it back into the
|
||||
# CMake list format.
|
||||
string(REGEX REPLACE "\\*" ";" COVERAGE_SRCS ${COVERAGE_SRCS})
|
||||
|
||||
find_program(GCOV_EXECUTABLE gcov)
|
||||
|
||||
if (NOT GCOV_EXECUTABLE)
|
||||
message(FATAL_ERROR "gcov not found! Aborting...")
|
||||
endif()
|
||||
|
||||
find_package(Git)
|
||||
|
||||
# TODO: Add these git things to the coveralls json.
|
||||
if (GIT_FOUND)
|
||||
# Branch.
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_BRANCH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
macro (git_log_format FORMAT_CHARS VAR_NAME)
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} log -1 --pretty=format:%${FORMAT_CHARS}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE ${VAR_NAME}
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
endmacro()
|
||||
|
||||
git_log_format(an GIT_AUTHOR_EMAIL)
|
||||
git_log_format(ae GIT_AUTHOR_EMAIL)
|
||||
git_log_format(cn GIT_COMMITTER_NAME)
|
||||
git_log_format(ce GIT_COMMITTER_EMAIL)
|
||||
git_log_format(B GIT_COMMIT_MESSAGE)
|
||||
|
||||
message("Git exe: ${GIT_EXECUTABLE}")
|
||||
message("Git branch: ${GIT_BRANCH}")
|
||||
message("Git author: ${GIT_AUTHOR_NAME}")
|
||||
message("Git e-mail: ${GIT_AUTHOR_EMAIL}")
|
||||
message("Git commiter name: ${GIT_COMMITTER_NAME}")
|
||||
message("Git commiter e-mail: ${GIT_COMMITTER_EMAIL}")
|
||||
message("Git commit message: ${GIT_COMMIT_MESSAGE}")
|
||||
|
||||
endif()
|
||||
|
||||
############################# Macros #########################################
|
||||
|
||||
#
|
||||
# This macro converts from the full path format gcov outputs:
|
||||
#
|
||||
# /path/to/project/root/build/#path#to#project#root#subdir#the_file.c.gcov
|
||||
#
|
||||
# to the original source file path the .gcov is for:
|
||||
#
|
||||
# /path/to/project/root/subdir/the_file.c
|
||||
#
|
||||
macro(get_source_path_from_gcov_filename _SRC_FILENAME _GCOV_FILENAME)
|
||||
|
||||
# /path/to/project/root/build/#path#to#project#root#subdir#the_file.c.gcov
|
||||
# ->
|
||||
# #path#to#project#root#subdir#the_file.c.gcov
|
||||
get_filename_component(_GCOV_FILENAME_WEXT ${_GCOV_FILENAME} NAME)
|
||||
|
||||
# #path#to#project#root#subdir#the_file.c.gcov -> /path/to/project/root/subdir/the_file.c
|
||||
string(REGEX REPLACE "\\.gcov$" "" SRC_FILENAME_TMP ${_GCOV_FILENAME_WEXT})
|
||||
string(REGEX REPLACE "\#" "/" SRC_FILENAME_TMP ${SRC_FILENAME_TMP})
|
||||
set(${_SRC_FILENAME} "${SRC_FILENAME_TMP}")
|
||||
endmacro()
|
||||
|
||||
##############################################################################
|
||||
|
||||
# Get the coverage data.
|
||||
file(GLOB_RECURSE GCDA_FILES "${COV_PATH}/*.gcda")
|
||||
message("GCDA files:")
|
||||
|
||||
# Get a list of all the object directories needed by gcov
|
||||
# (The directories the .gcda files and .o files are found in)
|
||||
# and run gcov on those.
|
||||
foreach(GCDA ${GCDA_FILES})
|
||||
message("Process: ${GCDA}")
|
||||
message("------------------------------------------------------------------------------")
|
||||
get_filename_component(GCDA_DIR ${GCDA} PATH)
|
||||
|
||||
#
|
||||
# The -p below refers to "Preserve path components",
|
||||
# This means that the generated gcov filename of a source file will
|
||||
# keep the original files entire filepath, but / is replaced with #.
|
||||
# Example:
|
||||
#
|
||||
# /path/to/project/root/build/CMakeFiles/the_file.dir/subdir/the_file.c.gcda
|
||||
# ------------------------------------------------------------------------------
|
||||
# File '/path/to/project/root/subdir/the_file.c'
|
||||
# Lines executed:68.34% of 199
|
||||
# /path/to/project/root/subdir/the_file.c:creating '#path#to#project#root#subdir#the_file.c.gcov'
|
||||
#
|
||||
# If -p is not specified then the file is named only "the_file.c.gcov"
|
||||
#
|
||||
execute_process(
|
||||
COMMAND ${GCOV_EXECUTABLE} -p -o ${GCDA_DIR} ${GCDA}
|
||||
WORKING_DIRECTORY ${COV_PATH}
|
||||
)
|
||||
endforeach()
|
||||
|
||||
# TODO: Make these be absolute path
|
||||
file(GLOB ALL_GCOV_FILES ${COV_PATH}/*.gcov)
|
||||
|
||||
# Get only the filenames to use for filtering.
|
||||
#set(COVERAGE_SRCS_NAMES "")
|
||||
#foreach (COVSRC ${COVERAGE_SRCS})
|
||||
# get_filename_component(COVSRC_NAME ${COVSRC} NAME)
|
||||
# message("${COVSRC} -> ${COVSRC_NAME}")
|
||||
# list(APPEND COVERAGE_SRCS_NAMES "${COVSRC_NAME}")
|
||||
#endforeach()
|
||||
|
||||
#
|
||||
# Filter out all but the gcov files we want.
|
||||
#
|
||||
# We do this by comparing the list of COVERAGE_SRCS filepaths that the
|
||||
# user wants the coverage data for with the paths of the generated .gcov files,
|
||||
# so that we only keep the relevant gcov files.
|
||||
#
|
||||
# Example:
|
||||
# COVERAGE_SRCS =
|
||||
# /path/to/project/root/subdir/the_file.c
|
||||
#
|
||||
# ALL_GCOV_FILES =
|
||||
# /path/to/project/root/build/#path#to#project#root#subdir#the_file.c.gcov
|
||||
# /path/to/project/root/build/#path#to#project#root#subdir#other_file.c.gcov
|
||||
#
|
||||
# Result should be:
|
||||
# GCOV_FILES =
|
||||
# /path/to/project/root/build/#path#to#project#root#subdir#the_file.c.gcov
|
||||
#
|
||||
set(GCOV_FILES "")
|
||||
#message("Look in coverage sources: ${COVERAGE_SRCS}")
|
||||
message("\nFilter out unwanted GCOV files:")
|
||||
message("===============================")
|
||||
|
||||
set(COVERAGE_SRCS_REMAINING ${COVERAGE_SRCS})
|
||||
|
||||
foreach (GCOV_FILE ${ALL_GCOV_FILES})
|
||||
|
||||
#
|
||||
# /path/to/project/root/build/#path#to#project#root#subdir#the_file.c.gcov
|
||||
# ->
|
||||
# /path/to/project/root/subdir/the_file.c
|
||||
get_source_path_from_gcov_filename(GCOV_SRC_PATH ${GCOV_FILE})
|
||||
|
||||
# Is this in the list of source files?
|
||||
# TODO: We want to match against relative path filenames from the source file root...
|
||||
list(FIND COVERAGE_SRCS ${GCOV_SRC_PATH} WAS_FOUND)
|
||||
|
||||
if (NOT WAS_FOUND EQUAL -1)
|
||||
message("YES: ${GCOV_FILE}")
|
||||
list(APPEND GCOV_FILES ${GCOV_FILE})
|
||||
|
||||
# We remove it from the list, so we don't bother searching for it again.
|
||||
# Also files left in COVERAGE_SRCS_REMAINING after this loop ends should
|
||||
# have coverage data generated from them (no lines are covered).
|
||||
list(REMOVE_ITEM COVERAGE_SRCS_REMAINING ${GCOV_SRC_PATH})
|
||||
else()
|
||||
message("NO: ${GCOV_FILE}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# TODO: Enable setting these
|
||||
set(JSON_SERVICE_NAME "travis-ci")
|
||||
set(JSON_SERVICE_JOB_ID $ENV{TRAVIS_JOB_ID})
|
||||
|
||||
set(JSON_TEMPLATE
|
||||
"{
|
||||
\"service_name\": \"\@JSON_SERVICE_NAME\@\",
|
||||
\"service_job_id\": \"\@JSON_SERVICE_JOB_ID\@\",
|
||||
\"source_files\": \@JSON_GCOV_FILES\@
|
||||
}"
|
||||
)
|
||||
|
||||
set(SRC_FILE_TEMPLATE
|
||||
"{
|
||||
\"name\": \"\@GCOV_SRC_REL_PATH\@\",
|
||||
\"source\": \"\@GCOV_FILE_SOURCE\@\",
|
||||
\"coverage\": \@GCOV_FILE_COVERAGE\@
|
||||
}"
|
||||
)
|
||||
|
||||
message("\nGenerate JSON for files:")
|
||||
message("=========================")
|
||||
|
||||
set(JSON_GCOV_FILES "[")
|
||||
|
||||
# Read the GCOV files line by line and get the coverage data.
|
||||
foreach (GCOV_FILE ${GCOV_FILES})
|
||||
|
||||
get_source_path_from_gcov_filename(GCOV_SRC_PATH ${GCOV_FILE})
|
||||
file(RELATIVE_PATH GCOV_SRC_REL_PATH "${PROJECT_ROOT}" "${GCOV_SRC_PATH}")
|
||||
|
||||
# Loads the gcov file as a list of lines.
|
||||
file(STRINGS ${GCOV_FILE} GCOV_LINES)
|
||||
|
||||
# Instead of trying to parse the source from the
|
||||
# gcov file, simply read the file contents from the source file.
|
||||
# (Parsing it from the gcov is hard because C-code uses ; in many places
|
||||
# which also happens to be the same as the CMake list delimeter).
|
||||
file(READ ${GCOV_SRC_PATH} GCOV_FILE_SOURCE)
|
||||
|
||||
string(REPLACE "\\" "\\\\" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
|
||||
string(REGEX REPLACE "\"" "\\\\\"" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
|
||||
string(REPLACE "\t" "\\\\t" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
|
||||
string(REPLACE "\r" "\\\\r" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
|
||||
string(REPLACE "\n" "\\\\n" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
|
||||
# According to http://json.org/ these should be escaped as well.
|
||||
# Don't know how to do that in CMake however...
|
||||
#string(REPLACE "\b" "\\\\b" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
|
||||
#string(REPLACE "\f" "\\\\f" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
|
||||
#string(REGEX REPLACE "\u([a-fA-F0-9]{4})" "\\\\u\\1" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
|
||||
|
||||
# We want a json array of coverage data as a single string
|
||||
# start building them from the contents of the .gcov
|
||||
set(GCOV_FILE_COVERAGE "[")
|
||||
|
||||
foreach (GCOV_LINE ${GCOV_LINES})
|
||||
# Example of what we're parsing:
|
||||
# Hitcount |Line | Source
|
||||
# " 8: 26: if (!allowed || (strlen(allowed) == 0))"
|
||||
string(REGEX REPLACE
|
||||
"^([^:]*):([^:]*):(.*)$"
|
||||
"\\1;\\2;\\3"
|
||||
RES
|
||||
"${GCOV_LINE}")
|
||||
|
||||
list(LENGTH RES RES_COUNT)
|
||||
if (RES_COUNT GREATER 2)
|
||||
list(GET RES 0 HITCOUNT)
|
||||
list(GET RES 1 LINE)
|
||||
list(GET RES 2 SOURCE)
|
||||
|
||||
string(STRIP ${HITCOUNT} HITCOUNT)
|
||||
string(STRIP ${LINE} LINE)
|
||||
|
||||
# Lines with 0 line numbers are metadata and can be ignored.
|
||||
if (NOT ${LINE} EQUAL 0)
|
||||
|
||||
# Translate the hitcount into valid JSON values.
|
||||
if (${HITCOUNT} STREQUAL "#####")
|
||||
set(GCOV_FILE_COVERAGE "${GCOV_FILE_COVERAGE}0, ")
|
||||
elseif (${HITCOUNT} STREQUAL "-")
|
||||
set(GCOV_FILE_COVERAGE "${GCOV_FILE_COVERAGE}null, ")
|
||||
else()
|
||||
set(GCOV_FILE_COVERAGE "${GCOV_FILE_COVERAGE}${HITCOUNT}, ")
|
||||
endif()
|
||||
# TODO: Look for LCOV_EXCL_LINE in SOURCE to get rid of false positives.
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "Failed to properly parse line --> ${GCOV_LINE}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Advanced way of removing the trailing comma in the JSON array.
|
||||
# "[1, 2, 3, " -> "[1, 2, 3"
|
||||
string(REGEX REPLACE ",[ ]*$" "" GCOV_FILE_COVERAGE ${GCOV_FILE_COVERAGE})
|
||||
|
||||
# Append the trailing ] to complete the JSON array.
|
||||
set(GCOV_FILE_COVERAGE "${GCOV_FILE_COVERAGE}]")
|
||||
|
||||
# Generate the final JSON for this file.
|
||||
message("Generate JSON for file: ${GCOV_SRC_REL_PATH}...")
|
||||
string(CONFIGURE ${SRC_FILE_TEMPLATE} FILE_JSON)
|
||||
|
||||
set(JSON_GCOV_FILES "${JSON_GCOV_FILES}${FILE_JSON}, ")
|
||||
endforeach()
|
||||
|
||||
# Loop through all files we couldn't find any coverage for
|
||||
# as well, and generate JSON for those as well with 0% coverage.
|
||||
foreach(NOT_COVERED_SRC ${COVERAGE_SRCS_REMAINING})
|
||||
|
||||
# Loads the source file as a list of lines.
|
||||
file(STRINGS ${NOT_COVERED_SRC} SRC_LINES)
|
||||
|
||||
set(GCOV_FILE_COVERAGE "[")
|
||||
set(GCOV_FILE_SOURCE "")
|
||||
|
||||
foreach (SOURCE ${SRC_LINES})
|
||||
set(GCOV_FILE_COVERAGE "${GCOV_FILE_COVERAGE}0, ")
|
||||
|
||||
string(REPLACE "\\" "\\\\" SOURCE "${SOURCE}")
|
||||
string(REGEX REPLACE "\"" "\\\\\"" SOURCE "${SOURCE}")
|
||||
string(REPLACE "\t" "\\\\t" SOURCE "${SOURCE}")
|
||||
string(REPLACE "\r" "\\\\r" SOURCE "${SOURCE}")
|
||||
set(GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}${SOURCE}\\n")
|
||||
endforeach()
|
||||
|
||||
# Remove trailing comma, and complete JSON array with ]
|
||||
string(REGEX REPLACE ",[ ]*$" "" GCOV_FILE_COVERAGE ${GCOV_FILE_COVERAGE})
|
||||
set(GCOV_FILE_COVERAGE "${GCOV_FILE_COVERAGE}]")
|
||||
|
||||
# Generate the final JSON for this file.
|
||||
message("Generate JSON for non-gcov file: ${NOT_COVERED_SRC}...")
|
||||
string(CONFIGURE ${SRC_FILE_TEMPLATE} FILE_JSON)
|
||||
set(JSON_GCOV_FILES "${JSON_GCOV_FILES}${FILE_JSON}, ")
|
||||
endforeach()
|
||||
|
||||
# Get rid of trailing comma.
|
||||
string(REGEX REPLACE ",[ ]*$" "" JSON_GCOV_FILES ${JSON_GCOV_FILES})
|
||||
set(JSON_GCOV_FILES "${JSON_GCOV_FILES}]")
|
||||
|
||||
# Generate the final complete JSON!
|
||||
message("Generate final JSON...")
|
||||
string(CONFIGURE ${JSON_TEMPLATE} JSON)
|
||||
|
||||
file(WRITE "${COVERALLS_OUTPUT_FILE}" "${JSON}")
|
||||
message("###########################################################################")
|
||||
message("Generated coveralls JSON containing coverage data:")
|
||||
message("${COVERALLS_OUTPUT_FILE}")
|
||||
message("###########################################################################")
|
||||
|
|
@ -1,17 +1,4 @@
|
|||
# - Config file for the jansson package
|
||||
# It defines the following variables
|
||||
# JANSSON_INCLUDE_DIRS - include directories for FooBar
|
||||
# JANSSON_LIBRARIES - libraries to link against
|
||||
|
||||
# Get the path of the current file.
|
||||
get_filename_component(JANSSON_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
||||
|
||||
# Set the include directories.
|
||||
set(JANSSON_INCLUDE_DIRS "@JANSSON__INCLUDE_DIRS@")
|
||||
|
||||
# Include the project Targets file, this contains definitions for IMPORTED targets.
|
||||
include(${JANSSON_CMAKE_DIR}/JanssonTargets.cmake)
|
||||
|
||||
# IMPORTED targets from JanssonTargets.cmake
|
||||
set(JANSSON_LIBRARIES jansson)
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/janssonTargets.cmake")
|
||||
check_required_components("@PROJECT_NAME@")
|
||||
|
|
|
@ -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 @JSON_HAVE_LOCALECONV@
|
||||
|
||||
/* If __atomic builtins are available they will be used to manage
|
||||
reference counts of json_t. */
|
||||
#define JSON_HAVE_ATOMIC_BUILTINS @JSON_HAVE_ATOMIC_BUILTINS@
|
||||
|
||||
/* If __atomic builtins are not available we try using __sync builtins
|
||||
to manage reference counts of json_t. */
|
||||
#define JSON_HAVE_SYNC_BUILTINS @JSON_HAVE_SYNC_BUILTINS@
|
||||
|
||||
/* 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
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
# define snprintf @JSON_SNPRINTF@
|
||||
#endif
|
||||
|
||||
#cmakedefine HAVE_VSNPRINTF
|
||||
|
||||
#cmakedefine USE_URANDOM 1
|
||||
#cmakedefine USE_WINDOWS_CRYPTOAPI 1
|
||||
|
||||
#define INITIAL_HASHTABLE_ORDER @JANSSON_INITIAL_HASHTABLE_ORDER@
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
AC_PREREQ([2.60])
|
||||
AC_INIT([jansson], [2.6], [petri@digip.org])
|
||||
AC_INIT([jansson], [2.12], [petri@digip.org])
|
||||
|
||||
AC_CONFIG_AUX_DIR([.])
|
||||
AM_INIT_AUTOMAKE([1.10 foreign])
|
||||
|
||||
AC_CONFIG_SRCDIR([src/value.c])
|
||||
|
@ -37,25 +38,33 @@ AC_CHECK_FUNCS([close getpid gettimeofday localeconv open read sched_yield strto
|
|||
AC_MSG_CHECKING([for gcc __sync builtins])
|
||||
have_sync_builtins=no
|
||||
AC_TRY_LINK(
|
||||
[], [unsigned long val; __sync_bool_compare_and_swap(&val, 0, 1);],
|
||||
[], [unsigned long val; __sync_bool_compare_and_swap(&val, 0, 1); __sync_add_and_fetch(&val, 1); __sync_sub_and_fetch(&val, 1);],
|
||||
[have_sync_builtins=yes],
|
||||
)
|
||||
if test "x$have_sync_builtins" = "xyes"; then
|
||||
AC_DEFINE([HAVE_SYNC_BUILTINS], [1],
|
||||
[Define to 1 if gcc's __sync builtins are available])
|
||||
json_have_sync_builtins=1
|
||||
else
|
||||
json_have_sync_builtins=0
|
||||
fi
|
||||
AC_SUBST([json_have_sync_builtins])
|
||||
AC_MSG_RESULT([$have_sync_builtins])
|
||||
|
||||
AC_MSG_CHECKING([for gcc __atomic builtins])
|
||||
have_atomic_builtins=no
|
||||
AC_TRY_LINK(
|
||||
[], [char l; unsigned long v; __atomic_test_and_set(&l, __ATOMIC_RELAXED); __atomic_store_n(&v, 1, __ATOMIC_RELEASE); __atomic_load_n(&v, __ATOMIC_ACQUIRE);],
|
||||
[], [char l; unsigned long v; __atomic_test_and_set(&l, __ATOMIC_RELAXED); __atomic_store_n(&v, 1, __ATOMIC_RELEASE); __atomic_load_n(&v, __ATOMIC_ACQUIRE); __atomic_add_fetch(&v, 1, __ATOMIC_ACQUIRE); __atomic_sub_fetch(&v, 1, __ATOMIC_RELEASE);],
|
||||
[have_atomic_builtins=yes],
|
||||
)
|
||||
if test "x$have_atomic_builtins" = "xyes"; then
|
||||
AC_DEFINE([HAVE_ATOMIC_BUILTINS], [1],
|
||||
[Define to 1 if gcc's __atomic builtins are available])
|
||||
json_have_atomic_builtins=1
|
||||
else
|
||||
json_have_atomic_builtins=0
|
||||
fi
|
||||
AC_SUBST([json_have_atomic_builtins])
|
||||
AC_MSG_RESULT([$have_atomic_builtins])
|
||||
|
||||
case "$ac_cv_type_long_long_int$ac_cv_func_strtoll" in
|
||||
|
@ -91,6 +100,54 @@ AC_DEFINE([USE_WINDOWS_CRYPTOAPI], [1],
|
|||
[Define to 1 if CryptGenRandom should be used for seeding the hash function])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE([initial-hashtable-order],
|
||||
[AS_HELP_STRING([--enable-initial-hashtable-order=VAL],
|
||||
[Number of buckets new object hashtables contain is 2 raised to this power. The default is 3, so empty hashtables contain 2^3 = 8 buckets.])],
|
||||
[initial_hashtable_order=$enableval], [initial_hashtable_order=3])
|
||||
AC_DEFINE_UNQUOTED([INITIAL_HASHTABLE_ORDER], [$initial_hashtable_order],
|
||||
[Number of buckets new object hashtables contain is 2 raised to this power. E.g. 3 -> 2^3 = 8.])
|
||||
|
||||
AC_ARG_ENABLE([Bsymbolic],
|
||||
[AS_HELP_STRING([--disable-Bsymbolic],
|
||||
[Avoid linking with -Bsymbolic-function])],
|
||||
[], [with_Bsymbolic=check])
|
||||
|
||||
if test "x$with_Bsymbolic" != "xno" ; then
|
||||
AC_MSG_CHECKING([for -Bsymbolic-functions linker flag])
|
||||
saved_LDFLAGS="${LDFLAGS}"
|
||||
LDFLAGS=-Wl,-Bsymbolic-functions
|
||||
AC_TRY_LINK(
|
||||
[], [int main (void) { return 0; }],
|
||||
[AC_MSG_RESULT([yes])
|
||||
have_Bsymbolic=yes],
|
||||
[AC_MSG_RESULT([no])
|
||||
have_Bsymbolic=no]
|
||||
)
|
||||
LDFLAGS="${saved_LDFLAGS}"
|
||||
|
||||
if test "x$with_Bsymbolic" = "xcheck" ; then
|
||||
with_Bsymbolic=$have_Bsymbolic;
|
||||
fi
|
||||
if test "x$with_Bsymbolic:x$have_Bsymbolic" = "xyes:xno" ; then
|
||||
AC_MSG_ERROR([linker support is required for -Bsymbolic])
|
||||
fi
|
||||
fi
|
||||
|
||||
AS_IF([test "x$with_Bsymbolic" = "xyes"], [JSON_BSYMBOLIC_LDFLAGS=-Wl[,]-Bsymbolic-functions])
|
||||
AC_SUBST(JSON_BSYMBOLIC_LDFLAGS)
|
||||
|
||||
if test x$GCC = xyes; then
|
||||
AC_MSG_CHECKING(for -Wno-format-truncation)
|
||||
wnoformat_truncation="-Wno-format-truncation"
|
||||
AS_IF([${CC} -Wno-format-truncation -Werror -S -o /dev/null -xc /dev/null > /dev/null 2>&1],
|
||||
[AC_MSG_RESULT(yes)],
|
||||
[AC_MSG_RESULT(no)
|
||||
wnoformat_truncation=""])
|
||||
|
||||
AM_CFLAGS="-Wall -Wextra -Wdeclaration-after-statement -Wshadow ${wnoformat_truncation}"
|
||||
fi
|
||||
AC_SUBST([AM_CFLAGS])
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
jansson.pc
|
||||
Makefile
|
||||
|
|
|
@ -52,12 +52,17 @@ the library:
|
|||
``JANSSON_VERSION_HEX``
|
||||
A 3-byte hexadecimal representation of the version, e.g.
|
||||
``0x010201`` for version 1.2.1 and ``0x010300`` for version 1.3.
|
||||
This is useful in numeric comparisions, e.g.::
|
||||
This is useful in numeric comparisons, e.g.::
|
||||
|
||||
#if JANSSON_VERSION_HEX >= 0x010300
|
||||
/* Code specific to version 1.3 and above */
|
||||
#endif
|
||||
|
||||
``JANSSON_THREAD_SAFE_REFCOUNT``
|
||||
If this value is defined all read-only operations and reference counting in
|
||||
Jansson are thread safe. This value is not defined for versions older than
|
||||
``2.11`` or when the compiler does not provide built-in atomic functions.
|
||||
|
||||
|
||||
Value Representation
|
||||
====================
|
||||
|
@ -90,9 +95,6 @@ also cause errors.
|
|||
Type
|
||||
----
|
||||
|
||||
The type of a JSON value is queried and tested using the following
|
||||
functions:
|
||||
|
||||
.. type:: enum json_type
|
||||
|
||||
The type of a JSON value. The following members are defined:
|
||||
|
@ -155,6 +157,8 @@ functions:
|
|||
Alias of :func:`json_is_true()`, i.e. returns 1 for ``JSON_TRUE``
|
||||
and 0 otherwise.
|
||||
|
||||
.. versionadded:: 2.7
|
||||
|
||||
|
||||
.. _apiref-reference-count:
|
||||
|
||||
|
@ -169,8 +173,6 @@ no longer needed, the reference count is decremented. When the
|
|||
reference count drops to zero, there are no references left, and the
|
||||
value can be destroyed.
|
||||
|
||||
The following functions are used to manipulate the reference count.
|
||||
|
||||
.. function:: json_t *json_incref(json_t *json)
|
||||
|
||||
Increment the reference count of *json* if it's not *NULL*.
|
||||
|
@ -256,6 +258,26 @@ other. Moreover, trying to encode the values with any of the encoding
|
|||
functions will fail. The encoder detects circular references and
|
||||
returns an error status.
|
||||
|
||||
Scope Dereferencing
|
||||
-------------------
|
||||
|
||||
.. versionadded:: 2.9
|
||||
|
||||
It is possible to use the ``json_auto_t`` type to automatically
|
||||
dereference a value at the end of a scope. For example::
|
||||
|
||||
void function(void) {
|
||||
json_auto_t *value = NULL;
|
||||
value = json_string("foo");
|
||||
/* json_decref(value) is automatically called. */
|
||||
}
|
||||
|
||||
This feature is only available on GCC and Clang. So if your project
|
||||
has a portability requirement for other compilers, you should avoid
|
||||
this feature.
|
||||
|
||||
Additionally, as always, care should be taken when passing values to
|
||||
functions that steal references.
|
||||
|
||||
True, False and Null
|
||||
====================
|
||||
|
@ -297,18 +319,16 @@ String
|
|||
======
|
||||
|
||||
Jansson uses UTF-8 as the character encoding. All JSON strings must be
|
||||
valid UTF-8 (or ASCII, as it's a subset of UTF-8). Normal null
|
||||
terminated C strings are used, so JSON strings may not contain
|
||||
embedded null characters. All other Unicode codepoints U+0000 through
|
||||
U+10FFFF are allowed, but you must use length-aware functions if you
|
||||
wish to embed NUL bytes in strings.
|
||||
valid UTF-8 (or ASCII, as it's a subset of UTF-8). All Unicode
|
||||
codepoints U+0000 through U+10FFFF are allowed, but you must use
|
||||
length-aware functions if you wish to embed null bytes in strings.
|
||||
|
||||
.. function:: json_t *json_string(const char *value)
|
||||
|
||||
.. refcounting:: new
|
||||
|
||||
Returns a new JSON string, or *NULL* on error. *value* must be a
|
||||
valid UTF-8 encoded Unicode string.
|
||||
valid null terminated UTF-8 encoded Unicode string.
|
||||
|
||||
.. function:: json_t *json_stringn(const char *value, size_t len)
|
||||
|
||||
|
@ -317,6 +337,8 @@ wish to embed NUL bytes in strings.
|
|||
Like :func:`json_string`, but with explicit length, so *value* may
|
||||
contain null characters or not be null terminated.
|
||||
|
||||
.. versionadded:: 2.7
|
||||
|
||||
.. function:: json_t *json_string_nocheck(const char *value)
|
||||
|
||||
.. refcounting:: new
|
||||
|
@ -332,12 +354,14 @@ wish to embed NUL bytes in strings.
|
|||
Like :func:`json_string_nocheck`, but with explicit length, so
|
||||
*value* may contain null characters or not be null terminated.
|
||||
|
||||
.. versionadded:: 2.7
|
||||
|
||||
.. function:: const char *json_string_value(const json_t *string)
|
||||
|
||||
Returns the associated value of *string* as a null terminated UTF-8
|
||||
encoded string, or *NULL* if *string* is not a JSON string.
|
||||
|
||||
The retuned value is read-only and must not be modified or freed by
|
||||
The returned value is read-only and must not be modified or freed by
|
||||
the user. It is valid as long as *string* exists, i.e. as long as
|
||||
its reference count has not dropped to zero.
|
||||
|
||||
|
@ -346,7 +370,9 @@ wish to embed NUL bytes in strings.
|
|||
Returns the length of *string* in its UTF-8 presentation, or zero
|
||||
if *string* is not a JSON string.
|
||||
|
||||
.. function:: int json_string_set(const json_t *string, const char *value)
|
||||
.. versionadded:: 2.7
|
||||
|
||||
.. function:: int json_string_set(json_t *string, const char *value)
|
||||
|
||||
Sets the associated value of *string* to *value*. *value* must be a
|
||||
valid UTF-8 encoded Unicode string. Returns 0 on success and -1 on
|
||||
|
@ -357,7 +383,9 @@ wish to embed NUL bytes in strings.
|
|||
Like :func:`json_string_set`, but with explicit length, so *value*
|
||||
may contain null characters or not be null terminated.
|
||||
|
||||
.. function:: int json_string_set_nocheck(const json_t *string, const char *value)
|
||||
.. versionadded:: 2.7
|
||||
|
||||
.. function:: int json_string_set_nocheck(json_t *string, const char *value)
|
||||
|
||||
Like :func:`json_string_set`, but doesn't check that *value* is
|
||||
valid UTF-8. Use this function only if you are certain that this
|
||||
|
@ -369,6 +397,18 @@ wish to embed NUL bytes in strings.
|
|||
Like :func:`json_string_set_nocheck`, but with explicit length,
|
||||
so *value* may contain null characters or not be null terminated.
|
||||
|
||||
.. versionadded:: 2.7
|
||||
|
||||
.. function:: json_t *json_sprintf(const char *format, ...)
|
||||
json_t *json_vsprintf(const char *format, va_list ap)
|
||||
|
||||
.. refcounting:: new
|
||||
|
||||
Construct a JSON string from a format string and varargs, just like
|
||||
:func:`printf()`.
|
||||
|
||||
.. versionadded:: 2.11
|
||||
|
||||
|
||||
Number
|
||||
======
|
||||
|
@ -407,7 +447,7 @@ information, see :ref:`rfc-conformance`.
|
|||
specifier that corresponds to :type:`json_int_t`, without the
|
||||
leading ``%`` sign, i.e. either ``"lld"`` or ``"ld"``. This macro
|
||||
is required because the actual type of :type:`json_int_t` can be
|
||||
either ``long`` or ``long long``, and :func:`printf()` reuiqres
|
||||
either ``long`` or ``long long``, and :func:`printf()` requires
|
||||
different length modifiers for the two.
|
||||
|
||||
Example::
|
||||
|
@ -448,9 +488,6 @@ information, see :ref:`rfc-conformance`.
|
|||
Sets the associated value of *real* to *value*. Returns 0 on
|
||||
success and -1 if *real* is not a JSON real.
|
||||
|
||||
In addition to the functions above, there's a common query function
|
||||
for integers and reals:
|
||||
|
||||
.. function:: double json_number_value(const json_t *json)
|
||||
|
||||
Returns the associated value of the JSON integer or JSON real
|
||||
|
@ -530,7 +567,7 @@ A JSON array is an ordered collection of other JSON values.
|
|||
|
||||
.. function:: int json_array_clear(json_t *array)
|
||||
|
||||
Removes all elements from *array*. Returns 0 on sucess and -1 on
|
||||
Removes all elements from *array*. Returns 0 on success and -1 on
|
||||
error. The reference count of all removed values are decremented.
|
||||
|
||||
.. function:: int json_array_extend(json_t *array, json_t *other_array)
|
||||
|
@ -538,9 +575,6 @@ A JSON array is an ordered collection of other JSON values.
|
|||
Appends all elements in *other_array* to the end of *array*.
|
||||
Returns 0 on success and -1 on error.
|
||||
|
||||
The following macro can be used to iterate through all elements
|
||||
in an array.
|
||||
|
||||
.. function:: json_array_foreach(array, index, value)
|
||||
|
||||
Iterate over every element of ``array``, running the block
|
||||
|
@ -562,8 +596,7 @@ in an array.
|
|||
preprocessing, so its performance is equivalent to that of
|
||||
hand-written code using the array access functions.
|
||||
The main advantage of this macro is that it abstracts
|
||||
away the complexity, and makes for shorter, more
|
||||
concise code.
|
||||
away the complexity, and makes for more concise and readable code.
|
||||
|
||||
.. versionadded:: 2.5
|
||||
|
||||
|
@ -574,7 +607,7 @@ Object
|
|||
A JSON object is a dictionary of key-value pairs, where the key is a
|
||||
Unicode string and the value is any JSON value.
|
||||
|
||||
Even though NUL bytes are allowed in string values, they are not
|
||||
Even though null bytes are allowed in string values, they are not
|
||||
allowed in object keys.
|
||||
|
||||
.. function:: json_t *json_object(void)
|
||||
|
@ -656,9 +689,6 @@ allowed in object keys.
|
|||
|
||||
.. versionadded:: 2.3
|
||||
|
||||
The following macro can be used to iterate through all key-value pairs
|
||||
in an object.
|
||||
|
||||
.. function:: json_object_foreach(object, key, value)
|
||||
|
||||
Iterate over every key-value pair of ``object``, running the block
|
||||
|
@ -674,22 +704,35 @@ in an object.
|
|||
/* block of code that uses key and value */
|
||||
}
|
||||
|
||||
The items are not returned in any particular order.
|
||||
The items are returned in the order they were inserted to the
|
||||
object.
|
||||
|
||||
**Note:** It's not safe to call ``json_object_del(object, key)``
|
||||
during iteration. If you need to, use
|
||||
:func:`json_object_foreach_safe` instead.
|
||||
|
||||
This macro expands to an ordinary ``for`` statement upon
|
||||
preprocessing, so its performance is equivalent to that of
|
||||
hand-written iteration code using the object iteration protocol
|
||||
(see below). The main advantage of this macro is that it abstracts
|
||||
away the complexity behind iteration, and makes for shorter, more
|
||||
concise code.
|
||||
away the complexity behind iteration, and makes for more concise and
|
||||
readable code.
|
||||
|
||||
.. versionadded:: 2.3
|
||||
|
||||
|
||||
The following functions implement an iteration protocol for objects,
|
||||
allowing to iterate through all key-value pairs in an object. The
|
||||
items are not returned in any particular order, as this would require
|
||||
sorting due to the internal hashtable implementation.
|
||||
.. function:: json_object_foreach_safe(object, tmp, key, value)
|
||||
|
||||
Like :func:`json_object_foreach()`, but it's safe to call
|
||||
``json_object_del(object, key)`` during iteration. You need to pass
|
||||
an extra ``void *`` parameter ``tmp`` that is used for temporary storage.
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
|
||||
The following functions can be used to iterate through all key-value
|
||||
pairs in an object. The items are returned in the order they were
|
||||
inserted to the object.
|
||||
|
||||
.. function:: void *json_object_iter(json_t *object)
|
||||
|
||||
|
@ -736,32 +779,30 @@ sorting due to the internal hashtable implementation.
|
|||
Like :func:`json_object_iter_at()`, but much faster. Only works for
|
||||
values returned by :func:`json_object_iter_key()`. Using other keys
|
||||
will lead to segfaults. This function is used internally to
|
||||
implement :func:`json_object_foreach`.
|
||||
implement :func:`json_object_foreach`. Example::
|
||||
|
||||
/* obj is a JSON object */
|
||||
const char *key;
|
||||
json_t *value;
|
||||
|
||||
void *iter = json_object_iter(obj);
|
||||
while(iter)
|
||||
{
|
||||
key = json_object_iter_key(iter);
|
||||
value = json_object_iter_value(iter);
|
||||
/* use key and value ... */
|
||||
iter = json_object_iter_next(obj, iter);
|
||||
}
|
||||
|
||||
.. versionadded:: 2.3
|
||||
|
||||
The iteration protocol can be used for example as follows::
|
||||
|
||||
/* obj is a JSON object */
|
||||
const char *key;
|
||||
json_t *value;
|
||||
|
||||
void *iter = json_object_iter(obj);
|
||||
while(iter)
|
||||
{
|
||||
key = json_object_iter_key(iter);
|
||||
value = json_object_iter_value(iter);
|
||||
/* use key and value ... */
|
||||
iter = json_object_iter_next(obj, iter);
|
||||
}
|
||||
|
||||
.. function:: void json_object_seed(size_t seed)
|
||||
|
||||
Seed the hash function used in Jansson's hashtable implementation.
|
||||
The seed is used to randomize the hash function so that an
|
||||
attacker cannot control its output.
|
||||
|
||||
If *seed* is 0, Jansson generates the seed itselfy by reading
|
||||
If *seed* is 0, Jansson generates the seed itself by reading
|
||||
random data from the operating system's entropy sources. If no
|
||||
entropy sources are available, falls back to using a combination
|
||||
of the current timestamp (with microsecond precision if possible)
|
||||
|
@ -797,10 +838,13 @@ this struct.
|
|||
The error message (in UTF-8), or an empty string if a message is
|
||||
not available.
|
||||
|
||||
The last byte of this array contains a numeric error code. Use
|
||||
:func:`json_error_code()` to extract this code.
|
||||
|
||||
.. member:: char source[]
|
||||
|
||||
Source of the error. This can be (a part of) the file name or a
|
||||
special identifier in angle brackers (e.g. ``<string>``).
|
||||
special identifier in angle brackets (e.g. ``<string>``).
|
||||
|
||||
.. member:: int line
|
||||
|
||||
|
@ -812,7 +856,7 @@ this struct.
|
|||
*character column*, not the byte column, i.e. a multibyte UTF-8
|
||||
character counts as one column.
|
||||
|
||||
.. member:: size_t position
|
||||
.. member:: int position
|
||||
|
||||
The position in bytes from the start of the input. This is
|
||||
useful for debugging Unicode encoding problems.
|
||||
|
@ -839,6 +883,97 @@ success. See :ref:`apiref-decoding` for more info.
|
|||
All functions also accept *NULL* as the :type:`json_error_t` pointer,
|
||||
in which case no error information is returned to the caller.
|
||||
|
||||
.. type:: enum json_error_code
|
||||
|
||||
An enumeration containing numeric error codes. The following errors are
|
||||
currently defined:
|
||||
|
||||
``json_error_unknown``
|
||||
|
||||
Unknown error. This should only be returned for non-errorneous
|
||||
:type:`json_error_t` structures.
|
||||
|
||||
``json_error_out_of_memory``
|
||||
|
||||
The library couldn’t allocate any heap memory.
|
||||
|
||||
``json_error_stack_overflow``
|
||||
|
||||
Nesting too deep.
|
||||
|
||||
``json_error_cannot_open_file``
|
||||
|
||||
Couldn’t open input file.
|
||||
|
||||
``json_error_invalid_argument``
|
||||
|
||||
A function argument was invalid.
|
||||
|
||||
``json_error_invalid_utf8``
|
||||
|
||||
The input string isn’t valid UTF-8.
|
||||
|
||||
``json_error_premature_end_of_input``
|
||||
|
||||
The input ended in the middle of a JSON value.
|
||||
|
||||
``json_error_end_of_input_expected``
|
||||
|
||||
There was some text after the end of a JSON value. See the
|
||||
``JSON_DISABLE_EOF_CHECK`` flag.
|
||||
|
||||
``json_error_invalid_syntax``
|
||||
|
||||
JSON syntax error.
|
||||
|
||||
``json_error_invalid_format``
|
||||
|
||||
Invalid format string for packing or unpacking.
|
||||
|
||||
``json_error_wrong_type``
|
||||
|
||||
When packing or unpacking, the actual type of a value differed from the
|
||||
one specified in the format string.
|
||||
|
||||
``json_error_null_character``
|
||||
|
||||
A null character was detected in a JSON string. See the
|
||||
``JSON_ALLOW_NUL`` flag.
|
||||
|
||||
``json_error_null_value``
|
||||
|
||||
When packing or unpacking, some key or value was ``NULL``.
|
||||
|
||||
``json_error_null_byte_in_key``
|
||||
|
||||
An object key would contain a null byte. Jansson can’t represent such
|
||||
keys; see :ref:`rfc-conformance`.
|
||||
|
||||
``json_error_duplicate_key``
|
||||
|
||||
Duplicate key in object. See the ``JSON_REJECT_DUPLICATES`` flag.
|
||||
|
||||
``json_error_numeric_overflow``
|
||||
|
||||
When converting a JSON number to a C numeric type, a numeric overflow
|
||||
was detected.
|
||||
|
||||
``json_error_item_not_found``
|
||||
|
||||
Key in object not found.
|
||||
|
||||
``json_error_index_out_of_range``
|
||||
|
||||
Array index is out of range.
|
||||
|
||||
.. versionadded:: 2.11
|
||||
|
||||
.. function:: enum json_error_code json_error_code(const json_error_t *error)
|
||||
|
||||
Returns the error code embedded in ``error->text``.
|
||||
|
||||
.. versionadded:: 2.11
|
||||
|
||||
|
||||
Encoding
|
||||
========
|
||||
|
@ -866,6 +1001,12 @@ can be ORed together to obtain *flags*.
|
|||
output. If ``JSON_INDENT`` is not used or *n* is 0, no newlines are
|
||||
inserted between array and object items.
|
||||
|
||||
The ``JSON_MAX_INDENT`` constant defines the maximum indentation
|
||||
that can be used, and its value is 31.
|
||||
|
||||
.. versionchanged:: 2.7
|
||||
Added ``JSON_MAX_INDENT``.
|
||||
|
||||
``JSON_COMPACT``
|
||||
This flag enables a compact representation, i.e. sets the separator
|
||||
between array and object items to ``","`` and between object keys
|
||||
|
@ -874,7 +1015,7 @@ can be ORed together to obtain *flags*.
|
|||
|
||||
``JSON_ENSURE_ASCII``
|
||||
If this flag is used, the output is guaranteed to consist only of
|
||||
ASCII characters. This is achived by escaping all Unicode
|
||||
ASCII characters. This is achieved by escaping all Unicode
|
||||
characters outside the ASCII range.
|
||||
|
||||
``JSON_SORT_KEYS``
|
||||
|
@ -883,19 +1024,22 @@ can be ORed together to obtain *flags*.
|
|||
compared.
|
||||
|
||||
``JSON_PRESERVE_ORDER``
|
||||
If this flag is used, object keys in the output are sorted into the
|
||||
same order in which they were first inserted to the object. For
|
||||
example, decoding a JSON text and then encoding with this flag
|
||||
preserves the order of object keys.
|
||||
**Deprecated since version 2.8:** Order of object keys
|
||||
is always preserved.
|
||||
|
||||
Prior to version 2.8: If this flag is used, object keys in the
|
||||
output are sorted into the same order in which they were first
|
||||
inserted to the object. For example, decoding a JSON text and then
|
||||
encoding with this flag preserves the order of object keys.
|
||||
|
||||
``JSON_ENCODE_ANY``
|
||||
Specifying this flag makes it possible to encode any JSON value on
|
||||
its own. Without it, only objects and arrays can be passed as the
|
||||
*root* value to the encoding functions.
|
||||
*json* value to the encoding functions.
|
||||
|
||||
**Note:** Encoding any value may be useful in some scenarios, but
|
||||
it's generally discouraged as it violates strict compatiblity with
|
||||
:rfc:`4627`. If you use this flag, don't expect interoperatibility
|
||||
it's generally discouraged as it violates strict compatibility with
|
||||
:rfc:`4627`. If you use this flag, don't expect interoperability
|
||||
with other JSON systems.
|
||||
|
||||
.. versionadded:: 2.1
|
||||
|
@ -915,26 +1059,71 @@ can be ORed together to obtain *flags*.
|
|||
|
||||
.. versionadded:: 2.7
|
||||
|
||||
The following functions perform the actual JSON encoding. The result
|
||||
is in UTF-8.
|
||||
``JSON_EMBED``
|
||||
If this flag is used, the opening and closing characters of the top-level
|
||||
array ('[', ']') or object ('{', '}') are omitted during encoding. This
|
||||
flag is useful when concatenating multiple arrays or objects into a stream.
|
||||
|
||||
.. function:: char *json_dumps(const json_t *root, size_t flags)
|
||||
.. versionadded:: 2.10
|
||||
|
||||
Returns the JSON representation of *root* as a string, or *NULL* on
|
||||
These functions output UTF-8:
|
||||
|
||||
.. function:: char *json_dumps(const json_t *json, size_t flags)
|
||||
|
||||
Returns the JSON representation of *json* as a string, or *NULL* on
|
||||
error. *flags* is described above. The return value must be freed
|
||||
by the caller using :func:`free()`.
|
||||
|
||||
.. function:: int json_dumpf(const json_t *root, FILE *output, size_t flags)
|
||||
.. function:: size_t json_dumpb(const json_t *json, char *buffer, size_t size, size_t flags)
|
||||
|
||||
Write the JSON representation of *root* to the stream *output*.
|
||||
Writes the JSON representation of *json* to the *buffer* of
|
||||
*size* bytes. Returns the number of bytes that would be written
|
||||
or 0 on error. *flags* is described above. *buffer* is not
|
||||
null-terminated.
|
||||
|
||||
This function never writes more than *size* bytes. If the return
|
||||
value is greater than *size*, the contents of the *buffer* are
|
||||
undefined. This behavior enables you to specify a NULL *buffer*
|
||||
to determine the length of the encoding. For example::
|
||||
|
||||
size_t size = json_dumpb(json, NULL, 0, 0);
|
||||
if (size == 0)
|
||||
return -1;
|
||||
|
||||
char *buf = alloca(size);
|
||||
|
||||
size = json_dumpb(json, buf, size, 0);
|
||||
|
||||
.. versionadded:: 2.10
|
||||
|
||||
.. function:: int json_dumpf(const json_t *json, FILE *output, size_t flags)
|
||||
|
||||
Write the JSON representation of *json* to the stream *output*.
|
||||
*flags* is described above. Returns 0 on success and -1 on error.
|
||||
If an error occurs, something may have already been written to
|
||||
*output*. In this case, the output is undefined and most likely not
|
||||
valid JSON.
|
||||
|
||||
.. function:: int json_dumpfd(const json_t *json, int output, size_t flags)
|
||||
|
||||
Write the JSON representation of *json* to the stream *output*.
|
||||
*flags* is described above. Returns 0 on success and -1 on error.
|
||||
If an error occurs, something may have already been written to
|
||||
*output*. In this case, the output is undefined and most likely not
|
||||
valid JSON.
|
||||
|
||||
It is important to note that this function can only succeed on stream
|
||||
file descriptors (such as SOCK_STREAM). Using this function on a
|
||||
non-stream file descriptor will result in undefined behavior. For
|
||||
non-stream file descriptors, see instead :func:`json_dumpb()`.
|
||||
|
||||
This function requires POSIX and fails on all non-POSIX systems.
|
||||
|
||||
.. versionadded:: 2.10
|
||||
|
||||
.. function:: int json_dump_file(const json_t *json, const char *path, size_t flags)
|
||||
|
||||
Write the JSON representation of *root* to the file *path*. If
|
||||
Write the JSON representation of *json* to the file *path*. If
|
||||
*path* already exists, it is overwritten. *flags* is described
|
||||
above. Returns 0 on success and -1 on error.
|
||||
|
||||
|
@ -949,6 +1138,10 @@ is in UTF-8.
|
|||
the length of the buffer, and *data* is the corresponding
|
||||
:func:`json_dump_callback()` argument passed through.
|
||||
|
||||
*buffer* is guaranteed to be a valid UTF-8 string (i.e. multi-byte
|
||||
code unit sequences are preserved). *buffer* never contains
|
||||
embedded null bytes.
|
||||
|
||||
On error, the function should return -1 to stop the encoding
|
||||
process. On success, it should return 0.
|
||||
|
||||
|
@ -957,7 +1150,7 @@ is in UTF-8.
|
|||
.. function:: int json_dump_callback(const json_t *json, json_dump_callback_t callback, void *data, size_t flags)
|
||||
|
||||
Call *callback* repeatedly, passing a chunk of the JSON
|
||||
representation of *root* each time. *flags* is described above.
|
||||
representation of *json* each time. *flags* is described above.
|
||||
Returns 0 on success and -1 on error.
|
||||
|
||||
.. versionadded:: 2.2
|
||||
|
@ -987,7 +1180,7 @@ macros can be ORed together to obtain *flags*.
|
|||
``JSON_REJECT_DUPLICATES``
|
||||
Issue a decoding error if any JSON object in the input text
|
||||
contains duplicate keys. Without this flag, the value of the last
|
||||
occurence of each key ends up in the result. Key equivalence is
|
||||
occurrence of each key ends up in the result. Key equivalence is
|
||||
checked byte-by-byte, without special Unicode comparison
|
||||
algorithms.
|
||||
|
||||
|
@ -998,8 +1191,8 @@ macros can be ORed together to obtain *flags*.
|
|||
With this flag enabled, the decoder accepts any valid JSON value.
|
||||
|
||||
**Note:** Decoding any value may be useful in some scenarios, but
|
||||
it's generally discouraged as it violates strict compatiblity with
|
||||
:rfc:`4627`. If you use this flag, don't expect interoperatibility
|
||||
it's generally discouraged as it violates strict compatibility with
|
||||
:rfc:`4627`. If you use this flag, don't expect interoperability
|
||||
with other JSON systems.
|
||||
|
||||
.. versionadded:: 2.3
|
||||
|
@ -1034,13 +1227,13 @@ macros can be ORed together to obtain *flags*.
|
|||
|
||||
``JSON_ALLOW_NUL``
|
||||
Allow ``\u0000`` escape inside string values. This is a safety
|
||||
measure; If you know your input can contain NUL bytes, use this
|
||||
flag. If you don't use this flag, you don't have to worry about NUL
|
||||
measure; If you know your input can contain null bytes, use this
|
||||
flag. If you don't use this flag, you don't have to worry about null
|
||||
bytes inside strings unless you explicitly create themselves by
|
||||
using e.g. :func:`json_stringn()` or ``s#`` format specifier for
|
||||
:func:`json_pack()`.
|
||||
|
||||
Object keys cannot have embedded NUL bytes even if this flag is
|
||||
Object keys cannot have embedded null bytes even if this flag is
|
||||
used.
|
||||
|
||||
.. versionadded:: 2.6
|
||||
|
@ -1057,8 +1250,6 @@ its ``position`` field. This is especially useful when using
|
|||
|
||||
If no error or position information is needed, you can pass *NULL*.
|
||||
|
||||
The following functions perform the actual JSON decoding.
|
||||
|
||||
.. function:: json_t *json_loads(const char *input, size_t flags, json_error_t *error)
|
||||
|
||||
.. refcounting:: new
|
||||
|
@ -1089,7 +1280,7 @@ The following functions perform the actual JSON decoding.
|
|||
above.
|
||||
|
||||
This function will start reading the input from whatever position
|
||||
the input file was, without attempting to seek first. If an error
|
||||
the input file was in, 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
|
||||
|
@ -1098,6 +1289,35 @@ The following functions perform the actual JSON decoding.
|
|||
multiple times, if the input consists of consecutive JSON texts,
|
||||
possibly separated by whitespace.
|
||||
|
||||
.. function:: json_t *json_loadfd(int input, size_t flags, json_error_t *error)
|
||||
|
||||
.. refcounting:: new
|
||||
|
||||
Decodes the JSON text in stream *input* and returns the array or
|
||||
object it contains, or *NULL* on error, in which case *error* is
|
||||
filled with information about the error. *flags* is described
|
||||
above.
|
||||
|
||||
This function will start reading the input from whatever position
|
||||
the input file descriptor was in, 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
|
||||
descriptor's position will be at the first character after the last
|
||||
``]`` or ``}`` in the JSON input. This allows calling
|
||||
:func:`json_loadfd()` on the same file descriptor multiple times,
|
||||
if the input consists of consecutive JSON texts, possibly separated
|
||||
by whitespace.
|
||||
|
||||
It is important to note that this function can only succeed on stream
|
||||
file descriptors (such as SOCK_STREAM). Using this function on a
|
||||
non-stream file descriptor will result in undefined behavior. For
|
||||
non-stream file descriptors, see instead :func:`json_loadb()`.
|
||||
|
||||
This function requires POSIX and fails on all non-POSIX systems.
|
||||
|
||||
.. versionadded:: 2.10
|
||||
|
||||
.. function:: json_t *json_load_file(const char *path, size_t flags, json_error_t *error)
|
||||
|
||||
.. refcounting:: new
|
||||
|
@ -1117,11 +1337,19 @@ The following functions perform the actual JSON decoding.
|
|||
*buffer* points to a buffer of *buflen* bytes, and *data* is the
|
||||
corresponding :func:`json_load_callback()` argument passed through.
|
||||
|
||||
On success, the function should return the number of bytes read; a
|
||||
returned value of 0 indicates that no data was read and that the
|
||||
end of file has been reached. On error, the function should return
|
||||
On success, the function should write at most *buflen* bytes to
|
||||
*buffer*, and return the number of bytes written; a returned value
|
||||
of 0 indicates that no data was produced and that the end of file
|
||||
has been reached. On error, the function should return
|
||||
``(size_t)-1`` to abort the decoding process.
|
||||
|
||||
In UTF-8, some code points are encoded as multi-byte sequences. The
|
||||
callback function doesn't need to worry about this, as Jansson
|
||||
handles it at a higher level. For example, you can safely read a
|
||||
fixed number of bytes from a network connection without having to
|
||||
care about code unit sequences broken apart by the chunk
|
||||
boundaries.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
.. function:: json_t *json_load_callback(json_load_callback_t callback, void *data, size_t flags, json_error_t *error)
|
||||
|
@ -1164,7 +1392,21 @@ denotes the C type that is expected as the corresponding argument or
|
|||
arguments.
|
||||
|
||||
``s`` (string) [const char \*]
|
||||
Convert a NULL terminated UTF-8 string to a JSON string.
|
||||
Convert a null terminated UTF-8 string to a JSON string.
|
||||
|
||||
``s?`` (string) [const char \*]
|
||||
Like ``s``, but if the argument is *NULL*, output a JSON null
|
||||
value.
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
``s*`` (string) [const char \*]
|
||||
Like ``s``, but if the argument is *NULL*, do not output any value.
|
||||
This format can only be used inside an object or an array. If used
|
||||
inside an object, the corresponding key is additionally suppressed
|
||||
when the value is omitted. See below for an example.
|
||||
|
||||
.. versionadded:: 2.11
|
||||
|
||||
``s#`` (string) [const char \*, int]
|
||||
Convert a UTF-8 buffer of a given length to a JSON string.
|
||||
|
@ -1220,6 +1462,21 @@ arguments.
|
|||
keep the reference for the JSON value consumed by ``O`` to
|
||||
yourself.
|
||||
|
||||
``o?``, ``O?`` (any value) [json_t \*]
|
||||
Like ``o`` and ``O``, respectively, but if the argument is
|
||||
*NULL*, output a JSON null value.
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
``o*``, ``O*`` (any value) [json_t \*]
|
||||
Like ``o`` and ``O``, respectively, but if the argument is
|
||||
*NULL*, do not output any value. This format can only be used
|
||||
inside an object or an array. If used inside an object, the
|
||||
corresponding key is additionally suppressed. See below for an
|
||||
example.
|
||||
|
||||
.. versionadded:: 2.11
|
||||
|
||||
``[fmt]`` (array)
|
||||
Build an array with contents from the inner format string. ``fmt``
|
||||
may contain objects and arrays, i.e. recursive value building is
|
||||
|
@ -1235,8 +1492,6 @@ arguments.
|
|||
|
||||
Whitespace, ``:`` and ``,`` are ignored.
|
||||
|
||||
The following functions compose the value building API:
|
||||
|
||||
.. function:: json_t *json_pack(const char *fmt, ...)
|
||||
|
||||
.. refcounting:: new
|
||||
|
@ -1273,13 +1528,17 @@ More examples::
|
|||
/* Build the JSON array [[1, 2], {"cool": true}] */
|
||||
json_pack("[[i,i],{s:b}]", 1, 2, "cool", 1);
|
||||
|
||||
/* Build a string from a non-NUL terminated buffer */
|
||||
/* Build a string from a non-null terminated buffer */
|
||||
char buffer[4] = {'t', 'e', 's', 't'};
|
||||
json_pack("s#", buffer, 4);
|
||||
|
||||
/* Concatentate strings together to build the JSON string "foobarbaz" */
|
||||
/* Concatenate strings together to build the JSON string "foobarbaz" */
|
||||
json_pack("s++", "foo", "bar", "baz");
|
||||
|
||||
/* Create an empty object or array when optional members are missing */
|
||||
json_pack("{s:s*,s:o*,s:O*}", "foo", NULL, "bar", NULL, "baz", NULL);
|
||||
json_pack("[s*,o*,O*]", NULL, NULL, NULL);
|
||||
|
||||
|
||||
.. _apiref-unpack:
|
||||
|
||||
|
@ -1302,13 +1561,13 @@ denotes the JSON type, and the type in brackets (if any) denotes the C
|
|||
type whose address should be passed.
|
||||
|
||||
``s`` (string) [const char \*]
|
||||
Convert a JSON string to a pointer to a NULL terminated UTF-8
|
||||
Convert a JSON string to a pointer to a null terminated UTF-8
|
||||
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.
|
||||
|
||||
``s%`` (string) [const char \*, size_t *]
|
||||
Convert a JSON string to a pointer to a NULL terminated UTF-8
|
||||
``s%`` (string) [const char \*, size_t \*]
|
||||
Convert a JSON string to a pointer to a null terminated UTF-8
|
||||
string and its length.
|
||||
|
||||
.. versionadded:: 2.6
|
||||
|
@ -1336,12 +1595,15 @@ type whose address should be passed.
|
|||
Store a JSON value with no conversion to a :type:`json_t` pointer.
|
||||
|
||||
``O`` (any value) [json_t \*]
|
||||
Like ``O``, but the JSON value's reference count is incremented.
|
||||
Like ``o``, but the JSON value's reference count is incremented.
|
||||
Storage pointers should be initialized NULL before using unpack.
|
||||
The caller is responsible for releasing all references incremented
|
||||
by unpack, even when an error occurs.
|
||||
|
||||
``[fmt]`` (array)
|
||||
Convert each item in the JSON array according to the inner format
|
||||
string. ``fmt`` may contain objects and arrays, i.e. recursive
|
||||
value extraction is supporetd.
|
||||
value extraction is supported.
|
||||
|
||||
``{fmt}`` (object)
|
||||
Convert each item in the JSON object according to the inner format
|
||||
|
@ -1353,7 +1615,7 @@ type whose address should be passed.
|
|||
argument is read from and every other is written to.
|
||||
|
||||
``fmt`` may contain objects and arrays as values, i.e. recursive
|
||||
value extraction is supporetd.
|
||||
value extraction is supported.
|
||||
|
||||
.. versionadded:: 2.3
|
||||
Any ``s`` representing a key may be suffixed with a ``?`` to
|
||||
|
@ -1376,8 +1638,6 @@ type whose address should be passed.
|
|||
|
||||
Whitespace, ``:`` and ``,`` are ignored.
|
||||
|
||||
The following functions compose the parsing and validation API:
|
||||
|
||||
.. function:: int json_unpack(json_t *root, const char *fmt, ...)
|
||||
|
||||
Validate and unpack the JSON value *root* according to the format
|
||||
|
@ -1443,7 +1703,7 @@ Examples::
|
|||
/* returns -1 for failed validation */
|
||||
|
||||
/* root is an empty JSON object */
|
||||
int myint = 0, myint2 = 0;
|
||||
int myint = 0, myint2 = 0, myint3 = 0;
|
||||
json_unpack(root, "{s?i, s?[ii]}",
|
||||
"foo", &myint1,
|
||||
"bar", &myint2, &myint3);
|
||||
|
@ -1479,13 +1739,10 @@ only if they are exactly the same value, but also if they have equal
|
|||
if their types are equal. (Because these values are singletons,
|
||||
their equality can actually be tested with ``==``.)
|
||||
|
||||
The following function can be used to test whether two JSON values are
|
||||
equal.
|
||||
|
||||
.. function:: int json_equal(json_t *value1, json_t *value2)
|
||||
|
||||
Returns 1 if *value1* and *value2* are equal, as defined above.
|
||||
Returns 0 if they are inequal or one or both of the pointers are
|
||||
Returns 0 if they are unequal or one or both of the pointers are
|
||||
*NULL*.
|
||||
|
||||
|
||||
|
@ -1504,6 +1761,8 @@ the same child values in the copied value. Deep copying makes a fresh
|
|||
copy of the child values, too. Moreover, all the child values are deep
|
||||
copied in a recursive fashion.
|
||||
|
||||
Copying objects preserves the insertion order of keys.
|
||||
|
||||
.. function:: json_t *json_copy(json_t *value)
|
||||
|
||||
.. refcounting:: new
|
||||
|
@ -1547,6 +1806,13 @@ behavior is needed.
|
|||
Jansson's API functions to ensure that all memory operations use
|
||||
the same functions.
|
||||
|
||||
.. function:: void json_get_alloc_funcs(json_malloc_t *malloc_fn, json_free_t *free_fn)
|
||||
|
||||
Fetch the current malloc_fn and free_fn used. Either parameter
|
||||
may be NULL.
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
**Examples:**
|
||||
|
||||
Circumvent problems with different CRT heaps on Windows by using
|
||||
|
@ -1559,7 +1825,7 @@ operations::
|
|||
|
||||
json_set_alloc_funcs(GC_malloc, GC_free);
|
||||
|
||||
.. _Boehm's conservative garbage collector: http://www.hpl.hp.com/personal/Hans_Boehm/gc/
|
||||
.. _Boehm's conservative garbage collector: http://www.hboehm.info/gc/
|
||||
|
||||
Allow storing sensitive data (e.g. passwords or encryption keys) in
|
||||
JSON structures by zeroing all memory when freed::
|
||||
|
|
|
@ -41,14 +41,14 @@ master_doc = 'index'
|
|||
|
||||
# General information about the project.
|
||||
project = u'Jansson'
|
||||
copyright = u'2009-2014, Petri Lehtinen'
|
||||
copyright = u'2009-2016, Petri Lehtinen'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '2.6'
|
||||
version = '2.12'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = version
|
||||
|
||||
|
|
|
@ -108,3 +108,13 @@ types, ``long double``, etc. Obviously, shorter types like ``short``,
|
|||
are implicitly handled via the ordinary C type coercion rules (subject
|
||||
to overflow semantics). Also, no support or hooks are provided for any
|
||||
supplemental "bignum" type add-on packages.
|
||||
|
||||
Depth of nested values
|
||||
----------------------
|
||||
|
||||
To avoid stack exhaustion, Jansson currently limits the nesting depth
|
||||
for arrays and objects to a certain value (default: 2048), defined as
|
||||
a macro ``JSON_PARSER_MAX_DEPTH`` within ``jansson_config.h``.
|
||||
|
||||
The limit is allowed to be set by the RFC; there is no recommended value
|
||||
or required minimum depth to be supported.
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
<description of the json_object function>
|
||||
|
||||
:copyright: Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>
|
||||
:copyright: Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
|
||||
:license: MIT, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -55,5 +55,6 @@ def setup(app):
|
|||
app.add_node(refcounting,
|
||||
html=(html_visit, html_depart),
|
||||
latex=(visit, depart),
|
||||
text=(visit, depart))
|
||||
text=(visit, depart),
|
||||
man=(visit, depart))
|
||||
app.add_directive('refcounting', refcounting_directive, 0, (1, 0, 0))
|
||||
|
|
|
@ -30,8 +30,7 @@ compiling and installing is extremely simple::
|
|||
|
||||
To change the destination directory (``/usr/local`` by default), use
|
||||
the ``--prefix=DIR`` argument to ``./configure``. See ``./configure
|
||||
--help`` for the list of all possible installation options. (There are
|
||||
no options to customize the resulting Jansson binary.)
|
||||
--help`` for the list of all possible configuration options.
|
||||
|
||||
The command ``make check`` runs the test suite distributed with
|
||||
Jansson. This step is not strictly necessary, but it may find possible
|
||||
|
@ -44,7 +43,7 @@ version control. To create the script, the build system needs to be
|
|||
bootstrapped. There are many ways to do this, but the easiest one is
|
||||
to use ``autoreconf``::
|
||||
|
||||
autoreconf -vi
|
||||
autoreconf -fi
|
||||
|
||||
This command creates the ``./configure`` script, which can then be
|
||||
used as described above.
|
||||
|
@ -83,10 +82,10 @@ Generating make files on unix:
|
|||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. # or `ccmake ..` for a GUI.
|
||||
cmake .. # or ccmake .. for a GUI.
|
||||
|
||||
Then to build::
|
||||
|
||||
|
||||
make
|
||||
make check
|
||||
make install
|
||||
|
@ -102,12 +101,27 @@ Creating Visual Studio project files from the command line:
|
|||
|
||||
md build
|
||||
cd build
|
||||
cmake -G "Visual Studio 10" ..
|
||||
cmake -G "Visual Studio 15 2017" ..
|
||||
|
||||
.. note::
|
||||
|
||||
You should replace the name of the generator (``-G`` flag) matching
|
||||
the Visual Studio version installed on your system. Currently, the
|
||||
following versions are supported:
|
||||
|
||||
- ``Visual Studio 9 2008``
|
||||
- ``Visual Studio 10 2010``
|
||||
- ``Visual Studio 11 2012``
|
||||
- ``Visual Studio 12 2013``
|
||||
- ``Visual Studio 14 2015``
|
||||
- ``Visual Studio 15 2017``
|
||||
|
||||
Any later version should also work.
|
||||
|
||||
You will now have a *Visual Studio Solution* in your build directory.
|
||||
To run the unit tests build the ``RUN_TESTS`` project.
|
||||
|
||||
If you prefer a GUI the ``cmake`` line in the above example can
|
||||
If you prefer a GUI the ``cmake`` line in the above example can
|
||||
be replaced with::
|
||||
|
||||
cmake-gui ..
|
||||
|
@ -117,7 +131,7 @@ for CMake_ simply run::
|
|||
|
||||
cmake
|
||||
|
||||
To list available CMake_ settings (and what they are currently set to)
|
||||
To list available CMake_ settings (and what they are currently set to)
|
||||
for the project, run::
|
||||
|
||||
cmake -LH ..
|
||||
|
@ -125,7 +139,7 @@ for the project, run::
|
|||
Mac OSX (Xcode)
|
||||
^^^^^^^^^^^^^^^
|
||||
If you prefer using Xcode instead of make files on OSX,
|
||||
do the following. (Use the same steps as
|
||||
do the following. (Use the same steps as
|
||||
for :ref:`Unix <build-cmake-unix>`)::
|
||||
|
||||
...
|
||||
|
@ -140,12 +154,12 @@ By default the CMake_ project will generate build files for building the
|
|||
static library. To build the shared version use::
|
||||
|
||||
...
|
||||
cmake -DBUILD_SHARED=1 ..
|
||||
cmake -DJANSSON_BUILD_SHARED_LIBS=1 ..
|
||||
|
||||
Changing install directory (same as autoconf --prefix)
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
Just as with the autoconf_ project you can change the destination directory
|
||||
for ``make install``. The equivalent for autoconfs ``./configure --prefix``
|
||||
for ``make install``. The equivalent for autoconfs ``./configure --prefix``
|
||||
in CMake_ is::
|
||||
|
||||
...
|
||||
|
@ -220,7 +234,9 @@ link the program as follows::
|
|||
|
||||
cc -o prog prog.c -ljansson
|
||||
|
||||
Starting from version 1.2, there's also support for pkg-config_::
|
||||
Starting from version 1.2, there's also support for pkg-config_:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
cc -o prog prog.c `pkg-config --cflags --libs jansson`
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -7,29 +7,31 @@ Portability
|
|||
Thread safety
|
||||
-------------
|
||||
|
||||
Jansson is thread safe and has no mutable global state. The only
|
||||
exceptions are the hash function seed and memory allocation functions,
|
||||
see below.
|
||||
Jansson as a library is thread safe and has no mutable global state.
|
||||
The only exceptions are the hash function seed and memory allocation
|
||||
functions, see below.
|
||||
|
||||
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.
|
||||
There's no locking performed inside Jansson's code. **Read-only**
|
||||
access to JSON values shared by multiple threads is safe, but
|
||||
**mutating** a JSON value that's shared by multiple threads is not. A
|
||||
multithreaded program must perform its own locking if JSON values
|
||||
shared by multiple threads are mutated.
|
||||
|
||||
The encoding functions (:func:`json_dumps()` and friends) track
|
||||
reference loops by modifying the internal state of objects and arrays.
|
||||
For this reason, encoding functions must not be run on the same JSON
|
||||
values in two separate threads at the same time. As already noted
|
||||
above, be especially careful if two arrays or objects share their
|
||||
contained values with another array or object.
|
||||
However, **reference count manipulation** (:func:`json_incref()`,
|
||||
:func:`json_decref()`) is usually thread-safe, and can be performed on
|
||||
JSON values that are shared among threads. The thread-safety of
|
||||
reference counting can be checked with the
|
||||
``JANSSON_THREAD_SAFE_REFCOUNT`` preprocessor constant. Thread-safe
|
||||
reference count manipulation is achieved using compiler built-in
|
||||
atomic functions, which are available in most modern compilers.
|
||||
|
||||
If you want to make sure that two JSON value hierarchies do not
|
||||
contain shared values, use :func:`json_deep_copy()` to make copies.
|
||||
If compiler support is not available (``JANSSON_THREAD_SAFE_REFCOUNT``
|
||||
is not defined), it may be very difficult to ensure thread safety of
|
||||
reference counting. It's possible to have a reference to a value
|
||||
that's also stored inside an array or object in another thread.
|
||||
Modifying the container (adding or removing values) may trigger
|
||||
concurrent access to such values, as containers manage the reference
|
||||
count of their contained values.
|
||||
|
||||
|
||||
Hash function seed
|
||||
|
|
|
@ -10,7 +10,7 @@ In this tutorial, we create a program that fetches the latest commits
|
|||
of a repository in GitHub_ over the web. `GitHub API`_ uses JSON, so
|
||||
the result can be parsed using Jansson.
|
||||
|
||||
To stick to the the scope of this tutorial, we will only cover the the
|
||||
To stick to the scope of this tutorial, we will only cover the
|
||||
parts of the program related to handling JSON data. For the best user
|
||||
experience, the full source code is available:
|
||||
:download:`github_commits.c`. To compile it (on Unix-like systems with
|
||||
|
@ -238,7 +238,7 @@ from a JSON string using :func:`json_string_value()`::
|
|||
|
||||
message_text = json_string_value(message);
|
||||
printf("%.8s %.*s\n",
|
||||
json_string_value(id),
|
||||
json_string_value(sha),
|
||||
newline_offset(message_text),
|
||||
message_text);
|
||||
}
|
||||
|
@ -256,7 +256,9 @@ For a detailed explanation of reference counting in Jansson, see
|
|||
:ref:`apiref-reference-count` in :ref:`apiref`.
|
||||
|
||||
The program's ready, let's test it and view the latest commits in
|
||||
Jansson's repository::
|
||||
Jansson's repository:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ ./github_commits akheron jansson
|
||||
1581f26a Merge branch '2.3'
|
||||
|
|
4
jansson/examples/README.rst
Normal file
4
jansson/examples/README.rst
Normal file
|
@ -0,0 +1,4 @@
|
|||
Jansson examples
|
||||
================
|
||||
|
||||
This directory contains simple example programs that use Jansson.
|
203
jansson/examples/simple_parse.c
Normal file
203
jansson/examples/simple_parse.c
Normal file
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* Simple example of parsing and printing JSON using jansson.
|
||||
*
|
||||
* SYNOPSIS:
|
||||
* $ examples/simple_parse
|
||||
* Type some JSON > [true, false, null, 1, 0.0, -0.0, "", {"name": "barney"}]
|
||||
* JSON Array of 8 elements:
|
||||
* JSON True
|
||||
* JSON False
|
||||
* JSON Null
|
||||
* JSON Integer: "1"
|
||||
* JSON Real: 0.000000
|
||||
* JSON Real: -0.000000
|
||||
* JSON String: ""
|
||||
* JSON Object of 1 pair:
|
||||
* JSON Key: "name"
|
||||
* JSON String: "barney"
|
||||
*
|
||||
* Copyright (c) 2014 Robert Poor <rdpoor@gmail.com>
|
||||
*
|
||||
* Jansson is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <jansson.h>
|
||||
|
||||
/* forward refs */
|
||||
void print_json(json_t *root);
|
||||
void print_json_aux(json_t *element, int indent);
|
||||
void print_json_indent(int indent);
|
||||
const char *json_plural(int count);
|
||||
void print_json_object(json_t *element, int indent);
|
||||
void print_json_array(json_t *element, int indent);
|
||||
void print_json_string(json_t *element, int indent);
|
||||
void print_json_integer(json_t *element, int indent);
|
||||
void print_json_real(json_t *element, int indent);
|
||||
void print_json_true(json_t *element, int indent);
|
||||
void print_json_false(json_t *element, int indent);
|
||||
void print_json_null(json_t *element, int indent);
|
||||
|
||||
void print_json(json_t *root) {
|
||||
print_json_aux(root, 0);
|
||||
}
|
||||
|
||||
void print_json_aux(json_t *element, int indent) {
|
||||
switch (json_typeof(element)) {
|
||||
case JSON_OBJECT:
|
||||
print_json_object(element, indent);
|
||||
break;
|
||||
case JSON_ARRAY:
|
||||
print_json_array(element, indent);
|
||||
break;
|
||||
case JSON_STRING:
|
||||
print_json_string(element, indent);
|
||||
break;
|
||||
case JSON_INTEGER:
|
||||
print_json_integer(element, indent);
|
||||
break;
|
||||
case JSON_REAL:
|
||||
print_json_real(element, indent);
|
||||
break;
|
||||
case JSON_TRUE:
|
||||
print_json_true(element, indent);
|
||||
break;
|
||||
case JSON_FALSE:
|
||||
print_json_false(element, indent);
|
||||
break;
|
||||
case JSON_NULL:
|
||||
print_json_null(element, indent);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unrecognized JSON type %d\n", json_typeof(element));
|
||||
}
|
||||
}
|
||||
|
||||
void print_json_indent(int indent) {
|
||||
int i;
|
||||
for (i = 0; i < indent; i++) { putchar(' '); }
|
||||
}
|
||||
|
||||
const char *json_plural(int count) {
|
||||
return count == 1 ? "" : "s";
|
||||
}
|
||||
|
||||
void print_json_object(json_t *element, int indent) {
|
||||
size_t size;
|
||||
const char *key;
|
||||
json_t *value;
|
||||
|
||||
print_json_indent(indent);
|
||||
size = json_object_size(element);
|
||||
|
||||
printf("JSON Object of %ld pair%s:\n", size, json_plural(size));
|
||||
json_object_foreach(element, key, value) {
|
||||
print_json_indent(indent + 2);
|
||||
printf("JSON Key: \"%s\"\n", key);
|
||||
print_json_aux(value, indent + 2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void print_json_array(json_t *element, int indent) {
|
||||
size_t i;
|
||||
size_t size = json_array_size(element);
|
||||
print_json_indent(indent);
|
||||
|
||||
printf("JSON Array of %ld element%s:\n", size, json_plural(size));
|
||||
for (i = 0; i < size; i++) {
|
||||
print_json_aux(json_array_get(element, i), indent + 2);
|
||||
}
|
||||
}
|
||||
|
||||
void print_json_string(json_t *element, int indent) {
|
||||
print_json_indent(indent);
|
||||
printf("JSON String: \"%s\"\n", json_string_value(element));
|
||||
}
|
||||
|
||||
void print_json_integer(json_t *element, int indent) {
|
||||
print_json_indent(indent);
|
||||
printf("JSON Integer: \"%" JSON_INTEGER_FORMAT "\"\n", json_integer_value(element));
|
||||
}
|
||||
|
||||
void print_json_real(json_t *element, int indent) {
|
||||
print_json_indent(indent);
|
||||
printf("JSON Real: %f\n", json_real_value(element));
|
||||
}
|
||||
|
||||
void print_json_true(json_t *element, int indent) {
|
||||
(void)element;
|
||||
print_json_indent(indent);
|
||||
printf("JSON True\n");
|
||||
}
|
||||
|
||||
void print_json_false(json_t *element, int indent) {
|
||||
(void)element;
|
||||
print_json_indent(indent);
|
||||
printf("JSON False\n");
|
||||
}
|
||||
|
||||
void print_json_null(json_t *element, int indent) {
|
||||
(void)element;
|
||||
print_json_indent(indent);
|
||||
printf("JSON Null\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse text into a JSON object. If text is valid JSON, returns a
|
||||
* json_t structure, otherwise prints and error and returns null.
|
||||
*/
|
||||
json_t *load_json(const char *text) {
|
||||
json_t *root;
|
||||
json_error_t error;
|
||||
|
||||
root = json_loads(text, 0, &error);
|
||||
|
||||
if (root) {
|
||||
return root;
|
||||
} else {
|
||||
fprintf(stderr, "json error on line %d: %s\n", error.line, error.text);
|
||||
return (json_t *)0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print a prompt and return (by reference) a null-terminated line of
|
||||
* text. Returns NULL on eof or some error.
|
||||
*/
|
||||
char *read_line(char *line, int max_chars) {
|
||||
printf("Type some JSON > ");
|
||||
fflush(stdout);
|
||||
return fgets(line, max_chars, stdin);
|
||||
}
|
||||
|
||||
/* ================================================================
|
||||
* main
|
||||
*/
|
||||
|
||||
#define MAX_CHARS 4096
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char line[MAX_CHARS];
|
||||
|
||||
if (argc != 1) {
|
||||
fprintf(stderr, "Usage: %s\n", argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
while (read_line(line, MAX_CHARS) != (char *)NULL) {
|
||||
|
||||
/* parse text into JSON structure */
|
||||
json_t *root = load_json(line);
|
||||
|
||||
if (root) {
|
||||
/* print and release the JSON structure */
|
||||
print_json(root);
|
||||
json_decref(root);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=${prefix}/include
|
||||
includedir=@includedir@
|
||||
|
||||
Name: Jansson
|
||||
Description: Library for encoding, decoding and manipulating JSON data
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
EXTRA_DIST = jansson.def
|
||||
|
||||
include_HEADERS = jansson.h jansson_config.h
|
||||
include_HEADERS = jansson.h
|
||||
nodist_include_HEADERS = jansson_config.h
|
||||
|
||||
lib_LTLIBRARIES = libjansson.la
|
||||
libjansson_la_SOURCES = \
|
||||
|
@ -23,4 +24,5 @@ libjansson_la_SOURCES = \
|
|||
libjansson_la_LDFLAGS = \
|
||||
-no-undefined \
|
||||
-export-symbols-regex '^json_' \
|
||||
-version-info 10:0:6
|
||||
-version-info 15:1:11 \
|
||||
@JSON_BSYMBOLIC_LDFLAGS@
|
||||
|
|
|
@ -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,13 +9,17 @@
|
|||
#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"
|
||||
|
||||
|
@ -25,9 +29,10 @@
|
|||
#define FLAGS_TO_INDENT(f) ((f) & 0x1F)
|
||||
#define FLAGS_TO_PRECISION(f) (((f) >> 11) & 0x1F)
|
||||
|
||||
struct object_key {
|
||||
size_t serial;
|
||||
const char *key;
|
||||
struct buffer {
|
||||
const size_t size;
|
||||
size_t used;
|
||||
char *data;
|
||||
};
|
||||
|
||||
static int dump_to_strbuffer(const char *buffer, size_t size, void *data)
|
||||
|
@ -35,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;
|
||||
|
@ -43,6 +59,16 @@ 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[] = " ";
|
||||
|
||||
|
@ -50,15 +76,19 @@ static int dump_indent(size_t flags, int depth, int space, json_dump_callback_t
|
|||
{
|
||||
if(FLAGS_TO_INDENT(flags) > 0)
|
||||
{
|
||||
int i, ws_count = FLAGS_TO_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))
|
||||
|
@ -71,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;
|
||||
|
@ -130,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;
|
||||
}
|
||||
|
||||
|
@ -143,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;
|
||||
}
|
||||
|
||||
|
@ -161,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;
|
||||
|
||||
|
@ -224,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 = ":";
|
||||
|
@ -288,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)
|
||||
|
@ -355,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
|
||||
|
@ -363,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -382,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:
|
||||
|
@ -432,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;
|
||||
|
@ -447,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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,16 +154,19 @@ 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;
|
||||
|
||||
new_order = hashtable->order + 1;
|
||||
new_size = hashsize(new_order);
|
||||
|
||||
new_buckets = jsonp_malloc(new_size * sizeof(bucket_t));
|
||||
if(!new_buckets)
|
||||
return -1;
|
||||
|
||||
jsonp_free(hashtable->buckets);
|
||||
|
||||
hashtable->order++;
|
||||
new_size = hashsize(hashtable->order);
|
||||
|
||||
hashtable->buckets = jsonp_malloc(new_size * sizeof(bucket_t));
|
||||
if(!hashtable->buckets)
|
||||
return -1;
|
||||
hashtable->buckets = new_buckets;
|
||||
hashtable->order = new_order;
|
||||
|
||||
for(i = 0; i < hashsize(hashtable->order); i++)
|
||||
{
|
||||
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
@ -156,13 +158,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
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@ EXPORTS
|
|||
json_true
|
||||
json_false
|
||||
json_null
|
||||
json_sprintf
|
||||
json_vsprintf
|
||||
json_string
|
||||
json_stringn
|
||||
json_string_nocheck
|
||||
|
@ -48,12 +50,15 @@ EXPORTS
|
|||
json_object_key_to_iter
|
||||
json_object_seed
|
||||
json_dumps
|
||||
json_dumpb
|
||||
json_dumpf
|
||||
json_dumpfd
|
||||
json_dump_file
|
||||
json_dump_callback
|
||||
json_loads
|
||||
json_loadb
|
||||
json_loadf
|
||||
json_loadfd
|
||||
json_load_file
|
||||
json_load_callback
|
||||
json_equal
|
||||
|
@ -66,4 +71,5 @@ EXPORTS
|
|||
json_unpack_ex
|
||||
json_vunpack_ex
|
||||
json_set_alloc_funcs
|
||||
json_get_alloc_funcs
|
||||
|
||||
|
|
|
@ -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,16 +322,18 @@ 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_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
|
||||
|
@ -267,11 +341,14 @@ json_t *json_load_callback(json_load_callback_t callback, void *data, size_t fla
|
|||
#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);
|
||||
|
||||
|
@ -281,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
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -36,4 +36,16 @@
|
|||
otherwise to 0. */
|
||||
#define JSON_HAVE_LOCALECONV @json_have_localeconv@
|
||||
|
||||
/* If __atomic builtins are available they will be used to manage
|
||||
reference counts of json_t. */
|
||||
#define JSON_HAVE_ATOMIC_BUILTINS @json_have_atomic_builtins@
|
||||
|
||||
/* If __atomic builtins are not available we try using __sync builtins
|
||||
to manage reference counts of json_t. */
|
||||
#define JSON_HAVE_SYNC_BUILTINS @json_have_sync_builtins@
|
||||
|
||||
/* 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
|
||||
|
|
|
@ -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,20 +73,23 @@ 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 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 */
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -498,16 +510,18 @@ 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') {
|
||||
if(!(lex->flags & JSON_DECODE_INT_AS_REAL) &&
|
||||
c != '.' && c != 'E' && c != 'e')
|
||||
{
|
||||
json_int_t intval;
|
||||
|
||||
lex_unget_unsave(lex, c);
|
||||
|
@ -518,9 +532,9 @@ static int lex_scan_number(lex_t *lex, int c, json_error_t *error)
|
|||
intval = json_strtoint(saved_text, &end, 10);
|
||||
if(errno == ERANGE) {
|
||||
if(intval < 0)
|
||||
error_set(error, lex, "too big negative integer");
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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,15 +568,15 @@ 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, &doubleval)) {
|
||||
error_set(error, lex, "real number overflow");
|
||||
error_set(error, lex, json_error_numeric_overflow, "real number overflow");
|
||||
goto 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, input))
|
||||
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)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);
|
||||
|
|
|
@ -359,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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,12 +208,18 @@ static char *read_string(scanner_t *s, va_list *ap,
|
|||
}
|
||||
}
|
||||
|
||||
if(!utf8_check_string(strbuff.value, strbuff.length)) {
|
||||
set_error(s, "<args>", "Invalid UTF-8 %s", purpose);
|
||||
if(s->has_error) {
|
||||
strbuffer_close(&strbuff);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!utf8_check_string(strbuff.value, strbuff.length)) {
|
||||
set_error(s, "<args>", json_error_invalid_utf8, "Invalid UTF-8 %s", purpose);
|
||||
strbuffer_close(&strbuff);
|
||||
s->has_error = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*out_len = strbuff.length;
|
||||
*ours = 1;
|
||||
return strbuffer_steal_value(&strbuff);
|
||||
|
@ -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");
|
||||
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");
|
||||
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) {
|
||||
if(valueOptional != '*') {
|
||||
s->has_error = 1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 == HUGE_VAL || value == -HUGE_VAL) && errno == ERANGE) {
|
||||
/* Overflow */
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
@ -67,9 +67,6 @@ json_t *json_object(void)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
object->serial = 0;
|
||||
object->visited = 0;
|
||||
|
||||
return &object->json;
|
||||
}
|
||||
|
||||
|
@ -115,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;
|
||||
|
@ -154,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;
|
||||
}
|
||||
|
@ -261,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;
|
||||
|
@ -275,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))
|
||||
|
@ -354,8 +352,6 @@ json_t *json_array(void)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
array->visited = 0;
|
||||
|
||||
return &array->json;
|
||||
}
|
||||
|
||||
|
@ -584,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;
|
||||
|
||||
|
@ -656,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);
|
||||
|
@ -768,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);
|
||||
|
@ -784,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 ***/
|
||||
|
||||
|
@ -828,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);
|
||||
}
|
||||
|
@ -880,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);
|
||||
}
|
||||
|
@ -931,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));
|
||||
if (!json)
|
||||
return;
|
||||
|
||||
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));
|
||||
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 */
|
||||
}
|
||||
|
@ -952,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;
|
||||
|
@ -964,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -990,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)
|
||||
|
@ -1016,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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -181,6 +181,7 @@ int use_conf(char *test_path)
|
|||
|
||||
if (conf.indent < 0 || conf.indent > 31) {
|
||||
fprintf(stderr, "invalid value for JSON_INDENT: %d\n", conf.indent);
|
||||
fclose(infile);
|
||||
return 2;
|
||||
}
|
||||
if (conf.indent)
|
||||
|
@ -201,6 +202,7 @@ int use_conf(char *test_path)
|
|||
if (conf.precision < 0 || conf.precision > 31) {
|
||||
fprintf(stderr, "invalid value for JSON_REAL_PRECISION: %d\n",
|
||||
conf.precision);
|
||||
fclose(infile);
|
||||
return 2;
|
||||
}
|
||||
if (conf.precision)
|
||||
|
@ -303,17 +305,19 @@ int use_env()
|
|||
if(getenv_int("STRIP")) {
|
||||
/* Load to memory, strip leading and trailing whitespace */
|
||||
size_t size = 0, used = 0;
|
||||
char *buffer = NULL;
|
||||
char *buffer = NULL, *buf_ck = NULL;
|
||||
|
||||
while(1) {
|
||||
size_t count;
|
||||
|
||||
size = (size == 0 ? 128 : size * 2);
|
||||
buffer = realloc(buffer, size);
|
||||
if(!buffer) {
|
||||
buf_ck = realloc(buffer, size);
|
||||
if(!buf_ck) {
|
||||
fprintf(stderr, "Unable to allocate %d bytes\n", (int)size);
|
||||
free(buffer);
|
||||
return 1;
|
||||
}
|
||||
buffer = buf_ck;
|
||||
|
||||
count = fread(buffer + used, 1, size - used, stdin);
|
||||
if(count < size - used) {
|
||||
|
|
|
@ -34,15 +34,15 @@ failed=0
|
|||
for suite in $SUITES; do
|
||||
echo "Suite: $suite"
|
||||
if $suites_srcdir/$suite/run $suite; then
|
||||
passed=$(($passed+1))
|
||||
passed=`expr $passed + 1`
|
||||
else
|
||||
failed=$(($failed+1))
|
||||
failed=`expr $failed + 1`
|
||||
[ $STOP -eq 1 ] && break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $failed -gt 0 ]; then
|
||||
echo "$failed of $((passed+failed)) test suites failed"
|
||||
echo "$failed of `expr $passed + $failed` test suites failed"
|
||||
exit 1
|
||||
else
|
||||
echo "$passed test suites passed"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# 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.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# 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.
|
||||
|
|
|
@ -2,6 +2,7 @@ EXTRA_DIST = run check-exports
|
|||
|
||||
check_PROGRAMS = \
|
||||
test_array \
|
||||
test_chaos \
|
||||
test_copy \
|
||||
test_dump \
|
||||
test_dump_callback \
|
||||
|
@ -14,9 +15,11 @@ check_PROGRAMS = \
|
|||
test_object \
|
||||
test_pack \
|
||||
test_simple \
|
||||
test_sprintf \
|
||||
test_unpack
|
||||
|
||||
test_array_SOURCES = test_array.c util.h
|
||||
test_chaos_SOURCES = test_chaos.c util.h
|
||||
test_copy_SOURCES = test_copy.c util.h
|
||||
test_dump_SOURCES = test_dump.c util.h
|
||||
test_dump_callback_SOURCES = test_dump_callback.c util.h
|
||||
|
@ -27,6 +30,7 @@ test_number_SOURCES = test_number.c util.h
|
|||
test_object_SOURCES = test_object.c util.h
|
||||
test_pack_SOURCES = test_pack.c util.h
|
||||
test_simple_SOURCES = test_simple.c util.h
|
||||
test_sprintf_SOURCES = test_sprintf.c util.h
|
||||
test_unpack_SOURCES = test_unpack.c util.h
|
||||
|
||||
AM_CPPFLAGS = -I$(top_builddir)/src -I$(top_srcdir)/src
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# 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.
|
||||
|
|
|
@ -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.
|
||||
|
@ -419,6 +419,78 @@ static void test_array_foreach()
|
|||
json_decref(array2);
|
||||
}
|
||||
|
||||
static void test_bad_args(void)
|
||||
{
|
||||
json_t *arr = json_array();
|
||||
json_t *num = json_integer(1);
|
||||
|
||||
if(!arr || !num)
|
||||
fail("failed to create required objects");
|
||||
|
||||
if(json_array_size(NULL) != 0)
|
||||
fail("NULL array has nonzero size");
|
||||
if(json_array_size(num) != 0)
|
||||
fail("non-array has nonzero array size");
|
||||
|
||||
if(json_array_get(NULL, 0))
|
||||
fail("json_array_get did not return NULL for non-array");
|
||||
if(json_array_get(num, 0))
|
||||
fail("json_array_get did not return NULL for non-array");
|
||||
|
||||
if(!json_array_set_new(NULL, 0, json_incref(num)))
|
||||
fail("json_array_set_new did not return error for non-array");
|
||||
if(!json_array_set_new(num, 0, json_incref(num)))
|
||||
fail("json_array_set_new did not return error for non-array");
|
||||
if(!json_array_set_new(arr, 0, NULL))
|
||||
fail("json_array_set_new did not return error for NULL value");
|
||||
if(!json_array_set_new(arr, 0, json_incref(arr)))
|
||||
fail("json_array_set_new did not return error for value == array");
|
||||
|
||||
if(!json_array_remove(NULL, 0))
|
||||
fail("json_array_remove did not return error for non-array");
|
||||
if(!json_array_remove(num, 0))
|
||||
fail("json_array_remove did not return error for non-array");
|
||||
|
||||
if(!json_array_clear(NULL))
|
||||
fail("json_array_clear did not return error for non-array");
|
||||
if(!json_array_clear(num))
|
||||
fail("json_array_clear did not return error for non-array");
|
||||
|
||||
if(!json_array_append_new(NULL, json_incref(num)))
|
||||
fail("json_array_append_new did not return error for non-array");
|
||||
if(!json_array_append_new(num, json_incref(num)))
|
||||
fail("json_array_append_new did not return error for non-array");
|
||||
if(!json_array_append_new(arr, NULL))
|
||||
fail("json_array_append_new did not return error for NULL value");
|
||||
if(!json_array_append_new(arr, json_incref(arr)))
|
||||
fail("json_array_append_new did not return error for value == array");
|
||||
|
||||
if(!json_array_insert_new(NULL, 0, json_incref(num)))
|
||||
fail("json_array_insert_new did not return error for non-array");
|
||||
if(!json_array_insert_new(num, 0, json_incref(num)))
|
||||
fail("json_array_insert_new did not return error for non-array");
|
||||
if(!json_array_insert_new(arr, 0, NULL))
|
||||
fail("json_array_insert_new did not return error for NULL value");
|
||||
if(!json_array_insert_new(arr, 0, json_incref(arr)))
|
||||
fail("json_array_insert_new did not return error for value == array");
|
||||
|
||||
if(!json_array_extend(NULL, arr))
|
||||
fail("json_array_extend did not return error for first argument non-array");
|
||||
if(!json_array_extend(num, arr))
|
||||
fail("json_array_extend did not return error for first argument non-array");
|
||||
if(!json_array_extend(arr, NULL))
|
||||
fail("json_array_extend did not return error for second arguemnt non-array");
|
||||
if(!json_array_extend(arr, num))
|
||||
fail("json_array_extend did not return error for second arguemnt non-array");
|
||||
|
||||
if(num->refcount != 1)
|
||||
fail("unexpected reference count on num");
|
||||
if(arr->refcount != 1)
|
||||
fail("unexpected reference count on arr");
|
||||
|
||||
json_decref(num);
|
||||
json_decref(arr);
|
||||
}
|
||||
|
||||
static void run_tests()
|
||||
{
|
||||
|
@ -429,4 +501,5 @@ static void run_tests()
|
|||
test_extend();
|
||||
test_circular();
|
||||
test_array_foreach();
|
||||
test_bad_args();
|
||||
}
|
||||
|
|
177
jansson/test/suites/api/test_chaos.c
Normal file
177
jansson/test/suites/api/test_chaos.c
Normal file
|
@ -0,0 +1,177 @@
|
|||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <jansson.h>
|
||||
#include "util.h"
|
||||
|
||||
static int chaos_pos = 0;
|
||||
static int chaos_fail = 0;
|
||||
#define CHAOS_MAX_FAILURE 100
|
||||
|
||||
void *chaos_malloc(size_t size)
|
||||
{
|
||||
if (chaos_pos == chaos_fail)
|
||||
return NULL;
|
||||
|
||||
chaos_pos++;
|
||||
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void chaos_free(void *obj)
|
||||
{
|
||||
free(obj);
|
||||
}
|
||||
|
||||
/* Test all potential allocation failures. */
|
||||
#define chaos_loop(condition, code, cleanup) \
|
||||
{ \
|
||||
chaos_pos = chaos_fail = 0; \
|
||||
while (condition) { \
|
||||
if (chaos_fail > CHAOS_MAX_FAILURE) \
|
||||
fail("too many chaos failures"); \
|
||||
code \
|
||||
chaos_pos = 0; \
|
||||
chaos_fail++; \
|
||||
} \
|
||||
cleanup \
|
||||
}
|
||||
|
||||
#define chaos_loop_new_value(json, initcall) \
|
||||
chaos_loop(!json, json = initcall;, json_decref(json); json = NULL;)
|
||||
|
||||
int test_unpack()
|
||||
{
|
||||
int ret = -1;
|
||||
int v1;
|
||||
int v2;
|
||||
json_error_t error;
|
||||
json_t *root = json_pack("{s:i, s:i, s:i, s:i}", "n1", 1, "n2", 2, "n3", 3, "n4", 4);
|
||||
|
||||
if (!root)
|
||||
return -1;
|
||||
|
||||
if (!json_unpack_ex(root, &error, JSON_STRICT, "{s:i, s:i}", "n1", &v1, "n2", &v2))
|
||||
fail("Unexpected success");
|
||||
|
||||
if (json_error_code(&error) != json_error_end_of_input_expected) {
|
||||
if (json_error_code(&error) != json_error_out_of_memory)
|
||||
fail("Unexpected error code");
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strcmp(error.text, "2 object item(s) left unpacked: n3, n4"))
|
||||
goto out;
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
json_decref(root);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dump_chaos_callback(const char *buffer, size_t size, void *data)
|
||||
{
|
||||
json_t *obj = json_object();
|
||||
|
||||
(void)buffer;
|
||||
(void)size;
|
||||
(void)data;
|
||||
|
||||
if (!obj)
|
||||
return -1;
|
||||
|
||||
json_decref(obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_chaos()
|
||||
{
|
||||
json_malloc_t orig_malloc;
|
||||
json_free_t orig_free;
|
||||
json_t *json = NULL;
|
||||
json_t *obj = json_object();
|
||||
json_t *arr1 = json_array();
|
||||
json_t *arr2 = json_array();
|
||||
json_t *txt = json_string("test");
|
||||
json_t *intnum = json_integer(1);
|
||||
json_t *dblnum = json_real(0.5);
|
||||
char *dumptxt = NULL;
|
||||
json_t *dumpobj = json_pack("{s:[iiis], s:s}",
|
||||
"key1", 1, 2, 3, "txt",
|
||||
"key2", "v2");
|
||||
int keyno;
|
||||
|
||||
if (!obj || !arr1 || !arr2 || !txt || !intnum || !dblnum || !dumpobj)
|
||||
fail("failed to allocate basic objects");
|
||||
|
||||
json_get_alloc_funcs(&orig_malloc, &orig_free);
|
||||
json_set_alloc_funcs(chaos_malloc, chaos_free);
|
||||
|
||||
chaos_loop_new_value(json, json_pack("{s:s}", "key", "value"));
|
||||
chaos_loop_new_value(json, json_pack("{s:[]}", "key"));
|
||||
chaos_loop_new_value(json, json_pack("[biIf]", 1, 1, (json_int_t)1, 1.0));
|
||||
chaos_loop_new_value(json, json_pack("[s*,s*]", "v1", "v2"));
|
||||
chaos_loop_new_value(json, json_pack("o", json_incref(txt)));
|
||||
chaos_loop_new_value(json, json_pack("O", txt));
|
||||
chaos_loop_new_value(json, json_pack("s++", "a",
|
||||
"long string to force realloc",
|
||||
"another long string to force yet another reallocation of the string because "
|
||||
"that's what we are testing."));
|
||||
|
||||
chaos_loop(test_unpack(),,);
|
||||
|
||||
chaos_loop(json_dump_callback(dumpobj, dump_chaos_callback, NULL, JSON_INDENT(1)),,);
|
||||
chaos_loop(json_dump_callback(dumpobj, dump_chaos_callback, NULL, JSON_INDENT(1) | JSON_SORT_KEYS),,);
|
||||
chaos_loop(!dumptxt, dumptxt = json_dumps(dumpobj, JSON_COMPACT);, free(dumptxt); dumptxt = NULL;);
|
||||
|
||||
chaos_loop_new_value(json, json_copy(obj));
|
||||
chaos_loop_new_value(json, json_deep_copy(obj));
|
||||
|
||||
chaos_loop_new_value(json, json_copy(arr1));
|
||||
chaos_loop_new_value(json, json_deep_copy(arr1));
|
||||
|
||||
chaos_loop_new_value(json, json_copy(txt));
|
||||
chaos_loop_new_value(json, json_copy(intnum));
|
||||
chaos_loop_new_value(json, json_copy(dblnum));
|
||||
|
||||
#define JSON_LOAD_TXT "{\"n\":[1,2,3,4,5,6,7,8,9,10]}"
|
||||
chaos_loop_new_value(json, json_loads(JSON_LOAD_TXT, 0, NULL));
|
||||
chaos_loop_new_value(json, json_loadb(JSON_LOAD_TXT, strlen(JSON_LOAD_TXT), 0, NULL));
|
||||
|
||||
chaos_loop_new_value(json, json_sprintf("%s", "string"));
|
||||
|
||||
for (keyno = 0; keyno < 100; ++keyno) {
|
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1900
|
||||
/* Skip this test on old Windows compilers. */
|
||||
char testkey[10];
|
||||
|
||||
snprintf(testkey, sizeof(testkey), "test%d", keyno);
|
||||
chaos_loop(json_object_set_new_nocheck(obj, testkey, json_object()),,);
|
||||
#endif
|
||||
chaos_loop(json_array_append_new(arr1, json_null()),,);
|
||||
chaos_loop(json_array_insert_new(arr2, 0, json_null()),,);
|
||||
}
|
||||
|
||||
chaos_loop(json_array_extend(arr1, arr2),,);
|
||||
chaos_loop(json_string_set_nocheck(txt, "test"),,);
|
||||
|
||||
json_set_alloc_funcs(orig_malloc, orig_free);
|
||||
json_decref(obj);
|
||||
json_decref(arr1);
|
||||
json_decref(arr2);
|
||||
json_decref(txt);
|
||||
json_decref(intnum);
|
||||
json_decref(dblnum);
|
||||
json_decref(dumpobj);
|
||||
}
|
||||
|
||||
static void run_tests()
|
||||
{
|
||||
test_chaos();
|
||||
}
|
|
@ -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.
|
||||
|
@ -232,6 +232,9 @@ static void test_copy_object(void)
|
|||
const char *json_object_text =
|
||||
"{\"foo\": \"bar\", \"a\": 1, \"b\": 3.141592, \"c\": [1,2,3,4]}";
|
||||
|
||||
const char *keys[] = {"foo", "a", "b", "c"};
|
||||
int i;
|
||||
|
||||
json_t *object, *copy;
|
||||
void *iter;
|
||||
|
||||
|
@ -247,6 +250,7 @@ static void test_copy_object(void)
|
|||
if(!json_equal(copy, object))
|
||||
fail("copying an object produces an inequal copy");
|
||||
|
||||
i = 0;
|
||||
iter = json_object_iter(object);
|
||||
while(iter)
|
||||
{
|
||||
|
@ -258,9 +262,13 @@ static void test_copy_object(void)
|
|||
value2 = json_object_get(copy, key);
|
||||
|
||||
if(value1 != value2)
|
||||
fail("deep copying an object modifies its items");
|
||||
fail("copying an object modifies its items");
|
||||
|
||||
if (strcmp(key, keys[i]) != 0)
|
||||
fail("copying an object doesn't preserve key order");
|
||||
|
||||
iter = json_object_iter_next(object, iter);
|
||||
i++;
|
||||
}
|
||||
|
||||
json_decref(object);
|
||||
|
@ -272,6 +280,9 @@ static void test_deep_copy_object(void)
|
|||
const char *json_object_text =
|
||||
"{\"foo\": \"bar\", \"a\": 1, \"b\": 3.141592, \"c\": [1,2,3,4]}";
|
||||
|
||||
const char *keys[] = {"foo", "a", "b", "c"};
|
||||
int i;
|
||||
|
||||
json_t *object, *copy;
|
||||
void *iter;
|
||||
|
||||
|
@ -287,6 +298,7 @@ static void test_deep_copy_object(void)
|
|||
if(!json_equal(copy, object))
|
||||
fail("deep copying an object produces an inequal copy");
|
||||
|
||||
i = 0;
|
||||
iter = json_object_iter(object);
|
||||
while(iter)
|
||||
{
|
||||
|
@ -300,7 +312,11 @@ static void test_deep_copy_object(void)
|
|||
if(value1 == value2)
|
||||
fail("deep copying an object doesn't copy its items");
|
||||
|
||||
if (strcmp(key, keys[i]) != 0)
|
||||
fail("deep copying an object doesn't preserve key order");
|
||||
|
||||
iter = json_object_iter_next(object, iter);
|
||||
i++;
|
||||
}
|
||||
|
||||
json_decref(object);
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "jansson_private_config.h"
|
||||
|
||||
#include <jansson.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include "util.h"
|
||||
|
||||
static int encode_null_callback(const char *buffer, size_t size, void *data)
|
||||
|
@ -22,9 +27,17 @@ static void encode_null()
|
|||
if(json_dumps(NULL, JSON_ENCODE_ANY) != NULL)
|
||||
fail("json_dumps didn't fail for NULL");
|
||||
|
||||
if(json_dumpb(NULL, NULL, 0, JSON_ENCODE_ANY) != 0)
|
||||
fail("json_dumps didn't fail for NULL");
|
||||
|
||||
if(json_dumpf(NULL, stderr, JSON_ENCODE_ANY) != -1)
|
||||
fail("json_dumpf didn't fail for NULL");
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
if(json_dumpfd(NULL, STDERR_FILENO, JSON_ENCODE_ANY) != -1)
|
||||
fail("json_dumpfd didn't fail for NULL");
|
||||
#endif
|
||||
|
||||
/* Don't test json_dump_file to avoid creating a file */
|
||||
|
||||
if(json_dump_callback(NULL, encode_null_callback, NULL, JSON_ENCODE_ANY) != -1)
|
||||
|
@ -124,14 +137,15 @@ static void encode_other_than_array_or_object()
|
|||
* succeed if the JSON_ENCODE_ANY flag is used */
|
||||
|
||||
json_t *json;
|
||||
FILE *fp = NULL;
|
||||
char *result;
|
||||
|
||||
json = json_string("foo");
|
||||
if(json_dumps(json, 0) != NULL)
|
||||
fail("json_dumps encoded a string!");
|
||||
if(json_dumpf(json, fp, 0) == 0)
|
||||
if(json_dumpf(json, NULL, 0) == 0)
|
||||
fail("json_dumpf encoded a string!");
|
||||
if(json_dumpfd(json, -1, 0) == 0)
|
||||
fail("json_dumpfd encoded a string!");
|
||||
|
||||
result = json_dumps(json, JSON_ENCODE_ANY);
|
||||
if(!result || strcmp(result, "\"foo\"") != 0)
|
||||
|
@ -143,8 +157,10 @@ static void encode_other_than_array_or_object()
|
|||
json = json_integer(42);
|
||||
if(json_dumps(json, 0) != NULL)
|
||||
fail("json_dumps encoded an integer!");
|
||||
if(json_dumpf(json, fp, 0) == 0)
|
||||
if(json_dumpf(json, NULL, 0) == 0)
|
||||
fail("json_dumpf encoded an integer!");
|
||||
if(json_dumpfd(json, -1, 0) == 0)
|
||||
fail("json_dumpfd encoded an integer!");
|
||||
|
||||
result = json_dumps(json, JSON_ENCODE_ANY);
|
||||
if(!result || strcmp(result, "42") != 0)
|
||||
|
@ -194,6 +210,107 @@ static void encode_nul_byte()
|
|||
json_decref(json);
|
||||
}
|
||||
|
||||
static void dump_file()
|
||||
{
|
||||
json_t *json;
|
||||
int result;
|
||||
|
||||
result = json_dump_file(NULL, "", 0);
|
||||
if (result != -1)
|
||||
fail("json_dump_file succeeded with invalid args");
|
||||
|
||||
json = json_object();
|
||||
result = json_dump_file(json, "json_dump_file.json", 0);
|
||||
if (result != 0)
|
||||
fail("json_dump_file failed");
|
||||
|
||||
json_decref(json);
|
||||
remove("json_dump_file.json");
|
||||
}
|
||||
|
||||
static void dumpb()
|
||||
{
|
||||
char buf[2];
|
||||
json_t *obj;
|
||||
size_t size;
|
||||
|
||||
obj = json_object();
|
||||
|
||||
size = json_dumpb(obj, buf, sizeof(buf), 0);
|
||||
if(size != 2 || strncmp(buf, "{}", 2))
|
||||
fail("json_dumpb failed");
|
||||
|
||||
json_decref(obj);
|
||||
obj = json_pack("{s:s}", "foo", "bar");
|
||||
|
||||
size = json_dumpb(obj, buf, sizeof(buf), JSON_COMPACT);
|
||||
if(size != 13)
|
||||
fail("json_dumpb size check failed");
|
||||
|
||||
json_decref(obj);
|
||||
}
|
||||
|
||||
static void dumpfd()
|
||||
{
|
||||
#ifdef HAVE_UNISTD_H
|
||||
int fds[2] = {-1, -1};
|
||||
json_t *a, *b;
|
||||
|
||||
if(pipe(fds))
|
||||
fail("pipe() failed");
|
||||
|
||||
a = json_pack("{s:s}", "foo", "bar");
|
||||
|
||||
if(json_dumpfd(a, fds[1], 0))
|
||||
fail("json_dumpfd() failed");
|
||||
close(fds[1]);
|
||||
|
||||
b = json_loadfd(fds[0], 0, NULL);
|
||||
if (!b)
|
||||
fail("json_loadfd() failed");
|
||||
close(fds[0]);
|
||||
|
||||
if (!json_equal(a, b))
|
||||
fail("json_equal() failed for fd test");
|
||||
|
||||
json_decref(a);
|
||||
json_decref(b);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void embed()
|
||||
{
|
||||
static const char *plains[] = {
|
||||
"{\"bar\":[],\"foo\":{}}",
|
||||
"[[],{}]",
|
||||
"{}",
|
||||
"[]",
|
||||
NULL
|
||||
};
|
||||
|
||||
size_t i;
|
||||
|
||||
for(i = 0; plains[i]; i++) {
|
||||
const char *plain = plains[i];
|
||||
json_t *parse = NULL;
|
||||
char *embed = NULL;
|
||||
size_t psize = 0;
|
||||
size_t esize = 0;
|
||||
|
||||
psize = strlen(plain) - 2;
|
||||
embed = calloc(1, psize);
|
||||
parse = json_loads(plain, 0, NULL);
|
||||
esize = json_dumpb(parse, embed, psize,
|
||||
JSON_COMPACT | JSON_SORT_KEYS | JSON_EMBED);
|
||||
json_decref(parse);
|
||||
if(esize != psize)
|
||||
fail("json_dumpb(JSON_EMBED) returned an invalid size");
|
||||
if(strncmp(plain + 1, embed, esize) != 0)
|
||||
fail("json_dumps(JSON_EMBED) returned an invalid value");
|
||||
free(embed);
|
||||
}
|
||||
}
|
||||
|
||||
static void run_tests()
|
||||
{
|
||||
encode_null();
|
||||
|
@ -202,4 +319,8 @@ static void run_tests()
|
|||
encode_other_than_array_or_object();
|
||||
escape_slashes();
|
||||
encode_nul_byte();
|
||||
dump_file();
|
||||
dumpb();
|
||||
dumpfd();
|
||||
embed();
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
@ -74,6 +74,13 @@ static void test_equal_simple()
|
|||
fail("unable to create an string");
|
||||
if(json_equal(value1, value2))
|
||||
fail("json_equal fails for two inequal strings");
|
||||
json_decref(value2);
|
||||
|
||||
value2 = json_string("bar2");
|
||||
if(!value2)
|
||||
fail("unable to create an string");
|
||||
if(json_equal(value1, value2))
|
||||
fail("json_equal fails for two inequal length strings");
|
||||
|
||||
json_decref(value1);
|
||||
json_decref(value2);
|
||||
|
|
|
@ -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.
|
||||
|
@ -32,6 +32,24 @@ static void file_not_found()
|
|||
|
||||
if(strcmp(error.text, "unable to open /path/to/nonexistent/file.json") != 0)
|
||||
fail("json_load_file returned an invalid error message");
|
||||
if(json_error_code(&error) != json_error_cannot_open_file)
|
||||
fail("json_load_file returned an invalid error code");
|
||||
}
|
||||
|
||||
static void very_long_file_name() {
|
||||
json_t *json;
|
||||
json_error_t error;
|
||||
|
||||
json = json_load_file("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0, &error);
|
||||
if(json)
|
||||
fail("json_load_file returned non-NULL for a nonexistent file");
|
||||
if(error.line != -1)
|
||||
fail("json_load_file returned an invalid line number");
|
||||
|
||||
if (strncmp(error.source, "...aaa", 6) != 0)
|
||||
fail("error source was set incorrectly");
|
||||
if(json_error_code(&error) != json_error_cannot_open_file)
|
||||
fail("error code was set incorrectly");
|
||||
}
|
||||
|
||||
static void reject_duplicates()
|
||||
|
@ -40,7 +58,7 @@ static void reject_duplicates()
|
|||
|
||||
if(json_loads("{\"foo\": 1, \"foo\": 2}", JSON_REJECT_DUPLICATES, &error))
|
||||
fail("json_loads did not detect a duplicate key");
|
||||
check_error("duplicate object key near '\"foo\"'", "<string>", 1, 16, 16);
|
||||
check_error(json_error_duplicate_key, "duplicate object key near '\"foo\"'", "<string>", 1, 16, 16);
|
||||
}
|
||||
|
||||
static void disable_eof_check()
|
||||
|
@ -52,7 +70,7 @@ static void disable_eof_check()
|
|||
|
||||
if(json_loads(text, 0, &error))
|
||||
fail("json_loads did not detect garbage after JSON text");
|
||||
check_error("end of file expected near 'garbage'", "<string>", 1, 18, 18);
|
||||
check_error(json_error_end_of_input_expected, "end of file expected near 'garbage'", "<string>", 1, 18, 18);
|
||||
|
||||
json = json_loads(text, JSON_DISABLE_EOF_CHECK, &error);
|
||||
if(!json)
|
||||
|
@ -97,6 +115,8 @@ static void decode_int_as_real()
|
|||
json_int_t expected;
|
||||
#endif
|
||||
|
||||
char big[311];
|
||||
|
||||
json = json_loads("42", JSON_DECODE_INT_AS_REAL | JSON_DECODE_ANY, &error);
|
||||
if (!json || !json_is_real(json) || json_real_value(json) != 42.0)
|
||||
fail("json_load decode int as real failed - int");
|
||||
|
@ -113,6 +133,19 @@ static void decode_int_as_real()
|
|||
fail("json_load decode int as real failed - expected imprecision");
|
||||
json_decref(json);
|
||||
#endif
|
||||
|
||||
/* 1E309 overflows. Here we create 1E309 as a decimal number, i.e.
|
||||
1000...(309 zeroes)...0. */
|
||||
big[0] = '1';
|
||||
memset(big + 1, '0', 309);
|
||||
big[310] = '\0';
|
||||
|
||||
json = json_loads(big, JSON_DECODE_INT_AS_REAL | JSON_DECODE_ANY, &error);
|
||||
if (json || strcmp(error.text, "real number overflow") != 0 ||
|
||||
json_error_code(&error) != json_error_numeric_overflow)
|
||||
fail("json_load decode int as real failed - expected overflow");
|
||||
json_decref(json);
|
||||
|
||||
}
|
||||
|
||||
static void allow_nul()
|
||||
|
@ -152,9 +185,13 @@ static void load_wrong_args()
|
|||
if (json)
|
||||
fail("json_loadf should return NULL if the first argument is NULL");
|
||||
|
||||
json = json_loadfd(-1, 0, &error);
|
||||
if (json)
|
||||
fail("json_loadfd should return NULL if the first argument is < 0");
|
||||
|
||||
json = json_load_file(NULL, 0, &error);
|
||||
if (json)
|
||||
fail("json_loadf should return NULL if the first argument is NULL");
|
||||
fail("json_load_file should return NULL if the first argument is NULL");
|
||||
}
|
||||
|
||||
static void position()
|
||||
|
@ -174,9 +211,30 @@ static void position()
|
|||
json_decref(json);
|
||||
}
|
||||
|
||||
static void error_code()
|
||||
{
|
||||
json_error_t error;
|
||||
json_t *json = json_loads("[123] garbage", 0, &error);
|
||||
if(json != NULL)
|
||||
fail("json_loads returned not NULL");
|
||||
if(strlen(error.text) >= JSON_ERROR_TEXT_LENGTH)
|
||||
fail("error.text longer than expected");
|
||||
if(json_error_code(&error) != json_error_end_of_input_expected)
|
||||
fail("json_loads returned incorrect error code");
|
||||
|
||||
json = json_loads("{\"foo\": ", 0, &error);
|
||||
if(json != NULL)
|
||||
fail("json_loads returned not NULL");
|
||||
if(strlen(error.text) >= JSON_ERROR_TEXT_LENGTH)
|
||||
fail("error.text longer than expected");
|
||||
if(json_error_code(&error) != json_error_premature_end_of_input)
|
||||
fail("json_loads returned incorrect error code");
|
||||
}
|
||||
|
||||
static void run_tests()
|
||||
{
|
||||
file_not_found();
|
||||
very_long_file_name();
|
||||
reject_duplicates();
|
||||
disable_eof_check();
|
||||
decode_any();
|
||||
|
@ -184,4 +242,5 @@ static void run_tests()
|
|||
allow_nul();
|
||||
load_wrong_args();
|
||||
position();
|
||||
error_code();
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -5,13 +5,14 @@
|
|||
|
||||
static int malloc_called = 0;
|
||||
static int free_called = 0;
|
||||
static size_t malloc_used = 0;
|
||||
|
||||
/* helper */
|
||||
/* helpers */
|
||||
static void create_and_free_complex_object()
|
||||
{
|
||||
json_t *obj;
|
||||
|
||||
obj = json_pack("{s:i,s:n,s:b,s:b,s:{s:s},s:[i,i,i]",
|
||||
obj = json_pack("{s:i,s:n,s:b,s:b,s:{s:s},s:[i,i,i]}",
|
||||
"foo", 42,
|
||||
"bar",
|
||||
"baz", 1,
|
||||
|
@ -22,6 +23,21 @@ static void create_and_free_complex_object()
|
|||
json_decref(obj);
|
||||
}
|
||||
|
||||
static void create_and_free_object_with_oom()
|
||||
{
|
||||
int i;
|
||||
char key[4];
|
||||
json_t *obj = json_object();
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
snprintf(key, sizeof key, "%d", i);
|
||||
json_object_set_new(obj, key, json_integer(i));
|
||||
}
|
||||
|
||||
json_decref(obj);
|
||||
}
|
||||
|
||||
static void *my_malloc(size_t size)
|
||||
{
|
||||
malloc_called = 1;
|
||||
|
@ -36,14 +52,45 @@ static void my_free(void *ptr)
|
|||
|
||||
static void test_simple()
|
||||
{
|
||||
json_malloc_t mfunc = NULL;
|
||||
json_free_t ffunc = NULL;
|
||||
|
||||
json_set_alloc_funcs(my_malloc, my_free);
|
||||
json_get_alloc_funcs(&mfunc, &ffunc);
|
||||
create_and_free_complex_object();
|
||||
|
||||
if(malloc_called != 1 || free_called != 1)
|
||||
if (malloc_called != 1 || free_called != 1
|
||||
|| mfunc != my_malloc || ffunc != my_free)
|
||||
fail("Custom allocation failed");
|
||||
}
|
||||
|
||||
|
||||
static void *oom_malloc(size_t size)
|
||||
{
|
||||
if (malloc_used + size > 800)
|
||||
return NULL;
|
||||
|
||||
malloc_used += size;
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
static void oom_free(void *ptr)
|
||||
{
|
||||
free_called++;
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
static void test_oom()
|
||||
{
|
||||
free_called = 0;
|
||||
json_set_alloc_funcs(oom_malloc, oom_free);
|
||||
create_and_free_object_with_oom();
|
||||
|
||||
if (free_called == 0)
|
||||
fail("Allocation with OOM failed");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Test the secure memory functions code given in the API reference
|
||||
documentation, but by using plain memset instead of
|
||||
|
@ -75,8 +122,16 @@ static void test_secure_funcs(void)
|
|||
create_and_free_complex_object();
|
||||
}
|
||||
|
||||
static void test_bad_args(void)
|
||||
{
|
||||
/* The result of this test is not crashing. */
|
||||
json_get_alloc_funcs(NULL, NULL);
|
||||
}
|
||||
|
||||
static void run_tests()
|
||||
{
|
||||
test_simple();
|
||||
test_secure_funcs();
|
||||
test_oom();
|
||||
test_bad_args();
|
||||
}
|
||||
|
|
|
@ -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,6 +9,69 @@
|
|||
#include <jansson.h>
|
||||
#include "util.h"
|
||||
|
||||
#ifdef INFINITY
|
||||
// This test triggers "warning C4756: overflow in constant arithmetic"
|
||||
// in Visual Studio. This warning is triggered here by design, so disable it.
|
||||
// (This can only be done on function level so we keep these tests separate)
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning (disable: 4756)
|
||||
#endif
|
||||
static void test_inifity()
|
||||
{
|
||||
json_t *real = json_real(INFINITY);
|
||||
if (real != NULL)
|
||||
fail("could construct a real from Inf");
|
||||
|
||||
real = json_real(1.0);
|
||||
if (json_real_set(real, INFINITY) != -1)
|
||||
fail("could set a real to Inf");
|
||||
|
||||
if (json_real_value(real) != 1.0)
|
||||
fail("real value changed unexpectedly");
|
||||
|
||||
json_decref(real);
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
#endif // INFINITY
|
||||
|
||||
static void test_bad_args(void)
|
||||
{
|
||||
json_t *txt = json_string("test");
|
||||
|
||||
if(json_integer_value(NULL) != 0)
|
||||
fail("json_integer_value did not return 0 for non-integer");
|
||||
if(json_integer_value(txt) != 0)
|
||||
fail("json_integer_value did not return 0 for non-integer");
|
||||
|
||||
if(!json_integer_set(NULL, 0))
|
||||
fail("json_integer_set did not return error for non-integer");
|
||||
if(!json_integer_set(txt, 0))
|
||||
fail("json_integer_set did not return error for non-integer");
|
||||
|
||||
if(json_real_value(NULL) != 0.0)
|
||||
fail("json_real_value did not return 0.0 for non-real");
|
||||
if(json_real_value(txt) != 0.0)
|
||||
fail("json_real_value did not return 0.0 for non-real");
|
||||
|
||||
if(!json_real_set(NULL, 0.0))
|
||||
fail("json_real_set did not return error for non-real");
|
||||
if(!json_real_set(txt, 0.0))
|
||||
fail("json_real_set did not return error for non-real");
|
||||
|
||||
if(json_number_value(NULL) != 0.0)
|
||||
fail("json_number_value did not return 0.0 for non-numeric");
|
||||
if(json_number_value(txt) != 0.0)
|
||||
fail("json_number_value did not return 0.0 for non-numeric");
|
||||
|
||||
if (txt->refcount != 1)
|
||||
fail("unexpected reference count for txt");
|
||||
|
||||
json_decref(txt);
|
||||
}
|
||||
|
||||
static void run_tests()
|
||||
{
|
||||
json_t *integer, *real;
|
||||
|
@ -57,17 +120,7 @@ static void run_tests()
|
|||
#endif
|
||||
|
||||
#ifdef INFINITY
|
||||
real = json_real(INFINITY);
|
||||
if(real != NULL)
|
||||
fail("could construct a real from Inf");
|
||||
|
||||
real = json_real(1.0);
|
||||
if(json_real_set(real, INFINITY) != -1)
|
||||
fail("could set a real to Inf");
|
||||
|
||||
if(json_real_value(real) != 1.0)
|
||||
fail("real value changed unexpectedly");
|
||||
|
||||
json_decref(real);
|
||||
test_inifity();
|
||||
#endif
|
||||
test_bad_args();
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -139,6 +139,32 @@ static void test_update()
|
|||
json_decref(object);
|
||||
}
|
||||
|
||||
static void test_set_many_keys()
|
||||
{
|
||||
json_t *object, *value;
|
||||
const char *keys = "abcdefghijklmnopqrstuvwxyz";
|
||||
char buf[2];
|
||||
size_t i;
|
||||
|
||||
object = json_object();
|
||||
if (!object)
|
||||
fail("unable to create object");
|
||||
|
||||
value = json_string("a");
|
||||
if (!value)
|
||||
fail("unable to create string");
|
||||
|
||||
buf[1] = '\0';
|
||||
for (i = 0; i < strlen(keys); i++) {
|
||||
buf[0] = keys[i];
|
||||
if (json_object_set(object, buf, value))
|
||||
fail("unable to set object key");
|
||||
}
|
||||
|
||||
json_decref(object);
|
||||
json_decref(value);
|
||||
}
|
||||
|
||||
static void test_conditional_updates()
|
||||
{
|
||||
json_t *object, *other;
|
||||
|
@ -249,11 +275,7 @@ static void test_set_nocheck()
|
|||
|
||||
static void test_iterators()
|
||||
{
|
||||
int i;
|
||||
json_t *object, *foo, *bar, *baz;
|
||||
const char *iter_keys[3];
|
||||
int have_key[3] = { 0, 0, 0 };
|
||||
json_t *iter_values[3];
|
||||
void *iter;
|
||||
|
||||
if(json_object_iter(NULL))
|
||||
|
@ -266,7 +288,7 @@ static void test_iterators()
|
|||
foo = json_string("foo");
|
||||
bar = json_string("bar");
|
||||
baz = json_string("baz");
|
||||
if(!object || !foo || !bar || !bar)
|
||||
if(!object || !foo || !bar || !baz)
|
||||
fail("unable to create values");
|
||||
|
||||
if(json_object_iter_next(object, NULL))
|
||||
|
@ -280,50 +302,30 @@ static void test_iterators()
|
|||
iter = json_object_iter(object);
|
||||
if(!iter)
|
||||
fail("unable to get iterator");
|
||||
iter_keys[0] = json_object_iter_key(iter);
|
||||
iter_values[0] = json_object_iter_value(iter);
|
||||
if (strcmp(json_object_iter_key(iter), "a") != 0)
|
||||
fail("iterating doesn't yield keys in order");
|
||||
if (json_object_iter_value(iter) != foo)
|
||||
fail("iterating doesn't yield values in order");
|
||||
|
||||
iter = json_object_iter_next(object, iter);
|
||||
if(!iter)
|
||||
fail("unable to increment iterator");
|
||||
iter_keys[1] = json_object_iter_key(iter);
|
||||
iter_values[1] = json_object_iter_value(iter);
|
||||
if (strcmp(json_object_iter_key(iter), "b") != 0)
|
||||
fail("iterating doesn't yield keys in order");
|
||||
if (json_object_iter_value(iter) != bar)
|
||||
fail("iterating doesn't yield values in order");
|
||||
|
||||
iter = json_object_iter_next(object, iter);
|
||||
if(!iter)
|
||||
fail("unable to increment iterator");
|
||||
iter_keys[2] = json_object_iter_key(iter);
|
||||
iter_values[2] = json_object_iter_value(iter);
|
||||
if (strcmp(json_object_iter_key(iter), "c") != 0)
|
||||
fail("iterating doesn't yield keys in order");
|
||||
if (json_object_iter_value(iter) != baz)
|
||||
fail("iterating doesn't yield values in order");
|
||||
|
||||
if(json_object_iter_next(object, iter) != NULL)
|
||||
fail("able to iterate over the end");
|
||||
|
||||
/* Check that keys have correct values */
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (strcmp(iter_keys[i], "a") == 0) {
|
||||
if (iter_values[i] != foo)
|
||||
fail("wrong value for iter key a");
|
||||
else
|
||||
have_key[0] = 1;
|
||||
} else if (strcmp(iter_keys[i], "b") == 0) {
|
||||
if (iter_values[i] != bar)
|
||||
fail("wrong value for iter key b");
|
||||
else
|
||||
have_key[1] = 1;
|
||||
} else if (strcmp(iter_keys[i], "c") == 0) {
|
||||
if (iter_values[i] != baz)
|
||||
fail("wrong value for iter key c");
|
||||
else
|
||||
have_key[2] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that we got all keys */
|
||||
for(i = 0; i < 3; i++) {
|
||||
if(!have_key[i])
|
||||
fail("a key wasn't iterated over");
|
||||
}
|
||||
|
||||
if(json_object_iter_at(object, "foo"))
|
||||
fail("json_object_iter_at() succeeds for non-existent key");
|
||||
|
||||
|
@ -374,6 +376,12 @@ static void test_misc()
|
|||
if(!json_object_set(object, NULL, string))
|
||||
fail("able to set NULL key");
|
||||
|
||||
if(json_object_del(object, "a"))
|
||||
fail("unable to del the only key");
|
||||
|
||||
if(json_object_set(object, "a", string))
|
||||
fail("unable to set value");
|
||||
|
||||
if(!json_object_set(object, "a", NULL))
|
||||
fail("able to set NULL value");
|
||||
|
||||
|
@ -513,15 +521,157 @@ static void test_object_foreach()
|
|||
json_decref(object2);
|
||||
}
|
||||
|
||||
static void test_object_foreach_safe()
|
||||
{
|
||||
const char *key;
|
||||
void *tmp;
|
||||
json_t *object, *value;
|
||||
|
||||
object = json_pack("{sisisi}", "foo", 1, "bar", 2, "baz", 3);
|
||||
|
||||
json_object_foreach_safe(object, tmp, key, value) {
|
||||
json_object_del(object, key);
|
||||
}
|
||||
|
||||
if(json_object_size(object) != 0)
|
||||
fail("json_object_foreach_safe failed to iterate all key-value pairs");
|
||||
|
||||
json_decref(object);
|
||||
}
|
||||
|
||||
static void test_bad_args(void)
|
||||
{
|
||||
json_t *obj = json_object();
|
||||
json_t *num = json_integer(1);
|
||||
void *iter;
|
||||
|
||||
if (!obj || !num)
|
||||
fail("failed to allocate test objects");
|
||||
|
||||
if (json_object_set(obj, "testkey", json_null()))
|
||||
fail("failed to set testkey on object");
|
||||
|
||||
iter = json_object_iter(obj);
|
||||
if (!iter)
|
||||
fail("failed to retrieve test iterator");
|
||||
|
||||
if(json_object_size(NULL) != 0)
|
||||
fail("json_object_size with non-object argument returned non-zero");
|
||||
if(json_object_size(num) != 0)
|
||||
fail("json_object_size with non-object argument returned non-zero");
|
||||
|
||||
if(json_object_get(NULL, "test") != NULL)
|
||||
fail("json_object_get with non-object argument returned non-NULL");
|
||||
if(json_object_get(num, "test") != NULL)
|
||||
fail("json_object_get with non-object argument returned non-NULL");
|
||||
if(json_object_get(obj, NULL) != NULL)
|
||||
fail("json_object_get with NULL key returned non-NULL");
|
||||
|
||||
if(!json_object_set_new_nocheck(NULL, "test", json_null()))
|
||||
fail("json_object_set_new_nocheck with non-object argument did not return error");
|
||||
if(!json_object_set_new_nocheck(num, "test", json_null()))
|
||||
fail("json_object_set_new_nocheck with non-object argument did not return error");
|
||||
if(!json_object_set_new_nocheck(obj, "test", json_incref(obj)))
|
||||
fail("json_object_set_new_nocheck with object == value did not return error");
|
||||
if(!json_object_set_new_nocheck(obj, NULL, json_object()))
|
||||
fail("json_object_set_new_nocheck with NULL key did not return error");
|
||||
|
||||
if(!json_object_del(NULL, "test"))
|
||||
fail("json_object_del with non-object argument did not return error");
|
||||
if(!json_object_del(num, "test"))
|
||||
fail("json_object_del with non-object argument did not return error");
|
||||
if(!json_object_del(obj, NULL))
|
||||
fail("json_object_del with NULL key did not return error");
|
||||
|
||||
if(!json_object_clear(NULL))
|
||||
fail("json_object_clear with non-object argument did not return error");
|
||||
if(!json_object_clear(num))
|
||||
fail("json_object_clear with non-object argument did not return error");
|
||||
|
||||
if(!json_object_update(NULL, obj))
|
||||
fail("json_object_update with non-object first argument did not return error");
|
||||
if(!json_object_update(num, obj))
|
||||
fail("json_object_update with non-object first argument did not return error");
|
||||
if(!json_object_update(obj, NULL))
|
||||
fail("json_object_update with non-object second argument did not return error");
|
||||
if(!json_object_update(obj, num))
|
||||
fail("json_object_update with non-object second argument did not return error");
|
||||
|
||||
if(!json_object_update_existing(NULL, obj))
|
||||
fail("json_object_update_existing with non-object first argument did not return error");
|
||||
if(!json_object_update_existing(num, obj))
|
||||
fail("json_object_update_existing with non-object first argument did not return error");
|
||||
if(!json_object_update_existing(obj, NULL))
|
||||
fail("json_object_update_existing with non-object second argument did not return error");
|
||||
if(!json_object_update_existing(obj, num))
|
||||
fail("json_object_update_existing with non-object second argument did not return error");
|
||||
|
||||
if(!json_object_update_missing(NULL, obj))
|
||||
fail("json_object_update_missing with non-object first argument did not return error");
|
||||
if(!json_object_update_missing(num, obj))
|
||||
fail("json_object_update_missing with non-object first argument did not return error");
|
||||
if(!json_object_update_missing(obj, NULL))
|
||||
fail("json_object_update_missing with non-object second argument did not return error");
|
||||
if(!json_object_update_missing(obj, num))
|
||||
fail("json_object_update_missing with non-object second argument did not return error");
|
||||
|
||||
if(json_object_iter(NULL) != NULL)
|
||||
fail("json_object_iter with non-object argument returned non-NULL");
|
||||
if(json_object_iter(num) != NULL)
|
||||
fail("json_object_iter with non-object argument returned non-NULL");
|
||||
|
||||
if(json_object_iter_at(NULL, "test") != NULL)
|
||||
fail("json_object_iter_at with non-object argument returned non-NULL");
|
||||
if(json_object_iter_at(num, "test") != NULL)
|
||||
fail("json_object_iter_at with non-object argument returned non-NULL");
|
||||
if(json_object_iter_at(obj, NULL) != NULL)
|
||||
fail("json_object_iter_at with NULL iter returned non-NULL");
|
||||
|
||||
if(json_object_iter_next(obj, NULL) != NULL)
|
||||
fail("json_object_iter_next with NULL iter returned non-NULL");
|
||||
if(json_object_iter_next(num, iter) != NULL)
|
||||
fail("json_object_iter_next with non-object argument returned non-NULL");
|
||||
|
||||
if(json_object_iter_key(NULL) != NULL)
|
||||
fail("json_object_iter_key with NULL iter returned non-NULL");
|
||||
|
||||
if(json_object_key_to_iter(NULL) != NULL)
|
||||
fail("json_object_key_to_iter with NULL iter returned non-NULL");
|
||||
|
||||
if(json_object_iter_value(NULL) != NULL)
|
||||
fail("json_object_iter_value with NULL iter returned non-NULL");
|
||||
|
||||
if(!json_object_iter_set_new(NULL, iter, json_incref(num)))
|
||||
fail("json_object_iter_set_new with non-object argument did not return error");
|
||||
if(!json_object_iter_set_new(num, iter, json_incref(num)))
|
||||
fail("json_object_iter_set_new with non-object argument did not return error");
|
||||
if(!json_object_iter_set_new(obj, NULL, json_incref(num)))
|
||||
fail("json_object_iter_set_new with NULL iter did not return error");
|
||||
if(!json_object_iter_set_new(obj, iter, NULL))
|
||||
fail("json_object_iter_set_new with NULL value did not return error");
|
||||
|
||||
if (obj->refcount != 1)
|
||||
fail("unexpected reference count for obj");
|
||||
|
||||
if (num->refcount != 1)
|
||||
fail("unexpected reference count for num");
|
||||
|
||||
json_decref(obj);
|
||||
json_decref(num);
|
||||
}
|
||||
|
||||
static void run_tests()
|
||||
{
|
||||
test_misc();
|
||||
test_clear();
|
||||
test_update();
|
||||
test_set_many_keys();
|
||||
test_conditional_updates();
|
||||
test_circular();
|
||||
test_set_nocheck();
|
||||
test_iterators();
|
||||
test_preserve_order();
|
||||
test_object_foreach();
|
||||
test_object_foreach_safe();
|
||||
test_bad_args();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>
|
||||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
|
||||
* Copyright (c) 2010-2012 Graeme Smecher <graeme.smecher@mail.mcgill.ca>
|
||||
*
|
||||
* Jansson is free software; you can redistribute it and/or modify
|
||||
|
@ -15,8 +15,39 @@
|
|||
#include <string.h>
|
||||
#include <jansson.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "util.h"
|
||||
|
||||
#ifdef INFINITY
|
||||
// This test triggers "warning C4756: overflow in constant arithmetic"
|
||||
// in Visual Studio. This warning is triggered here by design, so disable it.
|
||||
// (This can only be done on function level so we keep these tests separate)
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning (disable: 4756)
|
||||
#endif
|
||||
static void test_inifity()
|
||||
{
|
||||
json_error_t error;
|
||||
|
||||
if (json_pack_ex(&error, 0, "f", INFINITY))
|
||||
fail("json_pack infinity incorrectly succeeded");
|
||||
check_error(json_error_numeric_overflow, "Invalid floating point value", "<args>", 1, 1, 1);
|
||||
|
||||
if (json_pack_ex(&error, 0, "[f]", INFINITY))
|
||||
fail("json_pack infinity array element incorrectly succeeded");
|
||||
check_error(json_error_numeric_overflow, "Invalid floating point value", "<args>", 1, 2, 2);
|
||||
|
||||
if (json_pack_ex(&error, 0, "{s:f}", "key", INFINITY))
|
||||
fail("json_pack infinity object value incorrectly succeeded");
|
||||
check_error(json_error_numeric_overflow, "Invalid floating point value", "<args>", 1, 4, 4);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
#endif // INFINITY
|
||||
|
||||
static void run_tests()
|
||||
{
|
||||
json_t *value;
|
||||
|
@ -83,6 +114,32 @@ static void run_tests()
|
|||
fail("json_pack string refcount failed");
|
||||
json_decref(value);
|
||||
|
||||
/* nullable string (defined case) */
|
||||
value = json_pack("s?", "test");
|
||||
if(!json_is_string(value) || strcmp("test", json_string_value(value)))
|
||||
fail("json_pack nullable string (defined case) failed");
|
||||
if(value->refcount != (size_t)1)
|
||||
fail("json_pack nullable string (defined case) refcount failed");
|
||||
json_decref(value);
|
||||
|
||||
/* nullable string (NULL case) */
|
||||
value = json_pack("s?", NULL);
|
||||
if(!json_is_null(value))
|
||||
fail("json_pack nullable string (NULL case) failed");
|
||||
if(value->refcount != (size_t)-1)
|
||||
fail("json_pack nullable string (NULL case) refcount failed");
|
||||
json_decref(value);
|
||||
|
||||
/* nullable string concatenation */
|
||||
if(json_pack_ex(&error, 0, "s?+", "test", "ing"))
|
||||
fail("json_pack failed to catch invalid format 's?+'");
|
||||
check_error(json_error_invalid_format, "Cannot use '+' on optional strings", "<format>", 1, 2, 2);
|
||||
|
||||
/* nullable string with integer length */
|
||||
if(json_pack_ex(&error, 0, "s?#", "test", 4))
|
||||
fail("json_pack failed to catch invalid format 's?#'");
|
||||
check_error(json_error_invalid_format, "Cannot use '#' on optional strings", "<format>", 1, 2, 2);
|
||||
|
||||
/* string and length (int) */
|
||||
value = json_pack("s#", "test asdf", 4);
|
||||
if(!json_is_string(value) || strcmp("test", json_string_value(value)))
|
||||
|
@ -116,6 +173,9 @@ static void run_tests()
|
|||
json_decref(value);
|
||||
|
||||
/* string concatenation */
|
||||
if (json_pack("s+", "test", NULL))
|
||||
fail("json_pack string concatenation succeeded with NULL string");
|
||||
|
||||
value = json_pack("s++", "te", "st", "ing");
|
||||
if(!json_is_string(value) || strcmp("testing", json_string_value(value)))
|
||||
fail("json_pack string concatenation failed");
|
||||
|
@ -163,6 +223,22 @@ static void run_tests()
|
|||
fail("json_pack integer refcount failed");
|
||||
json_decref(value);
|
||||
|
||||
/* non-incref'd nullable object (defined case) */
|
||||
value = json_pack("o?", json_integer(1));
|
||||
if(!json_is_integer(value) || json_integer_value(value) != 1)
|
||||
fail("json_pack nullable object (defined case) failed");
|
||||
if(value->refcount != (size_t)1)
|
||||
fail("json_pack nullable object (defined case) refcount failed");
|
||||
json_decref(value);
|
||||
|
||||
/* non-incref'd nullable object (NULL case) */
|
||||
value = json_pack("o?", NULL);
|
||||
if(!json_is_null(value))
|
||||
fail("json_pack nullable object (NULL case) failed");
|
||||
if(value->refcount != (size_t)-1)
|
||||
fail("json_pack nullable object (NULL case) refcount failed");
|
||||
json_decref(value);
|
||||
|
||||
/* incref'd object */
|
||||
value = json_pack("O", json_integer(1));
|
||||
if(!json_is_integer(value) || json_integer_value(value) != 1)
|
||||
|
@ -172,6 +248,22 @@ static void run_tests()
|
|||
json_decref(value);
|
||||
json_decref(value);
|
||||
|
||||
/* incref'd nullable object (defined case) */
|
||||
value = json_pack("O?", json_integer(1));
|
||||
if(!json_is_integer(value) || json_integer_value(value) != 1)
|
||||
fail("json_pack incref'd nullable object (defined case) failed");
|
||||
if(value->refcount != (size_t)2)
|
||||
fail("json_pack incref'd nullable object (defined case) refcount failed");
|
||||
json_decref(value);
|
||||
json_decref(value);
|
||||
|
||||
/* incref'd nullable object (NULL case) */
|
||||
value = json_pack("O?", NULL);
|
||||
if(!json_is_null(value))
|
||||
fail("json_pack incref'd nullable object (NULL case) failed");
|
||||
if(value->refcount != (size_t)-1)
|
||||
fail("json_pack incref'd nullable object (NULL case) refcount failed");
|
||||
|
||||
/* simple object */
|
||||
value = json_pack("{s:[]}", "foo");
|
||||
if(!json_is_object(value) || json_object_size(value) != 1)
|
||||
|
@ -192,6 +284,36 @@ static void run_tests()
|
|||
fail("json_pack object refcount failed");
|
||||
json_decref(value);
|
||||
|
||||
/* object with optional members */
|
||||
value = json_pack("{s:s,s:o,s:O}", "a", NULL, "b", NULL, "c", NULL);
|
||||
if(value)
|
||||
fail("json_pack object optional incorrectly succeeded");
|
||||
|
||||
value = json_pack("{s:**}", "a", NULL);
|
||||
if(value)
|
||||
fail("json_pack object optional invalid incorrectly succeeded");
|
||||
|
||||
if (json_pack_ex(&error, 0, "{s:i*}", "a", 1))
|
||||
fail("json_pack object optional invalid incorrectly succeeded");
|
||||
check_error(json_error_invalid_format, "Expected format 's', got '*'", "<format>", 1, 5, 5);
|
||||
|
||||
value = json_pack("{s:s*,s:o*,s:O*}", "a", NULL, "b", NULL, "c", NULL);
|
||||
if(!json_is_object(value) || json_object_size(value) != 0)
|
||||
fail("json_pack object optional failed");
|
||||
json_decref(value);
|
||||
|
||||
value = json_pack("{s:s*}", "key", "\xff\xff");
|
||||
if(value)
|
||||
fail("json_pack object optional with invalid UTF-8 incorrectly succeeded");
|
||||
|
||||
if(json_pack_ex(&error, 0, "{s: s*#}", "key", "test", 1))
|
||||
fail("json_pack failed to catch invalid format 's*#'");
|
||||
check_error(json_error_invalid_format, "Cannot use '#' on optional strings", "<format>", 1, 6, 6);
|
||||
|
||||
if(json_pack_ex(&error, 0, "{s: s*+}", "key", "test", "ing"))
|
||||
fail("json_pack failed to catch invalid format 's*+'");
|
||||
check_error(json_error_invalid_format, "Cannot use '+' on optional strings", "<format>", 1, 6, 6);
|
||||
|
||||
/* simple array */
|
||||
value = json_pack("[i,i,i]", 0, 1, 2);
|
||||
if(!json_is_array(value) || json_array_size(value) != 3)
|
||||
|
@ -205,8 +327,44 @@ static void run_tests()
|
|||
}
|
||||
json_decref(value);
|
||||
|
||||
/* simple array with optional members */
|
||||
value = json_pack("[s,o,O]", NULL, NULL, NULL);
|
||||
if(value)
|
||||
fail("json_pack array optional incorrectly succeeded");
|
||||
|
||||
if (json_pack_ex(&error, 0, "[i*]", 1))
|
||||
fail("json_pack array optional invalid incorrectly succeeded");
|
||||
check_error(json_error_invalid_format, "Unexpected format character '*'", "<format>", 1, 3, 3);
|
||||
|
||||
value = json_pack("[**]", NULL);
|
||||
if(value)
|
||||
fail("json_pack array optional invalid incorrectly succeeded");
|
||||
value = json_pack("[s*,o*,O*]", NULL, NULL, NULL);
|
||||
if(!json_is_array(value) || json_array_size(value) != 0)
|
||||
fail("json_pack array optional failed");
|
||||
json_decref(value);
|
||||
|
||||
#ifdef NAN
|
||||
/* Invalid float values */
|
||||
if (json_pack_ex(&error, 0, "f", NAN))
|
||||
fail("json_pack NAN incorrectly succeeded");
|
||||
check_error(json_error_numeric_overflow, "Invalid floating point value", "<args>", 1, 1, 1);
|
||||
|
||||
if (json_pack_ex(&error, 0, "[f]", NAN))
|
||||
fail("json_pack NAN array element incorrectly succeeded");
|
||||
check_error(json_error_numeric_overflow, "Invalid floating point value", "<args>", 1, 2, 2);
|
||||
|
||||
if (json_pack_ex(&error, 0, "{s:f}", "key", NAN))
|
||||
fail("json_pack NAN object value incorrectly succeeded");
|
||||
check_error(json_error_numeric_overflow, "Invalid floating point value", "<args>", 1, 4, 4);
|
||||
#endif
|
||||
|
||||
#ifdef INFINITY
|
||||
test_inifity();
|
||||
#endif
|
||||
|
||||
/* Whitespace; regular string */
|
||||
value = json_pack(" s ", "test");
|
||||
value = json_pack(" s\t ", "test");
|
||||
if(!json_is_string(value) || strcmp("test", json_string_value(value)))
|
||||
fail("json_pack string (with whitespace) failed");
|
||||
json_decref(value);
|
||||
|
@ -230,78 +388,131 @@ static void run_tests()
|
|||
/* newline in format string */
|
||||
if(json_pack_ex(&error, 0, "{\n\n1"))
|
||||
fail("json_pack failed to catch invalid format '1'");
|
||||
check_error("Expected format 's', got '1'", "<format>", 3, 1, 4);
|
||||
check_error(json_error_invalid_format, "Expected format 's', got '1'", "<format>", 3, 1, 4);
|
||||
|
||||
/* mismatched open/close array/object */
|
||||
if(json_pack_ex(&error, 0, "[}"))
|
||||
fail("json_pack failed to catch mismatched '}'");
|
||||
check_error("Unexpected format character '}'", "<format>", 1, 2, 2);
|
||||
check_error(json_error_invalid_format, "Unexpected format character '}'", "<format>", 1, 2, 2);
|
||||
|
||||
if(json_pack_ex(&error, 0, "{]"))
|
||||
fail("json_pack failed to catch mismatched ']'");
|
||||
check_error("Expected format 's', got ']'", "<format>", 1, 2, 2);
|
||||
check_error(json_error_invalid_format, "Expected format 's', got ']'", "<format>", 1, 2, 2);
|
||||
|
||||
/* missing close array */
|
||||
if(json_pack_ex(&error, 0, "["))
|
||||
fail("json_pack failed to catch missing ']'");
|
||||
check_error("Unexpected end of format string", "<format>", 1, 2, 2);
|
||||
check_error(json_error_invalid_format, "Unexpected end of format string", "<format>", 1, 2, 2);
|
||||
|
||||
/* missing close object */
|
||||
if(json_pack_ex(&error, 0, "{"))
|
||||
fail("json_pack failed to catch missing '}'");
|
||||
check_error("Unexpected end of format string", "<format>", 1, 2, 2);
|
||||
check_error(json_error_invalid_format, "Unexpected end of format string", "<format>", 1, 2, 2);
|
||||
|
||||
/* garbage after format string */
|
||||
if(json_pack_ex(&error, 0, "[i]a", 42))
|
||||
fail("json_pack failed to catch garbage after format string");
|
||||
check_error("Garbage after format string", "<format>", 1, 4, 4);
|
||||
check_error(json_error_invalid_format, "Garbage after format string", "<format>", 1, 4, 4);
|
||||
|
||||
if(json_pack_ex(&error, 0, "ia", 42))
|
||||
fail("json_pack failed to catch garbage after format string");
|
||||
check_error("Garbage after format string", "<format>", 1, 2, 2);
|
||||
check_error(json_error_invalid_format, "Garbage after format string", "<format>", 1, 2, 2);
|
||||
|
||||
/* NULL string */
|
||||
if(json_pack_ex(&error, 0, "s", NULL))
|
||||
fail("json_pack failed to catch null argument string");
|
||||
check_error("NULL string argument", "<args>", 1, 1, 1);
|
||||
check_error(json_error_null_value, "NULL string", "<args>", 1, 1, 1);
|
||||
|
||||
/* + on its own */
|
||||
if(json_pack_ex(&error, 0, "+", NULL))
|
||||
fail("json_pack failed to a lone +");
|
||||
check_error("Unexpected format character '+'", "<format>", 1, 1, 1);
|
||||
check_error(json_error_invalid_format, "Unexpected format character '+'", "<format>", 1, 1, 1);
|
||||
|
||||
/* Empty format */
|
||||
if(json_pack_ex(&error, 0, ""))
|
||||
fail("json_pack failed to catch empty format string");
|
||||
check_error(json_error_invalid_argument, "NULL or empty format string", "<format>", -1, -1, 0);
|
||||
|
||||
/* NULL format */
|
||||
if(json_pack_ex(&error, 0, NULL))
|
||||
fail("json_pack failed to catch NULL format string");
|
||||
check_error("NULL or empty format string", "<format>", -1, -1, 0);
|
||||
check_error(json_error_invalid_argument, "NULL or empty format string", "<format>", -1, -1, 0);
|
||||
|
||||
/* NULL key */
|
||||
if(json_pack_ex(&error, 0, "{s:i}", NULL, 1))
|
||||
fail("json_pack failed to catch NULL key");
|
||||
check_error("NULL string argument", "<args>", 1, 2, 2);
|
||||
check_error(json_error_null_value, "NULL object key", "<args>", 1, 2, 2);
|
||||
|
||||
/* NULL value followed by object still steals the object's ref */
|
||||
value = json_incref(json_object());
|
||||
if(json_pack_ex(&error, 0, "{s:s,s:o}", "badnull", NULL, "dontleak", value))
|
||||
fail("json_pack failed to catch NULL value");
|
||||
check_error(json_error_null_value, "NULL string", "<args>", 1, 4, 4);
|
||||
if(value->refcount != (size_t)1)
|
||||
fail("json_pack failed to steal reference after error.");
|
||||
json_decref(value);
|
||||
|
||||
/* More complicated checks for row/columns */
|
||||
if(json_pack_ex(&error, 0, "{ {}: s }", "foo"))
|
||||
fail("json_pack failed to catch object as key");
|
||||
check_error("Expected format 's', got '{'", "<format>", 1, 3, 3);
|
||||
check_error(json_error_invalid_format, "Expected format 's', got '{'", "<format>", 1, 3, 3);
|
||||
|
||||
/* Complex object */
|
||||
if(json_pack_ex(&error, 0, "{ s: {}, s:[ii{} }", "foo", "bar", 12, 13))
|
||||
fail("json_pack failed to catch missing ]");
|
||||
check_error("Unexpected format character '}'", "<format>", 1, 19, 19);
|
||||
check_error(json_error_invalid_format, "Unexpected format character '}'", "<format>", 1, 19, 19);
|
||||
|
||||
/* Complex array */
|
||||
if(json_pack_ex(&error, 0, "[[[[[ [[[[[ [[[[ }]]]] ]]]] ]]]]]"))
|
||||
fail("json_pack failed to catch extra }");
|
||||
check_error("Unexpected format character '}'", "<format>", 1, 21, 21);
|
||||
check_error(json_error_invalid_format, "Unexpected format character '}'", "<format>", 1, 21, 21);
|
||||
|
||||
/* Invalid UTF-8 in object key */
|
||||
if(json_pack_ex(&error, 0, "{s:i}", "\xff\xff", 42))
|
||||
fail("json_pack failed to catch invalid UTF-8 in an object key");
|
||||
check_error("Invalid UTF-8 object key", "<args>", 1, 2, 2);
|
||||
check_error(json_error_invalid_utf8, "Invalid UTF-8 object key", "<args>", 1, 2, 2);
|
||||
|
||||
/* Invalid UTF-8 in a string */
|
||||
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);
|
||||
check_error(json_error_invalid_utf8, "Invalid UTF-8 string", "<args>", 1, 4, 4);
|
||||
|
||||
/* Invalid UTF-8 in an optional '?' string */
|
||||
if(json_pack_ex(&error, 0, "{s:s?}", "foo", "\xff\xff"))
|
||||
fail("json_pack failed to catch invalid UTF-8 in an optional '?' string");
|
||||
check_error(json_error_invalid_utf8, "Invalid UTF-8 string", "<args>", 1, 5, 5);
|
||||
|
||||
/* Invalid UTF-8 in an optional '*' string */
|
||||
if(json_pack_ex(&error, 0, "{s:s*}", "foo", "\xff\xff"))
|
||||
fail("json_pack failed to catch invalid UTF-8 in an optional '*' string");
|
||||
check_error(json_error_invalid_utf8, "Invalid UTF-8 string", "<args>", 1, 5, 5);
|
||||
|
||||
/* Invalid UTF-8 in a concatenated key */
|
||||
if(json_pack_ex(&error, 0, "{s+:i}", "\xff\xff", "concat", 42))
|
||||
fail("json_pack failed to catch invalid UTF-8 in an object key");
|
||||
check_error(json_error_invalid_utf8, "Invalid UTF-8 object key", "<args>", 1, 3, 3);
|
||||
|
||||
if(json_pack_ex(&error, 0, "{s:o}", "foo", NULL))
|
||||
fail("json_pack failed to catch nullable object");
|
||||
check_error(json_error_null_value, "NULL object", "<args>", 1, 4, 4);
|
||||
|
||||
if(json_pack_ex(&error, 0, "{s:O}", "foo", NULL))
|
||||
fail("json_pack failed to catch nullable incref object");
|
||||
check_error(json_error_null_value, "NULL object", "<args>", 1, 4, 4);
|
||||
|
||||
if(json_pack_ex(&error, 0, "{s+:o}", "foo", "bar", NULL))
|
||||
fail("json_pack failed to catch non-nullable object value");
|
||||
check_error(json_error_null_value, "NULL object", "<args>", 1, 5, 5);
|
||||
|
||||
if(json_pack_ex(&error, 0, "[1s", "Hi"))
|
||||
fail("json_pack failed to catch invalid format");
|
||||
check_error(json_error_invalid_format, "Unexpected format character '1'", "<format>", 1, 2, 2);
|
||||
|
||||
if(json_pack_ex(&error, 0, "[1s+", "Hi", "ya"))
|
||||
fail("json_pack failed to catch invalid format");
|
||||
check_error(json_error_invalid_format, "Unexpected format character '1'", "<format>", 1, 2, 2);
|
||||
|
||||
if(json_pack_ex(&error, 0, "[so]", NULL, json_object()))
|
||||
fail("json_pack failed to catch NULL value");
|
||||
check_error(json_error_null_value, "NULL string", "<args>", 1, 2, 2);
|
||||
}
|
||||
|
|
|
@ -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,6 +9,56 @@
|
|||
#include <jansson.h>
|
||||
#include "util.h"
|
||||
|
||||
static void test_bad_args(void)
|
||||
{
|
||||
json_t *num = json_integer(1);
|
||||
json_t *txt = json_string("test");
|
||||
|
||||
if (!num || !txt)
|
||||
fail("failed to allocate test objects");
|
||||
|
||||
if(json_string_nocheck(NULL) != NULL)
|
||||
fail("json_string_nocheck with NULL argument did not return NULL");
|
||||
if(json_stringn_nocheck(NULL, 0) != NULL)
|
||||
fail("json_stringn_nocheck with NULL argument did not return NULL");
|
||||
if(json_string(NULL) != NULL)
|
||||
fail("json_string with NULL argument did not return NULL");
|
||||
if(json_stringn(NULL, 0) != NULL)
|
||||
fail("json_stringn with NULL argument did not return NULL");
|
||||
|
||||
if(json_string_length(NULL) != 0)
|
||||
fail("json_string_length with non-string argument did not return 0");
|
||||
if(json_string_length(num) != 0)
|
||||
fail("json_string_length with non-string argument did not return 0");
|
||||
|
||||
if(json_string_value(NULL) != NULL)
|
||||
fail("json_string_value with non-string argument did not return NULL");
|
||||
if(json_string_value(num) != NULL)
|
||||
fail("json_string_value with non-string argument did not return NULL");
|
||||
|
||||
if(!json_string_setn_nocheck(NULL, "", 0))
|
||||
fail("json_string_setn with non-string argument did not return error");
|
||||
if(!json_string_setn_nocheck(num, "", 0))
|
||||
fail("json_string_setn with non-string argument did not return error");
|
||||
if(!json_string_setn_nocheck(txt, NULL, 0))
|
||||
fail("json_string_setn_nocheck with NULL value did not return error");
|
||||
|
||||
if(!json_string_set_nocheck(txt, NULL))
|
||||
fail("json_string_set_nocheck with NULL value did not return error");
|
||||
if(!json_string_set(txt, NULL))
|
||||
fail("json_string_set with NULL value did not return error");
|
||||
if(!json_string_setn(txt, NULL, 0))
|
||||
fail("json_string_setn with NULL value did not return error");
|
||||
|
||||
if(num->refcount != 1)
|
||||
fail("unexpected reference count for num");
|
||||
if(txt->refcount != 1)
|
||||
fail("unexpected reference count for txt");
|
||||
|
||||
json_decref(num);
|
||||
json_decref(txt);
|
||||
}
|
||||
|
||||
/* Call the simple functions not covered by other tests of the public API */
|
||||
static void run_tests()
|
||||
{
|
||||
|
@ -224,4 +274,19 @@ static void run_tests()
|
|||
json_incref(value);
|
||||
if(value->refcount != (size_t)-1)
|
||||
fail("refcounting null works incorrectly");
|
||||
|
||||
#ifdef json_auto_t
|
||||
value = json_string("foo");
|
||||
{
|
||||
json_auto_t *test = json_incref(value);
|
||||
/* Use test so GCC doesn't complain it is unused. */
|
||||
if(!json_is_string(test))
|
||||
fail("value type check failed");
|
||||
}
|
||||
if(value->refcount != 1)
|
||||
fail("automatic decrement failed");
|
||||
json_decref(value);
|
||||
#endif
|
||||
|
||||
test_bad_args();
|
||||
}
|
||||
|
|
34
jansson/test/suites/api/test_sprintf.c
Normal file
34
jansson/test/suites/api/test_sprintf.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
#include <string.h>
|
||||
#include <jansson.h>
|
||||
#include "util.h"
|
||||
|
||||
|
||||
static void test_sprintf() {
|
||||
json_t *s = json_sprintf("foo bar %d", 42);
|
||||
if (!s)
|
||||
fail("json_sprintf returned NULL");
|
||||
if (!json_is_string(s))
|
||||
fail("json_sprintf didn't return a JSON string");
|
||||
if (strcmp(json_string_value(s), "foo bar 42"))
|
||||
fail("json_sprintf generated an unexpected string");
|
||||
|
||||
json_decref(s);
|
||||
|
||||
s = json_sprintf("%s", "");
|
||||
if (!s)
|
||||
fail("json_sprintf returned NULL");
|
||||
if (!json_is_string(s))
|
||||
fail("json_sprintf didn't return a JSON string");
|
||||
if (json_string_length(s) != 0)
|
||||
fail("string is not empty");
|
||||
json_decref(s);
|
||||
|
||||
if (json_sprintf("%s", "\xff\xff"))
|
||||
fail("json_sprintf unexpected success with invalid UTF");
|
||||
}
|
||||
|
||||
|
||||
static void run_tests()
|
||||
{
|
||||
test_sprintf();
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2009-2014 Petri Lehtinen <petri@digip.org>
|
||||
* Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
|
||||
* Copyright (c) 2010-2012 Graeme Smecher <graeme.smecher@mail.mcgill.ca>
|
||||
*
|
||||
* Jansson is free software; you can redistribute it and/or modify
|
||||
|
@ -144,65 +144,65 @@ static void run_tests()
|
|||
j = json_integer(42);
|
||||
if(!json_unpack_ex(j, &error, 0, "z"))
|
||||
fail("json_unpack succeeded with invalid format character");
|
||||
check_error("Unexpected format character 'z'", "<format>", 1, 1, 1);
|
||||
check_error(json_error_invalid_format, "Unexpected format character 'z'", "<format>", 1, 1, 1);
|
||||
|
||||
if(!json_unpack_ex(NULL, &error, 0, "[i]"))
|
||||
fail("json_unpack succeeded with NULL root");
|
||||
check_error("NULL root value", "<root>", -1, -1, 0);
|
||||
check_error(json_error_null_value, "NULL root value", "<root>", -1, -1, 0);
|
||||
json_decref(j);
|
||||
|
||||
/* mismatched open/close array/object */
|
||||
j = json_pack("[]");
|
||||
if(!json_unpack_ex(j, &error, 0, "[}"))
|
||||
fail("json_unpack failed to catch mismatched ']'");
|
||||
check_error("Unexpected format character '}'", "<format>", 1, 2, 2);
|
||||
check_error(json_error_invalid_format, "Unexpected format character '}'", "<format>", 1, 2, 2);
|
||||
json_decref(j);
|
||||
|
||||
j = json_pack("{}");
|
||||
if(!json_unpack_ex(j, &error, 0, "{]"))
|
||||
fail("json_unpack failed to catch mismatched '}'");
|
||||
check_error("Expected format 's', got ']'", "<format>", 1, 2, 2);
|
||||
check_error(json_error_invalid_format, "Expected format 's', got ']'", "<format>", 1, 2, 2);
|
||||
json_decref(j);
|
||||
|
||||
/* missing close array */
|
||||
j = json_pack("[]");
|
||||
if(!json_unpack_ex(j, &error, 0, "["))
|
||||
fail("json_unpack failed to catch missing ']'");
|
||||
check_error("Unexpected end of format string", "<format>", 1, 2, 2);
|
||||
check_error(json_error_invalid_format, "Unexpected end of format string", "<format>", 1, 2, 2);
|
||||
json_decref(j);
|
||||
|
||||
/* missing close object */
|
||||
j = json_pack("{}");
|
||||
if(!json_unpack_ex(j, &error, 0, "{"))
|
||||
fail("json_unpack failed to catch missing '}'");
|
||||
check_error("Unexpected end of format string", "<format>", 1, 2, 2);
|
||||
check_error(json_error_invalid_format, "Unexpected end of format string", "<format>", 1, 2, 2);
|
||||
json_decref(j);
|
||||
|
||||
/* garbage after format string */
|
||||
j = json_pack("[i]", 42);
|
||||
if(!json_unpack_ex(j, &error, 0, "[i]a", &i1))
|
||||
fail("json_unpack failed to catch garbage after format string");
|
||||
check_error("Garbage after format string", "<format>", 1, 4, 4);
|
||||
check_error(json_error_invalid_format, "Garbage after format string", "<format>", 1, 4, 4);
|
||||
json_decref(j);
|
||||
|
||||
j = json_integer(12345);
|
||||
if(!json_unpack_ex(j, &error, 0, "ia", &i1))
|
||||
fail("json_unpack failed to catch garbage after format string");
|
||||
check_error("Garbage after format string", "<format>", 1, 2, 2);
|
||||
check_error(json_error_invalid_format, "Garbage after format string", "<format>", 1, 2, 2);
|
||||
json_decref(j);
|
||||
|
||||
/* NULL format string */
|
||||
j = json_pack("[]");
|
||||
if(!json_unpack_ex(j, &error, 0, NULL))
|
||||
fail("json_unpack failed to catch null format string");
|
||||
check_error("NULL or empty format string", "<format>", -1, -1, 0);
|
||||
check_error(json_error_invalid_argument, "NULL or empty format string", "<format>", -1, -1, 0);
|
||||
json_decref(j);
|
||||
|
||||
/* NULL string pointer */
|
||||
j = json_string("foobie");
|
||||
if(!json_unpack_ex(j, &error, 0, "s", NULL))
|
||||
fail("json_unpack failed to catch null string pointer");
|
||||
check_error("NULL string argument", "<args>", 1, 1, 1);
|
||||
check_error(json_error_null_value, "NULL string argument", "<args>", 1, 1, 1);
|
||||
json_decref(j);
|
||||
|
||||
/* invalid types */
|
||||
|
@ -210,39 +210,39 @@ static void run_tests()
|
|||
j2 = json_string("foo");
|
||||
if(!json_unpack_ex(j, &error, 0, "s"))
|
||||
fail("json_unpack failed to catch invalid type");
|
||||
check_error("Expected string, got integer", "<validation>", 1, 1, 1);
|
||||
check_error(json_error_wrong_type, "Expected string, got integer", "<validation>", 1, 1, 1);
|
||||
|
||||
if(!json_unpack_ex(j, &error, 0, "n"))
|
||||
fail("json_unpack failed to catch invalid type");
|
||||
check_error("Expected null, got integer", "<validation>", 1, 1, 1);
|
||||
check_error(json_error_wrong_type, "Expected null, got integer", "<validation>", 1, 1, 1);
|
||||
|
||||
if(!json_unpack_ex(j, &error, 0, "b"))
|
||||
fail("json_unpack failed to catch invalid type");
|
||||
check_error("Expected true or false, got integer", "<validation>", 1, 1, 1);
|
||||
check_error(json_error_wrong_type, "Expected true or false, got integer", "<validation>", 1, 1, 1);
|
||||
|
||||
if(!json_unpack_ex(j2, &error, 0, "i"))
|
||||
fail("json_unpack failed to catch invalid type");
|
||||
check_error("Expected integer, got string", "<validation>", 1, 1, 1);
|
||||
check_error(json_error_wrong_type, "Expected integer, got string", "<validation>", 1, 1, 1);
|
||||
|
||||
if(!json_unpack_ex(j2, &error, 0, "I"))
|
||||
fail("json_unpack failed to catch invalid type");
|
||||
check_error("Expected integer, got string", "<validation>", 1, 1, 1);
|
||||
check_error(json_error_wrong_type, "Expected integer, got string", "<validation>", 1, 1, 1);
|
||||
|
||||
if(!json_unpack_ex(j, &error, 0, "f"))
|
||||
fail("json_unpack failed to catch invalid type");
|
||||
check_error("Expected real, got integer", "<validation>", 1, 1, 1);
|
||||
check_error(json_error_wrong_type, "Expected real, got integer", "<validation>", 1, 1, 1);
|
||||
|
||||
if(!json_unpack_ex(j2, &error, 0, "F"))
|
||||
fail("json_unpack failed to catch invalid type");
|
||||
check_error("Expected real or integer, got string", "<validation>", 1, 1, 1);
|
||||
check_error(json_error_wrong_type, "Expected real or integer, got string", "<validation>", 1, 1, 1);
|
||||
|
||||
if(!json_unpack_ex(j, &error, 0, "[i]"))
|
||||
fail("json_unpack failed to catch invalid type");
|
||||
check_error("Expected array, got integer", "<validation>", 1, 1, 1);
|
||||
check_error(json_error_wrong_type, "Expected array, got integer", "<validation>", 1, 1, 1);
|
||||
|
||||
if(!json_unpack_ex(j, &error, 0, "{si}", "foo"))
|
||||
fail("json_unpack failed to catch invalid type");
|
||||
check_error("Expected object, got integer", "<validation>", 1, 1, 1);
|
||||
check_error(json_error_wrong_type, "Expected object, got integer", "<validation>", 1, 1, 1);
|
||||
|
||||
json_decref(j);
|
||||
json_decref(j2);
|
||||
|
@ -251,21 +251,21 @@ static void run_tests()
|
|||
j = json_pack("[i]", 1);
|
||||
if(!json_unpack_ex(j, &error, 0, "[ii]", &i1, &i2))
|
||||
fail("json_unpack failed to catch index out of array bounds");
|
||||
check_error("Array index 1 out of range", "<validation>", 1, 3, 3);
|
||||
check_error(json_error_index_out_of_range, "Array index 1 out of range", "<validation>", 1, 3, 3);
|
||||
json_decref(j);
|
||||
|
||||
/* NULL object key */
|
||||
j = json_pack("{si}", "foo", 42);
|
||||
if(!json_unpack_ex(j, &error, 0, "{si}", NULL, &i1))
|
||||
fail("json_unpack failed to catch null string pointer");
|
||||
check_error("NULL object key", "<args>", 1, 2, 2);
|
||||
check_error(json_error_null_value, "NULL object key", "<args>", 1, 2, 2);
|
||||
json_decref(j);
|
||||
|
||||
/* Object key not found */
|
||||
j = json_pack("{si}", "foo", 42);
|
||||
if(!json_unpack_ex(j, &error, 0, "{si}", "baz", &i1))
|
||||
fail("json_unpack failed to catch null string pointer");
|
||||
check_error("Object item not found: baz", "<validation>", 1, 3, 3);
|
||||
check_error(json_error_item_not_found, "Object item not found: baz", "<validation>", 1, 3, 3);
|
||||
json_decref(j);
|
||||
|
||||
/*
|
||||
|
@ -281,14 +281,14 @@ static void run_tests()
|
|||
j = json_pack("[iii]", 1, 2, 3);
|
||||
if(!json_unpack_ex(j, &error, 0, "[ii!]", &i1, &i2))
|
||||
fail("json_unpack array with strict validation failed");
|
||||
check_error("1 array item(s) left unpacked", "<validation>", 1, 5, 5);
|
||||
check_error(json_error_end_of_input_expected, "1 array item(s) left unpacked", "<validation>", 1, 5, 5);
|
||||
json_decref(j);
|
||||
|
||||
/* Like above, but with JSON_STRICT instead of '!' format */
|
||||
j = json_pack("[iii]", 1, 2, 3);
|
||||
if(!json_unpack_ex(j, &error, JSON_STRICT, "[ii]", &i1, &i2))
|
||||
fail("json_unpack array with strict validation failed");
|
||||
check_error("1 array item(s) left unpacked", "<validation>", 1, 4, 4);
|
||||
check_error(json_error_end_of_input_expected, "1 array item(s) left unpacked", "<validation>", 1, 4, 4);
|
||||
json_decref(j);
|
||||
|
||||
j = json_pack("{s:s, s:i}", "foo", "bar", "baz", 42);
|
||||
|
@ -298,10 +298,16 @@ static void run_tests()
|
|||
json_decref(j);
|
||||
|
||||
/* Unpack the same item twice */
|
||||
j = json_pack("{s:s, s:i}", "foo", "bar", "baz", 42);
|
||||
j = json_pack("{s:s, s:i, s:b}", "foo", "bar", "baz", 42, "quux", 1);
|
||||
if(!json_unpack_ex(j, &error, 0, "{s:s,s:s!}", "foo", &s, "foo", &s))
|
||||
fail("json_unpack object with strict validation failed");
|
||||
check_error("1 object item(s) left unpacked", "<validation>", 1, 10, 10);
|
||||
{
|
||||
const char *possible_errors[] = {
|
||||
"2 object item(s) left unpacked: baz, quux",
|
||||
"2 object item(s) left unpacked: quux, baz"
|
||||
};
|
||||
check_errors(json_error_end_of_input_expected, possible_errors, 2, "<validation>", 1, 10, 10);
|
||||
}
|
||||
json_decref(j);
|
||||
|
||||
j = json_pack("[i,{s:i,s:n},[i,i]]", 1, "foo", 2, "bar", 3, 4);
|
||||
|
@ -314,35 +320,35 @@ static void run_tests()
|
|||
j = json_pack("[ii]", 1, 2);
|
||||
if(!json_unpack_ex(j, &error, 0, "[i!i]", &i1, &i2))
|
||||
fail("json_unpack failed to catch ! in the middle of an array");
|
||||
check_error("Expected ']' after '!', got 'i'", "<format>", 1, 4, 4);
|
||||
check_error(json_error_invalid_format, "Expected ']' after '!', got 'i'", "<format>", 1, 4, 4);
|
||||
|
||||
if(!json_unpack_ex(j, &error, 0, "[i*i]", &i1, &i2))
|
||||
fail("json_unpack failed to catch * in the middle of an array");
|
||||
check_error("Expected ']' after '*', got 'i'", "<format>", 1, 4, 4);
|
||||
check_error(json_error_invalid_format, "Expected ']' after '*', got 'i'", "<format>", 1, 4, 4);
|
||||
json_decref(j);
|
||||
|
||||
j = json_pack("{sssi}", "foo", "bar", "baz", 42);
|
||||
if(!json_unpack_ex(j, &error, 0, "{ss!si}", "foo", &s, "baz", &i1))
|
||||
fail("json_unpack failed to catch ! in the middle of an object");
|
||||
check_error("Expected '}' after '!', got 's'", "<format>", 1, 5, 5);
|
||||
check_error(json_error_invalid_format, "Expected '}' after '!', got 's'", "<format>", 1, 5, 5);
|
||||
|
||||
if(!json_unpack_ex(j, &error, 0, "{ss*si}", "foo", &s, "baz", &i1))
|
||||
fail("json_unpack failed to catch ! in the middle of an object");
|
||||
check_error("Expected '}' after '*', got 's'", "<format>", 1, 5, 5);
|
||||
check_error(json_error_invalid_format, "Expected '}' after '*', got 's'", "<format>", 1, 5, 5);
|
||||
json_decref(j);
|
||||
|
||||
/* Error in nested object */
|
||||
j = json_pack("{s{snsn}}", "foo", "bar", "baz");
|
||||
if(!json_unpack_ex(j, &error, 0, "{s{sn!}}", "foo", "bar"))
|
||||
fail("json_unpack nested object with strict validation failed");
|
||||
check_error("1 object item(s) left unpacked", "<validation>", 1, 7, 7);
|
||||
check_error(json_error_end_of_input_expected, "1 object item(s) left unpacked: baz", "<validation>", 1, 7, 7);
|
||||
json_decref(j);
|
||||
|
||||
/* Error in nested array */
|
||||
j = json_pack("[[ii]]", 1, 2);
|
||||
if(!json_unpack_ex(j, &error, 0, "[[i!]]", &i1))
|
||||
fail("json_unpack nested array with strict validation failed");
|
||||
check_error("1 array item(s) left unpacked", "<validation>", 1, 5, 5);
|
||||
check_error(json_error_end_of_input_expected, "1 array item(s) left unpacked", "<validation>", 1, 5, 5);
|
||||
json_decref(j);
|
||||
|
||||
/* Optional values */
|
||||
|
@ -395,6 +401,6 @@ static void run_tests()
|
|||
i1 = i2 = i3 = 0;
|
||||
if(!json_unpack_ex(j, &error, 0, "{sis?i!}", "foo", &i1, "bar", &i2))
|
||||
fail("json_unpack failed for optional values with strict mode and compensation");
|
||||
check_error("1 object item(s) left unpacked", "<validation>", 1, 8, 8);
|
||||
check_error(json_error_end_of_input_expected, "1 object item(s) left unpacked: baz", "<validation>", 1, 8, 8);
|
||||
json_decref(j);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -20,7 +20,7 @@
|
|||
|
||||
#include <jansson.h>
|
||||
|
||||
#define failhdr fprintf(stderr, "%s:%s:%d: ", __FILE__, __FUNCTION__, __LINE__)
|
||||
#define failhdr fprintf(stderr, "%s:%d: ", __FILE__, __LINE__)
|
||||
|
||||
#define fail(msg) \
|
||||
do { \
|
||||
|
@ -30,11 +30,29 @@
|
|||
} while(0)
|
||||
|
||||
/* Assumes json_error_t error */
|
||||
#define check_error(text_, source_, line_, column_, position_) \
|
||||
#define check_errors(code_, texts_, num_, source_, \
|
||||
line_, column_, position_) \
|
||||
do { \
|
||||
if(strcmp(error.text, text_) != 0) { \
|
||||
int i_, found_ = 0; \
|
||||
if(json_error_code(&error) != code_) { \
|
||||
failhdr; \
|
||||
fprintf(stderr, "text: \"%s\" != \"%s\"\n", error.text, text_); \
|
||||
fprintf(stderr, "code: %d != %d\n", \
|
||||
json_error_code(&error), code_); \
|
||||
exit(1); \
|
||||
} \
|
||||
for(i_ = 0; i_ < num_; i_++) { \
|
||||
if(strcmp(error.text, texts_[i_]) == 0) { \
|
||||
found_ = 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
if (!found_) { \
|
||||
failhdr; \
|
||||
if (num_ == 1) { \
|
||||
fprintf(stderr, "text: \"%s\" != \"%s\"\n", error.text, texts_[0]); \
|
||||
} else { \
|
||||
fprintf(stderr, "text: \"%s\" does not match\n", error.text); \
|
||||
} \
|
||||
exit(1); \
|
||||
} \
|
||||
if(strcmp(error.source, source_) != 0) { \
|
||||
|
@ -61,6 +79,11 @@
|
|||
} while(0)
|
||||
|
||||
|
||||
/* Assumes json_error_t error */
|
||||
#define check_error(code_, text_, source_, line_, column_, position_) \
|
||||
check_errors(code_, &text_, 1, source_, line_, column_, position_)
|
||||
|
||||
|
||||
static void run_tests();
|
||||
|
||||
int main() {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# 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.
|
||||
|
|
2
jansson/test/suites/invalid/invalid-unicode-escape/error
Normal file
2
jansson/test/suites/invalid/invalid-unicode-escape/error
Normal file
|
@ -0,0 +1,2 @@
|
|||
1 5 5
|
||||
invalid escape near '"\uq'
|
1
jansson/test/suites/invalid/invalid-unicode-escape/input
Normal file
1
jansson/test/suites/invalid/invalid-unicode-escape/input
Normal file
|
@ -0,0 +1 @@
|
|||
["\uqqqq <-- invalid unicode escape"]
|
2
jansson/test/suites/invalid/null-escape-in-string/error
Normal file
2
jansson/test/suites/invalid/null-escape-in-string/error
Normal file
|
@ -0,0 +1,2 @@
|
|||
1 33 33
|
||||
\u0000 is not allowed without JSON_ALLOW_NUL
|
1
jansson/test/suites/invalid/null-escape-in-string/input
Normal file
1
jansson/test/suites/invalid/null-escape-in-string/input
Normal file
|
@ -0,0 +1 @@
|
|||
["null escape \u0000 not allowed"]
|
2
jansson/test/suites/invalid/recursion-depth/error
Normal file
2
jansson/test/suites/invalid/recursion-depth/error
Normal file
|
@ -0,0 +1,2 @@
|
|||
1 2049 2049
|
||||
maximum parsing depth reached near '['
|
1
jansson/test/suites/invalid/recursion-depth/input
Normal file
1
jansson/test/suites/invalid/recursion-depth/input
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,6 +1,6 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# 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.
|
||||
|
|
1
jansson/test/suites/valid/real-subnormal-number/input
Normal file
1
jansson/test/suites/valid/real-subnormal-number/input
Normal file
|
@ -0,0 +1 @@
|
|||
[1.8011670033376514e-308]
|
1
jansson/test/suites/valid/real-subnormal-number/output
Normal file
1
jansson/test/suites/valid/real-subnormal-number/output
Normal file
|
@ -0,0 +1 @@
|
|||
[1.8011670033376514e-308]
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# 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.
|
||||
|
|
47
libpng/ANNOUNCE
Normal file
47
libpng/ANNOUNCE
Normal file
|
@ -0,0 +1,47 @@
|
|||
libpng 1.6.37 - April 14, 2019
|
||||
==============================
|
||||
|
||||
This is a public release of libpng, intended for use in production code.
|
||||
|
||||
|
||||
Files available for download
|
||||
----------------------------
|
||||
|
||||
Source files with LF line endings (for Unix/Linux):
|
||||
|
||||
* libpng-1.6.37.tar.xz (LZMA-compressed, recommended)
|
||||
* libpng-1.6.37.tar.gz
|
||||
|
||||
Source files with CRLF line endings (for Windows):
|
||||
|
||||
* lp1637.7z (LZMA-compressed, recommended)
|
||||
* lp1637.zip
|
||||
|
||||
Other information:
|
||||
|
||||
* README.md
|
||||
* LICENSE.md
|
||||
* AUTHORS.md
|
||||
* TRADEMARK.md
|
||||
|
||||
|
||||
Changes since the previous public release (version 1.6.36)
|
||||
----------------------------------------------------------
|
||||
|
||||
* Fixed a use-after-free vulnerability (CVE-2019-7317) in png_image_free.
|
||||
* Fixed a memory leak in the ARM NEON implementation of png_do_expand_palette.
|
||||
* Fixed a memory leak in pngtest.c.
|
||||
* Fixed two vulnerabilities (CVE-2018-14048, CVE-2018-14550) in
|
||||
contrib/pngminus; refactor.
|
||||
* Changed the license of contrib/pngminus to MIT; refresh makefile and docs.
|
||||
(Contributed by Willem van Schaik)
|
||||
* Fixed a typo in the libpng license v2.
|
||||
(Contributed by Miguel Ojeda)
|
||||
* Added makefiles for AddressSanitizer-enabled builds.
|
||||
* Cleaned up various makefiles.
|
||||
|
||||
|
||||
Send comments/corrections/commendations to png-mng-implement at lists.sf.net.
|
||||
Subscription is required; visit
|
||||
https://lists.sourceforge.net/lists/listinfo/png-mng-implement
|
||||
to subscribe.
|
45
libpng/AUTHORS
Normal file
45
libpng/AUTHORS
Normal file
|
@ -0,0 +1,45 @@
|
|||
PNG REFERENCE LIBRARY AUTHORS
|
||||
=============================
|
||||
|
||||
This is the list of PNG Reference Library ("libpng") Contributing
|
||||
Authors, for copyright and licensing purposes.
|
||||
|
||||
* Andreas Dilger
|
||||
* Cosmin Truta
|
||||
* Dave Martindale
|
||||
* Eric S. Raymond
|
||||
* Gilles Vollant
|
||||
* Glenn Randers-Pehrson
|
||||
* Greg Roelofs
|
||||
* Guy Eric Schalnat
|
||||
* James Yu
|
||||
* John Bowler
|
||||
* Kevin Bracey
|
||||
* Magnus Holmgren
|
||||
* Mandar Sahastrabuddhe
|
||||
* Mans Rullgard
|
||||
* Matt Sarett
|
||||
* Mike Klein
|
||||
* Paul Schmidt
|
||||
* Sam Bushell
|
||||
* Samuel Williams
|
||||
* Simon-Pierre Cadieux
|
||||
* Tim Wegner
|
||||
* Tom Lane
|
||||
* Tom Tanner
|
||||
* Vadim Barkov
|
||||
* Willem van Schaik
|
||||
* Zhijie Liang
|
||||
* Arm Holdings
|
||||
- Richard Townsend
|
||||
* Google Inc.
|
||||
- Matt Sarett
|
||||
- Mike Klein
|
||||
|
||||
The build projects, the build scripts, the test scripts, and other
|
||||
files in the "projects", "scripts" and "tests" directories, have other
|
||||
copyright owners, but are released under the libpng license.
|
||||
|
||||
Some files in the "contrib" directory, and some tools-generated files
|
||||
that are distributed with libpng, have other copyright owners, and are
|
||||
released under other open source licenses.
|
6109
libpng/CHANGES
Normal file
6109
libpng/CHANGES
Normal file
File diff suppressed because it is too large
Load diff
931
libpng/CMakeLists.txt
Normal file
931
libpng/CMakeLists.txt
Normal file
|
@ -0,0 +1,931 @@
|
|||
# CMakeLists.txt
|
||||
|
||||
# Copyright (C) 2018 Cosmin Truta
|
||||
# Copyright (C) 2007,2009-2018 Glenn Randers-Pehrson
|
||||
# Written by Christian Ehrlicher, 2007
|
||||
# Revised by Roger Lowman, 2009-2010
|
||||
# Revised by Clifford Yapp, 2011-2012,2017
|
||||
# Revised by Roger Leigh, 2016
|
||||
# Revised by Andreas Franek, 2016
|
||||
# Revised by Sam Serrels, 2017
|
||||
# Revised by Vadim Barkov, 2017
|
||||
# Revised by Vicky Pfau, 2018
|
||||
# Revised by Cameron Cawley, 2018
|
||||
# Revised by Cosmin Truta, 2018
|
||||
# Revised by Kyle Bentley, 2018
|
||||
|
||||
# This code is released under the libpng license.
|
||||
# For conditions of distribution and use, see the disclaimer
|
||||
# and license in png.h
|
||||
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
cmake_policy(VERSION 3.1)
|
||||
|
||||
project(libpng C ASM)
|
||||
enable_testing()
|
||||
|
||||
set(PNGLIB_MAJOR 1)
|
||||
set(PNGLIB_MINOR 6)
|
||||
set(PNGLIB_RELEASE 37)
|
||||
set(PNGLIB_NAME libpng${PNGLIB_MAJOR}${PNGLIB_MINOR})
|
||||
set(PNGLIB_VERSION ${PNGLIB_MAJOR}.${PNGLIB_MINOR}.${PNGLIB_RELEASE})
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# needed packages
|
||||
|
||||
# Allow users to specify location of Zlib.
|
||||
# Useful if zlib is being built alongside this as a sub-project.
|
||||
option(PNG_BUILD_ZLIB "Custom zlib Location, else find_package is used" OFF)
|
||||
|
||||
if(NOT PNG_BUILD_ZLIB)
|
||||
find_package(ZLIB REQUIRED)
|
||||
include_directories(${ZLIB_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE AND NOT BEOS AND NOT HAIKU)
|
||||
find_library(M_LIBRARY m)
|
||||
else()
|
||||
# libm is not needed and/or not available
|
||||
set(M_LIBRARY "")
|
||||
endif()
|
||||
|
||||
# COMMAND LINE OPTIONS
|
||||
option(PNG_SHARED "Build shared lib" ON)
|
||||
option(PNG_STATIC "Build static lib" ON)
|
||||
option(PNG_TESTS "Build libpng tests" ON)
|
||||
|
||||
# Many more configuration options could be added here
|
||||
option(PNG_FRAMEWORK "Build OS X framework" OFF)
|
||||
option(PNG_DEBUG "Build with debug output" OFF)
|
||||
option(PNG_HARDWARE_OPTIMIZATIONS "Enable hardware optimizations" ON)
|
||||
|
||||
set(PNG_PREFIX "" CACHE STRING "Prefix to add to the API function names")
|
||||
set(DFA_XTRA "" CACHE FILEPATH "File containing extra configuration settings")
|
||||
|
||||
if(PNG_HARDWARE_OPTIMIZATIONS)
|
||||
|
||||
# set definitions and sources for arm
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" OR
|
||||
CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64")
|
||||
set(PNG_ARM_NEON_POSSIBLE_VALUES check on off)
|
||||
set(PNG_ARM_NEON "check" CACHE STRING "Enable ARM NEON optimizations:
|
||||
check: (default) use internal checking code;
|
||||
off: disable the optimizations;
|
||||
on: turn on unconditionally.")
|
||||
set_property(CACHE PNG_ARM_NEON PROPERTY STRINGS
|
||||
${PNG_ARM_NEON_POSSIBLE_VALUES})
|
||||
list(FIND PNG_ARM_NEON_POSSIBLE_VALUES ${PNG_ARM_NEON} index)
|
||||
if(index EQUAL -1)
|
||||
message(FATAL_ERROR
|
||||
"PNG_ARM_NEON must be one of [${PNG_ARM_NEON_POSSIBLE_VALUES}]")
|
||||
elseif(NOT ${PNG_ARM_NEON} STREQUAL "off")
|
||||
set(libpng_arm_sources
|
||||
arm/arm_init.c
|
||||
arm/filter_neon.S
|
||||
arm/filter_neon_intrinsics.c
|
||||
arm/palette_neon_intrinsics.c)
|
||||
|
||||
if(${PNG_ARM_NEON} STREQUAL "on")
|
||||
add_definitions(-DPNG_ARM_NEON_OPT=2)
|
||||
elseif(${PNG_ARM_NEON} STREQUAL "check")
|
||||
add_definitions(-DPNG_ARM_NEON_CHECK_SUPPORTED)
|
||||
endif()
|
||||
else()
|
||||
add_definitions(-DPNG_ARM_NEON_OPT=0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# set definitions and sources for powerpc
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^powerpc*" OR
|
||||
CMAKE_SYSTEM_PROCESSOR MATCHES "^ppc64*")
|
||||
set(PNG_POWERPC_VSX_POSSIBLE_VALUES on off)
|
||||
set(PNG_POWERPC_VSX "on" CACHE STRING "Enable POWERPC VSX optimizations:
|
||||
off: disable the optimizations.")
|
||||
set_property(CACHE PNG_POWERPC_VSX PROPERTY STRINGS
|
||||
${PNG_POWERPC_VSX_POSSIBLE_VALUES})
|
||||
list(FIND PNG_POWERPC_VSX_POSSIBLE_VALUES ${PNG_POWERPC_VSX} index)
|
||||
if(index EQUAL -1)
|
||||
message(FATAL_ERROR
|
||||
"PNG_POWERPC_VSX must be one of [${PNG_POWERPC_VSX_POSSIBLE_VALUES}]")
|
||||
elseif(NOT ${PNG_POWERPC_VSX} STREQUAL "off")
|
||||
set(libpng_powerpc_sources
|
||||
powerpc/powerpc_init.c
|
||||
powerpc/filter_vsx_intrinsics.c)
|
||||
if(${PNG_POWERPC_VSX} STREQUAL "on")
|
||||
add_definitions(-DPNG_POWERPC_VSX_OPT=2)
|
||||
endif()
|
||||
else()
|
||||
add_definitions(-DPNG_POWERPC_VSX_OPT=0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# set definitions and sources for intel
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^i?86" OR
|
||||
CMAKE_SYSTEM_PROCESSOR MATCHES "^x86_64*")
|
||||
set(PNG_INTEL_SSE_POSSIBLE_VALUES on off)
|
||||
set(PNG_INTEL_SSE "on" CACHE STRING "Enable INTEL_SSE optimizations:
|
||||
off: disable the optimizations")
|
||||
set_property(CACHE PNG_INTEL_SSE PROPERTY STRINGS
|
||||
${PNG_INTEL_SSE_POSSIBLE_VALUES})
|
||||
list(FIND PNG_INTEL_SSE_POSSIBLE_VALUES ${PNG_INTEL_SSE} index)
|
||||
if(index EQUAL -1)
|
||||
message(FATAL_ERROR
|
||||
"PNG_INTEL_SSE must be one of [${PNG_INTEL_SSE_POSSIBLE_VALUES}]")
|
||||
elseif(NOT ${PNG_INTEL_SSE} STREQUAL "off")
|
||||
set(libpng_intel_sources
|
||||
intel/intel_init.c
|
||||
intel/filter_sse2_intrinsics.c)
|
||||
if(${PNG_INTEL_SSE} STREQUAL "on")
|
||||
add_definitions(-DPNG_INTEL_SSE_OPT=1)
|
||||
endif()
|
||||
else()
|
||||
add_definitions(-DPNG_INTEL_SSE_OPT=0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# set definitions and sources for MIPS
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "mipsel*" OR
|
||||
CMAKE_SYSTEM_PROCESSOR MATCHES "mips64el*")
|
||||
set(PNG_MIPS_MSA_POSSIBLE_VALUES on off)
|
||||
set(PNG_MIPS_MSA "on" CACHE STRING "Enable MIPS_MSA optimizations:
|
||||
off: disable the optimizations")
|
||||
set_property(CACHE PNG_MIPS_MSA PROPERTY STRINGS
|
||||
${PNG_MIPS_MSA_POSSIBLE_VALUES})
|
||||
list(FIND PNG_MIPS_MSA_POSSIBLE_VALUES ${PNG_MIPS_MSA} index)
|
||||
if(index EQUAL -1)
|
||||
message(FATAL_ERROR
|
||||
"PNG_MIPS_MSA must be one of [${PNG_MIPS_MSA_POSSIBLE_VALUES}]")
|
||||
elseif(NOT ${PNG_MIPS_MSA} STREQUAL "off")
|
||||
set(libpng_mips_sources
|
||||
mips/mips_init.c
|
||||
mips/filter_msa_intrinsics.c)
|
||||
if(${PNG_MIPS_MSA} STREQUAL "on")
|
||||
add_definitions(-DPNG_MIPS_MSA_OPT=2)
|
||||
endif()
|
||||
else()
|
||||
add_definitions(-DPNG_MIPS_MSA_OPT=0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
else(PNG_HARDWARE_OPTIMIZATIONS)
|
||||
|
||||
# set definitions and sources for arm
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" OR
|
||||
CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64")
|
||||
add_definitions(-DPNG_ARM_NEON_OPT=0)
|
||||
endif()
|
||||
|
||||
# set definitions and sources for powerpc
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^powerpc*" OR
|
||||
CMAKE_SYSTEM_PROCESSOR MATCHES "^ppc64*")
|
||||
add_definitions(-DPNG_POWERPC_VSX_OPT=0)
|
||||
endif()
|
||||
|
||||
# set definitions and sources for intel
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^i?86" OR
|
||||
CMAKE_SYSTEM_PROCESSOR MATCHES "^x86_64*")
|
||||
add_definitions(-DPNG_INTEL_SSE_OPT=0)
|
||||
endif()
|
||||
|
||||
# set definitions and sources for MIPS
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "mipsel*" OR
|
||||
CMAKE_SYSTEM_PROCESSOR MATCHES "mips64el*")
|
||||
add_definitions(-DPNG_MIPS_MSA_OPT=0)
|
||||
endif()
|
||||
|
||||
endif(PNG_HARDWARE_OPTIMIZATIONS)
|
||||
|
||||
# SET LIBNAME
|
||||
set(PNG_LIB_NAME png${PNGLIB_MAJOR}${PNGLIB_MINOR})
|
||||
|
||||
# to distinguish between debug and release lib
|
||||
set(CMAKE_DEBUG_POSTFIX "d")
|
||||
|
||||
include(CheckCSourceCompiles)
|
||||
option(ld-version-script "Enable linker version script" ON)
|
||||
if(ld-version-script AND NOT APPLE)
|
||||
# Check if LD supports linker scripts.
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map" "VERS_1 {
|
||||
global: sym;
|
||||
local: *;
|
||||
};
|
||||
|
||||
VERS_2 {
|
||||
global: sym2;
|
||||
main;
|
||||
} VERS_1;
|
||||
")
|
||||
set(CMAKE_REQUIRED_FLAGS_SAVE ${CMAKE_REQUIRED_FLAGS})
|
||||
set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} "-Wl,--version-script='${CMAKE_CURRENT_BINARY_DIR}/conftest.map'")
|
||||
check_c_source_compiles("void sym(void) {}
|
||||
void sym2(void) {}
|
||||
int main(void) {return 0;}
|
||||
" HAVE_LD_VERSION_SCRIPT)
|
||||
if(NOT HAVE_LD_VERSION_SCRIPT)
|
||||
set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS_SAVE} "-Wl,-M -Wl,${CMAKE_CURRENT_BINARY_DIR}/conftest.map")
|
||||
check_c_source_compiles("void sym(void) {}
|
||||
void sym2(void) {}
|
||||
int main(void) {return 0;}
|
||||
" HAVE_SOLARIS_LD_VERSION_SCRIPT)
|
||||
endif()
|
||||
set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS_SAVE})
|
||||
file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map")
|
||||
endif()
|
||||
|
||||
# Find symbol prefix. Likely obsolete and unnecessary with recent
|
||||
# toolchains (it's not done in many other projects).
|
||||
function(symbol_prefix)
|
||||
set(SYMBOL_PREFIX)
|
||||
|
||||
execute_process(COMMAND "${CMAKE_C_COMPILER}" "-E" "-"
|
||||
INPUT_FILE /dev/null
|
||||
OUTPUT_VARIABLE OUT
|
||||
RESULT_VARIABLE STATUS)
|
||||
|
||||
if(CPP_FAIL)
|
||||
message(WARNING "Failed to run the C preprocessor")
|
||||
endif()
|
||||
|
||||
string(REPLACE "\n" ";" OUT "${OUT}")
|
||||
foreach(line ${OUT})
|
||||
string(REGEX MATCH "^PREFIX=" found_match "${line}")
|
||||
if(found_match)
|
||||
string(REGEX REPLACE "^PREFIX=(.*\)" "\\1" prefix "${line}")
|
||||
string(REGEX MATCH "__USER_LABEL_PREFIX__" found_match "${prefix}")
|
||||
if(found_match)
|
||||
string(REGEX REPLACE "(.*)__USER_LABEL_PREFIX__(.*)" "\\1\\2" prefix "${prefix}")
|
||||
endif()
|
||||
set(SYMBOL_PREFIX "${prefix}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
message(STATUS "Symbol prefix: ${SYMBOL_PREFIX}")
|
||||
set(SYMBOL_PREFIX "${SYMBOL_PREFIX}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
if(UNIX)
|
||||
symbol_prefix()
|
||||
endif()
|
||||
|
||||
find_program(AWK NAMES gawk awk)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
if(NOT AWK OR ANDROID)
|
||||
# No awk available to generate sources; use pre-built pnglibconf.h
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt
|
||||
${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h)
|
||||
add_custom_target(genfiles) # Dummy
|
||||
else()
|
||||
include(CMakeParseArguments)
|
||||
# Generate .chk from .out with awk
|
||||
# generate_chk(INPUT inputfile OUTPUT outputfile [DEPENDS dep1 [dep2...]])
|
||||
function(generate_chk)
|
||||
set(options)
|
||||
set(oneValueArgs INPUT OUTPUT)
|
||||
set(multiValueArgs DEPENDS)
|
||||
cmake_parse_arguments(_GC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
if(NOT _GC_INPUT)
|
||||
message(FATAL_ERROR "generate_chk: Missing INPUT argument")
|
||||
endif()
|
||||
if(NOT _GC_OUTPUT)
|
||||
message(FATAL_ERROR "generate_chk: Missing OUTPUT argument")
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT "${_GC_OUTPUT}"
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
"-DINPUT=${_GC_INPUT}"
|
||||
"-DOUTPUT=${_GC_OUTPUT}"
|
||||
-P "${CMAKE_CURRENT_BINARY_DIR}/scripts/genchk.cmake"
|
||||
DEPENDS "${_GC_INPUT}" ${_GC_DEPENDS}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
endfunction()
|
||||
|
||||
# Generate .out from .c with awk
|
||||
# generate_out(INPUT inputfile OUTPUT outputfile [DEPENDS dep1 [dep2...]])
|
||||
function(generate_out)
|
||||
set(options)
|
||||
set(oneValueArgs INPUT OUTPUT)
|
||||
set(multiValueArgs DEPENDS)
|
||||
cmake_parse_arguments(_GO "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
if(NOT _GO_INPUT)
|
||||
message(FATAL_ERROR "generate_out: Missing INPUT argument")
|
||||
endif()
|
||||
if(NOT _GO_OUTPUT)
|
||||
message(FATAL_ERROR "generate_out: Missing OUTPUT argument")
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT "${_GO_OUTPUT}"
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
"-DINPUT=${_GO_INPUT}"
|
||||
"-DOUTPUT=${_GO_OUTPUT}"
|
||||
-P "${CMAKE_CURRENT_BINARY_DIR}/scripts/genout.cmake"
|
||||
DEPENDS "${_GO_INPUT}" ${_GO_DEPENDS}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
endfunction()
|
||||
|
||||
# Generate specific source file with awk
|
||||
# generate_source(OUTPUT outputfile [DEPENDS dep1 [dep2...]])
|
||||
function(generate_source)
|
||||
set(options)
|
||||
set(oneValueArgs OUTPUT)
|
||||
set(multiValueArgs DEPENDS)
|
||||
cmake_parse_arguments(_GSO "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
if(NOT _GSO_OUTPUT)
|
||||
message(FATAL_ERROR "generate_source: Missing OUTPUT argument")
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${_GSO_OUTPUT}"
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
"-DOUTPUT=${_GSO_OUTPUT}"
|
||||
-P "${CMAKE_CURRENT_BINARY_DIR}/scripts/gensrc.cmake"
|
||||
DEPENDS ${_GSO_DEPENDS}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
endfunction()
|
||||
|
||||
# Copy file
|
||||
function(generate_copy source destination)
|
||||
add_custom_command(OUTPUT "${destination}"
|
||||
COMMAND "${CMAKE_COMMAND}" -E remove "${destination}"
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy "${source}"
|
||||
"${destination}"
|
||||
DEPENDS "${source}")
|
||||
endfunction()
|
||||
|
||||
# Generate scripts/pnglibconf.h
|
||||
generate_source(OUTPUT "scripts/pnglibconf.c"
|
||||
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.dfa"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/options.awk"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h")
|
||||
|
||||
# Generate pnglibconf.c
|
||||
generate_source(OUTPUT "pnglibconf.c"
|
||||
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.dfa"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/options.awk"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h")
|
||||
|
||||
if(PNG_PREFIX)
|
||||
set(PNGLIBCONF_H_EXTRA_DEPENDS
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/scripts/prefix.out"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/macro.lst")
|
||||
set(PNGPREFIX_H_EXTRA_DEPENDS
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/scripts/intprefix.out")
|
||||
endif()
|
||||
|
||||
generate_out(INPUT "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.c"
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out")
|
||||
|
||||
# Generate pnglibconf.h
|
||||
generate_source(OUTPUT "pnglibconf.h"
|
||||
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out"
|
||||
${PNGLIBCONF_H_EXTRA_DEPENDS})
|
||||
|
||||
generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/intprefix.c"
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/intprefix.out"
|
||||
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h")
|
||||
|
||||
generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/prefix.c"
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/prefix.out"
|
||||
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out")
|
||||
|
||||
# Generate pngprefix.h
|
||||
generate_source(OUTPUT "pngprefix.h"
|
||||
DEPENDS ${PNGPREFIX_H_EXTRA_DEPENDS})
|
||||
|
||||
generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/sym.c"
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out"
|
||||
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h")
|
||||
|
||||
generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/symbols.c"
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out"
|
||||
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt")
|
||||
|
||||
generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/vers.c"
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out"
|
||||
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h")
|
||||
|
||||
generate_chk(INPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out"
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.chk"
|
||||
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/checksym.awk"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/symbols.def")
|
||||
|
||||
add_custom_target(symbol-check DEPENDS
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.chk")
|
||||
|
||||
generate_copy("${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/libpng.sym")
|
||||
generate_copy("${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/libpng.vers")
|
||||
|
||||
add_custom_target(genvers DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/libpng.vers")
|
||||
add_custom_target(gensym DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/libpng.sym")
|
||||
|
||||
add_custom_target("genprebuilt"
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
"-DOUTPUT=scripts/pnglibconf.h.prebuilt"
|
||||
-P "${CMAKE_CURRENT_BINARY_DIR}/scripts/gensrc.cmake"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
|
||||
# A single target handles generation of all generated files. If
|
||||
# they are depended upon separately by multiple targets, this
|
||||
# confuses parallel make (it would require a separate top-level
|
||||
# target for each file to track the dependencies properly).
|
||||
add_custom_target(genfiles DEPENDS
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/libpng.sym"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/libpng.vers"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.c"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/pngprefix.h"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/scripts/intprefix.out"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf.c"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/scripts/prefix.out"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.chk"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out")
|
||||
endif(NOT AWK OR ANDROID)
|
||||
|
||||
# OUR SOURCES
|
||||
set(libpng_public_hdrs
|
||||
png.h
|
||||
pngconf.h
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h"
|
||||
)
|
||||
set(libpng_private_hdrs
|
||||
pngpriv.h
|
||||
pngdebug.h
|
||||
pnginfo.h
|
||||
pngstruct.h
|
||||
)
|
||||
if(AWK AND NOT ANDROID)
|
||||
list(APPEND libpng_private_hdrs "${CMAKE_CURRENT_BINARY_DIR}/pngprefix.h")
|
||||
endif()
|
||||
set(libpng_sources
|
||||
${libpng_public_hdrs}
|
||||
${libpng_private_hdrs}
|
||||
png.c
|
||||
pngerror.c
|
||||
pngget.c
|
||||
pngmem.c
|
||||
pngpread.c
|
||||
pngread.c
|
||||
pngrio.c
|
||||
pngrtran.c
|
||||
pngrutil.c
|
||||
pngset.c
|
||||
pngtrans.c
|
||||
pngwio.c
|
||||
pngwrite.c
|
||||
pngwtran.c
|
||||
pngwutil.c
|
||||
${libpng_arm_sources}
|
||||
${libpng_intel_sources}
|
||||
${libpng_mips_sources}
|
||||
${libpng_powerpc_sources}
|
||||
)
|
||||
set(pngtest_sources
|
||||
pngtest.c
|
||||
)
|
||||
set(pngvalid_sources
|
||||
contrib/libtests/pngvalid.c
|
||||
)
|
||||
set(pngstest_sources
|
||||
contrib/libtests/pngstest.c
|
||||
)
|
||||
set(pngunknown_sources
|
||||
contrib/libtests/pngunknown.c
|
||||
)
|
||||
set(pngimage_sources
|
||||
contrib/libtests/pngimage.c
|
||||
)
|
||||
set(pngfix_sources
|
||||
contrib/tools/pngfix.c
|
||||
)
|
||||
set(png_fix_itxt_sources
|
||||
contrib/tools/png-fix-itxt.c
|
||||
)
|
||||
|
||||
if(MSVC)
|
||||
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
|
||||
endif()
|
||||
|
||||
if(PNG_DEBUG)
|
||||
add_definitions(-DPNG_DEBUG)
|
||||
endif()
|
||||
|
||||
# NOW BUILD OUR TARGET
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${ZLIB_INCLUDE_DIR})
|
||||
|
||||
unset(PNG_LIB_TARGETS)
|
||||
|
||||
if(PNG_SHARED)
|
||||
add_library(png SHARED ${libpng_sources})
|
||||
set(PNG_LIB_TARGETS png)
|
||||
set_target_properties(png PROPERTIES OUTPUT_NAME ${PNG_LIB_NAME})
|
||||
add_dependencies(png genfiles)
|
||||
if(MSVC)
|
||||
# msvc does not append 'lib' - do it here to have consistent name
|
||||
set_target_properties(png PROPERTIES PREFIX "lib")
|
||||
set_target_properties(png PROPERTIES IMPORT_PREFIX "lib")
|
||||
endif()
|
||||
target_link_libraries(png ${ZLIB_LIBRARY} ${M_LIBRARY})
|
||||
|
||||
if(UNIX AND AWK)
|
||||
if(HAVE_LD_VERSION_SCRIPT)
|
||||
set_target_properties(png PROPERTIES LINK_FLAGS
|
||||
"-Wl,--version-script='${CMAKE_CURRENT_BINARY_DIR}/libpng.vers'")
|
||||
elseif(HAVE_SOLARIS_LD_VERSION_SCRIPT)
|
||||
set_target_properties(png PROPERTIES LINK_FLAGS
|
||||
"-Wl,-M -Wl,'${CMAKE_CURRENT_BINARY_DIR}/libpng.vers'")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(PNG_STATIC)
|
||||
# does not work without changing name
|
||||
set(PNG_LIB_NAME_STATIC png_static)
|
||||
add_library(png_static STATIC ${libpng_sources})
|
||||
add_dependencies(png_static genfiles)
|
||||
# MSVC doesn't use a different file extension for shared vs. static
|
||||
# libs. We are able to change OUTPUT_NAME to remove the _static
|
||||
# for all other platforms.
|
||||
if(NOT MSVC)
|
||||
set_target_properties(png_static PROPERTIES
|
||||
OUTPUT_NAME "${PNG_LIB_NAME}"
|
||||
CLEAN_DIRECT_OUTPUT 1)
|
||||
else()
|
||||
set_target_properties(png_static PROPERTIES
|
||||
OUTPUT_NAME "${PNG_LIB_NAME}_static"
|
||||
CLEAN_DIRECT_OUTPUT 1)
|
||||
endif()
|
||||
list(APPEND PNG_LIB_TARGETS png_static)
|
||||
if(MSVC)
|
||||
# msvc does not append 'lib' - do it here to have consistent name
|
||||
set_target_properties(png_static PROPERTIES PREFIX "lib")
|
||||
endif()
|
||||
target_link_libraries(png_static ${ZLIB_LIBRARY} ${M_LIBRARY})
|
||||
endif()
|
||||
|
||||
if(PNG_FRAMEWORK)
|
||||
set(PNG_LIB_NAME_FRAMEWORK png_framework)
|
||||
add_library(png_framework SHARED ${libpng_sources})
|
||||
add_dependencies(png_framework genfiles)
|
||||
list(APPEND PNG_LIB_TARGETS png_framework)
|
||||
set_target_properties(png_framework PROPERTIES
|
||||
FRAMEWORK TRUE
|
||||
FRAMEWORK_VERSION ${PNGLIB_VERSION}
|
||||
MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${PNGLIB_MAJOR}.${PNGLIB_MINOR}
|
||||
MACOSX_FRAMEWORK_BUNDLE_VERSION ${PNGLIB_VERSION}
|
||||
MACOSX_FRAMEWORK_IDENTIFIER org.libpng.libpng
|
||||
XCODE_ATTRIBUTE_INSTALL_PATH "@rpath"
|
||||
PUBLIC_HEADER "${libpng_public_hdrs}"
|
||||
OUTPUT_NAME png)
|
||||
target_link_libraries(png_framework ${ZLIB_LIBRARY} ${M_LIBRARY})
|
||||
endif()
|
||||
|
||||
if(NOT PNG_LIB_TARGETS)
|
||||
message(SEND_ERROR
|
||||
"No library variant selected to build. "
|
||||
"Please enable at least one of the following options: "
|
||||
"PNG_STATIC, PNG_SHARED, PNG_FRAMEWORK")
|
||||
endif()
|
||||
|
||||
if(PNG_SHARED AND WIN32)
|
||||
set_target_properties(png PROPERTIES DEFINE_SYMBOL PNG_BUILD_DLL)
|
||||
endif()
|
||||
|
||||
function(png_add_test)
|
||||
set(options)
|
||||
set(oneValueArgs NAME COMMAND)
|
||||
set(multiValueArgs OPTIONS FILES)
|
||||
cmake_parse_arguments(_PAT "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
if(NOT _PAT_NAME)
|
||||
message(FATAL_ERROR "png_add_test: Missing NAME argument")
|
||||
endif()
|
||||
if(NOT _PAT_COMMAND)
|
||||
message(FATAL_ERROR "png_add_test: Missing COMMAND argument")
|
||||
endif()
|
||||
|
||||
set(TEST_OPTIONS "${_PAT_OPTIONS}")
|
||||
set(TEST_FILES "${_PAT_FILES}")
|
||||
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scripts/test.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/tests/${_PAT_NAME}.cmake" @ONLY)
|
||||
add_test(NAME "${_PAT_NAME}"
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
"-DLIBPNG=$<TARGET_FILE:png>"
|
||||
"-DTEST_COMMAND=$<TARGET_FILE:${_PAT_COMMAND}>"
|
||||
-P "${CMAKE_CURRENT_BINARY_DIR}/tests/${_PAT_NAME}.cmake")
|
||||
endfunction()
|
||||
|
||||
if(PNG_TESTS AND PNG_SHARED)
|
||||
# Find test PNG files by globbing, but sort lists to ensure
|
||||
# consistency between different filesystems.
|
||||
file(GLOB PNGSUITE_PNGS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/*.png")
|
||||
list(SORT PNGSUITE_PNGS)
|
||||
file(GLOB TEST_PNGS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/*.png")
|
||||
list(SORT TEST_PNGS)
|
||||
|
||||
set(PNGTEST_PNG "${CMAKE_CURRENT_SOURCE_DIR}/pngtest.png")
|
||||
|
||||
add_executable(pngtest ${pngtest_sources})
|
||||
target_link_libraries(pngtest png)
|
||||
|
||||
png_add_test(NAME pngtest COMMAND pngtest FILES "${PNGTEST_PNG}")
|
||||
|
||||
add_executable(pngvalid ${pngvalid_sources})
|
||||
target_link_libraries(pngvalid png)
|
||||
|
||||
png_add_test(NAME pngvalid-gamma-16-to-8
|
||||
COMMAND pngvalid OPTIONS --gamma-16-to-8)
|
||||
png_add_test(NAME pngvalid-gamma-alpha-mode
|
||||
COMMAND pngvalid OPTIONS --gamma-alpha-mode)
|
||||
png_add_test(NAME pngvalid-gamma-background
|
||||
COMMAND pngvalid OPTIONS --gamma-background)
|
||||
png_add_test(NAME pngvalid-gamma-expand16-alpha-mode
|
||||
COMMAND pngvalid OPTIONS --gamma-alpha-mode --expand16)
|
||||
png_add_test(NAME pngvalid-gamma-expand16-background
|
||||
COMMAND pngvalid OPTIONS --gamma-background --expand16)
|
||||
png_add_test(NAME pngvalid-gamma-expand16-transform
|
||||
COMMAND pngvalid OPTIONS --gamma-transform --expand16)
|
||||
png_add_test(NAME pngvalid-gamma-sbit
|
||||
COMMAND pngvalid OPTIONS --gamma-sbit)
|
||||
png_add_test(NAME pngvalid-gamma-threshold
|
||||
COMMAND pngvalid OPTIONS --gamma-threshold)
|
||||
png_add_test(NAME pngvalid-gamma-transform
|
||||
COMMAND pngvalid OPTIONS --gamma-transform)
|
||||
png_add_test(NAME pngvalid-progressive-interlace-standard
|
||||
COMMAND pngvalid OPTIONS --standard --progressive-read --interlace)
|
||||
png_add_test(NAME pngvalid-progressive-size
|
||||
COMMAND pngvalid OPTIONS --size --progressive-read)
|
||||
png_add_test(NAME pngvalid-progressive-standard
|
||||
COMMAND pngvalid OPTIONS --standard --progressive-read)
|
||||
png_add_test(NAME pngvalid-standard
|
||||
COMMAND pngvalid OPTIONS --standard)
|
||||
png_add_test(NAME pngvalid-transform
|
||||
COMMAND pngvalid OPTIONS --transform)
|
||||
|
||||
add_executable(pngstest ${pngstest_sources})
|
||||
target_link_libraries(pngstest png)
|
||||
|
||||
foreach(gamma_type 1.8 linear none sRGB)
|
||||
foreach(alpha_type none alpha)
|
||||
set(PNGSTEST_FILES)
|
||||
foreach(test_png ${TEST_PNGS})
|
||||
string(REGEX MATCH ".*-linear[-.].*" TEST_PNG_LINEAR "${test_png}")
|
||||
string(REGEX MATCH ".*-sRGB[-.].*" TEST_PNG_SRGB "${test_png}")
|
||||
string(REGEX MATCH ".*-1.8[-.].*" TEST_PNG_G18 "${test_png}")
|
||||
string(REGEX MATCH ".*-alpha-.*" TEST_PNG_ALPHA "${test_png}")
|
||||
|
||||
set(TEST_PNG_VALID TRUE)
|
||||
|
||||
if(TEST_PNG_ALPHA)
|
||||
if(NOT "${alpha_type}" STREQUAL "alpha")
|
||||
set(TEST_PNG_VALID FALSE)
|
||||
endif()
|
||||
else()
|
||||
if("${alpha_type}" STREQUAL "alpha")
|
||||
set(TEST_PNG_VALID FALSE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(TEST_PNG_LINEAR)
|
||||
if(NOT "${gamma_type}" STREQUAL "linear")
|
||||
set(TEST_PNG_VALID FALSE)
|
||||
endif()
|
||||
elseif(TEST_PNG_SRGB)
|
||||
if(NOT "${gamma_type}" STREQUAL "sRGB")
|
||||
set(TEST_PNG_VALID FALSE)
|
||||
endif()
|
||||
elseif(TEST_PNG_G18)
|
||||
if(NOT "${gamma_type}" STREQUAL "1.8")
|
||||
set(TEST_PNG_VALID FALSE)
|
||||
endif()
|
||||
else()
|
||||
if(NOT "${gamma_type}" STREQUAL "none")
|
||||
set(TEST_PNG_VALID FALSE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(TEST_PNG_VALID)
|
||||
list(APPEND PNGSTEST_FILES "${test_png}")
|
||||
endif()
|
||||
endforeach()
|
||||
# Should already be sorted, but sort anyway to be certain.
|
||||
list(SORT PNGSTEST_FILES)
|
||||
png_add_test(NAME pngstest-${gamma_type}-${alpha_type}
|
||||
COMMAND pngstest
|
||||
OPTIONS --tmpfile "${gamma_type}-${alpha_type}-" --log
|
||||
FILES ${PNGSTEST_FILES})
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
add_executable(pngunknown ${pngunknown_sources})
|
||||
target_link_libraries(pngunknown png)
|
||||
|
||||
png_add_test(NAME pngunknown-discard COMMAND pngunknown OPTIONS --strict default=discard FILES "${PNGTEST_PNG}")
|
||||
png_add_test(NAME pngunknown-IDAT COMMAND pngunknown OPTIONS --strict default=discard IDAT=save FILES "${PNGTEST_PNG}")
|
||||
png_add_test(NAME pngunknown-if-safe COMMAND pngunknown OPTIONS --strict default=if-safe FILES "${PNGTEST_PNG}")
|
||||
png_add_test(NAME pngunknown-sAPI COMMAND pngunknown OPTIONS --strict bKGD=save cHRM=save gAMA=save all=discard iCCP=save sBIT=save sRGB=save FILES "${PNGTEST_PNG}")
|
||||
png_add_test(NAME pngunknown-save COMMAND pngunknown OPTIONS --strict default=save FILES "${PNGTEST_PNG}")
|
||||
png_add_test(NAME pngunknown-sTER COMMAND pngunknown OPTIONS --strict sTER=if-safe FILES "${PNGTEST_PNG}")
|
||||
png_add_test(NAME pngunknown-vpAg COMMAND pngunknown OPTIONS --strict vpAg=if-safe FILES "${PNGTEST_PNG}")
|
||||
|
||||
add_executable(pngimage ${pngimage_sources})
|
||||
target_link_libraries(pngimage png)
|
||||
|
||||
png_add_test(NAME pngimage-quick COMMAND pngimage OPTIONS --list-combos --log FILES ${PNGSUITE_PNGS})
|
||||
png_add_test(NAME pngimage-full COMMAND pngimage OPTIONS --exhaustive --list-combos --log FILES ${PNGSUITE_PNGS})
|
||||
endif()
|
||||
|
||||
if(PNG_SHARED)
|
||||
add_executable(pngfix ${pngfix_sources})
|
||||
target_link_libraries(pngfix png)
|
||||
set(PNG_BIN_TARGETS pngfix)
|
||||
|
||||
add_executable(png-fix-itxt ${png_fix_itxt_sources})
|
||||
target_link_libraries(png-fix-itxt ${ZLIB_LIBRARY} ${M_LIBRARY})
|
||||
list(APPEND PNG_BIN_TARGETS png-fix-itxt)
|
||||
endif()
|
||||
|
||||
# Set a variable with CMake code which:
|
||||
# Creates a symlink from src to dest (if possible) or alternatively
|
||||
# copies if different.
|
||||
include(CMakeParseArguments)
|
||||
|
||||
function(create_symlink DEST_FILE)
|
||||
|
||||
cmake_parse_arguments(S "" "FILE;TARGET" "" ${ARGN})
|
||||
|
||||
if(NOT S_TARGET AND NOT S_FILE)
|
||||
message(FATAL_ERROR "create_symlink: Missing TARGET or FILE argument")
|
||||
endif()
|
||||
|
||||
if(S_TARGET AND S_FILE)
|
||||
message(FATAL_ERROR "create_symlink: Both source file ${S_FILE} and build target ${S_TARGET} arguments are present; can only have one.")
|
||||
endif()
|
||||
|
||||
if(S_FILE)
|
||||
# If we don't need to symlink something that's coming from a build target,
|
||||
# we can go ahead and symlink/copy at configure time.
|
||||
if(CMAKE_HOST_WIN32 AND NOT CYGWIN)
|
||||
execute_process(
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy_if_different ${S_FILE} ${DEST_FILE}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
else()
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E create_symlink ${S_FILE} ${DEST_FILE}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(S_TARGET)
|
||||
# We need to use generator expressions, which can be a bit tricky, so for
|
||||
# simplicity make the symlink a POST_BUILD step and use the TARGET
|
||||
# signature of add_custom_command.
|
||||
if(CMAKE_HOST_WIN32 AND NOT CYGWIN)
|
||||
add_custom_command(TARGET ${S_TARGET} POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy_if_different $<TARGET_LINKER_FILE_NAME:${S_TARGET}> $<TARGET_LINKER_FILE_DIR:${S_TARGET}>/${DEST_FILE})
|
||||
else()
|
||||
add_custom_command(TARGET ${S_TARGET} POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E create_symlink $<TARGET_LINKER_FILE_NAME:${S_TARGET}> $<TARGET_LINKER_FILE_DIR:${S_TARGET}>/${DEST_FILE})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endfunction()
|
||||
|
||||
# Create source generation scripts.
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/genchk.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/scripts/genchk.cmake @ONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/genout.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/scripts/genout.cmake @ONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/gensrc.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/scripts/gensrc.cmake @ONLY)
|
||||
|
||||
# libpng is a library so default to 'lib'
|
||||
if(NOT DEFINED CMAKE_INSTALL_LIBDIR)
|
||||
set(CMAKE_INSTALL_LIBDIR lib)
|
||||
endif()
|
||||
|
||||
# CREATE PKGCONFIG FILES
|
||||
# We use the same files like ./configure, so we have to set its vars.
|
||||
# Only do this on Windows for Cygwin - the files don't make much sense outside
|
||||
# of a UNIX look-alike.
|
||||
if(NOT WIN32 OR CYGWIN OR MINGW)
|
||||
set(prefix ${CMAKE_INSTALL_PREFIX})
|
||||
set(exec_prefix ${CMAKE_INSTALL_PREFIX})
|
||||
set(libdir ${CMAKE_INSTALL_FULL_LIBDIR})
|
||||
set(includedir ${CMAKE_INSTALL_FULL_INCLUDEDIR})
|
||||
set(LIBS "-lz -lm")
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libpng.pc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}.pc @ONLY)
|
||||
create_symlink(libpng.pc FILE ${PNGLIB_NAME}.pc)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libpng-config.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config @ONLY)
|
||||
create_symlink(libpng-config FILE ${PNGLIB_NAME}-config)
|
||||
endif()
|
||||
|
||||
# SET UP LINKS
|
||||
if(PNG_SHARED)
|
||||
set_target_properties(png PROPERTIES
|
||||
# VERSION 16.${PNGLIB_RELEASE}.1.6.37
|
||||
VERSION 16.${PNGLIB_RELEASE}.0
|
||||
SOVERSION 16
|
||||
CLEAN_DIRECT_OUTPUT 1)
|
||||
endif()
|
||||
|
||||
# INSTALL
|
||||
if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
|
||||
install(TARGETS ${PNG_LIB_TARGETS}
|
||||
EXPORT libpng
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
|
||||
if(PNG_SHARED)
|
||||
# Create a symlink for libpng.dll.a => libpng16.dll.a on Cygwin
|
||||
if(CYGWIN OR MINGW)
|
||||
create_symlink(libpng${CMAKE_IMPORT_LIBRARY_SUFFIX} TARGET png)
|
||||
install(FILES $<TARGET_LINKER_FILE_DIR:png>/libpng${CMAKE_IMPORT_LIBRARY_SUFFIX}
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif()
|
||||
|
||||
if(NOT WIN32)
|
||||
create_symlink(libpng${CMAKE_SHARED_LIBRARY_SUFFIX} TARGET png)
|
||||
install(FILES $<TARGET_LINKER_FILE_DIR:png>/libpng${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(PNG_STATIC)
|
||||
if(NOT WIN32 OR CYGWIN OR MINGW)
|
||||
create_symlink(libpng${CMAKE_STATIC_LIBRARY_SUFFIX} TARGET png_static)
|
||||
install(FILES $<TARGET_LINKER_FILE_DIR:png_static>/libpng${CMAKE_STATIC_LIBRARY_SUFFIX}
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL)
|
||||
install(FILES ${libpng_public_hdrs} DESTINATION include)
|
||||
install(FILES ${libpng_public_hdrs} DESTINATION include/${PNGLIB_NAME})
|
||||
endif()
|
||||
if(NOT SKIP_INSTALL_EXECUTABLES AND NOT SKIP_INSTALL_ALL)
|
||||
if(NOT WIN32 OR CYGWIN OR MINGW)
|
||||
install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/libpng-config DESTINATION bin)
|
||||
install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config DESTINATION bin)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT SKIP_INSTALL_PROGRAMS AND NOT SKIP_INSTALL_ALL)
|
||||
install(TARGETS ${PNG_BIN_TARGETS}
|
||||
RUNTIME DESTINATION bin)
|
||||
endif()
|
||||
|
||||
if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL)
|
||||
# Install man pages
|
||||
if(NOT PNG_MAN_DIR)
|
||||
set(PNG_MAN_DIR "share/man")
|
||||
endif()
|
||||
install(FILES libpng.3 libpngpf.3 DESTINATION ${PNG_MAN_DIR}/man3)
|
||||
install(FILES png.5 DESTINATION ${PNG_MAN_DIR}/man5)
|
||||
# Install pkg-config files
|
||||
if(NOT CMAKE_HOST_WIN32 OR CYGWIN OR MINGW)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpng.pc
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/libpng-config
|
||||
DESTINATION bin)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}.pc
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config
|
||||
DESTINATION bin)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Create an export file that CMake users can include() to import our targets.
|
||||
if(NOT SKIP_INSTALL_EXPORT AND NOT SKIP_INSTALL_ALL)
|
||||
install(EXPORT libpng DESTINATION lib/libpng FILE lib${PNG_LIB_NAME}.cmake)
|
||||
endif()
|
||||
|
||||
# what's with libpng-manual.txt and all the extra files?
|
||||
|
||||
# UNINSTALL
|
||||
# do we need this?
|
||||
|
||||
# DIST
|
||||
# do we need this?
|
||||
|
||||
# to create msvc import lib for mingw compiled shared lib
|
||||
# pexports libpng.dll > libpng.def
|
||||
# lib /def:libpng.def /machine:x86
|
465
libpng/INSTALL
Normal file
465
libpng/INSTALL
Normal file
|
@ -0,0 +1,465 @@
|
|||
|
||||
Installing libpng
|
||||
|
||||
Contents
|
||||
|
||||
I. Simple installation
|
||||
II. Rebuilding the configure scripts
|
||||
III. Using scripts/makefile*
|
||||
IV. Using cmake
|
||||
V. Directory structure
|
||||
VI. Building with project files
|
||||
VII. Building with makefiles
|
||||
VIII. Configuring libpng for 16-bit platforms
|
||||
IX. Configuring for DOS
|
||||
X. Configuring for Medium Model
|
||||
XI. Prepending a prefix to exported symbols
|
||||
XII. Configuring for compiler xxx:
|
||||
XIII. Removing unwanted object code
|
||||
XIV. Enabling or disabling hardware optimizations
|
||||
XV. Changes to the build and configuration of libpng in libpng-1.5.x
|
||||
XVI. Setjmp/longjmp issues
|
||||
XVII. Common linking failures
|
||||
XVIII. Other sources of information about libpng
|
||||
|
||||
I. Simple installation
|
||||
|
||||
On Unix/Linux and similar systems, you can simply type
|
||||
|
||||
./configure [--prefix=/path]
|
||||
make check
|
||||
make install
|
||||
|
||||
and ignore the rest of this document. "/path" is the path to the directory
|
||||
where you want to install the libpng "lib", "include", and "bin"
|
||||
subdirectories.
|
||||
|
||||
If you downloaded a GIT clone, you will need to run ./autogen.sh before
|
||||
running ./configure, to create "configure" and "Makefile.in" which are
|
||||
not included in the GIT repository.
|
||||
|
||||
Note that "configure" is only included in the "*.tar" distributions and not
|
||||
in the "*.zip" or "*.7z" distributions. If you downloaded one of those
|
||||
distributions, see "Building with project files" or "Building with makefiles",
|
||||
below.
|
||||
|
||||
II. Rebuilding the configure scripts
|
||||
|
||||
If configure does not work on your system, or if you have a need to
|
||||
change configure.ac or Makefile.am, and you have a reasonably
|
||||
up-to-date set of tools, running ./autogen.sh in a git clone before
|
||||
running ./configure may fix the problem. To be really sure that you
|
||||
aren't using any of the included pre-built scripts, especially if you
|
||||
are building from a tar distribution instead of a git distribution,
|
||||
do this:
|
||||
|
||||
./configure --enable-maintainer-mode
|
||||
make maintainer-clean
|
||||
./autogen.sh --maintainer --clean
|
||||
./autogen.sh --maintainer
|
||||
./configure [--prefix=/path] [other options]
|
||||
make
|
||||
make install
|
||||
make check
|
||||
|
||||
III. Using scripts/makefile*
|
||||
|
||||
Instead, you can use one of the custom-built makefiles in the
|
||||
"scripts" directory
|
||||
|
||||
cp scripts/pnglibconf.h.prebuilt pnglibconf.h
|
||||
cp scripts/makefile.system makefile
|
||||
make test
|
||||
make install
|
||||
|
||||
The files that are presently available in the scripts directory
|
||||
are listed and described in scripts/README.txt.
|
||||
|
||||
Or you can use one of the "projects" in the "projects" directory.
|
||||
|
||||
Before installing libpng, you must first install zlib, if it
|
||||
is not already on your system. zlib can usually be found
|
||||
wherever you got libpng; otherwise go to https://zlib.net/. You can
|
||||
place zlib in the same directory as libpng or in another directory.
|
||||
|
||||
If your system already has a preinstalled zlib you will still need
|
||||
to have access to the zlib.h and zconf.h include files that
|
||||
correspond to the version of zlib that's installed.
|
||||
|
||||
If you wish to test with a particular zlib that is not first in the
|
||||
standard library search path, put ZLIBLIB, ZLIBINC, CPPFLAGS, LDFLAGS,
|
||||
and LD_LIBRARY_PATH in your environment before running "make test"
|
||||
or "make distcheck":
|
||||
|
||||
ZLIBLIB=/path/to/lib export ZLIBLIB
|
||||
ZLIBINC=/path/to/include export ZLIBINC
|
||||
CPPFLAGS="-I$ZLIBINC" export CPPFLAGS
|
||||
LDFLAGS="-L$ZLIBLIB" export LDFLAGS
|
||||
LD_LIBRARY_PATH="$ZLIBLIB:$LD_LIBRARY_PATH" export LD_LIBRARY_PATH
|
||||
|
||||
If you are using one of the makefile scripts, put ZLIBLIB and ZLIBINC
|
||||
in your environment and type
|
||||
|
||||
make ZLIBLIB=$ZLIBLIB ZLIBINC=$ZLIBINC test
|
||||
|
||||
IV. Using cmake
|
||||
|
||||
If you want to use "cmake" (see www.cmake.org), type
|
||||
|
||||
cmake . -DCMAKE_INSTALL_PREFIX=/path
|
||||
make
|
||||
make install
|
||||
|
||||
As when using the simple configure method described above, "/path" points to
|
||||
the installation directory where you want to put the libpng "lib", "include",
|
||||
and "bin" subdirectories.
|
||||
|
||||
V. Directory structure
|
||||
|
||||
You can rename the directories that you downloaded (they
|
||||
might be called "libpng-x.y.z" or "libpngNN" and "zlib-1.2.8"
|
||||
or "zlib128") so that you have directories called "zlib" and "libpng".
|
||||
|
||||
Your directory structure should look like this:
|
||||
|
||||
.. (the parent directory)
|
||||
libpng (this directory)
|
||||
INSTALL (this file)
|
||||
README
|
||||
*.h, *.c => libpng source files
|
||||
CMakeLists.txt => "cmake" script
|
||||
configuration files:
|
||||
configure.ac, configure, Makefile.am, Makefile.in,
|
||||
autogen.sh, config.guess, ltmain.sh, missing, libpng.pc.in,
|
||||
libpng-config.in, aclocal.m4, config.h.in, config.sub,
|
||||
depcomp, install-sh, mkinstalldirs, test-pngtest.sh
|
||||
contrib
|
||||
arm-neon, conftest, examples, gregbook, libtests, pngminim,
|
||||
pngminus, pngsuite, tools, visupng
|
||||
projects
|
||||
cbuilder5, owatcom, visualc71, vstudio, xcode
|
||||
scripts
|
||||
makefile.*
|
||||
*.def (module definition files)
|
||||
etc.
|
||||
pngtest.png
|
||||
etc.
|
||||
zlib
|
||||
README, *.h, *.c contrib, etc.
|
||||
|
||||
If the line endings in the files look funny, you may wish to get the other
|
||||
distribution of libpng. It is available in both tar.gz (UNIX style line
|
||||
endings) and zip (DOS style line endings) formats.
|
||||
|
||||
VI. Building with project files
|
||||
|
||||
If you are building libpng with MSVC, you can enter the
|
||||
libpng projects\visualc71 or vstudio directory and follow the instructions
|
||||
in README.txt.
|
||||
|
||||
Otherwise enter the zlib directory and follow the instructions in zlib/README,
|
||||
then come back here and run "configure" or choose the appropriate
|
||||
makefile.sys in the scripts directory.
|
||||
|
||||
VII. Building with makefiles
|
||||
|
||||
Copy the file (or files) that you need from the
|
||||
scripts directory into this directory, for example
|
||||
|
||||
MSDOS example:
|
||||
|
||||
copy scripts\makefile.msc makefile
|
||||
copy scripts\pnglibconf.h.prebuilt pnglibconf.h
|
||||
|
||||
UNIX example:
|
||||
|
||||
cp scripts/makefile.std makefile
|
||||
cp scripts/pnglibconf.h.prebuilt pnglibconf.h
|
||||
|
||||
Read the makefile to see if you need to change any source or
|
||||
target directories to match your preferences.
|
||||
|
||||
Then read pnglibconf.dfa to see if you want to make any configuration
|
||||
changes.
|
||||
|
||||
Then just run "make" which will create the libpng library in
|
||||
this directory and "make test" which will run a quick test that reads
|
||||
the "pngtest.png" file and writes a "pngout.png" file that should be
|
||||
identical to it. Look for "9782 zero samples" in the output of the
|
||||
test. For more confidence, you can run another test by typing
|
||||
"pngtest pngnow.png" and looking for "289 zero samples" in the output.
|
||||
Also, you can run "pngtest -m contrib/pngsuite/*.png" and compare
|
||||
your output with the result shown in contrib/pngsuite/README.
|
||||
|
||||
Most of the makefiles will allow you to run "make install" to
|
||||
put the library in its final resting place (if you want to
|
||||
do that, run "make install" in the zlib directory first if necessary).
|
||||
Some also allow you to run "make test-installed" after you have
|
||||
run "make install".
|
||||
|
||||
VIII. Configuring libpng for 16-bit platforms
|
||||
|
||||
You will want to look into zconf.h to tell zlib (and thus libpng) that
|
||||
it cannot allocate more than 64K at a time. Even if you can, the memory
|
||||
won't be accessible. So limit zlib and libpng to 64K by defining MAXSEG_64K.
|
||||
|
||||
IX. Configuring for DOS
|
||||
|
||||
For DOS users who only have access to the lower 640K, you will
|
||||
have to limit zlib's memory usage via a png_set_compression_mem_level()
|
||||
call. See zlib.h or zconf.h in the zlib library for more information.
|
||||
|
||||
X. Configuring for Medium Model
|
||||
|
||||
Libpng's support for medium model has been tested on most of the popular
|
||||
compilers. Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets
|
||||
defined, and FAR gets defined to far in pngconf.h, and you should be
|
||||
all set. Everything in the library (except for zlib's structure) is
|
||||
expecting far data. You must use the typedefs with the p or pp on
|
||||
the end for pointers (or at least look at them and be careful). Make
|
||||
note that the rows of data are defined as png_bytepp, which is
|
||||
an "unsigned char far * far *".
|
||||
|
||||
XI. Prepending a prefix to exported symbols
|
||||
|
||||
Starting with libpng-1.6.0, you can configure libpng (when using the
|
||||
"configure" script) to prefix all exported symbols by means of the
|
||||
configuration option "--with-libpng-prefix=FOO_", where FOO_ can be any
|
||||
string beginning with a letter and containing only uppercase
|
||||
and lowercase letters, digits, and the underscore (i.e., a C language
|
||||
identifier). This creates a set of macros in pnglibconf.h, so this is
|
||||
transparent to applications; their function calls get transformed by
|
||||
the macros to use the modified names.
|
||||
|
||||
XII. Configuring for compiler xxx:
|
||||
|
||||
All includes for libpng are in pngconf.h. If you need to add, change
|
||||
or delete an include, this is the place to do it.
|
||||
The includes that are not needed outside libpng are placed in pngpriv.h,
|
||||
which is only used by the routines inside libpng itself.
|
||||
The files in libpng proper only include pngpriv.h and png.h, which
|
||||
in turn includes pngconf.h and, as of libpng-1.5.0, pnglibconf.h.
|
||||
As of libpng-1.5.0, pngpriv.h also includes three other private header
|
||||
files, pngstruct.h, pnginfo.h, and pngdebug.h, which contain material
|
||||
that previously appeared in the public headers.
|
||||
|
||||
XIII. Removing unwanted object code
|
||||
|
||||
There are a bunch of #define's in pngconf.h that control what parts of
|
||||
libpng are compiled. All the defines end in _SUPPORTED. If you are
|
||||
never going to use a capability, you can change the #define to #undef
|
||||
before recompiling libpng and save yourself code and data space, or
|
||||
you can turn off individual capabilities with defines that begin with
|
||||
"PNG_NO_".
|
||||
|
||||
In libpng-1.5.0 and later, the #define's are in pnglibconf.h instead.
|
||||
|
||||
You can also turn all of the transforms and ancillary chunk capabilities
|
||||
off en masse with compiler directives that define
|
||||
PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS,
|
||||
or all four, along with directives to turn on any of the capabilities that
|
||||
you do want. The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable the
|
||||
extra transformations but still leave the library fully capable of reading
|
||||
and writing PNG files with all known public chunks. Use of the
|
||||
PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive produces a library
|
||||
that is incapable of reading or writing ancillary chunks. If you are
|
||||
not using the progressive reading capability, you can turn that off
|
||||
with PNG_NO_PROGRESSIVE_READ (don't confuse this with the INTERLACING
|
||||
capability, which you'll still have).
|
||||
|
||||
All the reading and writing specific code are in separate files, so the
|
||||
linker should only grab the files it needs. However, if you want to
|
||||
make sure, or if you are building a stand alone library, all the
|
||||
reading files start with "pngr" and all the writing files start with "pngw".
|
||||
The files that don't match either (like png.c, pngtrans.c, etc.)
|
||||
are used for both reading and writing, and always need to be included.
|
||||
The progressive reader is in pngpread.c
|
||||
|
||||
If you are creating or distributing a dynamically linked library (a .so
|
||||
or DLL file), you should not remove or disable any parts of the library,
|
||||
as this will cause applications linked with different versions of the
|
||||
library to fail if they call functions not available in your library.
|
||||
The size of the library itself should not be an issue, because only
|
||||
those sections that are actually used will be loaded into memory.
|
||||
|
||||
XIV. Enabling or disabling hardware optimizations
|
||||
|
||||
Certain hardware capabilities, such as the Intel SSE instructions,
|
||||
are normally detected at run time. Enable them with configure options
|
||||
such as one of
|
||||
|
||||
--enable-arm-neon=yes
|
||||
--enable-mips-msa=yes
|
||||
--enable-intel-sse=yes
|
||||
--enable-powerpc-vsx=yes
|
||||
|
||||
or enable them all at once with
|
||||
|
||||
--enable-hardware-optimizations=yes
|
||||
|
||||
or, if you are not using "configure", you can use one
|
||||
or more of
|
||||
|
||||
CPPFLAGS += "-DPNG_ARM_NEON"
|
||||
CPPFLAGS += "-DPNG_MIPS_MSA"
|
||||
CPPFLAGS += "-DPNG_INTEL_SSE"
|
||||
CPPFLAGS += "-DPNG_POWERPC_VSX"
|
||||
|
||||
See for example scripts/makefile.linux-opt
|
||||
|
||||
If you wish to avoid using them,
|
||||
you can disable them via the configure option
|
||||
|
||||
--disable-hardware-optimizations
|
||||
|
||||
to disable them all, or
|
||||
|
||||
--enable-intel-sse=no
|
||||
|
||||
to disable a particular one,
|
||||
or via compiler-command options such as
|
||||
|
||||
CPPFLAGS += "-DPNG_ARM_NEON_OPT=0, -DPNG_MIPS_MSA_OPT=0,
|
||||
-DPNG_INTEL_SSE_OPT=0, -DPNG_POWERPC_VSX_OPT=0"
|
||||
|
||||
If you are using cmake, hardware optimizations are "on"
|
||||
by default. To disable them, use
|
||||
|
||||
cmake . -DPNG_ARM_NEON=no -DPNG_INTEL_SSE=no \
|
||||
-DPNG_MIPS_MSA=no -DPNG_POWERPC_VSX=no
|
||||
|
||||
or disable them all at once with
|
||||
|
||||
cmake . -DPNG_HARDWARE_OPTIMIZATIONS=no
|
||||
|
||||
XV. Changes to the build and configuration of libpng in libpng-1.5.x
|
||||
|
||||
Details of internal changes to the library code can be found in the CHANGES
|
||||
file and in the GIT repository logs. These will be of no concern to the vast
|
||||
majority of library users or builders; however, the few who configure libpng
|
||||
to a non-default feature set may need to change how this is done.
|
||||
|
||||
There should be no need for library builders to alter build scripts if
|
||||
these use the distributed build support - configure or the makefiles -
|
||||
however, users of the makefiles may care to update their build scripts
|
||||
to build pnglibconf.h where the corresponding makefile does not do so.
|
||||
|
||||
Building libpng with a non-default configuration has changed completely.
|
||||
The old method using pngusr.h should still work correctly even though the
|
||||
way pngusr.h is used in the build has been changed; however, library
|
||||
builders will probably want to examine the changes to take advantage of
|
||||
new capabilities and to simplify their build system.
|
||||
|
||||
A. Specific changes to library configuration capabilities
|
||||
|
||||
The exact mechanism used to control attributes of API functions has
|
||||
changed. A single set of operating system independent macro definitions
|
||||
is used and operating system specific directives are defined in
|
||||
pnglibconf.h
|
||||
|
||||
As part of this the mechanism used to choose procedure call standards on
|
||||
those systems that allow a choice has been changed. At present this only
|
||||
affects certain Microsoft (DOS, Windows) and IBM (OS/2) operating systems
|
||||
running on Intel processors. As before, PNGAPI is defined where required
|
||||
to control the exported API functions; however, two new macros, PNGCBAPI
|
||||
and PNGCAPI, are used instead for callback functions (PNGCBAPI) and
|
||||
(PNGCAPI) for functions that must match a C library prototype (currently
|
||||
only png_longjmp_ptr, which must match the C longjmp function.) The new
|
||||
approach is documented in pngconf.h
|
||||
|
||||
Despite these changes, libpng 1.5.0 only supports the native C function
|
||||
calling standard on those platforms tested so far ("__cdecl" on Microsoft
|
||||
Windows). This is because the support requirements for alternative
|
||||
calling conventions seem to no longer exist. Developers who find it
|
||||
necessary to set PNG_API_RULE to 1 should advise the mailing list
|
||||
(png-mng-implement) of this and library builders who use Openwatcom and
|
||||
therefore set PNG_API_RULE to 2 should also contact the mailing list.
|
||||
|
||||
B. Changes to the configuration mechanism
|
||||
|
||||
Prior to libpng-1.5.0 library builders who needed to configure libpng
|
||||
had either to modify the exported pngconf.h header file to add system
|
||||
specific configuration or had to write feature selection macros into
|
||||
pngusr.h and cause this to be included into pngconf.h by defining
|
||||
PNG_USER_CONFIG. The latter mechanism had the disadvantage that an
|
||||
application built without PNG_USER_CONFIG defined would see the
|
||||
unmodified, default, libpng API and thus would probably fail to link.
|
||||
|
||||
These mechanisms still work in the configure build and in any makefile
|
||||
build that builds pnglibconf.h, although the feature selection macros
|
||||
have changed somewhat as described above. In 1.5.0, however, pngusr.h is
|
||||
processed only once, at the time the exported header file pnglibconf.h is
|
||||
built. pngconf.h no longer includes pngusr.h; therefore, pngusr.h is ignored
|
||||
after the build of pnglibconf.h and it is never included in an application
|
||||
build.
|
||||
|
||||
The formerly used alternative of adding a list of feature macros to the
|
||||
CPPFLAGS setting in the build also still works; however, the macros will be
|
||||
copied to pnglibconf.h and this may produce macro redefinition warnings
|
||||
when the individual C files are compiled.
|
||||
|
||||
All configuration now only works if pnglibconf.h is built from
|
||||
scripts/pnglibconf.dfa. This requires the program awk. Brian Kernighan
|
||||
(the original author of awk) maintains C source code of that awk and this
|
||||
and all known later implementations (often called by subtly different
|
||||
names - nawk and gawk for example) are adequate to build pnglibconf.h.
|
||||
The Sun Microsystems (now Oracle) program 'awk' is an earlier version
|
||||
and does not work; this may also apply to other systems that have a
|
||||
functioning awk called 'nawk'.
|
||||
|
||||
Configuration options are now documented in scripts/pnglibconf.dfa. This
|
||||
file also includes dependency information that ensures a configuration is
|
||||
consistent; that is, if a feature is switched off, dependent features are
|
||||
also switched off. As a recommended alternative to using feature macros in
|
||||
pngusr.h a system builder may also define equivalent options in pngusr.dfa
|
||||
(or, indeed, any file) and add that to the configuration by setting
|
||||
DFA_XTRA to the file name. The makefiles in contrib/pngminim illustrate
|
||||
how to do this, and also illustrate a case where pngusr.h is still required.
|
||||
|
||||
After you have built libpng, the definitions that were recorded in
|
||||
pnglibconf.h are available to your application (pnglibconf.h is included
|
||||
in png.h and gets installed alongside png.h and pngconf.h in your
|
||||
$PREFIX/include directory). Do not edit pnglibconf.h after you have built
|
||||
libpng, because than the settings would not accurately reflect the settings
|
||||
that were used to build libpng.
|
||||
|
||||
XVI. Setjmp/longjmp issues
|
||||
|
||||
Libpng uses setjmp()/longjmp() for error handling. Unfortunately setjmp()
|
||||
is known to be not thread-safe on some platforms and we don't know of
|
||||
any platform where it is guaranteed to be thread-safe. Therefore, if
|
||||
your application is going to be using multiple threads, you should
|
||||
configure libpng with PNG_NO_SETJMP in your pngusr.dfa file, with
|
||||
-DPNG_NO_SETJMP on your compile line, or with
|
||||
|
||||
#undef PNG_SETJMP_SUPPORTED
|
||||
|
||||
in your pnglibconf.h or pngusr.h.
|
||||
|
||||
Starting with libpng-1.6.0, the library included a "simplified API".
|
||||
This requires setjmp/longjmp, so you must either build the library
|
||||
with PNG_SETJMP_SUPPORTED defined, or with PNG_SIMPLIFIED_READ_SUPPORTED
|
||||
and PNG_SIMPLIFIED_WRITE_SUPPORTED undefined.
|
||||
|
||||
XVII. Common linking failures
|
||||
|
||||
If your application fails to find libpng or zlib entries while linking:
|
||||
|
||||
Be sure "-lz" appears after "-lpng" on your linking command.
|
||||
|
||||
Be sure you have built libpng, zlib, and your application for the
|
||||
same platform (e.g., 32-bit or 64-bit).
|
||||
|
||||
If you are using the vstudio project, observe the WARNING in
|
||||
project/vstudio/README.txt.
|
||||
|
||||
XVIII. Other sources of information about libpng:
|
||||
|
||||
Further information can be found in the README and libpng-manual.txt
|
||||
files, in the individual makefiles, in png.h, and the manual pages
|
||||
libpng.3 and png.5.
|
||||
|
||||
Copyright (c) 1998-2002,2006-2016 Glenn Randers-Pehrson
|
||||
This document is released under the libpng license.
|
||||
For conditions of distribution and use, see the disclaimer
|
||||
and license in png.h.
|
134
libpng/LICENSE
Normal file
134
libpng/LICENSE
Normal file
|
@ -0,0 +1,134 @@
|
|||
COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
|
||||
=========================================
|
||||
|
||||
PNG Reference Library License version 2
|
||||
---------------------------------------
|
||||
|
||||
* Copyright (c) 1995-2019 The PNG Reference Library Authors.
|
||||
* Copyright (c) 2018-2019 Cosmin Truta.
|
||||
* Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
|
||||
* Copyright (c) 1996-1997 Andreas Dilger.
|
||||
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
|
||||
|
||||
The software is supplied "as is", without warranty of any kind,
|
||||
express or implied, including, without limitation, the warranties
|
||||
of merchantability, fitness for a particular purpose, title, and
|
||||
non-infringement. In no event shall the Copyright owners, or
|
||||
anyone distributing the software, be liable for any damages or
|
||||
other liability, whether in contract, tort or otherwise, arising
|
||||
from, out of, or in connection with the software, or the use or
|
||||
other dealings in the software, even if advised of the possibility
|
||||
of such damage.
|
||||
|
||||
Permission is hereby granted to use, copy, modify, and distribute
|
||||
this software, or portions hereof, for any purpose, without fee,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you
|
||||
must not claim that you wrote the original software. If you
|
||||
use this software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated, but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must
|
||||
not be misrepresented as being the original software.
|
||||
|
||||
3. This Copyright notice may not be removed or altered from any
|
||||
source or altered source distribution.
|
||||
|
||||
|
||||
PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are
|
||||
Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are
|
||||
derived from libpng-1.0.6, and are distributed according to the same
|
||||
disclaimer and license as libpng-1.0.6 with the following individuals
|
||||
added to the list of Contributing Authors:
|
||||
|
||||
Simon-Pierre Cadieux
|
||||
Eric S. Raymond
|
||||
Mans Rullgard
|
||||
Cosmin Truta
|
||||
Gilles Vollant
|
||||
James Yu
|
||||
Mandar Sahastrabuddhe
|
||||
Google Inc.
|
||||
Vadim Barkov
|
||||
|
||||
and with the following additions to the disclaimer:
|
||||
|
||||
There is no warranty against interference with your enjoyment of
|
||||
the library or against infringement. There is no warranty that our
|
||||
efforts or the library will fulfill any of your particular purposes
|
||||
or needs. This library is provided with all faults, and the entire
|
||||
risk of satisfactory quality, performance, accuracy, and effort is
|
||||
with the user.
|
||||
|
||||
Some files in the "contrib" directory and some configure-generated
|
||||
files that are distributed with libpng have other copyright owners, and
|
||||
are released under other open source licenses.
|
||||
|
||||
libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
|
||||
Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
|
||||
libpng-0.96, and are distributed according to the same disclaimer and
|
||||
license as libpng-0.96, with the following individuals added to the
|
||||
list of Contributing Authors:
|
||||
|
||||
Tom Lane
|
||||
Glenn Randers-Pehrson
|
||||
Willem van Schaik
|
||||
|
||||
libpng versions 0.89, June 1996, through 0.96, May 1997, are
|
||||
Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
|
||||
and are distributed according to the same disclaimer and license as
|
||||
libpng-0.88, with the following individuals added to the list of
|
||||
Contributing Authors:
|
||||
|
||||
John Bowler
|
||||
Kevin Bracey
|
||||
Sam Bushell
|
||||
Magnus Holmgren
|
||||
Greg Roelofs
|
||||
Tom Tanner
|
||||
|
||||
Some files in the "scripts" directory have other copyright owners,
|
||||
but are released under this license.
|
||||
|
||||
libpng versions 0.5, May 1995, through 0.88, January 1996, are
|
||||
Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
|
||||
|
||||
For the purposes of this copyright and license, "Contributing Authors"
|
||||
is defined as the following set of individuals:
|
||||
|
||||
Andreas Dilger
|
||||
Dave Martindale
|
||||
Guy Eric Schalnat
|
||||
Paul Schmidt
|
||||
Tim Wegner
|
||||
|
||||
The PNG Reference Library is supplied "AS IS". The Contributing
|
||||
Authors and Group 42, Inc. disclaim all warranties, expressed or
|
||||
implied, including, without limitation, the warranties of
|
||||
merchantability and of fitness for any purpose. The Contributing
|
||||
Authors and Group 42, Inc. assume no liability for direct, indirect,
|
||||
incidental, special, exemplary, or consequential damages, which may
|
||||
result from the use of the PNG Reference Library, even if advised of
|
||||
the possibility of such damage.
|
||||
|
||||
Permission is hereby granted to use, copy, modify, and distribute this
|
||||
source code, or portions hereof, for any purpose, without fee, subject
|
||||
to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented.
|
||||
|
||||
2. Altered versions must be plainly marked as such and must not
|
||||
be misrepresented as being the original source.
|
||||
|
||||
3. This Copyright notice may not be removed or altered from any
|
||||
source or altered source distribution.
|
||||
|
||||
The Contributing Authors and Group 42, Inc. specifically permit,
|
||||
without fee, and encourage the use of this source code as a component
|
||||
to supporting the PNG file format in commercial products. If you use
|
||||
this source code in a product, acknowledgment is not required but would
|
||||
be appreciated.
|
393
libpng/Makefile.am
Normal file
393
libpng/Makefile.am
Normal file
|
@ -0,0 +1,393 @@
|
|||
# Makefile.am, the source file for Makefile.in (and hence Makefile), is
|
||||
#
|
||||
# Copyright (c) 2018 Cosmin Truta
|
||||
# Copyright (c) 2004-2016 Glenn Randers-Pehrson
|
||||
#
|
||||
# This code is released under the libpng license.
|
||||
# For conditions of distribution and use, see the disclaimer
|
||||
# and license in png.h
|
||||
|
||||
PNGLIB_BASENAME= libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@
|
||||
|
||||
ACLOCAL_AMFLAGS = -I scripts
|
||||
|
||||
# test programs - run on make check, make distcheck
|
||||
check_PROGRAMS= pngtest pngunknown pngstest pngvalid pngimage pngcp
|
||||
if HAVE_CLOCK_GETTIME
|
||||
check_PROGRAMS += timepng
|
||||
endif
|
||||
|
||||
# Utilities - installed
|
||||
bin_PROGRAMS= pngfix png-fix-itxt
|
||||
|
||||
# This ensures that pnglibconf.h gets built at the start of 'make all' or
|
||||
# 'make check', but it does not add dependencies to the individual programs,
|
||||
# this is done below.
|
||||
#
|
||||
# IMPORTANT: always add the object modules of new programs to the list below
|
||||
# because otherwise the sequence 'configure; make new-program' will *sometimes*
|
||||
# result in the installed (system) pnglibconf.h being used and the result is
|
||||
# always wrong and always very confusing.
|
||||
BUILT_SOURCES = pnglibconf.h
|
||||
|
||||
pngtest_SOURCES = pngtest.c
|
||||
pngtest_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
|
||||
|
||||
pngvalid_SOURCES = contrib/libtests/pngvalid.c
|
||||
pngvalid_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
|
||||
|
||||
pngstest_SOURCES = contrib/libtests/pngstest.c
|
||||
pngstest_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
|
||||
|
||||
pngunknown_SOURCES = contrib/libtests/pngunknown.c
|
||||
pngunknown_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
|
||||
|
||||
pngimage_SOURCES = contrib/libtests/pngimage.c
|
||||
pngimage_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
|
||||
|
||||
timepng_SOURCES = contrib/libtests/timepng.c
|
||||
timepng_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
|
||||
|
||||
pngfix_SOURCES = contrib/tools/pngfix.c
|
||||
pngfix_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
|
||||
|
||||
png_fix_itxt_SOURCES = contrib/tools/png-fix-itxt.c
|
||||
|
||||
pngcp_SOURCES = contrib/tools/pngcp.c
|
||||
pngcp_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
|
||||
|
||||
# Generally these are single line shell scripts to run a test with a particular
|
||||
# set of parameters:
|
||||
TESTS =\
|
||||
tests/pngtest\
|
||||
tests/pngtest-badpngs\
|
||||
tests/pngvalid-gamma-16-to-8 tests/pngvalid-gamma-alpha-mode\
|
||||
tests/pngvalid-gamma-background tests/pngvalid-gamma-expand16-alpha-mode\
|
||||
tests/pngvalid-gamma-expand16-background\
|
||||
tests/pngvalid-gamma-expand16-transform tests/pngvalid-gamma-sbit\
|
||||
tests/pngvalid-gamma-threshold tests/pngvalid-gamma-transform\
|
||||
tests/pngvalid-progressive-size\
|
||||
tests/pngvalid-progressive-interlace-standard\
|
||||
tests/pngvalid-transform\
|
||||
tests/pngvalid-progressive-standard tests/pngvalid-standard\
|
||||
tests/pngstest-1.8 tests/pngstest-1.8-alpha tests/pngstest-linear\
|
||||
tests/pngstest-linear-alpha tests/pngstest-none tests/pngstest-none-alpha\
|
||||
tests/pngstest-sRGB tests/pngstest-sRGB-alpha tests/pngunknown-IDAT\
|
||||
tests/pngunknown-discard tests/pngunknown-if-safe tests/pngunknown-sAPI\
|
||||
tests/pngunknown-sTER tests/pngunknown-save tests/pngunknown-vpAg\
|
||||
tests/pngimage-quick tests/pngimage-full
|
||||
|
||||
# man pages
|
||||
dist_man_MANS= libpng.3 libpngpf.3 png.5
|
||||
|
||||
# generate the -config scripts if required
|
||||
binconfigs= libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config
|
||||
EXTRA_SCRIPTS= libpng-config libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config
|
||||
bin_SCRIPTS= @binconfigs@
|
||||
|
||||
# rules to build libpng, only build the old library on request
|
||||
lib_LTLIBRARIES=libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
|
||||
# EXTRA_LTLIBRARIES= libpng.la
|
||||
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = png.c pngerror.c\
|
||||
pngget.c pngmem.c pngpread.c pngread.c pngrio.c pngrtran.c pngrutil.c\
|
||||
pngset.c pngtrans.c pngwio.c pngwrite.c pngwtran.c pngwutil.c\
|
||||
png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h pngusr.dfa
|
||||
|
||||
if PNG_ARM_NEON
|
||||
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += arm/arm_init.c\
|
||||
arm/filter_neon.S arm/filter_neon_intrinsics.c \
|
||||
arm/palette_neon_intrinsics.c
|
||||
endif
|
||||
|
||||
if PNG_MIPS_MSA
|
||||
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += mips/mips_init.c\
|
||||
mips/filter_msa_intrinsics.c
|
||||
endif
|
||||
|
||||
if PNG_INTEL_SSE
|
||||
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += intel/intel_init.c\
|
||||
intel/filter_sse2_intrinsics.c
|
||||
endif
|
||||
|
||||
if PNG_POWERPC_VSX
|
||||
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += powerpc/powerpc_init.c\
|
||||
powerpc/filter_vsx_intrinsics.c
|
||||
endif
|
||||
|
||||
nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = pnglibconf.h
|
||||
|
||||
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS = -no-undefined -export-dynamic \
|
||||
-version-number @PNGLIB_MAJOR@@PNGLIB_MINOR@:@PNGLIB_RELEASE@:0
|
||||
|
||||
if HAVE_LD_VERSION_SCRIPT
|
||||
# Versioned symbols and restricted exports
|
||||
if HAVE_SOLARIS_LD
|
||||
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS += -Wl,-M -Wl,libpng.vers
|
||||
else
|
||||
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS += -Wl,--version-script=libpng.vers
|
||||
endif
|
||||
|
||||
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES = libpng.vers
|
||||
else
|
||||
# Only restricted exports when possible
|
||||
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS += -export-symbols libpng.sym
|
||||
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES = libpng.sym
|
||||
endif
|
||||
|
||||
#distribute headers in /usr/include/libpng/*
|
||||
pkgincludedir= $(includedir)/$(PNGLIB_BASENAME)
|
||||
pkginclude_HEADERS= png.h pngconf.h
|
||||
nodist_pkginclude_HEADERS= pnglibconf.h
|
||||
|
||||
# pkg-config stuff, note that libpng.pc is always required in order
|
||||
# to get the correct library
|
||||
pkgconfigdir = @pkgconfigdir@
|
||||
pkgconfig_DATA = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.pc
|
||||
|
||||
# Extra source distribution files, '${srcdir}' is used below to stop build files
|
||||
# from those directories being included. This only works if the configure is
|
||||
# not done in the source directory!
|
||||
EXTRA_DIST= \
|
||||
ANNOUNCE AUTHORS CHANGES INSTALL LICENSE README TODO TRADEMARK \
|
||||
pngtest.png pngbar.png pngnow.png pngbar.jpg autogen.sh \
|
||||
${srcdir}/contrib ${srcdir}/projects ${srcdir}/scripts \
|
||||
$(TESTS) $(XFAIL_TESTS) tests/pngstest \
|
||||
CMakeLists.txt example.c libpng-manual.txt
|
||||
|
||||
SCRIPT_CLEANFILES=scripts/*.out scripts/*.chk
|
||||
|
||||
CLEANFILES= *.tf? pngout.png libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.pc \
|
||||
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config libpng.vers libpng.sym \
|
||||
check.new pnglibconf.h pngprefix.h symbols.new pngtest-log.txt \
|
||||
pnglibconf.out pnglibconf.c pnglibconf.pre pnglibconf.dfn \
|
||||
$(SCRIPT_CLEANFILES)
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess config.h.in \
|
||||
config.sub configure depcomp install-sh ltmain.sh missing
|
||||
|
||||
# PNG_COPTS give extra options for the C compiler to be used on all compilation
|
||||
# steps (unless targe_CFLAGS is specified; that will take precedence over
|
||||
# AM_CFLAGS)
|
||||
PNG_COPTS = @PNG_COPTS@
|
||||
AM_CFLAGS = ${PNG_COPTS}
|
||||
|
||||
# DFNCPP is normally just CPP - the C preprocessor - but on Solaris and maybe
|
||||
# other operating systems (NeXT?) the C preprocessor selected by configure
|
||||
# checks input tokens for validity - effectively it performs part of the ANSI-C
|
||||
# parsing - and therefore fails with the .df files. configure.ac has special
|
||||
# checks for this and sets DFNCPP appropriately.
|
||||
DFNCPP = @DFNCPP@
|
||||
|
||||
SUFFIXES = .chk .out
|
||||
|
||||
$(PNGLIB_BASENAME).pc: libpng.pc
|
||||
cp libpng.pc $@
|
||||
|
||||
$(PNGLIB_BASENAME)-config: libpng-config
|
||||
cp libpng-config $@
|
||||
|
||||
scripts/sym.out scripts/vers.out: png.h pngconf.h pnglibconf.h
|
||||
scripts/prefix.out: png.h pngconf.h pnglibconf.out
|
||||
scripts/symbols.out: png.h pngconf.h $(srcdir)/scripts/pnglibconf.h.prebuilt
|
||||
scripts/intprefix.out: pnglibconf.h
|
||||
|
||||
libpng.sym: scripts/sym.out
|
||||
rm -f $@
|
||||
cp $? $@
|
||||
libpng.vers: scripts/vers.out
|
||||
rm -f $@
|
||||
cp $? $@
|
||||
|
||||
if DO_PNG_PREFIX
|
||||
# Rename functions in scripts/prefix.out with a PNG_PREFIX prefix.
|
||||
# Rename macros in scripts/macro.lst from PNG_PREFIXpng_ to PNG_ (the actual
|
||||
# implementation of the macro).
|
||||
pnglibconf.h: pnglibconf.out scripts/prefix.out scripts/macro.lst
|
||||
rm -f $@
|
||||
$(AWK) 's==0 && NR>1{print prev}\
|
||||
s==0{prev=$$0}\
|
||||
s==1{print "#define", $$1, "@PNG_PREFIX@" $$1}\
|
||||
s==2{print "#define @PNG_PREFIX@png_" $$1, "PNG_" $$1}\
|
||||
END{print prev}' s=0 pnglibconf.out s=1 scripts/prefix.out\
|
||||
s=2 ${srcdir}/scripts/macro.lst >pnglibconf.tf8
|
||||
mv pnglibconf.tf8 $@
|
||||
|
||||
pngprefix.h: scripts/intprefix.out
|
||||
rm -f pngprefix.tf1
|
||||
$(AWK) '{print "#define", $$1, "@PNG_PREFIX@" $$1}' $? >pngprefix.tf1
|
||||
mv pngprefix.tf1 $@
|
||||
else
|
||||
pnglibconf.h: pnglibconf.out
|
||||
rm -f $@
|
||||
cp $? $@
|
||||
|
||||
pngprefix.h: # is empty
|
||||
:>$@
|
||||
endif
|
||||
|
||||
$(srcdir)/scripts/pnglibconf.h.prebuilt:
|
||||
@echo "Attempting to build $@" >&2
|
||||
@echo "This is a machine generated file, but if you want to make" >&2
|
||||
@echo "a new one simply make 'scripts/pnglibconf.out', copy that" >&2
|
||||
@echo "AND set PNG_ZLIB_VERNUM to 0 (you MUST do this)" >&2
|
||||
@exit 1
|
||||
|
||||
# The following is necessary to ensure that the local pnglibconf.h is used, not
|
||||
# an installed one (this can happen immediately after on a clean system if
|
||||
# 'make test' is the first thing the user does.) Only files which include
|
||||
# one of the png source files (typically png.h or pngpriv.h) need to be listed
|
||||
# here:
|
||||
pngtest.o: pnglibconf.h
|
||||
|
||||
contrib/libtests/makepng.o: pnglibconf.h
|
||||
contrib/libtests/pngstest.o: pnglibconf.h
|
||||
contrib/libtests/pngunknown.o: pnglibconf.h
|
||||
contrib/libtests/pngimage.o: pnglibconf.h
|
||||
contrib/libtests/pngvalid.o: pnglibconf.h
|
||||
contrib/libtests/readpng.o: pnglibconf.h
|
||||
contrib/libtests/tarith.o: pnglibconf.h
|
||||
contrib/libtests/timepng.o: pnglibconf.h
|
||||
|
||||
contrib/tools/makesRGB.o: pnglibconf.h
|
||||
contrib/tools/pngfix.o: pnglibconf.h
|
||||
contrib/tools/pngcp.o: pnglibconf.h
|
||||
|
||||
# We must use -DPNG_NO_USE_READ_MACROS here even when the library may actually
|
||||
# be built with PNG_USE_READ_MACROS; this prevents the read macros from
|
||||
# interfering with the symbol file format.
|
||||
SYMBOL_CFLAGS = -DPNGLIB_LIBNAME='PNG@PNGLIB_MAJOR@@PNGLIB_MINOR@_0'\
|
||||
-DPNGLIB_VERSION='@PNGLIB_VERSION@'\
|
||||
-DSYMBOL_PREFIX='$(SYMBOL_PREFIX)'\
|
||||
-DPNG_NO_USE_READ_MACROS -DPNG_BUILDING_SYMBOL_TABLE
|
||||
|
||||
if DO_PNG_PREFIX
|
||||
SYMBOL_CFLAGS += -DPNG_PREFIX='@PNG_PREFIX@'
|
||||
endif
|
||||
|
||||
.c.out:
|
||||
rm -f $@ $*.tf[12]
|
||||
test -d scripts || mkdir scripts || test -d scripts
|
||||
$(DFNCPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES)\
|
||||
$(CPPFLAGS) $(SYMBOL_CFLAGS) $< > $*.tf1
|
||||
$(AWK) -f "${srcdir}/scripts/dfn.awk" out="$*.tf2" $*.tf1 1>&2
|
||||
rm -f $*.tf1
|
||||
mv $*.tf2 $@
|
||||
|
||||
# The .c file for pnglibconf.h is machine generated
|
||||
pnglibconf.c: scripts/pnglibconf.dfa scripts/options.awk pngconf.h pngusr.dfa $(DFA_XTRA)
|
||||
rm -f $@ $*.tf[45]
|
||||
$(AWK) -f ${srcdir}/scripts/options.awk out=$*.tf4 version=search\
|
||||
${srcdir}/pngconf.h ${srcdir}/scripts/pnglibconf.dfa\
|
||||
${srcdir}/pngusr.dfa $(DFA_XTRA) 1>&2
|
||||
$(AWK) -f ${srcdir}/scripts/options.awk out=$*.tf5 $*.tf4 1>&2
|
||||
rm $*.tf4
|
||||
mv $*.tf5 $@
|
||||
|
||||
# Symbol checks (.def and .out files should match)
|
||||
scripts/symbols.chk: scripts/checksym.awk scripts/symbols.def scripts/symbols.out
|
||||
|
||||
.out.chk:
|
||||
rm -f $@ $*.new
|
||||
$(AWK) -f ${srcdir}/scripts/checksym.awk ${srcdir}/scripts/${*F}.def\
|
||||
of="$*.new" $< >&2
|
||||
mv $*.new $@
|
||||
|
||||
# used on demand to regenerate the standard header, CPPFLAGS should
|
||||
# be empty - no non-standard defines
|
||||
scripts/pnglibconf.c: scripts/pnglibconf.dfa scripts/options.awk pngconf.h
|
||||
rm -f $@ pnglibconf.tf[67]
|
||||
test -z "$(CPPFLAGS)"
|
||||
echo "com @PNGLIB_VERSION@ STANDARD API DEFINITION" |\
|
||||
$(AWK) -f ${srcdir}/scripts/options.awk out=pnglibconf.tf6\
|
||||
logunsupported=1 version=search ${srcdir}/pngconf.h -\
|
||||
${srcdir}/scripts/pnglibconf.dfa 1>&2
|
||||
$(AWK) -f ${srcdir}/scripts/options.awk out=pnglibconf.tf7\
|
||||
pnglibconf.tf6 1>&2
|
||||
rm pnglibconf.tf6
|
||||
mv pnglibconf.tf7 $@
|
||||
|
||||
$(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS): png.h pngconf.h \
|
||||
pnglibconf.h pngpriv.h pngdebug.h pnginfo.h pngstruct.h pngprefix.h
|
||||
|
||||
test: check-am
|
||||
|
||||
# Extra checks
|
||||
check: scripts/symbols.chk
|
||||
|
||||
# Don't distribute the generated script files
|
||||
dist-hook:
|
||||
cd '$(top_distdir)'; rm -f $(SCRIPT_CLEANFILES)
|
||||
|
||||
# Make links between installed files with release-specific names and the generic
|
||||
# file names. If this install rule is run the generic names will be deleted and
|
||||
# recreated - this has obvious issues for systems with multiple installations.
|
||||
|
||||
install-header-links:
|
||||
@set -ex; cd '$(DESTDIR)$(includedir)'; for f in $(HEADERS); do \
|
||||
rm -f "$$f"; $(LN_S) "$(PNGLIB_BASENAME)/$$f" "$$f"; done
|
||||
|
||||
uninstall-header-links:
|
||||
cd '$(DESTDIR)$(includedir)'; rm -f $(HEADERS)
|
||||
|
||||
install-libpng-pc:
|
||||
@set -ex; cd '$(DESTDIR)$(pkgconfigdir)'; rm -f libpng.pc; \
|
||||
$(LN_S) '$(PNGLIB_BASENAME).pc' libpng.pc
|
||||
|
||||
uninstall-libpng-pc:
|
||||
rm -f '$(DESTDIR)$(pkgconfigdir)/libpng.pc'
|
||||
|
||||
# EXT_LIST is a list of the possibly library directory extensions, this exists
|
||||
# because we can't find a good way of discovering the file extensions that are
|
||||
# actually installed on a given system, so instead we check for every extension
|
||||
# we have seen.
|
||||
|
||||
EXT_LIST = a dll.a so so.@PNGLIB_MAJOR@@PNGLIB_MINOR@.@PNGLIB_RELEASE@ la sl dylib
|
||||
|
||||
install-library-links:
|
||||
@set -x; cd '$(DESTDIR)$(libdir)';\
|
||||
for ext in $(EXT_LIST); do\
|
||||
rm -f "libpng.$$ext";\
|
||||
if test -f "$(PNGLIB_BASENAME).$$ext"; then\
|
||||
$(LN_S) "$(PNGLIB_BASENAME).$$ext" "libpng.$$ext" || exit 1;\
|
||||
fi;\
|
||||
done
|
||||
|
||||
uninstall-library-links:
|
||||
@set -x; cd '$(DESTDIR)$(libdir)'; for ext in $(EXT_LIST); do\
|
||||
rm -f "libpng.$$ext"; done
|
||||
|
||||
install-libpng-config:
|
||||
@set -ex; cd '$(DESTDIR)$(bindir)'; rm -f libpng-config; \
|
||||
$(LN_S) '$(PNGLIB_BASENAME)-config' libpng-config
|
||||
|
||||
uninstall-libpng-config:
|
||||
rm -f '$(DESTDIR)$(bindir)/libpng-config'
|
||||
|
||||
if DO_INSTALL_LINKS
|
||||
# If --enable-unversioned-links is specified the header and lib file links
|
||||
# will be automatically made on a 'make install':
|
||||
|
||||
install-data-hook: install-header-links
|
||||
uninstall-hook: uninstall-header-links
|
||||
install-exec-hook: install-library-links
|
||||
uninstall-hook: uninstall-library-links
|
||||
endif
|
||||
|
||||
if DO_INSTALL_LIBPNG_PC
|
||||
# Likewise, --install-pc causes libpng.pc to be constructed:
|
||||
|
||||
install-data-hook: install-libpng-pc
|
||||
uninstall-hook: uninstall-libpng-pc
|
||||
endif
|
||||
|
||||
if DO_INSTALL_LIBPNG_CONFIG
|
||||
# And --install-config:
|
||||
|
||||
install-exec-hook: install-libpng-config
|
||||
uninstall-hook: uninstall-libpng-config
|
||||
endif
|
||||
|
||||
# The following addition ensures that 'make all' always builds the test programs
|
||||
# too. It used to, but some change either in libpng or configure stopped this
|
||||
# working.
|
||||
all-am: $(check_PROGRAMS)
|
2428
libpng/Makefile.in
Normal file
2428
libpng/Makefile.in
Normal file
File diff suppressed because it is too large
Load diff
183
libpng/README
Normal file
183
libpng/README
Normal file
|
@ -0,0 +1,183 @@
|
|||
README for libpng version 1.6.37 - April 14, 2019
|
||||
=================================================
|
||||
|
||||
See the note about version numbers near the top of png.h.
|
||||
See INSTALL for instructions on how to install libpng.
|
||||
|
||||
Libpng comes in several distribution formats. Get libpng-*.tar.gz or
|
||||
libpng-*.tar.xz or if you want UNIX-style line endings in the text
|
||||
files, or lpng*.7z or lpng*.zip if you want DOS-style line endings.
|
||||
|
||||
Version 0.89 was the first official release of libpng. Don't let the
|
||||
fact that it's the first release fool you. The libpng library has been
|
||||
in extensive use and testing since mid-1995. By late 1997 it had
|
||||
finally gotten to the stage where there hadn't been significant
|
||||
changes to the API in some time, and people have a bad feeling about
|
||||
libraries with versions < 1.0. Version 1.0.0 was released in
|
||||
March 1998.
|
||||
|
||||
****
|
||||
Note that some of the changes to the png_info structure render this
|
||||
version of the library binary incompatible with libpng-0.89 or
|
||||
earlier versions if you are using a shared library. The type of the
|
||||
"filler" parameter for png_set_filler() has changed from png_byte to
|
||||
png_uint_32, which will affect shared-library applications that use
|
||||
this function.
|
||||
|
||||
To avoid problems with changes to the internals of the png info_struct,
|
||||
new APIs have been made available in 0.95 to avoid direct application
|
||||
access to info_ptr. These functions are the png_set_<chunk> and
|
||||
png_get_<chunk> functions. These functions should be used when
|
||||
accessing/storing the info_struct data, rather than manipulating it
|
||||
directly, to avoid such problems in the future.
|
||||
|
||||
It is important to note that the APIs did not make current programs
|
||||
that access the info struct directly incompatible with the new
|
||||
library, through libpng-1.2.x. In libpng-1.4.x, which was meant to
|
||||
be a transitional release, members of the png_struct and the
|
||||
info_struct can still be accessed, but the compiler will issue a
|
||||
warning about deprecated usage. Since libpng-1.5.0, direct access
|
||||
to these structs is not allowed, and the definitions of the structs
|
||||
reside in private pngstruct.h and pnginfo.h header files that are not
|
||||
accessible to applications. It is strongly suggested that new
|
||||
programs use the new APIs (as shown in example.c and pngtest.c), and
|
||||
older programs be converted to the new format, to facilitate upgrades
|
||||
in the future.
|
||||
****
|
||||
|
||||
Additions since 0.90 include the ability to compile libpng as a
|
||||
Windows DLL, and new APIs for accessing data in the info struct.
|
||||
Experimental functions include the ability to set weighting and cost
|
||||
factors for row filter selection, direct reads of integers from buffers
|
||||
on big-endian processors that support misaligned data access, faster
|
||||
methods of doing alpha composition, and more accurate 16->8 bit color
|
||||
conversion.
|
||||
|
||||
The additions since 0.89 include the ability to read from a PNG stream
|
||||
which has had some (or all) of the signature bytes read by the calling
|
||||
application. This also allows the reading of embedded PNG streams that
|
||||
do not have the PNG file signature. As well, it is now possible to set
|
||||
the library action on the detection of chunk CRC errors. It is possible
|
||||
to set different actions based on whether the CRC error occurred in a
|
||||
critical or an ancillary chunk.
|
||||
|
||||
For a detailed description on using libpng, read libpng-manual.txt.
|
||||
For examples of libpng in a program, see example.c and pngtest.c. For
|
||||
usage information and restrictions (what little they are) on libpng,
|
||||
see png.h. For a description on using zlib (the compression library
|
||||
used by libpng) and zlib's restrictions, see zlib.h
|
||||
|
||||
I have included a general makefile, as well as several machine and
|
||||
compiler specific ones, but you may have to modify one for your own
|
||||
needs.
|
||||
|
||||
You should use zlib 1.0.4 or later to run this, but it MAY work with
|
||||
versions as old as zlib 0.95. Even so, there are bugs in older zlib
|
||||
versions which can cause the output of invalid compression streams for
|
||||
some images.
|
||||
|
||||
You should also note that zlib is a compression library that is useful
|
||||
for more things than just PNG files. You can use zlib as a drop-in
|
||||
replacement for fread() and fwrite(), if you are so inclined.
|
||||
|
||||
zlib should be available at the same place that libpng is, or at
|
||||
https://zlib.net.
|
||||
|
||||
You may also want a copy of the PNG specification. It is available
|
||||
as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find
|
||||
these at http://www.libpng.org/pub/png/pngdocs.html .
|
||||
|
||||
This code is currently being archived at libpng.sourceforge.io in the
|
||||
[DOWNLOAD] area, and at http://libpng.download/src .
|
||||
|
||||
This release, based in a large way on Glenn's, Guy's and Andreas'
|
||||
earlier work, was created and will be supported by myself and the PNG
|
||||
development group.
|
||||
|
||||
Send comments/corrections/commendations to png-mng-implement at
|
||||
lists.sourceforge.net (subscription required; visit
|
||||
https://lists.sourceforge.net/lists/listinfo/png-mng-implement
|
||||
to subscribe).
|
||||
|
||||
Send general questions about the PNG specification to png-mng-misc
|
||||
at lists.sourceforge.net (subscription required; visit
|
||||
https://lists.sourceforge.net/lists/listinfo/png-mng-misc to
|
||||
subscribe).
|
||||
|
||||
Files in this distribution:
|
||||
|
||||
ANNOUNCE => Announcement of this version, with recent changes
|
||||
AUTHORS => List of contributing authors
|
||||
CHANGES => Description of changes between libpng versions
|
||||
KNOWNBUG => List of known bugs and deficiencies
|
||||
LICENSE => License to use and redistribute libpng
|
||||
README => This file
|
||||
TODO => Things not implemented in the current library
|
||||
TRADEMARK => Trademark information
|
||||
example.c => Example code for using libpng functions
|
||||
libpng.3 => manual page for libpng (includes libpng-manual.txt)
|
||||
libpng-manual.txt => Description of libpng and its functions
|
||||
libpngpf.3 => manual page for libpng's private functions
|
||||
png.5 => manual page for the PNG format
|
||||
png.c => Basic interface functions common to library
|
||||
png.h => Library function and interface declarations (public)
|
||||
pngpriv.h => Library function and interface declarations (private)
|
||||
pngconf.h => System specific library configuration (public)
|
||||
pngstruct.h => png_struct declaration (private)
|
||||
pnginfo.h => png_info struct declaration (private)
|
||||
pngdebug.h => debugging macros (private)
|
||||
pngerror.c => Error/warning message I/O functions
|
||||
pngget.c => Functions for retrieving info from struct
|
||||
pngmem.c => Memory handling functions
|
||||
pngbar.png => PNG logo, 88x31
|
||||
pngnow.png => PNG logo, 98x31
|
||||
pngpread.c => Progressive reading functions
|
||||
pngread.c => Read data/helper high-level functions
|
||||
pngrio.c => Lowest-level data read I/O functions
|
||||
pngrtran.c => Read data transformation functions
|
||||
pngrutil.c => Read data utility functions
|
||||
pngset.c => Functions for storing data into the info_struct
|
||||
pngtest.c => Library test program
|
||||
pngtest.png => Library test sample image
|
||||
pngtrans.c => Common data transformation functions
|
||||
pngwio.c => Lowest-level write I/O functions
|
||||
pngwrite.c => High-level write functions
|
||||
pngwtran.c => Write data transformations
|
||||
pngwutil.c => Write utility functions
|
||||
arm => Contains optimized code for the ARM platform
|
||||
powerpc => Contains optimized code for the PowerPC platform
|
||||
contrib => Contributions
|
||||
arm-neon => Optimized code for ARM-NEON platform
|
||||
powerpc-vsx => Optimized code for POWERPC-VSX platform
|
||||
examples => Example programs
|
||||
gregbook => source code for PNG reading and writing, from
|
||||
Greg Roelofs' "PNG: The Definitive Guide",
|
||||
O'Reilly, 1999
|
||||
libtests => Test programs
|
||||
mips-msa => Optimized code for MIPS-MSA platform
|
||||
pngminim => Minimal decoder, encoder, and progressive decoder
|
||||
programs demonstrating use of pngusr.dfa
|
||||
pngminus => Simple pnm2png and png2pnm programs
|
||||
pngsuite => Test images
|
||||
testpngs
|
||||
tools => Various tools
|
||||
visupng => Contains a MSVC workspace for VisualPng
|
||||
intel => Optimized code for INTEL-SSE2 platform
|
||||
mips => Optimized code for MIPS platform
|
||||
projects => Contains project files and workspaces for
|
||||
building a DLL
|
||||
owatcom => Contains a WATCOM project for building libpng
|
||||
visualc71 => Contains a Microsoft Visual C++ (MSVC)
|
||||
workspace for building libpng and zlib
|
||||
vstudio => Contains a Microsoft Visual C++ (MSVC)
|
||||
workspace for building libpng and zlib
|
||||
scripts => Directory containing scripts for building libpng:
|
||||
(see scripts/README.txt for the list of scripts)
|
||||
|
||||
Good luck, and happy coding!
|
||||
|
||||
* Cosmin Truta (current maintainer, since 2018)
|
||||
* Glenn Randers-Pehrson (former maintainer, 1998-2018)
|
||||
* Andreas Eric Dilger (former maintainer, 1996-1997)
|
||||
* Guy Eric Schalnat (original author and former maintainer, 1995-1996)
|
||||
(formerly of Group 42, Inc.)
|
23
libpng/TODO
Normal file
23
libpng/TODO
Normal file
|
@ -0,0 +1,23 @@
|
|||
TODO - list of things to do for libpng:
|
||||
|
||||
* Fix all defects (duh!)
|
||||
* Better C++ wrapper / full C++ implementation (?)
|
||||
* Fix the problems with C++ and 'extern "C"'.
|
||||
* cHRM transformation.
|
||||
* Palette creation.
|
||||
* "grayscale->palette" transformation and "palette->grayscale" detection.
|
||||
* Improved dithering.
|
||||
* Multi-lingual error and warning message support.
|
||||
* Complete sRGB transformation. (Currently it simply uses gamma=0.45455.)
|
||||
* Man pages for function calls.
|
||||
* Better documentation.
|
||||
* Better filter selection
|
||||
(e.g., counting huffman bits/precompression; filter inertia; filter costs).
|
||||
* Histogram creation.
|
||||
* Text conversion between different code pages (e.g., Latin-1 -> Mac).
|
||||
* Avoid building gamma tables whenever possible.
|
||||
* Greater precision in changing to linear gamma for compositing against
|
||||
background, and in doing rgb-to-gray transformations.
|
||||
* Investigate pre-incremented loop counters and other loop constructions.
|
||||
* Interpolated method of handling interlacing.
|
||||
* More validations for libpng transformations.
|
8
libpng/TRADEMARK
Normal file
8
libpng/TRADEMARK
Normal file
|
@ -0,0 +1,8 @@
|
|||
TRADEMARK
|
||||
=========
|
||||
|
||||
The name "libpng" has not been registered by the Copyright owners
|
||||
as a trademark in any jurisdiction. However, because libpng has
|
||||
been distributed and maintained world-wide, continually since 1995,
|
||||
the Copyright owners claim "common-law trademark protection" in any
|
||||
jurisdiction where common-law trademark is recognized.
|
1196
libpng/aclocal.m4
vendored
Normal file
1196
libpng/aclocal.m4
vendored
Normal file
File diff suppressed because it is too large
Load diff
136
libpng/arm/arm_init.c
Normal file
136
libpng/arm/arm_init.c
Normal file
|
@ -0,0 +1,136 @@
|
|||
|
||||
/* arm_init.c - NEON optimised filter functions
|
||||
*
|
||||
* Copyright (c) 2018 Cosmin Truta
|
||||
* Copyright (c) 2014,2016 Glenn Randers-Pehrson
|
||||
* Written by Mans Rullgard, 2011.
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*/
|
||||
|
||||
/* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are
|
||||
* called.
|
||||
*/
|
||||
#define _POSIX_SOURCE 1
|
||||
|
||||
#include "../pngpriv.h"
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
|
||||
#if PNG_ARM_NEON_OPT > 0
|
||||
#ifdef PNG_ARM_NEON_CHECK_SUPPORTED /* Do run-time checks */
|
||||
/* WARNING: it is strongly recommended that you do not build libpng with
|
||||
* run-time checks for CPU features if at all possible. In the case of the ARM
|
||||
* NEON instructions there is no processor-specific way of detecting the
|
||||
* presence of the required support, therefore run-time detection is extremely
|
||||
* OS specific.
|
||||
*
|
||||
* You may set the macro PNG_ARM_NEON_FILE to the file name of file containing
|
||||
* a fragment of C source code which defines the png_have_neon function. There
|
||||
* are a number of implementations in contrib/arm-neon, but the only one that
|
||||
* has partial support is contrib/arm-neon/linux.c - a generic Linux
|
||||
* implementation which reads /proc/cpufino.
|
||||
*/
|
||||
#ifndef PNG_ARM_NEON_FILE
|
||||
# ifdef __linux__
|
||||
# define PNG_ARM_NEON_FILE "contrib/arm-neon/linux.c"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef PNG_ARM_NEON_FILE
|
||||
|
||||
#include <signal.h> /* for sig_atomic_t */
|
||||
static int png_have_neon(png_structp png_ptr);
|
||||
#include PNG_ARM_NEON_FILE
|
||||
|
||||
#else /* PNG_ARM_NEON_FILE */
|
||||
# error "PNG_ARM_NEON_FILE undefined: no support for run-time ARM NEON checks"
|
||||
#endif /* PNG_ARM_NEON_FILE */
|
||||
#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */
|
||||
|
||||
#ifndef PNG_ALIGNED_MEMORY_SUPPORTED
|
||||
# error "ALIGNED_MEMORY is required; set: -DPNG_ALIGNED_MEMORY_SUPPORTED"
|
||||
#endif
|
||||
|
||||
void
|
||||
png_init_filter_functions_neon(png_structp pp, unsigned int bpp)
|
||||
{
|
||||
/* The switch statement is compiled in for ARM_NEON_API, the call to
|
||||
* png_have_neon is compiled in for ARM_NEON_CHECK. If both are defined
|
||||
* the check is only performed if the API has not set the NEON option on
|
||||
* or off explicitly. In this case the check controls what happens.
|
||||
*
|
||||
* If the CHECK is not compiled in and the option is UNSET the behavior prior
|
||||
* to 1.6.7 was to use the NEON code - this was a bug caused by having the
|
||||
* wrong order of the 'ON' and 'default' cases. UNSET now defaults to OFF,
|
||||
* as documented in png.h
|
||||
*/
|
||||
png_debug(1, "in png_init_filter_functions_neon");
|
||||
#ifdef PNG_ARM_NEON_API_SUPPORTED
|
||||
switch ((pp->options >> PNG_ARM_NEON) & 3)
|
||||
{
|
||||
case PNG_OPTION_UNSET:
|
||||
/* Allow the run-time check to execute if it has been enabled -
|
||||
* thus both API and CHECK can be turned on. If it isn't supported
|
||||
* this case will fall through to the 'default' below, which just
|
||||
* returns.
|
||||
*/
|
||||
#endif /* PNG_ARM_NEON_API_SUPPORTED */
|
||||
#ifdef PNG_ARM_NEON_CHECK_SUPPORTED
|
||||
{
|
||||
static volatile sig_atomic_t no_neon = -1; /* not checked */
|
||||
|
||||
if (no_neon < 0)
|
||||
no_neon = !png_have_neon(pp);
|
||||
|
||||
if (no_neon)
|
||||
return;
|
||||
}
|
||||
#ifdef PNG_ARM_NEON_API_SUPPORTED
|
||||
break;
|
||||
#endif
|
||||
#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */
|
||||
|
||||
#ifdef PNG_ARM_NEON_API_SUPPORTED
|
||||
default: /* OFF or INVALID */
|
||||
return;
|
||||
|
||||
case PNG_OPTION_ON:
|
||||
/* Option turned on */
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* IMPORTANT: any new external functions used here must be declared using
|
||||
* PNG_INTERNAL_FUNCTION in ../pngpriv.h. This is required so that the
|
||||
* 'prefix' option to configure works:
|
||||
*
|
||||
* ./configure --with-libpng-prefix=foobar_
|
||||
*
|
||||
* Verify you have got this right by running the above command, doing a build
|
||||
* and examining pngprefix.h; it must contain a #define for every external
|
||||
* function you add. (Notice that this happens automatically for the
|
||||
* initialization function.)
|
||||
*/
|
||||
pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_neon;
|
||||
|
||||
if (bpp == 3)
|
||||
{
|
||||
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_neon;
|
||||
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_neon;
|
||||
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
|
||||
png_read_filter_row_paeth3_neon;
|
||||
}
|
||||
|
||||
else if (bpp == 4)
|
||||
{
|
||||
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_neon;
|
||||
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_neon;
|
||||
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
|
||||
png_read_filter_row_paeth4_neon;
|
||||
}
|
||||
}
|
||||
#endif /* PNG_ARM_NEON_OPT > 0 */
|
||||
#endif /* READ */
|
253
libpng/arm/filter_neon.S
Normal file
253
libpng/arm/filter_neon.S
Normal file
|
@ -0,0 +1,253 @@
|
|||
|
||||
/* filter_neon.S - NEON optimised filter functions
|
||||
*
|
||||
* Copyright (c) 2018 Cosmin Truta
|
||||
* Copyright (c) 2014,2017 Glenn Randers-Pehrson
|
||||
* Written by Mans Rullgard, 2011.
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*/
|
||||
|
||||
/* This is required to get the symbol renames, which are #defines, and the
|
||||
* definitions (or not) of PNG_ARM_NEON_OPT and PNG_ARM_NEON_IMPLEMENTATION.
|
||||
*/
|
||||
#define PNG_VERSION_INFO_ONLY
|
||||
#include "../pngpriv.h"
|
||||
|
||||
#if (defined(__linux__) || defined(__FreeBSD__)) && defined(__ELF__)
|
||||
.section .note.GNU-stack,"",%progbits /* mark stack as non-executable */
|
||||
#endif
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
|
||||
/* Assembler NEON support - only works for 32-bit ARM (i.e. it does not work for
|
||||
* ARM64). The code in arm/filter_neon_intrinsics.c supports ARM64, however it
|
||||
* only works if -mfpu=neon is specified on the GCC command line. See pngpriv.h
|
||||
* for the logic which sets PNG_USE_ARM_NEON_ASM:
|
||||
*/
|
||||
#if PNG_ARM_NEON_IMPLEMENTATION == 2 /* hand-coded assembler */
|
||||
|
||||
#if PNG_ARM_NEON_OPT > 0
|
||||
|
||||
#ifdef __ELF__
|
||||
# define ELF
|
||||
#else
|
||||
# define ELF @
|
||||
#endif
|
||||
|
||||
.arch armv7-a
|
||||
.fpu neon
|
||||
|
||||
.macro func name, export=0
|
||||
.macro endfunc
|
||||
ELF .size \name, . - \name
|
||||
.endfunc
|
||||
.purgem endfunc
|
||||
.endm
|
||||
.text
|
||||
|
||||
/* Explicitly specifying alignment here because some versions of
|
||||
* GAS don't align code correctly. This is harmless in correctly
|
||||
* written versions of GAS.
|
||||
*/
|
||||
.align 2
|
||||
|
||||
.if \export
|
||||
.global \name
|
||||
.endif
|
||||
ELF .type \name, STT_FUNC
|
||||
.func \name
|
||||
\name:
|
||||
.endm
|
||||
|
||||
func png_read_filter_row_sub4_neon, export=1
|
||||
ldr r3, [r0, #4] @ rowbytes
|
||||
vmov.i8 d3, #0
|
||||
1:
|
||||
vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
|
||||
vadd.u8 d0, d3, d4
|
||||
vadd.u8 d1, d0, d5
|
||||
vadd.u8 d2, d1, d6
|
||||
vadd.u8 d3, d2, d7
|
||||
vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
|
||||
subs r3, r3, #16
|
||||
bgt 1b
|
||||
|
||||
bx lr
|
||||
endfunc
|
||||
|
||||
func png_read_filter_row_sub3_neon, export=1
|
||||
ldr r3, [r0, #4] @ rowbytes
|
||||
vmov.i8 d3, #0
|
||||
mov r0, r1
|
||||
mov r2, #3
|
||||
mov r12, #12
|
||||
vld1.8 {q11}, [r0], r12
|
||||
1:
|
||||
vext.8 d5, d22, d23, #3
|
||||
vadd.u8 d0, d3, d22
|
||||
vext.8 d6, d22, d23, #6
|
||||
vadd.u8 d1, d0, d5
|
||||
vext.8 d7, d23, d23, #1
|
||||
vld1.8 {q11}, [r0], r12
|
||||
vst1.32 {d0[0]}, [r1,:32], r2
|
||||
vadd.u8 d2, d1, d6
|
||||
vst1.32 {d1[0]}, [r1], r2
|
||||
vadd.u8 d3, d2, d7
|
||||
vst1.32 {d2[0]}, [r1], r2
|
||||
vst1.32 {d3[0]}, [r1], r2
|
||||
subs r3, r3, #12
|
||||
bgt 1b
|
||||
|
||||
bx lr
|
||||
endfunc
|
||||
|
||||
func png_read_filter_row_up_neon, export=1
|
||||
ldr r3, [r0, #4] @ rowbytes
|
||||
1:
|
||||
vld1.8 {q0}, [r1,:128]
|
||||
vld1.8 {q1}, [r2,:128]!
|
||||
vadd.u8 q0, q0, q1
|
||||
vst1.8 {q0}, [r1,:128]!
|
||||
subs r3, r3, #16
|
||||
bgt 1b
|
||||
|
||||
bx lr
|
||||
endfunc
|
||||
|
||||
func png_read_filter_row_avg4_neon, export=1
|
||||
ldr r12, [r0, #4] @ rowbytes
|
||||
vmov.i8 d3, #0
|
||||
1:
|
||||
vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
|
||||
vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]!
|
||||
vhadd.u8 d0, d3, d16
|
||||
vadd.u8 d0, d0, d4
|
||||
vhadd.u8 d1, d0, d17
|
||||
vadd.u8 d1, d1, d5
|
||||
vhadd.u8 d2, d1, d18
|
||||
vadd.u8 d2, d2, d6
|
||||
vhadd.u8 d3, d2, d19
|
||||
vadd.u8 d3, d3, d7
|
||||
vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
|
||||
subs r12, r12, #16
|
||||
bgt 1b
|
||||
|
||||
bx lr
|
||||
endfunc
|
||||
|
||||
func png_read_filter_row_avg3_neon, export=1
|
||||
push {r4,lr}
|
||||
ldr r12, [r0, #4] @ rowbytes
|
||||
vmov.i8 d3, #0
|
||||
mov r0, r1
|
||||
mov r4, #3
|
||||
mov lr, #12
|
||||
vld1.8 {q11}, [r0], lr
|
||||
1:
|
||||
vld1.8 {q10}, [r2], lr
|
||||
vext.8 d5, d22, d23, #3
|
||||
vhadd.u8 d0, d3, d20
|
||||
vext.8 d17, d20, d21, #3
|
||||
vadd.u8 d0, d0, d22
|
||||
vext.8 d6, d22, d23, #6
|
||||
vhadd.u8 d1, d0, d17
|
||||
vext.8 d18, d20, d21, #6
|
||||
vadd.u8 d1, d1, d5
|
||||
vext.8 d7, d23, d23, #1
|
||||
vld1.8 {q11}, [r0], lr
|
||||
vst1.32 {d0[0]}, [r1,:32], r4
|
||||
vhadd.u8 d2, d1, d18
|
||||
vst1.32 {d1[0]}, [r1], r4
|
||||
vext.8 d19, d21, d21, #1
|
||||
vadd.u8 d2, d2, d6
|
||||
vhadd.u8 d3, d2, d19
|
||||
vst1.32 {d2[0]}, [r1], r4
|
||||
vadd.u8 d3, d3, d7
|
||||
vst1.32 {d3[0]}, [r1], r4
|
||||
subs r12, r12, #12
|
||||
bgt 1b
|
||||
|
||||
pop {r4,pc}
|
||||
endfunc
|
||||
|
||||
.macro paeth rx, ra, rb, rc
|
||||
vaddl.u8 q12, \ra, \rb @ a + b
|
||||
vaddl.u8 q15, \rc, \rc @ 2*c
|
||||
vabdl.u8 q13, \rb, \rc @ pa
|
||||
vabdl.u8 q14, \ra, \rc @ pb
|
||||
vabd.u16 q15, q12, q15 @ pc
|
||||
vcle.u16 q12, q13, q14 @ pa <= pb
|
||||
vcle.u16 q13, q13, q15 @ pa <= pc
|
||||
vcle.u16 q14, q14, q15 @ pb <= pc
|
||||
vand q12, q12, q13 @ pa <= pb && pa <= pc
|
||||
vmovn.u16 d28, q14
|
||||
vmovn.u16 \rx, q12
|
||||
vbsl d28, \rb, \rc
|
||||
vbsl \rx, \ra, d28
|
||||
.endm
|
||||
|
||||
func png_read_filter_row_paeth4_neon, export=1
|
||||
ldr r12, [r0, #4] @ rowbytes
|
||||
vmov.i8 d3, #0
|
||||
vmov.i8 d20, #0
|
||||
1:
|
||||
vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
|
||||
vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]!
|
||||
paeth d0, d3, d16, d20
|
||||
vadd.u8 d0, d0, d4
|
||||
paeth d1, d0, d17, d16
|
||||
vadd.u8 d1, d1, d5
|
||||
paeth d2, d1, d18, d17
|
||||
vadd.u8 d2, d2, d6
|
||||
paeth d3, d2, d19, d18
|
||||
vmov d20, d19
|
||||
vadd.u8 d3, d3, d7
|
||||
vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
|
||||
subs r12, r12, #16
|
||||
bgt 1b
|
||||
|
||||
bx lr
|
||||
endfunc
|
||||
|
||||
func png_read_filter_row_paeth3_neon, export=1
|
||||
push {r4,lr}
|
||||
ldr r12, [r0, #4] @ rowbytes
|
||||
vmov.i8 d3, #0
|
||||
vmov.i8 d4, #0
|
||||
mov r0, r1
|
||||
mov r4, #3
|
||||
mov lr, #12
|
||||
vld1.8 {q11}, [r0], lr
|
||||
1:
|
||||
vld1.8 {q10}, [r2], lr
|
||||
paeth d0, d3, d20, d4
|
||||
vext.8 d5, d22, d23, #3
|
||||
vadd.u8 d0, d0, d22
|
||||
vext.8 d17, d20, d21, #3
|
||||
paeth d1, d0, d17, d20
|
||||
vst1.32 {d0[0]}, [r1,:32], r4
|
||||
vext.8 d6, d22, d23, #6
|
||||
vadd.u8 d1, d1, d5
|
||||
vext.8 d18, d20, d21, #6
|
||||
paeth d2, d1, d18, d17
|
||||
vext.8 d7, d23, d23, #1
|
||||
vld1.8 {q11}, [r0], lr
|
||||
vst1.32 {d1[0]}, [r1], r4
|
||||
vadd.u8 d2, d2, d6
|
||||
vext.8 d19, d21, d21, #1
|
||||
paeth d3, d2, d19, d18
|
||||
vst1.32 {d2[0]}, [r1], r4
|
||||
vmov d4, d19
|
||||
vadd.u8 d3, d3, d7
|
||||
vst1.32 {d3[0]}, [r1], r4
|
||||
subs r12, r12, #12
|
||||
bgt 1b
|
||||
|
||||
pop {r4,pc}
|
||||
endfunc
|
||||
#endif /* PNG_ARM_NEON_OPT > 0 */
|
||||
#endif /* PNG_ARM_NEON_IMPLEMENTATION == 2 (assembler) */
|
||||
#endif /* READ */
|
402
libpng/arm/filter_neon_intrinsics.c
Normal file
402
libpng/arm/filter_neon_intrinsics.c
Normal file
|
@ -0,0 +1,402 @@
|
|||
|
||||
/* filter_neon_intrinsics.c - NEON optimised filter functions
|
||||
*
|
||||
* Copyright (c) 2018 Cosmin Truta
|
||||
* Copyright (c) 2014,2016 Glenn Randers-Pehrson
|
||||
* Written by James Yu <james.yu at linaro.org>, October 2013.
|
||||
* Based on filter_neon.S, written by Mans Rullgard, 2011.
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*/
|
||||
|
||||
#include "../pngpriv.h"
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
|
||||
/* This code requires -mfpu=neon on the command line: */
|
||||
#if PNG_ARM_NEON_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */
|
||||
|
||||
#if defined(_MSC_VER) && defined(_M_ARM64)
|
||||
# include <arm64_neon.h>
|
||||
#else
|
||||
# include <arm_neon.h>
|
||||
#endif
|
||||
|
||||
/* libpng row pointers are not necessarily aligned to any particular boundary,
|
||||
* however this code will only work with appropriate alignment. arm/arm_init.c
|
||||
* checks for this (and will not compile unless it is done). This code uses
|
||||
* variants of png_aligncast to avoid compiler warnings.
|
||||
*/
|
||||
#define png_ptr(type,pointer) png_aligncast(type *,pointer)
|
||||
#define png_ptrc(type,pointer) png_aligncastconst(const type *,pointer)
|
||||
|
||||
/* The following relies on a variable 'temp_pointer' being declared with type
|
||||
* 'type'. This is written this way just to hide the GCC strict aliasing
|
||||
* warning; note that the code is safe because there never is an alias between
|
||||
* the input and output pointers.
|
||||
*
|
||||
* When compiling with MSVC ARM64, the png_ldr macro can't be passed directly
|
||||
* to vst4_lane_u32, because of an internal compiler error inside MSVC.
|
||||
* To avoid this compiler bug, we use a temporary variable (vdest_val) to store
|
||||
* the result of png_ldr.
|
||||
*/
|
||||
#define png_ldr(type,pointer)\
|
||||
(temp_pointer = png_ptr(type,pointer), *temp_pointer)
|
||||
|
||||
#if PNG_ARM_NEON_OPT > 0
|
||||
|
||||
void
|
||||
png_read_filter_row_up_neon(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_bytep rp_stop = row + row_info->rowbytes;
|
||||
png_const_bytep pp = prev_row;
|
||||
|
||||
png_debug(1, "in png_read_filter_row_up_neon");
|
||||
|
||||
for (; rp < rp_stop; rp += 16, pp += 16)
|
||||
{
|
||||
uint8x16_t qrp, qpp;
|
||||
|
||||
qrp = vld1q_u8(rp);
|
||||
qpp = vld1q_u8(pp);
|
||||
qrp = vaddq_u8(qrp, qpp);
|
||||
vst1q_u8(rp, qrp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
png_read_filter_row_sub3_neon(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_bytep rp_stop = row + row_info->rowbytes;
|
||||
|
||||
uint8x16_t vtmp = vld1q_u8(rp);
|
||||
uint8x8x2_t *vrpt = png_ptr(uint8x8x2_t, &vtmp);
|
||||
uint8x8x2_t vrp = *vrpt;
|
||||
|
||||
uint8x8x4_t vdest;
|
||||
vdest.val[3] = vdup_n_u8(0);
|
||||
|
||||
png_debug(1, "in png_read_filter_row_sub3_neon");
|
||||
|
||||
for (; rp < rp_stop;)
|
||||
{
|
||||
uint8x8_t vtmp1, vtmp2;
|
||||
uint32x2_t *temp_pointer;
|
||||
|
||||
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
|
||||
vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]);
|
||||
vtmp2 = vext_u8(vrp.val[0], vrp.val[1], 6);
|
||||
vdest.val[1] = vadd_u8(vdest.val[0], vtmp1);
|
||||
|
||||
vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
|
||||
vdest.val[2] = vadd_u8(vdest.val[1], vtmp2);
|
||||
vdest.val[3] = vadd_u8(vdest.val[2], vtmp1);
|
||||
|
||||
vtmp = vld1q_u8(rp + 12);
|
||||
vrpt = png_ptr(uint8x8x2_t, &vtmp);
|
||||
vrp = *vrpt;
|
||||
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
|
||||
rp += 3;
|
||||
}
|
||||
|
||||
PNG_UNUSED(prev_row)
|
||||
}
|
||||
|
||||
void
|
||||
png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_bytep rp_stop = row + row_info->rowbytes;
|
||||
|
||||
uint8x8x4_t vdest;
|
||||
vdest.val[3] = vdup_n_u8(0);
|
||||
|
||||
png_debug(1, "in png_read_filter_row_sub4_neon");
|
||||
|
||||
for (; rp < rp_stop; rp += 16)
|
||||
{
|
||||
uint32x2x4_t vtmp = vld4_u32(png_ptr(uint32_t,rp));
|
||||
uint8x8x4_t *vrpt = png_ptr(uint8x8x4_t,&vtmp);
|
||||
uint8x8x4_t vrp = *vrpt;
|
||||
uint32x2x4_t *temp_pointer;
|
||||
uint32x2x4_t vdest_val;
|
||||
|
||||
vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]);
|
||||
vdest.val[1] = vadd_u8(vdest.val[0], vrp.val[1]);
|
||||
vdest.val[2] = vadd_u8(vdest.val[1], vrp.val[2]);
|
||||
vdest.val[3] = vadd_u8(vdest.val[2], vrp.val[3]);
|
||||
|
||||
vdest_val = png_ldr(uint32x2x4_t, &vdest);
|
||||
vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0);
|
||||
}
|
||||
|
||||
PNG_UNUSED(prev_row)
|
||||
}
|
||||
|
||||
void
|
||||
png_read_filter_row_avg3_neon(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_const_bytep pp = prev_row;
|
||||
png_bytep rp_stop = row + row_info->rowbytes;
|
||||
|
||||
uint8x16_t vtmp;
|
||||
uint8x8x2_t *vrpt;
|
||||
uint8x8x2_t vrp;
|
||||
uint8x8x4_t vdest;
|
||||
vdest.val[3] = vdup_n_u8(0);
|
||||
|
||||
vtmp = vld1q_u8(rp);
|
||||
vrpt = png_ptr(uint8x8x2_t,&vtmp);
|
||||
vrp = *vrpt;
|
||||
|
||||
png_debug(1, "in png_read_filter_row_avg3_neon");
|
||||
|
||||
for (; rp < rp_stop; pp += 12)
|
||||
{
|
||||
uint8x8_t vtmp1, vtmp2, vtmp3;
|
||||
|
||||
uint8x8x2_t *vppt;
|
||||
uint8x8x2_t vpp;
|
||||
|
||||
uint32x2_t *temp_pointer;
|
||||
|
||||
vtmp = vld1q_u8(pp);
|
||||
vppt = png_ptr(uint8x8x2_t,&vtmp);
|
||||
vpp = *vppt;
|
||||
|
||||
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
|
||||
vdest.val[0] = vhadd_u8(vdest.val[3], vpp.val[0]);
|
||||
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
|
||||
|
||||
vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 3);
|
||||
vtmp3 = vext_u8(vrp.val[0], vrp.val[1], 6);
|
||||
vdest.val[1] = vhadd_u8(vdest.val[0], vtmp2);
|
||||
vdest.val[1] = vadd_u8(vdest.val[1], vtmp1);
|
||||
|
||||
vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 6);
|
||||
vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
|
||||
|
||||
vtmp = vld1q_u8(rp + 12);
|
||||
vrpt = png_ptr(uint8x8x2_t,&vtmp);
|
||||
vrp = *vrpt;
|
||||
|
||||
vdest.val[2] = vhadd_u8(vdest.val[1], vtmp2);
|
||||
vdest.val[2] = vadd_u8(vdest.val[2], vtmp3);
|
||||
|
||||
vtmp2 = vext_u8(vpp.val[1], vpp.val[1], 1);
|
||||
|
||||
vdest.val[3] = vhadd_u8(vdest.val[2], vtmp2);
|
||||
vdest.val[3] = vadd_u8(vdest.val[3], vtmp1);
|
||||
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
|
||||
rp += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_bytep rp_stop = row + row_info->rowbytes;
|
||||
png_const_bytep pp = prev_row;
|
||||
|
||||
uint8x8x4_t vdest;
|
||||
vdest.val[3] = vdup_n_u8(0);
|
||||
|
||||
png_debug(1, "in png_read_filter_row_avg4_neon");
|
||||
|
||||
for (; rp < rp_stop; rp += 16, pp += 16)
|
||||
{
|
||||
uint32x2x4_t vtmp;
|
||||
uint8x8x4_t *vrpt, *vppt;
|
||||
uint8x8x4_t vrp, vpp;
|
||||
uint32x2x4_t *temp_pointer;
|
||||
uint32x2x4_t vdest_val;
|
||||
|
||||
vtmp = vld4_u32(png_ptr(uint32_t,rp));
|
||||
vrpt = png_ptr(uint8x8x4_t,&vtmp);
|
||||
vrp = *vrpt;
|
||||
vtmp = vld4_u32(png_ptrc(uint32_t,pp));
|
||||
vppt = png_ptr(uint8x8x4_t,&vtmp);
|
||||
vpp = *vppt;
|
||||
|
||||
vdest.val[0] = vhadd_u8(vdest.val[3], vpp.val[0]);
|
||||
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
|
||||
vdest.val[1] = vhadd_u8(vdest.val[0], vpp.val[1]);
|
||||
vdest.val[1] = vadd_u8(vdest.val[1], vrp.val[1]);
|
||||
vdest.val[2] = vhadd_u8(vdest.val[1], vpp.val[2]);
|
||||
vdest.val[2] = vadd_u8(vdest.val[2], vrp.val[2]);
|
||||
vdest.val[3] = vhadd_u8(vdest.val[2], vpp.val[3]);
|
||||
vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]);
|
||||
|
||||
vdest_val = png_ldr(uint32x2x4_t, &vdest);
|
||||
vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8x8_t
|
||||
paeth(uint8x8_t a, uint8x8_t b, uint8x8_t c)
|
||||
{
|
||||
uint8x8_t d, e;
|
||||
uint16x8_t p1, pa, pb, pc;
|
||||
|
||||
p1 = vaddl_u8(a, b); /* a + b */
|
||||
pc = vaddl_u8(c, c); /* c * 2 */
|
||||
pa = vabdl_u8(b, c); /* pa */
|
||||
pb = vabdl_u8(a, c); /* pb */
|
||||
pc = vabdq_u16(p1, pc); /* pc */
|
||||
|
||||
p1 = vcleq_u16(pa, pb); /* pa <= pb */
|
||||
pa = vcleq_u16(pa, pc); /* pa <= pc */
|
||||
pb = vcleq_u16(pb, pc); /* pb <= pc */
|
||||
|
||||
p1 = vandq_u16(p1, pa); /* pa <= pb && pa <= pc */
|
||||
|
||||
d = vmovn_u16(pb);
|
||||
e = vmovn_u16(p1);
|
||||
|
||||
d = vbsl_u8(d, b, c);
|
||||
e = vbsl_u8(e, a, d);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
void
|
||||
png_read_filter_row_paeth3_neon(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_const_bytep pp = prev_row;
|
||||
png_bytep rp_stop = row + row_info->rowbytes;
|
||||
|
||||
uint8x16_t vtmp;
|
||||
uint8x8x2_t *vrpt;
|
||||
uint8x8x2_t vrp;
|
||||
uint8x8_t vlast = vdup_n_u8(0);
|
||||
uint8x8x4_t vdest;
|
||||
vdest.val[3] = vdup_n_u8(0);
|
||||
|
||||
vtmp = vld1q_u8(rp);
|
||||
vrpt = png_ptr(uint8x8x2_t,&vtmp);
|
||||
vrp = *vrpt;
|
||||
|
||||
png_debug(1, "in png_read_filter_row_paeth3_neon");
|
||||
|
||||
for (; rp < rp_stop; pp += 12)
|
||||
{
|
||||
uint8x8x2_t *vppt;
|
||||
uint8x8x2_t vpp;
|
||||
uint8x8_t vtmp1, vtmp2, vtmp3;
|
||||
uint32x2_t *temp_pointer;
|
||||
|
||||
vtmp = vld1q_u8(pp);
|
||||
vppt = png_ptr(uint8x8x2_t,&vtmp);
|
||||
vpp = *vppt;
|
||||
|
||||
vdest.val[0] = paeth(vdest.val[3], vpp.val[0], vlast);
|
||||
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
|
||||
|
||||
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
|
||||
vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 3);
|
||||
vdest.val[1] = paeth(vdest.val[0], vtmp2, vpp.val[0]);
|
||||
vdest.val[1] = vadd_u8(vdest.val[1], vtmp1);
|
||||
|
||||
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 6);
|
||||
vtmp3 = vext_u8(vpp.val[0], vpp.val[1], 6);
|
||||
vdest.val[2] = paeth(vdest.val[1], vtmp3, vtmp2);
|
||||
vdest.val[2] = vadd_u8(vdest.val[2], vtmp1);
|
||||
|
||||
vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
|
||||
vtmp2 = vext_u8(vpp.val[1], vpp.val[1], 1);
|
||||
|
||||
vtmp = vld1q_u8(rp + 12);
|
||||
vrpt = png_ptr(uint8x8x2_t,&vtmp);
|
||||
vrp = *vrpt;
|
||||
|
||||
vdest.val[3] = paeth(vdest.val[2], vtmp2, vtmp3);
|
||||
vdest.val[3] = vadd_u8(vdest.val[3], vtmp1);
|
||||
|
||||
vlast = vtmp2;
|
||||
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
|
||||
rp += 3;
|
||||
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
|
||||
rp += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row,
|
||||
png_const_bytep prev_row)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_bytep rp_stop = row + row_info->rowbytes;
|
||||
png_const_bytep pp = prev_row;
|
||||
|
||||
uint8x8_t vlast = vdup_n_u8(0);
|
||||
uint8x8x4_t vdest;
|
||||
vdest.val[3] = vdup_n_u8(0);
|
||||
|
||||
png_debug(1, "in png_read_filter_row_paeth4_neon");
|
||||
|
||||
for (; rp < rp_stop; rp += 16, pp += 16)
|
||||
{
|
||||
uint32x2x4_t vtmp;
|
||||
uint8x8x4_t *vrpt, *vppt;
|
||||
uint8x8x4_t vrp, vpp;
|
||||
uint32x2x4_t *temp_pointer;
|
||||
uint32x2x4_t vdest_val;
|
||||
|
||||
vtmp = vld4_u32(png_ptr(uint32_t,rp));
|
||||
vrpt = png_ptr(uint8x8x4_t,&vtmp);
|
||||
vrp = *vrpt;
|
||||
vtmp = vld4_u32(png_ptrc(uint32_t,pp));
|
||||
vppt = png_ptr(uint8x8x4_t,&vtmp);
|
||||
vpp = *vppt;
|
||||
|
||||
vdest.val[0] = paeth(vdest.val[3], vpp.val[0], vlast);
|
||||
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
|
||||
vdest.val[1] = paeth(vdest.val[0], vpp.val[1], vpp.val[0]);
|
||||
vdest.val[1] = vadd_u8(vdest.val[1], vrp.val[1]);
|
||||
vdest.val[2] = paeth(vdest.val[1], vpp.val[2], vpp.val[1]);
|
||||
vdest.val[2] = vadd_u8(vdest.val[2], vrp.val[2]);
|
||||
vdest.val[3] = paeth(vdest.val[2], vpp.val[3], vpp.val[2]);
|
||||
vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]);
|
||||
|
||||
vlast = vpp.val[3];
|
||||
|
||||
vdest_val = png_ldr(uint32x2x4_t, &vdest);
|
||||
vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* PNG_ARM_NEON_OPT > 0 */
|
||||
#endif /* PNG_ARM_NEON_IMPLEMENTATION == 1 (intrinsics) */
|
||||
#endif /* READ */
|
149
libpng/arm/palette_neon_intrinsics.c
Normal file
149
libpng/arm/palette_neon_intrinsics.c
Normal file
|
@ -0,0 +1,149 @@
|
|||
|
||||
/* palette_neon_intrinsics.c - NEON optimised palette expansion functions
|
||||
*
|
||||
* Copyright (c) 2018-2019 Cosmin Truta
|
||||
* Copyright (c) 2017-2018 Arm Holdings. All rights reserved.
|
||||
* Written by Richard Townsend <Richard.Townsend@arm.com>, February 2017.
|
||||
*
|
||||
* This code is released under the libpng license.
|
||||
* For conditions of distribution and use, see the disclaimer
|
||||
* and license in png.h
|
||||
*/
|
||||
|
||||
#include "../pngpriv.h"
|
||||
|
||||
#if PNG_ARM_NEON_IMPLEMENTATION == 1
|
||||
|
||||
#if defined(_MSC_VER) && defined(_M_ARM64)
|
||||
# include <arm64_neon.h>
|
||||
#else
|
||||
# include <arm_neon.h>
|
||||
#endif
|
||||
|
||||
/* Build an RGBA8 palette from the separate RGB and alpha palettes. */
|
||||
void
|
||||
png_riffle_palette_neon(png_structrp png_ptr)
|
||||
{
|
||||
png_const_colorp palette = png_ptr->palette;
|
||||
png_bytep riffled_palette = png_ptr->riffled_palette;
|
||||
png_const_bytep trans_alpha = png_ptr->trans_alpha;
|
||||
int num_trans = png_ptr->num_trans;
|
||||
int i;
|
||||
|
||||
png_debug(1, "in png_riffle_palette_neon");
|
||||
|
||||
/* Initially black, opaque. */
|
||||
uint8x16x4_t w = {{
|
||||
vdupq_n_u8(0x00),
|
||||
vdupq_n_u8(0x00),
|
||||
vdupq_n_u8(0x00),
|
||||
vdupq_n_u8(0xff),
|
||||
}};
|
||||
|
||||
/* First, riffle the RGB colours into an RGBA8 palette.
|
||||
* The alpha component is set to opaque for now.
|
||||
*/
|
||||
for (i = 0; i < 256; i += 16)
|
||||
{
|
||||
uint8x16x3_t v = vld3q_u8((png_const_bytep)(palette + i));
|
||||
w.val[0] = v.val[0];
|
||||
w.val[1] = v.val[1];
|
||||
w.val[2] = v.val[2];
|
||||
vst4q_u8(riffled_palette + (i << 2), w);
|
||||
}
|
||||
|
||||
/* Fix up the missing transparency values. */
|
||||
for (i = 0; i < num_trans; i++)
|
||||
riffled_palette[(i << 2) + 3] = trans_alpha[i];
|
||||
}
|
||||
|
||||
/* Expands a palettized row into RGBA8. */
|
||||
int
|
||||
png_do_expand_palette_rgba8_neon(png_structrp png_ptr, png_row_infop row_info,
|
||||
png_const_bytep row, png_bytepp ssp, png_bytepp ddp)
|
||||
{
|
||||
png_uint_32 row_width = row_info->width;
|
||||
const png_uint_32 *riffled_palette =
|
||||
(const png_uint_32 *)png_ptr->riffled_palette;
|
||||
const png_int_32 pixels_per_chunk = 4;
|
||||
int i;
|
||||
|
||||
png_debug(1, "in png_do_expand_palette_rgba8_neon");
|
||||
|
||||
if (row_width < pixels_per_chunk)
|
||||
return 0;
|
||||
|
||||
/* This function originally gets the last byte of the output row.
|
||||
* The NEON part writes forward from a given position, so we have
|
||||
* to seek this back by 4 pixels x 4 bytes.
|
||||
*/
|
||||
*ddp = *ddp - ((pixels_per_chunk * sizeof(png_uint_32)) - 1);
|
||||
|
||||
for (i = 0; i < row_width; i += pixels_per_chunk)
|
||||
{
|
||||
uint32x4_t cur;
|
||||
png_bytep sp = *ssp - i, dp = *ddp - (i << 2);
|
||||
cur = vld1q_dup_u32 (riffled_palette + *(sp - 3));
|
||||
cur = vld1q_lane_u32(riffled_palette + *(sp - 2), cur, 1);
|
||||
cur = vld1q_lane_u32(riffled_palette + *(sp - 1), cur, 2);
|
||||
cur = vld1q_lane_u32(riffled_palette + *(sp - 0), cur, 3);
|
||||
vst1q_u32((void *)dp, cur);
|
||||
}
|
||||
if (i != row_width)
|
||||
{
|
||||
/* Remove the amount that wasn't processed. */
|
||||
i -= pixels_per_chunk;
|
||||
}
|
||||
|
||||
/* Decrement output pointers. */
|
||||
*ssp = *ssp - i;
|
||||
*ddp = *ddp - (i << 2);
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Expands a palettized row into RGB8. */
|
||||
int
|
||||
png_do_expand_palette_rgb8_neon(png_structrp png_ptr, png_row_infop row_info,
|
||||
png_const_bytep row, png_bytepp ssp, png_bytepp ddp)
|
||||
{
|
||||
png_uint_32 row_width = row_info->width;
|
||||
png_const_bytep palette = (png_const_bytep)png_ptr->palette;
|
||||
const png_uint_32 pixels_per_chunk = 8;
|
||||
int i;
|
||||
|
||||
png_debug(1, "in png_do_expand_palette_rgb8_neon");
|
||||
|
||||
if (row_width <= pixels_per_chunk)
|
||||
return 0;
|
||||
|
||||
/* Seeking this back by 8 pixels x 3 bytes. */
|
||||
*ddp = *ddp - ((pixels_per_chunk * sizeof(png_color)) - 1);
|
||||
|
||||
for (i = 0; i < row_width; i += pixels_per_chunk)
|
||||
{
|
||||
uint8x8x3_t cur;
|
||||
png_bytep sp = *ssp - i, dp = *ddp - ((i << 1) + i);
|
||||
cur = vld3_dup_u8(palette + sizeof(png_color) * (*(sp - 7)));
|
||||
cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 6)), cur, 1);
|
||||
cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 5)), cur, 2);
|
||||
cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 4)), cur, 3);
|
||||
cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 3)), cur, 4);
|
||||
cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 2)), cur, 5);
|
||||
cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 1)), cur, 6);
|
||||
cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 0)), cur, 7);
|
||||
vst3_u8((void *)dp, cur);
|
||||
}
|
||||
|
||||
if (i != row_width)
|
||||
{
|
||||
/* Remove the amount that wasn't processed. */
|
||||
i -= pixels_per_chunk;
|
||||
}
|
||||
|
||||
/* Decrement output pointers. */
|
||||
*ssp = *ssp - i;
|
||||
*ddp = *ddp - ((i << 1) + i);
|
||||
return i;
|
||||
}
|
||||
|
||||
#endif /* PNG_ARM_NEON_IMPLEMENTATION */
|
225
libpng/autogen.sh
Executable file
225
libpng/autogen.sh
Executable file
|
@ -0,0 +1,225 @@
|
|||
#! /bin/sh
|
||||
#
|
||||
# Run 'autoreconf' to build 'configure', 'Makefile.in' and other configure
|
||||
# control files.
|
||||
#
|
||||
# The first time this is run on a GIT checkout the only files that exist are
|
||||
# configure.ac and Makefile.am; all of the autotools support scripts are
|
||||
# missing. They are instantiated with autoreconf --force --install.
|
||||
#
|
||||
# For regular ("tarball") distributions all the files should exist. We do not
|
||||
# want them to be updated *under any circumstances*. It should never be
|
||||
# necessary to run autogen.sh because ./configure --enable-maintainer-mode says
|
||||
# what to do if Makefile.am or configure.ac are changed.
|
||||
#
|
||||
# It is *probably* OK to update the files on a GIT checkout, because they have
|
||||
# come from the local tools, but leave that to the user who is assumed to know
|
||||
# whether it is ok or required.
|
||||
#
|
||||
# This script is intended to work without arguments, there are, however, hidden
|
||||
# arguments (a) for use while testing the script and (b) to fix up systems that
|
||||
# have been broken. If (b) is required the script prompts for the correct
|
||||
# options. For this reason the options are *NOT* documented in the help; this
|
||||
# is deliberate; UTSL.
|
||||
#
|
||||
clean=
|
||||
maintainer=
|
||||
while test $# -gt 0
|
||||
do
|
||||
case "$1" in
|
||||
--maintainer)
|
||||
maintainer=1;;
|
||||
|
||||
--clean)
|
||||
clean=1;;
|
||||
|
||||
*)
|
||||
exec >&2
|
||||
echo "$0: usage: ./autogen.sh"
|
||||
if test -d .git
|
||||
then
|
||||
echo " ./autogen.sh generates the configure script and"
|
||||
echo " Makefile.in, or refreshes them after changes to Makefile.am"
|
||||
echo " or configure.ac. You may prefer to just run autoreconf."
|
||||
elif test -z "$maintainer"
|
||||
then
|
||||
echo " DO NOT RUN THIS SCRIPT."
|
||||
echo " If you need to change Makefile.am or configure.ac then you"
|
||||
echo " also need to run ./configure --enable-maintainer-mode and"
|
||||
echo " use the appropriate autotools, *NOT* this script, to update"
|
||||
echo " everything, please check the documentation of autoreconf."
|
||||
echo " WARNING: libpng is intentionally generated with a known,"
|
||||
echo " fixed, set of autotools. It is known *NOT* to work with"
|
||||
echo " the collection of autotools distributed on highly reputable"
|
||||
echo " operating systems."
|
||||
echo " Remember: autotools is GNU software, you are expected to"
|
||||
echo " pay for support."
|
||||
else
|
||||
echo " You have run autogen.sh with --maintainer enabled and you"
|
||||
echo " are not using a GIT distribution, then you have given an"
|
||||
echo " unrecognized argument. This is not good. --maintainer"
|
||||
echo " switches off any assumptions that you might not know what"
|
||||
echo " you are doing."
|
||||
fi
|
||||
exit 1;;
|
||||
esac
|
||||
|
||||
shift
|
||||
done
|
||||
#
|
||||
# First check for a set of the autotools files; if absent then this is assumed
|
||||
# to be a GIT version and the local autotools must be used. If present this
|
||||
# is a tarball distribution and the script should not be used. If partially
|
||||
# present bad things are happening.
|
||||
#
|
||||
# The autotools generated files:
|
||||
libpng_autotools_files="Makefile.in aclocal.m4 config.guess config.h.in
|
||||
config.sub configure depcomp install-sh ltmain.sh missing\
|
||||
test-driver"
|
||||
#
|
||||
# Files generated by versions of configue >2.68 or automake >1.13 (i.e. later
|
||||
# versions than those required by configure.ac):
|
||||
libpng_autotools_extra="compile config.h.in~"
|
||||
#
|
||||
# These are separate because 'maintainer-clean' does not remove them.
|
||||
libpng_libtool_files="scripts/libtool.m4 scripts/ltoptions.m4\
|
||||
scripts/ltsugar.m4 scripts/ltversion.m4 scripts/lt~obsolete.m4"
|
||||
|
||||
libpng_autotools_dirs="autom4te.cache" # not required
|
||||
#
|
||||
# The configure generated files:
|
||||
libpng_configure_files="Makefile config.h config.log config.status\
|
||||
libpng-config libpng.pc libtool stamp-h1"
|
||||
|
||||
libpng_configure_dirs=".deps"
|
||||
#
|
||||
# We must remove the configure generated files as well as the autotools
|
||||
# generated files if autotools are regenerated because otherwise if configure
|
||||
# has been run without "--enable-maintainer-mode" make can do a partial update
|
||||
# of Makefile. These functions do the two bits of cleaning.
|
||||
clean_autotools(){
|
||||
rm -rf $libpng_autotools_files $libpng_libtool_files $libpng_autotools_dirs
|
||||
rm -rf $libpng_autotools_extra
|
||||
}
|
||||
|
||||
clean_configure(){
|
||||
rm -rf $libpng_configure_files $libpng_configure_dirs
|
||||
}
|
||||
#
|
||||
# Clean: remove everything (this is to help with testing)
|
||||
if test -n "$clean"
|
||||
then
|
||||
clean_configure
|
||||
if test -n "$maintainer"
|
||||
then
|
||||
clean_autotools
|
||||
fi
|
||||
|
||||
exit 0
|
||||
fi
|
||||
#
|
||||
# Validate the distribution.
|
||||
libpng_autotools_file_found=
|
||||
libpng_autotools_file_missing=
|
||||
for file in $libpng_autotools_files
|
||||
do
|
||||
if test -f "$file"
|
||||
then
|
||||
libpng_autotools_file_found=1
|
||||
else
|
||||
libpng_autotools_file_missing=1
|
||||
fi
|
||||
done
|
||||
#
|
||||
# Presence of one of these does not *invalidate* missing, but absence
|
||||
# invalidates found.
|
||||
for file in $libpng_libtool_files
|
||||
do
|
||||
if test ! -f "$file"
|
||||
then
|
||||
libpng_autotools_file_missing=1
|
||||
fi
|
||||
done
|
||||
#
|
||||
# The cache directory doesn't matter - it will be regenerated and does not exist
|
||||
# anyway in a tarball.
|
||||
#
|
||||
# Either everything is missing or everything is there, the --maintainer option
|
||||
# just changes this so that the mode is set to generate all the files.
|
||||
mode=
|
||||
if test -z "$libpng_autotools_file_found" -o -n "$maintainer"
|
||||
then
|
||||
mode="autoreconf"
|
||||
else
|
||||
if test -n "$libpng_autotools_file_missing"
|
||||
then
|
||||
mode="broken"
|
||||
else
|
||||
mode="configure"
|
||||
fi
|
||||
fi
|
||||
#
|
||||
# So:
|
||||
case "$mode" in
|
||||
autoreconf)
|
||||
# Clean in case configure files exist
|
||||
clean_configure
|
||||
clean_autotools
|
||||
# Everything must be initialized, so use --force
|
||||
if autoreconf --warnings=all --force --install
|
||||
then
|
||||
missing=
|
||||
for file in $libpng_autotools_files
|
||||
do
|
||||
test -f "$file" || missing=1
|
||||
done
|
||||
# ignore the cache directory
|
||||
test -z "$missing" || {
|
||||
exec >&2
|
||||
echo "autoreconf was run, but did not produce all the expected"
|
||||
echo "files. It is likely that your autotools installation is"
|
||||
echo "not compatible with that expected by libpng."
|
||||
exit 1
|
||||
}
|
||||
else
|
||||
exec >&2
|
||||
echo "autoreconf failed: your version of autotools is incompatible"
|
||||
echo "with this libpng version. Please use a distributed archive"
|
||||
echo "(which includes the autotools generated files) and run configure"
|
||||
echo "instead."
|
||||
exit 1
|
||||
fi;;
|
||||
|
||||
configure)
|
||||
if test -d .git
|
||||
then
|
||||
exec >&2
|
||||
echo "ERROR: running autoreconf on an initialized system"
|
||||
echo " This is not necessary; it is only necessary to remake the"
|
||||
echo " autotools generated files if Makefile.am or configure.ac"
|
||||
echo " change and make does the right thing with:"
|
||||
echo
|
||||
echo " ./configure --enable-maintainer-mode."
|
||||
echo
|
||||
echo " You can run autoreconf yourself if you don't like maintainer"
|
||||
echo " mode and you can also just run autoreconf -f -i to initialize"
|
||||
echo " everything in the first place; this script is only for"
|
||||
echo " compatibility with prior releases."
|
||||
exit 1
|
||||
else
|
||||
exec >&2
|
||||
echo "autogen.sh is intended only to generate 'configure' on systems"
|
||||
echo "that do not have it. You have a complete 'configure', if you"
|
||||
echo "need to change Makefile.am or configure.ac you also need to"
|
||||
echo "run configure with the --enable-maintainer-mode option."
|
||||
exit 1
|
||||
fi;;
|
||||
|
||||
broken)
|
||||
exec >&2
|
||||
echo "Your system has a partial set of autotools generated files."
|
||||
echo "autogen.sh is unable to proceed. The full set of files is"
|
||||
echo "contained in the libpng 'tar' distribution archive and you do"
|
||||
echo "not need to run autogen.sh if you use it."
|
||||
exit 1;;
|
||||
esac
|
348
libpng/compile
Executable file
348
libpng/compile
Executable file
|
@ -0,0 +1,348 @@
|
|||
#! /bin/sh
|
||||
# Wrapper for compilers which do not understand '-c -o'.
|
||||
|
||||
scriptversion=2018-03-07.03; # UTC
|
||||
|
||||
# Copyright (C) 1999-2018 Free Software Foundation, Inc.
|
||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
nl='
|
||||
'
|
||||
|
||||
# We need space, tab and new line, in precisely that order. Quoting is
|
||||
# there to prevent tools from complaining about whitespace usage.
|
||||
IFS=" "" $nl"
|
||||
|
||||
file_conv=
|
||||
|
||||
# func_file_conv build_file lazy
|
||||
# Convert a $build file to $host form and store it in $file
|
||||
# Currently only supports Windows hosts. If the determined conversion
|
||||
# type is listed in (the comma separated) LAZY, no conversion will
|
||||
# take place.
|
||||
func_file_conv ()
|
||||
{
|
||||
file=$1
|
||||
case $file in
|
||||
/ | /[!/]*) # absolute file, and not a UNC file
|
||||
if test -z "$file_conv"; then
|
||||
# lazily determine how to convert abs files
|
||||
case `uname -s` in
|
||||
MINGW*)
|
||||
file_conv=mingw
|
||||
;;
|
||||
CYGWIN*)
|
||||
file_conv=cygwin
|
||||
;;
|
||||
*)
|
||||
file_conv=wine
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
case $file_conv/,$2, in
|
||||
*,$file_conv,*)
|
||||
;;
|
||||
mingw/*)
|
||||
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
|
||||
;;
|
||||
cygwin/*)
|
||||
file=`cygpath -m "$file" || echo "$file"`
|
||||
;;
|
||||
wine/*)
|
||||
file=`winepath -w "$file" || echo "$file"`
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# func_cl_dashL linkdir
|
||||
# Make cl look for libraries in LINKDIR
|
||||
func_cl_dashL ()
|
||||
{
|
||||
func_file_conv "$1"
|
||||
if test -z "$lib_path"; then
|
||||
lib_path=$file
|
||||
else
|
||||
lib_path="$lib_path;$file"
|
||||
fi
|
||||
linker_opts="$linker_opts -LIBPATH:$file"
|
||||
}
|
||||
|
||||
# func_cl_dashl library
|
||||
# Do a library search-path lookup for cl
|
||||
func_cl_dashl ()
|
||||
{
|
||||
lib=$1
|
||||
found=no
|
||||
save_IFS=$IFS
|
||||
IFS=';'
|
||||
for dir in $lib_path $LIB
|
||||
do
|
||||
IFS=$save_IFS
|
||||
if $shared && test -f "$dir/$lib.dll.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.dll.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/$lib.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/lib$lib.a"; then
|
||||
found=yes
|
||||
lib=$dir/lib$lib.a
|
||||
break
|
||||
fi
|
||||
done
|
||||
IFS=$save_IFS
|
||||
|
||||
if test "$found" != yes; then
|
||||
lib=$lib.lib
|
||||
fi
|
||||
}
|
||||
|
||||
# func_cl_wrapper cl arg...
|
||||
# Adjust compile command to suit cl
|
||||
func_cl_wrapper ()
|
||||
{
|
||||
# Assume a capable shell
|
||||
lib_path=
|
||||
shared=:
|
||||
linker_opts=
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.[oO][bB][jJ])
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fo"$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fe"$file"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-I)
|
||||
eat=1
|
||||
func_file_conv "$2" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-I*)
|
||||
func_file_conv "${1#-I}" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-l)
|
||||
eat=1
|
||||
func_cl_dashl "$2"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-l*)
|
||||
func_cl_dashl "${1#-l}"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-L)
|
||||
eat=1
|
||||
func_cl_dashL "$2"
|
||||
;;
|
||||
-L*)
|
||||
func_cl_dashL "${1#-L}"
|
||||
;;
|
||||
-static)
|
||||
shared=false
|
||||
;;
|
||||
-Wl,*)
|
||||
arg=${1#-Wl,}
|
||||
save_ifs="$IFS"; IFS=','
|
||||
for flag in $arg; do
|
||||
IFS="$save_ifs"
|
||||
linker_opts="$linker_opts $flag"
|
||||
done
|
||||
IFS="$save_ifs"
|
||||
;;
|
||||
-Xlinker)
|
||||
eat=1
|
||||
linker_opts="$linker_opts $2"
|
||||
;;
|
||||
-*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
|
||||
func_file_conv "$1"
|
||||
set x "$@" -Tp"$file"
|
||||
shift
|
||||
;;
|
||||
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
|
||||
func_file_conv "$1" mingw
|
||||
set x "$@" "$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
if test -n "$linker_opts"; then
|
||||
linker_opts="-link$linker_opts"
|
||||
fi
|
||||
exec "$@" $linker_opts
|
||||
exit 1
|
||||
}
|
||||
|
||||
eat=
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: compile [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Wrapper for compilers which do not understand '-c -o'.
|
||||
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
|
||||
arguments, and rename the output as expected.
|
||||
|
||||
If you are trying to build a whole package this is not the
|
||||
right script to run: please start by reading the file 'INSTALL'.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "compile $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \
|
||||
icl | *[/\\]icl | icl.exe | *[/\\]icl.exe )
|
||||
func_cl_wrapper "$@" # Doesn't return...
|
||||
;;
|
||||
esac
|
||||
|
||||
ofile=
|
||||
cfile=
|
||||
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
# So we strip '-o arg' only if arg is an object.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.obj)
|
||||
ofile=$2
|
||||
;;
|
||||
*)
|
||||
set x "$@" -o "$2"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*.c)
|
||||
cfile=$1
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
if test -z "$ofile" || test -z "$cfile"; then
|
||||
# If no '-o' option was seen then we might have been invoked from a
|
||||
# pattern rule where we don't need one. That is ok -- this is a
|
||||
# normal compilation that the losing compiler can handle. If no
|
||||
# '.c' file was seen then we are probably linking. That is also
|
||||
# ok.
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
# Name of file we expect compiler to create.
|
||||
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
|
||||
|
||||
# Create the lock directory.
|
||||
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
|
||||
# that we are using for the .o file. Also, base the name on the expected
|
||||
# object file name, since that is what matters with a parallel build.
|
||||
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
|
||||
while true; do
|
||||
if mkdir "$lockdir" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
# FIXME: race condition here if user kills between mkdir and trap.
|
||||
trap "rmdir '$lockdir'; exit 1" 1 2 15
|
||||
|
||||
# Run the compile.
|
||||
"$@"
|
||||
ret=$?
|
||||
|
||||
if test -f "$cofile"; then
|
||||
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
|
||||
elif test -f "${cofile}bj"; then
|
||||
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
|
||||
fi
|
||||
|
||||
rmdir "$lockdir"
|
||||
exit $ret
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
1476
libpng/config.guess
vendored
Executable file
1476
libpng/config.guess
vendored
Executable file
File diff suppressed because it is too large
Load diff
126
libpng/config.h.in
Normal file
126
libpng/config.h.in
Normal file
|
@ -0,0 +1,126 @@
|
|||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* Define to 1 if you have the `feenableexcept' function. */
|
||||
#undef HAVE_FEENABLEEXCEPT
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the `m' library (-lm). */
|
||||
#undef HAVE_LIBM
|
||||
|
||||
/* Define to 1 if you have the `z' library (-lz). */
|
||||
#undef HAVE_LIBZ
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the `pow' function. */
|
||||
#undef HAVE_POW
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to the sub-directory where libtool stores uninstalled libraries. */
|
||||
#undef LT_OBJDIR
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Turn on ARM Neon optimizations at run-time */
|
||||
#undef PNG_ARM_NEON_API_SUPPORTED
|
||||
|
||||
/* Check for ARM Neon support at run-time */
|
||||
#undef PNG_ARM_NEON_CHECK_SUPPORTED
|
||||
|
||||
/* Enable ARM Neon optimizations */
|
||||
#undef PNG_ARM_NEON_OPT
|
||||
|
||||
/* Enable Intel SSE optimizations */
|
||||
#undef PNG_INTEL_SSE_OPT
|
||||
|
||||
/* Turn on MIPS MSA optimizations at run-time */
|
||||
#undef PNG_MIPS_MSA_API_SUPPORTED
|
||||
|
||||
/* Check for MIPS MSA support at run-time */
|
||||
#undef PNG_MIPS_MSA_CHECK_SUPPORTED
|
||||
|
||||
/* Enable MIPS MSA optimizations */
|
||||
#undef PNG_MIPS_MSA_OPT
|
||||
|
||||
/* Turn on POWERPC VSX optimizations at run-time */
|
||||
#undef PNG_POWERPC_VSX_API_SUPPORTED
|
||||
|
||||
/* Check for POWERPC VSX support at run-time */
|
||||
#undef PNG_POWERPC_VSX_CHECK_SUPPORTED
|
||||
|
||||
/* Enable POWERPC VSX optimizations */
|
||||
#undef PNG_POWERPC_VSX_OPT
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
|
||||
#undef TM_IN_SYS_TIME
|
||||
|
||||
/* Version number of package */
|
||||
#undef VERSION
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
#undef const
|
||||
|
||||
/* Define to the equivalent of the C99 'restrict' keyword, or to
|
||||
nothing if this is not supported. Do not define if restrict is
|
||||
supported directly. */
|
||||
#undef restrict
|
||||
/* Work around a bug in Sun C++: it does not support _Restrict or
|
||||
__restrict__, even though the corresponding Sun C compiler ends up with
|
||||
"#define restrict _Restrict" or "#define restrict __restrict__" in the
|
||||
previous line. Perhaps some future version of Sun C++ will work with
|
||||
restrict; if so, hopefully it defines __RESTRICT like Sun C does. */
|
||||
#if defined __SUNPRO_CC && !defined __RESTRICT
|
||||
# define _Restrict
|
||||
# define __restrict__
|
||||
#endif
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
#undef size_t
|
1801
libpng/config.sub
vendored
Executable file
1801
libpng/config.sub
vendored
Executable file
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue