Compare commits

..

15 Commits

Author SHA1 Message Date
Baptiste Lepilleur
710c73a950 Release 0.5.0 2010-03-12 07:31:04 +00:00
Baptiste Lepilleur
66464f2c62 Release 0.5.0 2010-03-11 21:09:07 +00:00
Baptiste Lepilleur
d0e9ec5d54 Release 0.5.0 2010-02-25 07:55:28 +00:00
Baptiste Lepilleur
d90fc720ef Release 0.5.0 2010-02-25 07:51:43 +00:00
Baptiste Lepilleur
97af24d2f8 Release 0.5.0 2010-02-24 22:46:35 +00:00
Baptiste Lepilleur
3a75efb375 Release 0.5.0 2010-02-24 22:41:18 +00:00
Baptiste Lepilleur
da6ccbbcfb Release 0.5.0 2010-02-24 22:37:29 +00:00
Baptiste Lepilleur
50c383ba01 Release 0.5.0 2010-02-24 22:34:06 +00:00
Baptiste Lepilleur
df75e4aa84 Release 0.5.0 2010-02-24 20:45:50 +00:00
Baptiste Lepilleur
2279ce36c4 Release 0.5.0 2010-02-24 07:36:38 +00:00
Baptiste Lepilleur
64cc86bf5f Release 0.5.0 2010-02-23 20:41:23 +00:00
Baptiste Lepilleur
6283d0c7c1 Release 0.5.0 2010-02-23 07:51:07 +00:00
Baptiste Lepilleur
c45da10999 Release 0.5.0 2010-02-23 07:43:10 +00:00
Baptiste Lepilleur
9597adfcd0 Release 0.5.0 2010-02-23 03:28:23 +00:00
Baptiste Lepilleur
d07ebe671a Release 0.5.0 2010-02-23 03:23:09 +00:00
89 changed files with 1063 additions and 6738 deletions

10
.gitignore vendored
View File

@@ -1,10 +0,0 @@
*.pyc
*.swp
*.actual
*.actual-rewrite
*.process-output
*.rewrite
bin/
buildscons/
libs/

View File

@@ -1,23 +0,0 @@
# Build matrix / environment variable are explained on:
# http://about.travis-ci.org/docs/user/build-configuration/
# This file can be validated on:
# http://lint.travis-ci.org/
before_install: sudo apt-get install cmake
language: cpp
compiler:
- gcc
- clang
script: cmake -DJSONCPP_LIB_BUILD_SHARED=$SHARED_LIBRARY -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_VERBOSE_MAKEFILE=$VERBOSE_MAKE . && make
env:
global:
- JSONCPP_CONTINUOUS_INTERATION=1
matrix:
- SHARED_LIBRARY=ON BUILD_TYPE=release VERBOSE_MAKE=false
- SHARED_LIBRARY=OFF BUILD_TYPE=release VERBOSE_MAKE=false
- SHARED_LIBRARY=OFF BUILD_TYPE=debug VERBOSE VERBOSE_MAKE=true
notifications:
recipients:
- baptiste.lepilleur@gmail.com
email:
on_success: change
on_failure: always

View File

@@ -1,90 +0,0 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
PROJECT(jsoncpp)
ENABLE_TESTING()
OPTION(JSONCPP_WITH_TESTS "Compile and run JsonCpp test executables" ON)
OPTION(JSONCPP_WITH_POST_BUILD_UNITTEST "Automatically run unit-tests as a post build step" ON)
OPTION(JSONCPP_WITH_WARNING_AS_ERROR "Force compilation to fail if a warning occurs" OFF)
# Ensures that CMAKE_BUILD_TYPE is visible in cmake-gui on Unix
IF(NOT WIN32)
IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE Release CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage."
FORCE)
ENDIF(NOT CMAKE_BUILD_TYPE)
ENDIF(NOT WIN32)
# This ensures shared DLL are in the same dir as executable on Windows.
# Put all executables / libraries are in a project global directory.
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib
CACHE PATH "Single directory for all static libraries.")
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib
CACHE PATH "Single directory for all dynamic libraries on Unix.")
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin
CACHE PATH "Single directory for all executable and dynamic libraries on Windows.")
MARK_AS_ADVANCED( CMAKE_RUNTIME_OUTPUT_DIRECTORY CMAKE_LIBRARY_OUTPUT_DIRECTORY CMAKE_ARCHIVE_OUTPUT_DIRECTORY )
# Set variable named ${VAR_NAME} to value ${VALUE}
FUNCTION(set_using_dynamic_name VAR_NAME VALUE)
SET( "${VAR_NAME}" "${VALUE}" PARENT_SCOPE)
ENDFUNCTION(set_using_dynamic_name)
# Extract major, minor, patch and qualifier from version text
# Parse a version string "X.Y.Z[-qualifier]" and outputs
# version parts in ${OUPUT_PREFIX}_MAJOR, _MINOR, _PATCH, _QUALIFIER.
# If parse succed then ${OUPUT_PREFIX}_FOUND is TRUE.
MACRO(jsoncpp_parse_version VERSION_TEXT OUPUT_PREFIX)
SET(VERSION_REGEX "[0-9]+\\.[0-9]+\\.[0-9]+(-[a-zA-Z0-9_]+)?")
IF( ${VERSION_TEXT} MATCHES ${VERSION_REGEX} )
STRING(REGEX MATCHALL "[0-9]+|-([A-Za-z0-9_]+)" VERSION_PARTS ${VERSION_TEXT})
list(APPEND VERSION_PARTS "") # empty qualifier to handle no qualifier case
LIST(GET VERSION_PARTS 0 ${OUPUT_PREFIX}_MAJOR)
LIST(GET VERSION_PARTS 1 ${OUPUT_PREFIX}_MINOR)
LIST(GET VERSION_PARTS 2 ${OUPUT_PREFIX}_PATCH)
LIST(GET VERSION_PARTS 3 ${OUPUT_PREFIX}_QUALIFIER)
set_using_dynamic_name( "${OUPUT_PREFIX}_FOUND" TRUE )
ELSE( ${VERSION_TEXT} MATCHES ${VERSION_REGEX} )
set_using_dynamic_name( "${OUPUT_PREFIX}_FOUND" FALSE )
ENDIF( ${VERSION_TEXT} MATCHES ${VERSION_REGEX} )
ENDMACRO(jsoncpp_parse_version)
# Read out version from "version" file
FILE(STRINGS "version" JSONCPP_VERSION)
jsoncpp_parse_version( ${JSONCPP_VERSION} JSONCPP_VERSION )
IF(NOT JSONCPP_VERSION_FOUND)
MESSAGE(FATAL_ERROR "Failed to parse version string properly. Expect X.Y.Z[-qualifier]")
ENDIF(NOT JSONCPP_VERSION_FOUND)
MESSAGE(STATUS "JsonCpp Version: ${JSONCPP_VERSION_MAJOR}.${JSONCPP_VERSION_MINOR}.${JSONCPP_VERSION_PATCH}${JSONCPP_VERSION_QUALIFIER}")
# File version.h is only regenerated on CMake configure step
CONFIGURE_FILE( "${PROJECT_SOURCE_DIR}/src/lib_json/version.h.in"
"${PROJECT_SOURCE_DIR}/include/json/version.h" )
macro(UseCompilationWarningAsError)
if ( MSVC )
# Only enabled in debug because some old versions of VS STL generate
# warnings when compiled in release configuration.
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /WX ")
endif( MSVC )
endmacro()
# Include our configuration header
INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/include )
if ( MSVC )
# Only enabled in debug because some old versions of VS STL generate
# unreachable code warning when compiled in release configuration.
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /W4 ")
endif( MSVC )
IF(JSONCPP_WITH_WARNING_AS_ERROR)
UseCompilationWarningAsError()
ENDIF(JSONCPP_WITH_WARNING_AS_ERROR)
# Build the different applications
ADD_SUBDIRECTORY( src )
#install the includes
ADD_SUBDIRECTORY( include )

56
LICENSE
View File

@@ -1,55 +1 @@
The JsonCpp library's source code, including accompanying documentation,
tests and demonstration applications, are licensed under the following
conditions...
The author (Baptiste Lepilleur) explicitly disclaims copyright in all
jurisdictions which recognize such a disclaimer. In such jurisdictions,
this software is released into the Public Domain.
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
released under the terms of the MIT License (see below).
In jurisdictions which recognize Public Domain property, the user of this
software may choose to accept it either as 1) Public Domain, 2) under the
conditions of the MIT License (see below), or 3) under the terms of dual
Public Domain/MIT License conditions described here, as they choose.
The MIT License is about as close to Public Domain as a license can get, and is
described in clear, concise terms at:
http://en.wikipedia.org/wiki/MIT_License
The full text of the MIT License follows:
========================================================================
Copyright (c) 2007-2010 Baptiste Lepilleur
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.
========================================================================
(END LICENSE TEXT)
The MIT license is compatible with both the GPL and commercial
software, affording one all of the rights of Public Domain with the
minor nuisance of being required to keep the above copyright notice
and license text in the source code. Note also that by accepting the
Public Domain "license" you can re-license your copy using whatever
license you like.
The json-cpp library and this documentation are in Public Domain.

175
NEWS.txt
View File

@@ -1,175 +0,0 @@
New in SVN
----------
* Updated the type system's behavior, in order to better support backwards
compatibility with code that was written before 64-bit integer support was
introduced. Here's how it works now:
* isInt, isInt64, isUInt, and isUInt64 return true if and only if the
value can be exactly represented as that type. In particular, a value
constructed with a double like 17.0 will now return true for all of
these methods.
* isDouble and isFloat now return true for all numeric values, since all
numeric values can be converted to a double or float without
truncation. Note however that the conversion may not be exact -- for
example, doubles cannot exactly represent all integers above 2^53 + 1.
* isBool, isNull, isString, isArray, and isObject now return true if and
only if the value is of that type.
* isConvertibleTo(fooValue) indicates that it is safe to call asFoo.
(For each type foo, isFoo always implies isConvertibleTo(fooValue).)
asFoo returns an approximate or exact representation as appropriate.
For example, a double value may be truncated when asInt is called.
* For backwards compatibility with old code, isConvertibleTo(intValue)
may return false even if type() == intValue. This is because the value
may have been constructed with a 64-bit integer larger than maxInt,
and calling asInt() would cause an exception. If you're writing new
code, use isInt64 to find out whether the value is exactly
representable using an Int64, or asDouble() combined with minInt64 and
maxInt64 to figure out whether it is approximately representable.
* Value
- Patch #10: BOOST_FOREACH compatibility. Made Json::iterator more
standard compliant, added missing iterator_category and value_type
typedefs (contribued by Robert A. Iannucci).
* Compilation
- New CMake based build system. Based in part on contribution from
Igor Okulist and Damien Buhl (Patch #14).
- New header json/version.h now contains version number macros
(JSONCPP_VERSION_MAJOR, JSONCPP_VERSION_MINOR, JSONCPP_VERSION_PATCH
and JSONCPP_VERSION_HEXA).
- Patch #11: added missing JSON_API on some classes causing link issues
when building as a dynamic library on Windows
(contributed by Francis Bolduc).
- Visual Studio DLL: suppressed warning "C4251: <data member>: <type>
needs to have dll-interface to be used by..." via pragma push/pop
in json-cpp headers.
- Added Travis CI intregration: https://travis-ci.org/blep/jsoncpp-mirror
* Bug fixes
- Patch #15: Copy constructor does not initialize allocated_ for stringValue
(contributed by rmongia).
- Patch #16: Missing field copy in Json::Value::iterator causing infinite
loop when using experimental internal map (#define JSON_VALUE_USE_INTERNAL_MAP)
(contributed by Ming-Lin Kao).
New in JsonCpp 0.6.0:
---------------------
* Compilation
- LD_LIBRARY_PATH and LIBRARY_PATH environment variables are now
propagated to the build environment as this is required for some
compiler installation.
- Added support for Microsoft Visual Studio 2008 (bug #2930462):
The platform "msvc90" has been added.
Notes: you need to setup the environment by running vcvars32.bat
(e.g. MSVC 2008 command prompt in start menu) before running scons.
- Added support for amalgamated source and header generation (a la sqlite).
Refer to README.txt section "Generating amalgamated source and header"
for detail.
* Value
- Removed experimental ValueAllocator, it caused static
initialization/destruction order issues (bug #2934500).
The DefaultValueAllocator has been inlined in code.
- Added support for 64 bits integer:
Types Json::Int64 and Json::UInt64 have been added. They are aliased
to 64 bits integers on system that support them (based on __int64 on
Microsoft Visual Studio platform, and long long on other platforms).
Types Json::LargestInt and Json::LargestUInt have been added. They are
aliased to the largest integer type supported:
either Json::Int/Json::UInt or Json::Int64/Json::UInt64 respectively.
Json::Value::asInt() and Json::Value::asUInt() still returns plain
"int" based types, but asserts if an attempt is made to retrieve
a 64 bits value that can not represented as the return type.
Json::Value::asInt64() and Json::Value::asUInt64() have been added
to obtain the 64 bits integer value.
Json::Value::asLargestInt() and Json::Value::asLargestUInt() returns
the integer as a LargestInt/LargestUInt respectively. Those functions
functions are typically used when implementing writer.
The reader attempts to read number as 64 bits integer, and fall back
to reading a double if the number is not in the range of 64 bits
integer.
Warning: Json::Value::asInt() and Json::Value::asUInt() now returns
long long. This changes break code that was passing the return value
to *printf() function.
Support for 64 bits integer can be disabled by defining the macro
JSON_NO_INT64 (uncomment it in json/config.h for example), though
it should have no impact on existing usage.
- The type Json::ArrayIndex is used for indexes of a JSON value array. It
is an unsigned int (typically 32 bits).
- Array index can be passed as int to operator[], allowing use of literal:
Json::Value array;
array.append( 1234 );
int value = array[0].asInt(); // did not compile previously
- Added float Json::Value::asFloat() to obtain a floating point value as a
float (avoid lost of precision warning caused by used of asDouble()
to initialize a float).
* Reader
- Renamed Reader::getFormatedErrorMessages() to getFormattedErrorMessages.
Bug #3023708 (Formatted has 2 't'). The old member function is deprecated
but still present for backward compatibility.
* Tests
- Added test to ensure that the escape sequence "\/" is corrected handled
by the parser.
* Bug fixes
- Bug #3139677: JSON [1 2 3] was incorrectly parsed as [1, 3]. Error is now
correctly detected.
- Bug #3139678: stack buffer overflow when parsing a double with a
length of 32 characters.
- Fixed Value::operator <= implementation (had the semantic of operator >=).
Found when adding unit tests for comparison operators.
- Value::compare() is now const and has an actual implementation with
unit tests.
- Bug #2407932: strpbrk() can fail for NULL pointer.
- Bug #3306345: Fixed minor typo in Path::resolve().
- Bug #3314841/#3306896: errors in amalgamate.py
- Fixed some Coverity warnings and line-endings.
* License
- See file LICENSE for details. Basically JsonCpp is now licensed under
MIT license, or public domain if desired and recognized in your jurisdiction.
Thanks to Stephan G. Beal [http://wanderinghorse.net/home/stephan/]) who
helped figuring out the solution to the public domain issue.

View File

@@ -5,80 +5,23 @@ JSON (JavaScript Object Notation) is a lightweight data-interchange format.
It can represent integer, real number, string, an ordered sequence of
value, and a collection of name/value pairs.
JsonCpp (http://jsoncpp.sourceforge.net/) is a simple API to manipulate
JSON value, handle serialization and unserialization to string.
JsonCpp is a simple API to manipulate JSON value, handle serialization
and unserialization to string.
It can also preserve existing comment in unserialization/serialization steps,
making it a convenient format to store user input files.
Unserialization parsing is user friendly and provides precise error reports.
* Using json-cpp in your project:
===============================
The recommended approach to integrate json-cpp in your project is to
build the the amalgamated source (a single .cpp) with your own build
system. This ensures compilation flags consistency and ABI compatibility.
See section "Generating amalgamated source and header" to generate them
from the source distribution.
Directory include/ should be added to your compiler include path.
json-cpp headers should be included as follow:
#include <json/json.h>
If json-cpp was build as a dynamic library on Windows, then your project
need to define macro "JSON_DLL" to JSON_API should import exported symbols.
* Building/Testing with new CMake build system:
=============================================
CMake is a C++ Makefiles/Solution generator that can be downloaded from:
http://www.cmake.org
It is usually available on most Linux system as package. On Ubuntu:
sudo apt-get install cmake
Notes that python is also required to run JSON reader/writer tests. If
missing, the build will skip running those tests.
When running CMake, a few parameters are required:
- a build directory where the makefiles/solution are generated. It is
also used to store objects, libraries and executables files.
- the generator to use: makefiles or Visual Studio solution? What version
or Visual Studio, 32 or 64 bits solution?
Generating solution/makefiles using cmake-gui:
- Makes "source code" points the source directory
- Makes "where to build the binary" points to the directory to use for
the build.
- Click on the "Grouped" check box
- Review JsonCpp build option (tick JSONCPP_LIB_BUILD_SHARED to build as
a dynamic library)
- Click configure button at the bottom, then the generate button.
- The generated solution/makefiles can be found in the binary directory.
Alternatively, from the command-line on Unix in the source directory:
mkdir -p ../build/debug
cd ../build/debug
cmake -DCMAKE_BUILD_TYPE=debug -DJSONCPP_LIB_BUILD_SHARED=OFF -G "Unix Makefiles" ../../jsoncpp-src
make
Running "cmake -h" will display the list of available generators (passed as -G option).
By default CMake hides compilation command-line. This can be modified by specifying:
-DCMAKE_VERBOSE_MAKEFILE=true when generating makefiles.
* Building/Testing with the legacy build system based on SCons:
=============================================================
* Building/Testing:
=================
JsonCpp uses Scons (http://www.scons.org) as a build system. Scons requires
python to be installed (http://www.python.org).
You download scons-local distribution from the following url:
http://sourceforge.net/projects/scons/files/scons-local/1.2.0/
http://sourceforge.net/project/showfiles.php?group_id=30337&package_id=67375
Unzip it in the directory where you found this README file. scons.py Should be
at the same level as README.
@@ -92,29 +35,18 @@ where PLTFRM may be one of:
msvc70 Microsoft Visual Studio 2002
msvc71 Microsoft Visual Studio 2003
msvc80 Microsoft Visual Studio 2005
msvc90 Microsoft Visual Studio 2008
linux-gcc Gnu C++ (linux, also reported to work for Mac OS X)
Notes: if you are building with Microsoft Visual Studio 2008, you need to
setup the environment by running vcvars32.bat (e.g. MSVC 2008 command prompt)
before running scons.
Adding platform is fairly simple. You need to change the Sconstruct file
adding platform is fairly simple. You need to change the Sconstruct file
to do so.
and TARGET may be:
check: build library and run unit tests.
* Running the test manually:
==========================
Notes that test can be run by scons using the 'check' target (see above).
You need to run test manually only if you are troubleshooting an issue.
In the instruction below, replace "path to jsontest.exe" with the path
of the 'jsontest' executable that was compiled on your platform.
cd test
# This will run the Reader/Writer tests
python runjsontests.py "path to jsontest.exe"
@@ -142,34 +74,6 @@ python doxybuild.py --open --with-dot
See doxybuild.py --help for options.
Notes that the documentation is also available for download as a tarball.
The documentation of the latest release is available online at:
http://jsoncpp.sourceforge.net/
* Generating amalgamated source and header
========================================
JsonCpp is provided with a script to generate a single header and a single
source file to ease inclusion in an existing project.
The amalgamated source can be generated at any time by running the following
command from the top-directory (requires python 2.6):
python amalgamate.py
It is possible to specify header name. See -h options for detail. By default,
the following files are generated:
- dist/jsoncpp.cpp: source file that need to be added to your project
- dist/json/json.h: header file corresponding to use in your project. It is
equivalent to including json/json.h in non-amalgamated source. This header
only depends on standard headers.
- dist/json/json-forwards.h: header the provides forward declaration
of all JsonCpp types. This typically what should be included in headers to
speed-up compilation.
The amalgamated sources are generated by concatenating JsonCpp source in the
correct order and defining macro JSON_IS_AMALGAMATION to prevent inclusion
of other headers.
* Adding a reader/writer test:
============================
@@ -211,10 +115,3 @@ Below is a short description of the content of each file:
jsontest.exe from reading test_complex_01.rewrite.
test_complex_01.process-output: jsontest.exe output, typically useful to
understand parsing error.
* License
=======
See file LICENSE for details. Basically JsonCpp is licensed under
MIT license, or public domain if desired and recognized in your jurisdiction.

View File

@@ -18,7 +18,7 @@ options = Variables()
options.Add( EnumVariable('platform',
'Platform (compiler/stl) used to build the project',
'msvc71',
allowed_values='suncc vacpp mingw msvc6 msvc7 msvc71 msvc80 msvc90 linux-gcc'.split(),
allowed_values='suncc vacpp mingw msvc6 msvc7 msvc71 msvc80 linux-gcc'.split(),
ignorecase=2) )
try:
@@ -57,9 +57,8 @@ def make_environ_vars():
"""Returns a dictionnary with environment variable to use when compiling."""
# PATH is required to find the compiler
# TEMP is required for at least mingw
# LD_LIBRARY_PATH & co is required on some system for the compiler
vars = {}
for name in ('PATH', 'TEMP', 'TMP', 'LD_LIBRARY_PATH', 'LIBRARY_PATH'):
for name in ('PATH', 'TEMP', 'TMP'):
if name in os.environ:
vars[name] = os.environ[name]
return vars
@@ -102,18 +101,6 @@ elif platform == 'msvc80':
for tool in ['msvc', 'msvs', 'mslink', 'masm', 'mslib']:
env.Tool( tool )
env['CXXFLAGS']='-GR -EHsc /nologo /MT'
elif platform == 'msvc90':
env['MSVS_VERSION']='9.0'
# Scons 1.2 fails to detect the correct location of the platform SDK.
# So we propagate those from the environment. This requires that the
# user run vcvars32.bat before compiling.
if 'INCLUDE' in os.environ:
env['ENV']['INCLUDE'] = os.environ['INCLUDE']
if 'LIB' in os.environ:
env['ENV']['LIB'] = os.environ['LIB']
for tool in ['msvc', 'msvs', 'mslink', 'masm', 'mslib']:
env.Tool( tool )
env['CXXFLAGS']='-GR -EHsc /nologo /MT'
elif platform == 'mingw':
env.Tool( 'mingw' )
env.Append( CPPDEFINES=[ "WIN32", "NDEBUG", "_MT" ] )

View File

@@ -1,150 +0,0 @@
"""Amalgate json-cpp library sources into a single source and header file.
Requires Python 2.6
Example of invocation (must be invoked from json-cpp top directory):
python amalgate.py
"""
import os
import os.path
import sys
class AmalgamationFile:
def __init__( self, top_dir ):
self.top_dir = top_dir
self.blocks = []
def add_text( self, text ):
if not text.endswith( '\n' ):
text += '\n'
self.blocks.append( text )
def add_file( self, relative_input_path, wrap_in_comment=False ):
def add_marker( prefix ):
self.add_text( '' )
self.add_text( '// ' + '/'*70 )
self.add_text( '// %s of content of file: %s' % (prefix, relative_input_path.replace('\\','/')) )
self.add_text( '// ' + '/'*70 )
self.add_text( '' )
add_marker( 'Beginning' )
f = open( os.path.join( self.top_dir, relative_input_path ), 'rt' )
content = f.read()
if wrap_in_comment:
content = '/*\n' + content + '\n*/'
self.add_text( content )
f.close()
add_marker( 'End' )
self.add_text( '\n\n\n\n' )
def get_value( self ):
return ''.join( self.blocks ).replace('\r\n','\n')
def write_to( self, output_path ):
output_dir = os.path.dirname( output_path )
if output_dir and not os.path.isdir( output_dir ):
os.makedirs( output_dir )
f = open( output_path, 'wb' )
f.write( self.get_value() )
f.close()
def amalgamate_source( source_top_dir=None,
target_source_path=None,
header_include_path=None ):
"""Produces amalgated source.
Parameters:
source_top_dir: top-directory
target_source_path: output .cpp path
header_include_path: generated header path relative to target_source_path.
"""
print 'Amalgating header...'
header = AmalgamationFile( source_top_dir )
header.add_text( '/// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/).' )
header.add_text( '/// It is intented to be used with #include <%s>' % header_include_path )
header.add_file( 'LICENSE', wrap_in_comment=True )
header.add_text( '#ifndef JSON_AMALGATED_H_INCLUDED' )
header.add_text( '# define JSON_AMALGATED_H_INCLUDED' )
header.add_text( '/// If defined, indicates that the source file is amalgated' )
header.add_text( '/// to prevent private header inclusion.' )
header.add_text( '#define JSON_IS_AMALGAMATION' )
header.add_file( 'include/json/version.h' )
header.add_file( 'include/json/config.h' )
header.add_file( 'include/json/forwards.h' )
header.add_file( 'include/json/features.h' )
header.add_file( 'include/json/value.h' )
header.add_file( 'include/json/reader.h' )
header.add_file( 'include/json/writer.h' )
header.add_file( 'include/json/assertions.h' )
header.add_text( '#endif //ifndef JSON_AMALGATED_H_INCLUDED' )
target_header_path = os.path.join( os.path.dirname(target_source_path), header_include_path )
print 'Writing amalgated header to %r' % target_header_path
header.write_to( target_header_path )
base, ext = os.path.splitext( header_include_path )
forward_header_include_path = base + '-forwards' + ext
print 'Amalgating forward header...'
header = AmalgamationFile( source_top_dir )
header.add_text( '/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/).' )
header.add_text( '/// It is intented to be used with #include <%s>' % forward_header_include_path )
header.add_text( '/// This header provides forward declaration for all JsonCpp types.' )
header.add_file( 'LICENSE', wrap_in_comment=True )
header.add_text( '#ifndef JSON_FORWARD_AMALGATED_H_INCLUDED' )
header.add_text( '# define JSON_FORWARD_AMALGATED_H_INCLUDED' )
header.add_text( '/// If defined, indicates that the source file is amalgated' )
header.add_text( '/// to prevent private header inclusion.' )
header.add_text( '#define JSON_IS_AMALGAMATION' )
header.add_file( 'include/json/config.h' )
header.add_file( 'include/json/forwards.h' )
header.add_text( '#endif //ifndef JSON_FORWARD_AMALGATED_H_INCLUDED' )
target_forward_header_path = os.path.join( os.path.dirname(target_source_path),
forward_header_include_path )
print 'Writing amalgated forward header to %r' % target_forward_header_path
header.write_to( target_forward_header_path )
print 'Amalgating source...'
source = AmalgamationFile( source_top_dir )
source.add_text( '/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/).' )
source.add_text( '/// It is intented to be used with #include <%s>' % header_include_path )
source.add_file( 'LICENSE', wrap_in_comment=True )
source.add_text( '' )
source.add_text( '#include <%s>' % header_include_path )
source.add_text( '' )
lib_json = 'src/lib_json'
source.add_file( os.path.join(lib_json, 'json_tool.h') )
source.add_file( os.path.join(lib_json, 'json_reader.cpp') )
source.add_file( os.path.join(lib_json, 'json_batchallocator.h') )
source.add_file( os.path.join(lib_json, 'json_valueiterator.inl') )
source.add_file( os.path.join(lib_json, 'json_value.cpp') )
source.add_file( os.path.join(lib_json, 'json_writer.cpp') )
print 'Writing amalgated source to %r' % target_source_path
source.write_to( target_source_path )
def main():
usage = """%prog [options]
Generate a single amalgated source and header file from the sources.
"""
from optparse import OptionParser
parser = OptionParser(usage=usage)
parser.allow_interspersed_args = False
parser.add_option('-s', '--source', dest="target_source_path", action='store', default='dist/jsoncpp.cpp',
help="""Output .cpp source path. [Default: %default]""")
parser.add_option('-i', '--include', dest="header_include_path", action='store', default='json/json.h',
help="""Header include path. Used to include the header from the amalgated source file. [Default: %default]""")
parser.add_option('-t', '--top-dir', dest="top_dir", action='store', default=os.getcwd(),
help="""Source top-directory. [Default: %default]""")
parser.enable_interspersed_args()
options, args = parser.parse_args()
msg = amalgamate_source( source_top_dir=options.top_dir,
target_source_path=options.target_source_path,
header_include_path=options.header_include_path )
if msg:
sys.stderr.write( msg + '\n' )
sys.exit( 1 )
else:
print 'Source succesfully amalagated'
if __name__ == '__main__':
main()

View File

@@ -1,33 +0,0 @@
{
"cmake_variants" : [
{"name": "generator",
"generators": [
{"generator": [
"Visual Studio 7 .NET 2003",
"Visual Studio 9 2008",
"Visual Studio 9 2008 Win64",
"Visual Studio 10",
"Visual Studio 10 Win64",
"Visual Studio 11",
"Visual Studio 11 Win64"
]
},
{"generator": ["MinGW Makefiles"],
"env_prepend": [{"path": "c:/wut/prg/MinGW/bin"}]
}
]
},
{"name": "shared_dll",
"variables": [
["JSONCPP_LIB_BUILD_SHARED=true"],
["JSONCPP_LIB_BUILD_SHARED=false"]
]
},
{"name": "build_type",
"build_types": [
"debug",
"release"
]
}
]
}

View File

@@ -1,26 +0,0 @@
{
"cmake_variants" : [
{"name": "generator",
"generators": [
{"generator": [
"Visual Studio 6",
"Visual Studio 7",
"Visual Studio 8 2005"
]
}
]
},
{"name": "shared_dll",
"variables": [
["JSONCPP_LIB_BUILD_SHARED=true"],
["JSONCPP_LIB_BUILD_SHARED=false"]
]
},
{"name": "build_type",
"build_types": [
"debug",
"release"
]
}
]
}

View File

@@ -55,20 +55,20 @@ ALL = DIR | FILE | LINKS
_ANT_RE = re.compile( r'(/\*\*/)|(\*\*/)|(/\*\*)|(\*)|(/)|([^\*/]*)' )
def ant_pattern_to_re( ant_pattern ):
"""Generates a regular expression from the ant pattern.
Matching convention:
**/a: match 'a', 'dir/a', 'dir1/dir2/a'
a/**/b: match 'a/b', 'a/c/b', 'a/d/c/b'
*.py: match 'script.py' but not 'a/script.py'
def ant_pattern_to_re( ant_pattern ):
"""Generates a regular expression from the ant pattern.
Matching convention:
**/a: match 'a', 'dir/a', 'dir1/dir2/a'
a/**/b: match 'a/b', 'a/c/b', 'a/d/c/b'
*.py: match 'script.py' but not 'a/script.py'
"""
rex = ['^']
next_pos = 0
sep_rex = r'(?:/|%s)' % re.escape( os.path.sep )
## print 'Converting', ant_pattern
for match in _ANT_RE.finditer( ant_pattern ):
## print 'Matched', match.group()
## print match.start(0), next_pos
sep_rex = r'(?:/|%s)' % re.escape( os.path.sep )
## print 'Converting', ant_pattern
for match in _ANT_RE.finditer( ant_pattern ):
## print 'Matched', match.group()
## print match.start(0), next_pos
if match.start(0) != next_pos:
raise ValueError( "Invalid ant pattern" )
if match.group(1): # /**/
@@ -83,14 +83,14 @@ def ant_pattern_to_re( ant_pattern ):
rex.append( sep_rex )
else: # somepath
rex.append( re.escape(match.group(6)) )
next_pos = match.end()
next_pos = match.end()
rex.append('$')
return re.compile( ''.join( rex ) )
def _as_list( l ):
if isinstance(l, basestring):
return l.split()
return l
def _as_list( l ):
if isinstance(l, basestring):
return l.split()
return l
def glob(dir_path,
includes = '**/*',
@@ -99,8 +99,8 @@ def glob(dir_path,
prune_dirs = prune_dirs,
max_depth = 25):
include_filter = [ant_pattern_to_re(p) for p in _as_list(includes)]
exclude_filter = [ant_pattern_to_re(p) for p in _as_list(excludes)]
prune_dirs = [p.replace('/',os.path.sep) for p in _as_list(prune_dirs)]
exclude_filter = [ant_pattern_to_re(p) for p in _as_list(excludes)]
prune_dirs = [p.replace('/',os.path.sep) for p in _as_list(prune_dirs)]
dir_path = dir_path.replace('/',os.path.sep)
entry_type_filter = entry_type
@@ -117,37 +117,37 @@ def glob(dir_path,
return True
return False
def glob_impl( root_dir_path ):
child_dirs = [root_dir_path]
while child_dirs:
def glob_impl( root_dir_path ):
child_dirs = [root_dir_path]
while child_dirs:
dir_path = child_dirs.pop()
for entry in listdir( dir_path ):
full_path = os.path.join( dir_path, entry )
## print 'Testing:', full_path,
is_dir = os.path.isdir( full_path )
if is_dir and not is_pruned_dir( entry ): # explore child directory ?
## print '===> marked for recursion',
child_dirs.append( full_path )
included = apply_filter( full_path, include_filter )
rejected = apply_filter( full_path, exclude_filter )
if not included or rejected: # do not include entry ?
## print '=> not included or rejected'
continue
link = os.path.islink( full_path )
is_file = os.path.isfile( full_path )
if not is_file and not is_dir:
## print '=> unknown entry type'
continue
if link:
entry_type = is_file and FILE_LINK or DIR_LINK
else:
entry_type = is_file and FILE or DIR
## print '=> type: %d' % entry_type,
if (entry_type & entry_type_filter) != 0:
## print ' => KEEP'
yield os.path.join( dir_path, entry )
## else:
## print ' => TYPE REJECTED'
for entry in listdir( dir_path ):
full_path = os.path.join( dir_path, entry )
## print 'Testing:', full_path,
is_dir = os.path.isdir( full_path )
if is_dir and not is_pruned_dir( entry ): # explore child directory ?
## print '===> marked for recursion',
child_dirs.append( full_path )
included = apply_filter( full_path, include_filter )
rejected = apply_filter( full_path, exclude_filter )
if not included or rejected: # do not include entry ?
## print '=> not included or rejected'
continue
link = os.path.islink( full_path )
is_file = os.path.isfile( full_path )
if not is_file and not is_dir:
## print '=> unknown entry type'
continue
if link:
entry_type = is_file and FILE_LINK or DIR_LINK
else:
entry_type = is_file and FILE or DIR
## print '=> type: %d' % entry_type,
if (entry_type & entry_type_filter) != 0:
## print ' => KEEP'
yield os.path.join( dir_path, entry )
## else:
## print ' => TYPE REJECTED'
return list( glob_impl( dir_path ) )
@@ -155,47 +155,47 @@ if __name__ == "__main__":
import unittest
class AntPatternToRETest(unittest.TestCase):
## def test_conversion( self ):
## self.assertEqual( '^somepath$', ant_pattern_to_re( 'somepath' ).pattern )
def test_matching( self ):
test_cases = [ ( 'path',
['path'],
['somepath', 'pathsuffix', '/path', '/path'] ),
( '*.py',
['source.py', 'source.ext.py', '.py'],
['path/source.py', '/.py', 'dir.py/z', 'z.pyc', 'z.c'] ),
( '**/path',
['path', '/path', '/a/path', 'c:/a/path', '/a/b/path', '//a/path', '/a/path/b/path'],
['path/', 'a/path/b', 'dir.py/z', 'somepath', 'pathsuffix', 'a/somepath'] ),
( 'path/**',
['path/a', 'path/path/a', 'path//'],
['path', 'somepath/a', 'a/path', 'a/path/a', 'pathsuffix/a'] ),
( '/**/path',
['/path', '/a/path', '/a/b/path/path', '/path/path'],
['path', 'path/', 'a/path', '/pathsuffix', '/somepath'] ),
( 'a/b',
['a/b'],
['somea/b', 'a/bsuffix', 'a/b/c'] ),
( '**/*.py',
['script.py', 'src/script.py', 'a/b/script.py', '/a/b/script.py'],
['script.pyc', 'script.pyo', 'a.py/b'] ),
( 'src/**/*.py',
['src/a.py', 'src/dir/a.py'],
['a/src/a.py', '/src/a.py'] ),
]
for ant_pattern, accepted_matches, rejected_matches in list(test_cases):
def local_path( paths ):
return [ p.replace('/',os.path.sep) for p in paths ]
test_cases.append( (ant_pattern, local_path(accepted_matches), local_path( rejected_matches )) )
for ant_pattern, accepted_matches, rejected_matches in test_cases:
rex = ant_pattern_to_re( ant_pattern )
print 'ant_pattern:', ant_pattern, ' => ', rex.pattern
for accepted_match in accepted_matches:
print 'Accepted?:', accepted_match
self.assert_( rex.match( accepted_match ) is not None )
for rejected_match in rejected_matches:
print 'Rejected?:', rejected_match
self.assert_( rex.match( rejected_match ) is None )
## def test_conversion( self ):
## self.assertEqual( '^somepath$', ant_pattern_to_re( 'somepath' ).pattern )
def test_matching( self ):
test_cases = [ ( 'path',
['path'],
['somepath', 'pathsuffix', '/path', '/path'] ),
( '*.py',
['source.py', 'source.ext.py', '.py'],
['path/source.py', '/.py', 'dir.py/z', 'z.pyc', 'z.c'] ),
( '**/path',
['path', '/path', '/a/path', 'c:/a/path', '/a/b/path', '//a/path', '/a/path/b/path'],
['path/', 'a/path/b', 'dir.py/z', 'somepath', 'pathsuffix', 'a/somepath'] ),
( 'path/**',
['path/a', 'path/path/a', 'path//'],
['path', 'somepath/a', 'a/path', 'a/path/a', 'pathsuffix/a'] ),
( '/**/path',
['/path', '/a/path', '/a/b/path/path', '/path/path'],
['path', 'path/', 'a/path', '/pathsuffix', '/somepath'] ),
( 'a/b',
['a/b'],
['somea/b', 'a/bsuffix', 'a/b/c'] ),
( '**/*.py',
['script.py', 'src/script.py', 'a/b/script.py', '/a/b/script.py'],
['script.pyc', 'script.pyo', 'a.py/b'] ),
( 'src/**/*.py',
['src/a.py', 'src/dir/a.py'],
['a/src/a.py', '/src/a.py'] ),
]
for ant_pattern, accepted_matches, rejected_matches in list(test_cases):
def local_path( paths ):
return [ p.replace('/',os.path.sep) for p in paths ]
test_cases.append( (ant_pattern, local_path(accepted_matches), local_path( rejected_matches )) )
for ant_pattern, accepted_matches, rejected_matches in test_cases:
rex = ant_pattern_to_re( ant_pattern )
print 'ant_pattern:', ant_pattern, ' => ', rex.pattern
for accepted_match in accepted_matches:
print 'Accepted?:', accepted_match
self.assert_( rex.match( accepted_match ) is not None )
for rejected_match in rejected_matches:
print 'Rejected?:', rejected_match
self.assert_( rex.match( rejected_match ) is None )
unittest.main()

View File

@@ -1,280 +0,0 @@
import collections
import itertools
import json
import os
import os.path
import re
import shutil
import string
import subprocess
import sys
import cgi
class BuildDesc:
def __init__(self, prepend_envs=None, variables=None, build_type=None, generator=None):
self.prepend_envs = prepend_envs or [] # [ { "var": "value" } ]
self.variables = variables or []
self.build_type = build_type
self.generator = generator
def merged_with( self, build_desc ):
"""Returns a new BuildDesc by merging field content.
Prefer build_desc fields to self fields for single valued field.
"""
return BuildDesc( self.prepend_envs + build_desc.prepend_envs,
self.variables + build_desc.variables,
build_desc.build_type or self.build_type,
build_desc.generator or self.generator )
def env( self ):
environ = os.environ.copy()
for values_by_name in self.prepend_envs:
for var, value in values_by_name.items():
var = var.upper()
if type(value) is unicode:
value = value.encode( sys.getdefaultencoding() )
if var in environ:
environ[var] = value + os.pathsep + environ[var]
else:
environ[var] = value
return environ
def cmake_args( self ):
args = ["-D%s" % var for var in self.variables]
# skip build type for Visual Studio solution as it cause warning
if self.build_type and 'Visual' not in self.generator:
args.append( "-DCMAKE_BUILD_TYPE=%s" % self.build_type )
if self.generator:
args.extend( ['-G', self.generator] )
return args
def __repr__( self ):
return "BuildDesc( %s, build_type=%s )" % (" ".join( self.cmake_args()), self.build_type)
class BuildData:
def __init__( self, desc, work_dir, source_dir ):
self.desc = desc
self.work_dir = work_dir
self.source_dir = source_dir
self.cmake_log_path = os.path.join( work_dir, 'batchbuild_cmake.log' )
self.build_log_path = os.path.join( work_dir, 'batchbuild_build.log' )
self.cmake_succeeded = False
self.build_succeeded = False
def execute_build(self):
print 'Build %s' % self.desc
self._make_new_work_dir( )
self.cmake_succeeded = self._generate_makefiles( )
if self.cmake_succeeded:
self.build_succeeded = self._build_using_makefiles( )
return self.build_succeeded
def _generate_makefiles(self):
print ' Generating makefiles: ',
cmd = ['cmake'] + self.desc.cmake_args( ) + [os.path.abspath( self.source_dir )]
succeeded = self._execute_build_subprocess( cmd, self.desc.env(), self.cmake_log_path )
print 'done' if succeeded else 'FAILED'
return succeeded
def _build_using_makefiles(self):
print ' Building:',
cmd = ['cmake', '--build', self.work_dir]
if self.desc.build_type:
cmd += ['--config', self.desc.build_type]
succeeded = self._execute_build_subprocess( cmd, self.desc.env(), self.build_log_path )
print 'done' if succeeded else 'FAILED'
return succeeded
def _execute_build_subprocess(self, cmd, env, log_path):
process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=self.work_dir,
env=env )
stdout, _ = process.communicate( )
succeeded = (process.returncode == 0)
with open( log_path, 'wb' ) as flog:
log = ' '.join( cmd ) + '\n' + stdout + '\nExit code: %r\n' % process.returncode
flog.write( fix_eol( log ) )
return succeeded
def _make_new_work_dir(self):
if os.path.isdir( self.work_dir ):
print ' Removing work directory', self.work_dir
shutil.rmtree( self.work_dir, ignore_errors=True )
if not os.path.isdir( self.work_dir ):
os.makedirs( self.work_dir )
def fix_eol( stdout ):
"""Fixes wrong EOL produced by cmake --build on Windows (\r\r\n instead of \r\n).
"""
return re.sub( '\r*\n', os.linesep, stdout )
def load_build_variants_from_config( config_path ):
with open( config_path, 'rb' ) as fconfig:
data = json.load( fconfig )
variants = data[ 'cmake_variants' ]
build_descs_by_axis = collections.defaultdict( list )
for axis in variants:
axis_name = axis["name"]
build_descs = []
if "generators" in axis:
for generator_data in axis["generators"]:
for generator in generator_data["generator"]:
build_desc = BuildDesc( generator=generator,
prepend_envs=generator_data.get("env_prepend") )
build_descs.append( build_desc )
elif "variables" in axis:
for variables in axis["variables"]:
build_desc = BuildDesc( variables=variables )
build_descs.append( build_desc )
elif "build_types" in axis:
for build_type in axis["build_types"]:
build_desc = BuildDesc( build_type=build_type )
build_descs.append( build_desc )
build_descs_by_axis[axis_name].extend( build_descs )
return build_descs_by_axis
def generate_build_variants( build_descs_by_axis ):
"""Returns a list of BuildDesc generated for the partial BuildDesc for each axis."""
axis_names = build_descs_by_axis.keys()
build_descs = []
for axis_name, axis_build_descs in build_descs_by_axis.items():
if len(build_descs):
# for each existing build_desc and each axis build desc, create a new build_desc
new_build_descs = []
for prototype_build_desc, axis_build_desc in itertools.product( build_descs, axis_build_descs):
new_build_descs.append( prototype_build_desc.merged_with( axis_build_desc ) )
build_descs = new_build_descs
else:
build_descs = axis_build_descs
return build_descs
HTML_TEMPLATE = string.Template('''<html>
<head>
<title>$title</title>
<style type="text/css">
td.failed {background-color:#f08080;}
td.ok {background-color:#c0eec0;}
</style>
</head>
<body>
<table border="1">
<thead>
<tr>
<th>Variables</th>
$th_vars
</tr>
<tr>
<th>Build type</th>
$th_build_types
</tr>
</thead>
<tbody>
$tr_builds
</tbody>
</table>
</body></html>''')
def generate_html_report( html_report_path, builds ):
report_dir = os.path.dirname( html_report_path )
# Vertical axis: generator
# Horizontal: variables, then build_type
builds_by_generator = collections.defaultdict( list )
variables = set()
build_types_by_variable = collections.defaultdict( set )
build_by_pos_key = {} # { (generator, var_key, build_type): build }
for build in builds:
builds_by_generator[build.desc.generator].append( build )
var_key = tuple(sorted(build.desc.variables))
variables.add( var_key )
build_types_by_variable[var_key].add( build.desc.build_type )
pos_key = (build.desc.generator, var_key, build.desc.build_type)
build_by_pos_key[pos_key] = build
variables = sorted( variables )
th_vars = []
th_build_types = []
for variable in variables:
build_types = sorted( build_types_by_variable[variable] )
nb_build_type = len(build_types_by_variable[variable])
th_vars.append( '<th colspan="%d">%s</th>' % (nb_build_type, cgi.escape( ' '.join( variable ) ) ) )
for build_type in build_types:
th_build_types.append( '<th>%s</th>' % cgi.escape(build_type) )
tr_builds = []
for generator in sorted( builds_by_generator ):
tds = [ '<td>%s</td>\n' % cgi.escape( generator ) ]
for variable in variables:
build_types = sorted( build_types_by_variable[variable] )
for build_type in build_types:
pos_key = (generator, variable, build_type)
build = build_by_pos_key.get(pos_key)
if build:
cmake_status = 'ok' if build.cmake_succeeded else 'FAILED'
build_status = 'ok' if build.build_succeeded else 'FAILED'
cmake_log_url = os.path.relpath( build.cmake_log_path, report_dir )
build_log_url = os.path.relpath( build.build_log_path, report_dir )
td = '<td class="%s"><a href="%s" class="%s">CMake: %s</a>' % (
build_status.lower(), cmake_log_url, cmake_status.lower(), cmake_status)
if build.cmake_succeeded:
td += '<br><a href="%s" class="%s">Build: %s</a>' % (
build_log_url, build_status.lower(), build_status)
td += '</td>'
else:
td = '<td></td>'
tds.append( td )
tr_builds.append( '<tr>%s</tr>' % '\n'.join( tds ) )
html = HTML_TEMPLATE.substitute(
title='Batch build report',
th_vars=' '.join(th_vars),
th_build_types=' '.join( th_build_types),
tr_builds='\n'.join( tr_builds ) )
with open( html_report_path, 'wt' ) as fhtml:
fhtml.write( html )
print 'HTML report generated in:', html_report_path
def main():
usage = r"""%prog WORK_DIR SOURCE_DIR CONFIG_JSON_PATH [CONFIG2_JSON_PATH...]
Build a given CMake based project located in SOURCE_DIR with multiple generators/options.dry_run
as described in CONFIG_JSON_PATH building in WORK_DIR.
Example of call:
python devtools\batchbuild.py e:\buildbots\jsoncpp\build . devtools\agent_vmw7.json
"""
from optparse import OptionParser
parser = OptionParser(usage=usage)
parser.allow_interspersed_args = True
# parser.add_option('-v', '--verbose', dest="verbose", action='store_true',
# help="""Be verbose.""")
parser.enable_interspersed_args()
options, args = parser.parse_args()
if len(args) < 3:
parser.error( "Missing one of WORK_DIR SOURCE_DIR CONFIG_JSON_PATH." )
work_dir = args[0]
source_dir = args[1].rstrip('/\\')
config_paths = args[2:]
for config_path in config_paths:
if not os.path.isfile( config_path ):
parser.error( "Can not read: %r" % config_path )
# generate build variants
build_descs = []
for config_path in config_paths:
build_descs_by_axis = load_build_variants_from_config( config_path )
build_descs.extend( generate_build_variants( build_descs_by_axis ) )
print 'Build variants (%d):' % len(build_descs)
# assign build directory for each variant
if not os.path.isdir( work_dir ):
os.makedirs( work_dir )
builds = []
with open( os.path.join( work_dir, 'matrix-dir-map.txt' ), 'wt' ) as fmatrixmap:
for index, build_desc in enumerate( build_descs ):
build_desc_work_dir = os.path.join( work_dir, '%03d' % (index+1) )
builds.append( BuildData( build_desc, build_desc_work_dir, source_dir ) )
fmatrixmap.write( '%s: %s\n' % (build_desc_work_dir, build_desc) )
for build in builds:
build.execute_build()
html_report_path = os.path.join( work_dir, 'batchbuild-report.html' )
generate_html_report( html_report_path, builds )
print 'Done'
if __name__ == '__main__':
main()

View File

@@ -1,63 +1,63 @@
import os.path
def fix_source_eol( path, is_dry_run = True, verbose = True, eol = '\n' ):
"""Makes sure that all sources have the specified eol sequence (default: unix)."""
if not os.path.isfile( path ):
raise ValueError( 'Path "%s" is not a file' % path )
try:
f = open(path, 'rb')
except IOError, msg:
print >> sys.stderr, "%s: I/O Error: %s" % (file, str(msg))
return False
try:
raw_lines = f.readlines()
finally:
f.close()
fixed_lines = [line.rstrip('\r\n') + eol for line in raw_lines]
if raw_lines != fixed_lines:
print '%s =>' % path,
if not is_dry_run:
f = open(path, "wb")
try:
f.writelines(fixed_lines)
finally:
f.close()
if verbose:
print is_dry_run and ' NEED FIX' or ' FIXED'
return True
##
##
##
##def _do_fix( is_dry_run = True ):
## from waftools import antglob
## python_sources = antglob.glob( '.',
## includes = '**/*.py **/wscript **/wscript_build',
## excludes = antglob.default_excludes + './waf.py',
## prune_dirs = antglob.prune_dirs + 'waf-* ./build' )
## for path in python_sources:
## _fix_python_source( path, is_dry_run )
##
## cpp_sources = antglob.glob( '.',
## includes = '**/*.cpp **/*.h **/*.inl',
## prune_dirs = antglob.prune_dirs + 'waf-* ./build' )
## for path in cpp_sources:
## _fix_source_eol( path, is_dry_run )
##
##
##def dry_fix(context):
## _do_fix( is_dry_run = True )
##
##def fix(context):
## _do_fix( is_dry_run = False )
##
##def shutdown():
## pass
##
##def check(context):
## # Unit tests are run when "check" target is used
## ut = UnitTest.unit_test()
## ut.change_to_testfile_dir = True
## ut.want_to_see_test_output = True
## ut.want_to_see_test_error = True
## ut.run()
## ut.print_results()
import os.path
def fix_source_eol( path, is_dry_run = True, verbose = True, eol = '\n' ):
"""Makes sure that all sources have the specified eol sequence (default: unix)."""
if not os.path.isfile( path ):
raise ValueError( 'Path "%s" is not a file' % path )
try:
f = open(path, 'rb')
except IOError, msg:
print >> sys.stderr, "%s: I/O Error: %s" % (file, str(msg))
return False
try:
raw_lines = f.readlines()
finally:
f.close()
fixed_lines = [line.rstrip('\r\n') + eol for line in raw_lines]
if raw_lines != fixed_lines:
print '%s =>' % path,
if not is_dry_run:
f = open(path, "wb")
try:
f.writelines(fixed_lines)
finally:
f.close()
if verbose:
print is_dry_run and ' NEED FIX' or ' FIXED'
return True
##
##
##
##def _do_fix( is_dry_run = True ):
## from waftools import antglob
## python_sources = antglob.glob( '.',
## includes = '**/*.py **/wscript **/wscript_build',
## excludes = antglob.default_excludes + './waf.py',
## prune_dirs = antglob.prune_dirs + 'waf-* ./build' )
## for path in python_sources:
## _fix_python_source( path, is_dry_run )
##
## cpp_sources = antglob.glob( '.',
## includes = '**/*.cpp **/*.h **/*.inl',
## prune_dirs = antglob.prune_dirs + 'waf-* ./build' )
## for path in cpp_sources:
## _fix_source_eol( path, is_dry_run )
##
##
##def dry_fix(context):
## _do_fix( is_dry_run = True )
##
##def fix(context):
## _do_fix( is_dry_run = False )
##
##def shutdown():
## pass
##
##def check(context):
## # Unit tests are run when "check" target is used
## ut = UnitTest.unit_test()
## ut.change_to_testfile_dir = True
## ut.want_to_see_test_output = True
## ut.want_to_see_test_error = True
## ut.run()
## ut.print_results()

View File

@@ -1,93 +0,0 @@
"""Updates the license text in source file.
"""
# An existing license is found if the file starts with the string below,
# and ends with the first blank line.
LICENSE_BEGIN = "// Copyright "
BRIEF_LICENSE = LICENSE_BEGIN + """2007-2010 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
""".replace('\r\n','\n')
def update_license( path, dry_run, show_diff ):
"""Update the license statement in the specified file.
Parameters:
path: path of the C++ source file to update.
dry_run: if True, just print the path of the file that would be updated,
but don't change it.
show_diff: if True, print the path of the file that would be modified,
as well as the change made to the file.
"""
with open( path, 'rt' ) as fin:
original_text = fin.read().replace('\r\n','\n')
newline = fin.newlines and fin.newlines[0] or '\n'
if not original_text.startswith( LICENSE_BEGIN ):
# No existing license found => prepend it
new_text = BRIEF_LICENSE + original_text
else:
license_end_index = original_text.index( '\n\n' ) # search first blank line
new_text = BRIEF_LICENSE + original_text[license_end_index+2:]
if original_text != new_text:
if not dry_run:
with open( path, 'wb' ) as fout:
fout.write( new_text.replace('\n', newline ) )
print 'Updated', path
if show_diff:
import difflib
print '\n'.join( difflib.unified_diff( original_text.split('\n'),
new_text.split('\n') ) )
return True
return False
def update_license_in_source_directories( source_dirs, dry_run, show_diff ):
"""Updates license text in C++ source files found in directory source_dirs.
Parameters:
source_dirs: list of directory to scan for C++ sources. Directories are
scanned recursively.
dry_run: if True, just print the path of the file that would be updated,
but don't change it.
show_diff: if True, print the path of the file that would be modified,
as well as the change made to the file.
"""
from devtools import antglob
prune_dirs = antglob.prune_dirs + 'scons-local* ./build* ./libs ./dist'
for source_dir in source_dirs:
cpp_sources = antglob.glob( source_dir,
includes = '''**/*.h **/*.cpp **/*.inl''',
prune_dirs = prune_dirs )
for source in cpp_sources:
update_license( source, dry_run, show_diff )
def main():
usage = """%prog DIR [DIR2...]
Updates license text in sources of the project in source files found
in the directory specified on the command-line.
Example of call:
python devtools\licenseupdater.py include src -n --diff
=> Show change that would be made to the sources.
python devtools\licenseupdater.py include src
=> Update license statement on all sources in directories include/ and src/.
"""
from optparse import OptionParser
parser = OptionParser(usage=usage)
parser.allow_interspersed_args = False
parser.add_option('-n', '--dry-run', dest="dry_run", action='store_true', default=False,
help="""Only show what files are updated, do not update the files""")
parser.add_option('--diff', dest="show_diff", action='store_true', default=False,
help="""On update, show change made to the file.""")
parser.enable_interspersed_args()
options, args = parser.parse_args()
update_license_in_source_directories( args, options.dry_run, options.show_diff )
print 'Done'
if __name__ == '__main__':
import sys
import os.path
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
main()

View File

@@ -1,53 +1,53 @@
import os.path
import gzip
import tarfile
TARGZ_DEFAULT_COMPRESSION_LEVEL = 9
def make_tarball(tarball_path, sources, base_dir, prefix_dir=''):
"""Parameters:
tarball_path: output path of the .tar.gz file
sources: list of sources to include in the tarball, relative to the current directory
base_dir: if a source file is in a sub-directory of base_dir, then base_dir is stripped
from path in the tarball.
prefix_dir: all files stored in the tarball be sub-directory of prefix_dir. Set to ''
to make them child of root.
"""
base_dir = os.path.normpath( os.path.abspath( base_dir ) )
def archive_name( path ):
"""Makes path relative to base_dir."""
path = os.path.normpath( os.path.abspath( path ) )
common_path = os.path.commonprefix( (base_dir, path) )
archive_name = path[len(common_path):]
if os.path.isabs( archive_name ):
archive_name = archive_name[1:]
return os.path.join( prefix_dir, archive_name )
def visit(tar, dirname, names):
for name in names:
path = os.path.join(dirname, name)
if os.path.isfile(path):
path_in_tar = archive_name(path)
tar.add(path, path_in_tar )
compression = TARGZ_DEFAULT_COMPRESSION_LEVEL
tar = tarfile.TarFile.gzopen( tarball_path, 'w', compresslevel=compression )
try:
for source in sources:
source_path = source
if os.path.isdir( source ):
os.path.walk(source_path, visit, tar)
else:
path_in_tar = archive_name(source_path)
tar.add(source_path, path_in_tar ) # filename, arcname
finally:
tar.close()
def decompress( tarball_path, base_dir ):
"""Decompress the gzipped tarball into directory base_dir.
"""
# !!! This class method is not documented in the online doc
# nor is bz2open!
tar = tarfile.TarFile.gzopen(tarball_path, mode='r')
try:
tar.extractall( base_dir )
finally:
tar.close()
import os.path
import gzip
import tarfile
TARGZ_DEFAULT_COMPRESSION_LEVEL = 9
def make_tarball(tarball_path, sources, base_dir, prefix_dir=''):
"""Parameters:
tarball_path: output path of the .tar.gz file
sources: list of sources to include in the tarball, relative to the current directory
base_dir: if a source file is in a sub-directory of base_dir, then base_dir is stripped
from path in the tarball.
prefix_dir: all files stored in the tarball be sub-directory of prefix_dir. Set to ''
to make them child of root.
"""
base_dir = os.path.normpath( os.path.abspath( base_dir ) )
def archive_name( path ):
"""Makes path relative to base_dir."""
path = os.path.normpath( os.path.abspath( path ) )
common_path = os.path.commonprefix( (base_dir, path) )
archive_name = path[len(common_path):]
if os.path.isabs( archive_name ):
archive_name = archive_name[1:]
return os.path.join( prefix_dir, archive_name )
def visit(tar, dirname, names):
for name in names:
path = os.path.join(dirname, name)
if os.path.isfile(path):
path_in_tar = archive_name(path)
tar.add(path, path_in_tar )
compression = TARGZ_DEFAULT_COMPRESSION_LEVEL
tar = tarfile.TarFile.gzopen( tarball_path, 'w', compresslevel=compression )
try:
for source in sources:
source_path = source
if os.path.isdir( source ):
os.path.walk(source_path, visit, tar)
else:
path_in_tar = archive_name(source_path)
tar.add(source_path, path_in_tar ) # filename, arcname
finally:
tar.close()
def decompress( tarball_path, base_dir ):
"""Decompress the gzipped tarball into directory base_dir.
"""
# !!! This class method is not documented in the online doc
# nor is bz2open!
tar = tarfile.TarFile.gzopen(tarball_path, mode='r')
try:
tar.extractall( base_dir )
finally:
tar.close()

View File

@@ -11,7 +11,7 @@ JsonCpp - JSON data format manipulation library
<table width="100%">
<tr>
<td width="40%" align="left" valign="center">
<a href="http://sourceforge.net/projects/jsoncpp/">
<a href="http://sourceforge.net/projects/jsoncpp">
JsonCpp project page
</a>
</td>

View File

@@ -22,7 +22,7 @@ Here is an example of JSON data:
],
// Tab indent size
"indent" : { "length" : 3, "use_space": true }
"indent" : { "length" : 3, "use_space" = true }
}
\endverbatim
@@ -46,7 +46,7 @@ if ( !parsingSuccessful )
{
// report to the user the failure and their locations in the document.
std::cout << "Failed to parse configuration\n"
<< reader.getFormattedErrorMessages();
<< reader.getFormatedErrorMessages();
return;
}
@@ -82,12 +82,12 @@ std::cin >> root["subtree"];
std::cout << root;
\endcode
\section _pbuild Build instructions
\section _plinks Build instructions
The build instructions are located in the file
<a HREF="README.txt">README.txt</a> in the top-directory of the project.
Permanent link to the latest revision of the file in subversion:
<a HREF="http://jsoncpp.svn.sourceforge.net/viewvc/jsoncpp/trunk/jsoncpp/README.txt?view=markup">latest README.txt</a>
<a HREF="http://svn.sourceforge.net/viewcvs.cgi/jsoncpp/README.txt?view=markup">latest README.txt</a>
\section _pdownload Download
The sources can be downloaded from
@@ -100,16 +100,9 @@ http://jsoncpp.svn.sourceforge.net/svnroot/jsoncpp/trunk/</a>
To checkout the source, see the following
<a HREF="http://sourceforge.net/scm/?type=svn&group_id=144446">instructions</a>.
\section _news What's New?
The description of latest changes can be found in
<a HREF="NEWS.txt">NEWS.txt</a> in the top-directory of the project.
Permanent link to the latest revision of the file in subversion:
<a HREF="http://svn.sourceforge.net/viewcvs.cgi/jsoncpp/README.txt?view=markup">latest NEWS.txt</a>
\section _plinks Project links
- <a HREF="http://jsoncpp.sourceforge.net">json-cpp home</a>
- <a HREF="http://www.sourceforge.net/projects/jsoncpp/">json-cpp sourceforge project</a>
- <a HREF="http://www.sourceforge.net/projects/jsoncpp">json-cpp sourceforge project</a>
\section _rlinks Related links
- <a HREF="http://www.json.org/">JSON</a> Specification and alternate language implementations.
@@ -117,10 +110,7 @@ Permanent link to the latest revision of the file in subversion:
- <a HREF="http://www.cl.cam.ac.uk/~mgk25/unicode.html">UTF-8 and Unicode FAQ</a>.
\section _license License
See file <a HREF="LICENSE">LICENSE</a> in the top-directory of the project.
Basically JsonCpp is licensed under MIT license, or public domain if desired
and recognized in your jurisdiction.
The json-cpp library and this documentation are in Public Domain.
\author Baptiste Lepilleur <blep@users.sourceforge.net>
*/

View File

@@ -2,7 +2,6 @@
\section ms_release Makes JsonCpp ready for release
- Build system clean-up:
- Fix build on Windows (shared-library build is broken)
- Compile and run tests using shared library on Windows to ensure no JSON_API macro is missing.
- Add enable/disable flag for static and shared library build
- Enhance help
- Platform portability check: (Notes: was ok on last check)
@@ -12,27 +11,22 @@
- aix/vacpp
- Add JsonCpp version to header as numeric for use in preprocessor test
- Remove buggy experimental hash stuff
- Release on sourceforge download
\section ms_strict Adds a strict mode to reader/parser
Strict JSON support as specific in RFC 4627 (http://www.ietf.org/rfc/rfc4627.txt?number=4627).
- Enforce only object or array as root element
- Disable comment support
- Get jsonchecker failing tests to pass in strict mode
\section ms_writer Writter control
Provides more control to determine how specific items are serialized when JSON allow choice:
- Optionally allow escaping of non-ASCII characters using unicode escape sequence "\\u".
- Optionally allow escaping of "/" using "\/".
\section ms_separation Expose json reader/writer API that do not impose using Json::Value.
Some typical use-case involve an application specific structure to/from a JSON document.
- Event base parser to allow unserializing a Json document directly in datastructure instead of
using the intermediate Json::Value.
- Stream based parser to serialized a Json document without using Json::Value as input.
- "Stream" based parser to serialized a Json document without using Json::Value as input.
- Performance oriented parser/writer:
- Provides an event based parser. Should allow pulling & skipping events for ease of use.
- Provides a JSON document builder: fast only.
\section ms_perfo Performance tuning
- Provides support for static property name definition avoiding allocation
- Provides support for static property name definition avoiding allocation
- Static property dictionnary can be provided to JSON reader
- Performance scenario & benchmarking
\section testing Testing
- Adds more tests for unicode parsing (e.g. including surrogate and error detection).
*/

View File

@@ -127,8 +127,6 @@ def build_doc( options, make_release=False ):
tarball_sources = [
output_dir,
'README.txt',
'LICENSE',
'NEWS.txt',
'version'
]
tarball_basedir = os.path.join( output_dir, html_output_dirname )

View File

@@ -1,2 +0,0 @@
FILE(GLOB INCLUDE_FILES "json/*.h")
INSTALL(FILES ${INCLUDE_FILES} DESTINATION include/json)

View File

@@ -1,32 +0,0 @@
// Copyright 2007-2010 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED
# define CPPTL_JSON_ASSERTIONS_H_INCLUDED
#include <stdlib.h>
#if !defined(JSON_IS_AMALGAMATION)
# include <json/config.h>
#endif // if !defined(JSON_IS_AMALGAMATION)
#if JSON_USE_EXCEPTION
# include <stdexcept>
#define JSON_ASSERT( condition ) assert( condition ); // @todo <= change this into an exception throw
#define JSON_FAIL_MESSAGE( message ) throw std::runtime_error( message );
#else // JSON_USE_EXCEPTION
#define JSON_ASSERT( condition ) assert( condition );
// The call to assert() will show the failure message in debug builds. In
// release bugs we write to invalid memory in order to crash hard, so that a
// debugger or crash reporter gets the chance to take over. We still call exit()
// afterward in order to tell the compiler that this macro doesn't return.
#define JSON_FAIL_MESSAGE( message ) { assert(false && message); strcpy(reinterpret_cast<char*>(666), message); exit(123); }
#endif
#define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) { JSON_FAIL_MESSAGE( message ) }
#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED

View File

@@ -1,8 +1,3 @@
// Copyright 2007-2010 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSON_AUTOLINK_H_INCLUDED
# define JSON_AUTOLINK_H_INCLUDED

View File

@@ -1,8 +1,3 @@
// Copyright 2007-2010 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSON_CONFIG_H_INCLUDED
# define JSON_CONFIG_H_INCLUDED
@@ -16,7 +11,7 @@
//# define JSON_USE_CPPTL_SMALLMAP 1
/// If defined, indicates that Json specific container should be used
/// (hash table & simple deque container with customizable allocator).
/// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332
/// THIS FEATURE IS STILL EXPERIMENTAL!
//# define JSON_VALUE_USE_INTERNAL_MAP 1
/// Force usage of standard new/malloc based allocator instead of memory pool based allocator.
/// The memory pools allocator used optimization (initializing Value and ValueInternalLink
@@ -24,17 +19,9 @@
/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined.
//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1
// If non-zero, the library uses exceptions to report bad input instead of C
// assertion macros. The default is to use exceptions.
# ifndef JSON_USE_EXCEPTION
/// If defined, indicates that Json use exception to report invalid type manipulation
/// instead of C assert macro.
# define JSON_USE_EXCEPTION 1
# endif
/// If defined, indicates that the source file is amalgated
/// to prevent private header inclusion.
/// Remarks: it is automatically defined in the generated amalgated header.
// #define JSON_IS_AMALGAMATION
# ifdef JSON_IN_CPPTL
# include <cpptl/config.h>
@@ -46,63 +33,11 @@
# ifdef JSON_IN_CPPTL
# define JSON_API CPPTL_API
# elif defined(JSON_DLL_BUILD)
# if defined(_MSC_VER)
# define JSON_API __declspec(dllexport)
# define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
# endif // if defined(_MSC_VER)
# define JSON_API __declspec(dllexport)
# elif defined(JSON_DLL)
# if defined(_MSC_VER)
# define JSON_API __declspec(dllimport)
# define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
# endif // if defined(_MSC_VER)
# endif // ifdef JSON_IN_CPPTL
# if !defined(JSON_API)
# define JSON_API __declspec(dllimport)
# else
# define JSON_API
# endif
// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for integer
// Storages, and 64 bits integer support is disabled.
// #define JSON_NO_INT64 1
#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6
// Microsoft Visual Studio 6 only support conversion from __int64 to double
// (no conversion from unsigned __int64).
#define JSON_USE_INT64_DOUBLE_CONVERSION 1
// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' characters in the debug information)
// All projects I've ever seen with VS6 were using this globally (not bothering with pragma push/pop).
#pragma warning(disable : 4786)
#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6
#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008
/// Indicates that the following function is deprecated.
# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
#endif
#if !defined(JSONCPP_DEPRECATED)
# define JSONCPP_DEPRECATED(message)
#endif // if !defined(JSONCPP_DEPRECATED)
namespace Json {
typedef int Int;
typedef unsigned int UInt;
# if defined(JSON_NO_INT64)
typedef int LargestInt;
typedef unsigned int LargestUInt;
# undef JSON_HAS_INT64
# else // if defined(JSON_NO_INT64)
// For Microsoft Visual use specific types as long long is not supported
# if defined(_MSC_VER) // Microsoft Visual Studio
typedef __int64 Int64;
typedef unsigned __int64 UInt64;
# else // if defined(_MSC_VER) // Other platforms, use long long
typedef long long int Int64;
typedef unsigned long long int UInt64;
# endif // if defined(_MSC_VER)
typedef Int64 LargestInt;
typedef UInt64 LargestUInt;
# define JSON_HAS_INT64
# endif // if defined(JSON_NO_INT64)
} // end namespace Json
#endif // JSON_CONFIG_H_INCLUDED

View File

@@ -1,55 +1,42 @@
// Copyright 2007-2010 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
# define CPPTL_JSON_FEATURES_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION)
# include "forwards.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
namespace Json {
/** \brief Configuration passed to reader and writer.
* This configuration object can be used to force the Reader or Writer
* to behave in a standard conforming way.
*/
class JSON_API Features
{
public:
/** \brief A configuration that allows all features and assumes all strings are UTF-8.
* - C & C++ comments are allowed
* - Root object can be any JSON value
* - Assumes Value strings are encoded in UTF-8
*/
static Features all();
/** \brief A configuration that is strictly compatible with the JSON specification.
* - Comments are forbidden.
* - Root object must be either an array or an object value.
* - Assumes Value strings are encoded in UTF-8
*/
static Features strictMode();
/** \brief Initialize the configuration like JsonConfig::allFeatures;
*/
Features();
/// \c true if comments are allowed. Default: \c true.
bool allowComments_;
/// \c true if root must be either an array or an object value. Default: \c false.
bool strictRoot_;
/// \c true if dropped null placeholders are allowed. Default: \c false.
bool allowDroppedNullPlaceholders_;
/// \c true if numeric object key are allowed. Default: \c false.
bool allowNumericKeys_;
};
} // namespace Json
#endif // CPPTL_JSON_FEATURES_H_INCLUDED
#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
# define CPPTL_JSON_FEATURES_H_INCLUDED
# include "forwards.h"
namespace Json {
/** \brief Configuration passed to reader and writer.
* This configuration object can be used to force the Reader or Writer
* to behave in a standard conforming way.
*/
class JSON_API Features
{
public:
/** \brief A configuration that allows all features and assumes all strings are UTF-8.
* - C & C++ comments are allowed
* - Root object can be any JSON value
* - Assumes Value strings are encoded in UTF-8
*/
static Features all();
/** \brief A configuration that is strictly compatible with the JSON specification.
* - Comments are forbidden.
* - Root object must be either an array or an object value.
* - Assumes Value strings are encoded in UTF-8
*/
static Features strictMode();
/** \brief Initialize the configuration like JsonConfig::allFeatures;
*/
Features();
/// \c true if comments are allowed. Default: \c true.
bool allowComments_;
/// \c true if root must be either an array or an object value. Default: \c false.
bool strictRoot_;
};
} // namespace Json
#endif // CPPTL_JSON_FEATURES_H_INCLUDED

View File

@@ -1,14 +1,7 @@
// Copyright 2007-2010 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSON_FORWARDS_H_INCLUDED
# define JSON_FORWARDS_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION)
# include "config.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
namespace Json {
@@ -23,7 +16,8 @@ namespace Json {
class Features;
// value.h
typedef unsigned int ArrayIndex;
typedef int Int;
typedef unsigned int UInt;
class StaticString;
class Path;
class PathArgument;
@@ -32,6 +26,7 @@ namespace Json {
class ValueIterator;
class ValueConstIterator;
#ifdef JSON_VALUE_USE_INTERNAL_MAP
class ValueAllocator;
class ValueMapAllocator;
class ValueInternalLink;
class ValueInternalArray;

View File

@@ -1,8 +1,3 @@
// Copyright 2007-2010 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSON_JSON_H_INCLUDED
# define JSON_JSON_H_INCLUDED

View File

@@ -1,26 +1,12 @@
// Copyright 2007-2010 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef CPPTL_JSON_READER_H_INCLUDED
# define CPPTL_JSON_READER_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION)
# include "features.h"
# include "value.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
# include <deque>
# include <iosfwd>
# include <stack>
# include <string>
// Disable warning C4251: <data member>: <type> needs to have dll-interface to be used by...
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
# pragma warning(push)
# pragma warning(disable:4251)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
# include <iostream>
namespace Json {
@@ -33,19 +19,6 @@ namespace Json {
typedef char Char;
typedef const Char *Location;
/** \brief An error tagged with where in the JSON text it was encountered.
*
* The offsets give the [start, limit) range of bytes within the text. Note
* that this is bytes, not codepoints.
*
*/
struct StructuredError
{
size_t offset_start;
size_t offset_limit;
std::string message;
};
/** \brief Constructs a Reader allowing all features
* for parsing.
*/
@@ -71,9 +44,7 @@ namespace Json {
bool collectComments = true );
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
* \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the document to read.
* \param endDoc Pointer on the end of the UTF-8 encoded string of the document to read.
\ Must be >= beginDoc.
* \param document UTF-8 encoded string containing the document to read.
* \param root [out] Contains the root value of the document if it was
* successfully parsed.
* \param collectComments \c true to collect comment and allow writing them back during
@@ -96,26 +67,9 @@ namespace Json {
* \return Formatted error message with the list of errors with their location in
* the parsed document. An empty string is returned if no error occurred
* during parsing.
* \deprecated Use getFormattedErrorMessages() instead (typo fix).
*/
JSONCPP_DEPRECATED("Use getFormattedErrorMessages instead")
std::string getFormatedErrorMessages() const;
/** \brief Returns a user friendly string that list errors in the parsed document.
* \return Formatted error message with the list of errors with their location in
* the parsed document. An empty string is returned if no error occurred
* during parsing.
*/
std::string getFormattedErrorMessages() const;
/** \brief Returns a vector of structured erros encounted while parsing.
* \return A (possibly empty) vector of StructuredError objects. Currently
* only one error can be returned, but the caller should tolerate multiple
* errors. This can occur if the parser recovers from a non-fatal
* parse error and then encounters additional errors.
*/
std::vector<StructuredError> getStructuredErrors() const;
private:
enum TokenType
{
@@ -167,11 +121,9 @@ namespace Json {
bool readObject( Token &token );
bool readArray( Token &token );
bool decodeNumber( Token &token );
bool decodeNumber( Token &token, Value &decoded );
bool decodeString( Token &token );
bool decodeString( Token &token, std::string &decoded );
bool decodeDouble( Token &token );
bool decodeDouble( Token &token, Value &decoded );
bool decodeUnicodeCodePoint( Token &token,
Location &current,
Location end,
@@ -227,23 +179,18 @@ namespace Json {
Result:
\verbatim
{
"dir": {
"file": {
// The input stream JSON would be nested here.
}
}
"dir": {
"file": {
// The input stream JSON would be nested here.
}
}
}
\endverbatim
\throw std::exception on parse error.
\see Json::operator<<()
*/
JSON_API std::istream& operator>>( std::istream&, Value& );
std::istream& operator>>( std::istream&, Value& );
} // namespace Json
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
# pragma warning(pop)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#endif // CPPTL_JSON_READER_H_INCLUDED

View File

@@ -1,14 +1,7 @@
// Copyright 2007-2010 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef CPPTL_JSON_H_INCLUDED
# define CPPTL_JSON_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION)
# include "forwards.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
# include <string>
# include <vector>
@@ -21,13 +14,6 @@
# include <cpptl/forwards.h>
# endif
// Disable warning C4251: <data member>: <type> needs to have dll-interface to be used by...
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
# pragma warning(push)
# pragma warning(disable:4251)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
/** \brief JSON (JavaScript Object Notation).
*/
namespace Json {
@@ -135,38 +121,13 @@ namespace Json {
typedef ValueConstIterator const_iterator;
typedef Json::UInt UInt;
typedef Json::Int Int;
# if defined(JSON_HAS_INT64)
typedef Json::UInt64 UInt64;
typedef Json::Int64 Int64;
#endif // defined(JSON_HAS_INT64)
typedef Json::LargestInt LargestInt;
typedef Json::LargestUInt LargestUInt;
typedef Json::ArrayIndex ArrayIndex;
typedef UInt ArrayIndex;
static const Value null;
/// Minimum signed integer value that can be stored in a Json::Value.
static const LargestInt minLargestInt;
/// Maximum signed integer value that can be stored in a Json::Value.
static const LargestInt maxLargestInt;
/// Maximum unsigned integer value that can be stored in a Json::Value.
static const LargestUInt maxLargestUInt;
/// Minimum signed int value that can be stored in a Json::Value.
static const Int minInt;
/// Maximum signed int value that can be stored in a Json::Value.
static const Int maxInt;
/// Maximum unsigned int value that can be stored in a Json::Value.
static const UInt maxUInt;
# if defined(JSON_HAS_INT64)
/// Minimum signed 64 bits int value that can be stored in a Json::Value.
static const Int64 minInt64;
/// Maximum signed 64 bits int value that can be stored in a Json::Value.
static const Int64 maxInt64;
/// Maximum unsigned 64 bits int value that can be stored in a Json::Value.
static const UInt64 maxUInt64;
#endif // defined(JSON_HAS_INT64)
private:
#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
# ifndef JSON_VALUE_USE_INTERNAL_MAP
@@ -179,20 +140,20 @@ namespace Json {
duplicate,
duplicateOnCopy
};
CZString( ArrayIndex index );
CZString( int index );
CZString( const char *cstr, DuplicationPolicy allocate );
CZString( const CZString &other );
~CZString();
CZString &operator =( const CZString &other );
bool operator<( const CZString &other ) const;
bool operator==( const CZString &other ) const;
ArrayIndex index() const;
int index() const;
const char *c_str() const;
bool isStaticString() const;
private:
void swap( CZString &other );
const char *cstr_;
ArrayIndex index_;
int index_;
};
public:
@@ -211,22 +172,18 @@ namespace Json {
To create an empty array, pass arrayValue.
To create an empty object, pass objectValue.
Another Value can then be set to this one by assignment.
This is useful since clear() and resize() will not alter types.
This is useful since clear() and resize() will not alter types.
Examples:
\code
Json::Value null_value; // null
Json::Value arr_value(Json::arrayValue); // []
Json::Value obj_value(Json::objectValue); // {}
\endcode
\code
Json::Value null_value; // null
Json::Value arr_value(Json::arrayValue); // []
Json::Value obj_value(Json::objectValue); // {}
\endcode
*/
Value( ValueType type = nullValue );
Value( Int value );
Value( UInt value );
#if defined(JSON_HAS_INT64)
Value( Int64 value );
Value( UInt64 value );
#endif // if defined(JSON_HAS_INT64)
Value( double value );
Value( const char *value );
Value( const char *beginValue, const char *endValue );
@@ -265,7 +222,7 @@ namespace Json {
bool operator ==( const Value &other ) const;
bool operator !=( const Value &other ) const;
int compare( const Value &other ) const;
int compare( const Value &other );
const char *asCString() const;
std::string asString() const;
@@ -274,22 +231,13 @@ namespace Json {
# endif
Int asInt() const;
UInt asUInt() const;
#if defined(JSON_HAS_INT64)
Int64 asInt64() const;
UInt64 asUInt64() const;
#endif // if defined(JSON_HAS_INT64)
LargestInt asLargestInt() const;
LargestUInt asLargestUInt() const;
float asFloat() const;
double asDouble() const;
bool asBool() const;
bool isNull() const;
bool isBool() const;
bool isInt() const;
bool isInt64() const;
bool isUInt() const;
bool isUInt64() const;
bool isIntegral() const;
bool isDouble() const;
bool isNumeric() const;
@@ -300,7 +248,7 @@ namespace Json {
bool isConvertibleTo( ValueType other ) const;
/// Number of values in array or object
ArrayIndex size() const;
UInt size() const;
/// \brief Return true if empty array, empty object, or null;
/// otherwise, false.
@@ -319,38 +267,24 @@ namespace Json {
/// May only be called on nullValue or arrayValue.
/// \pre type() is arrayValue or nullValue
/// \post type() is arrayValue
void resize( ArrayIndex size );
void resize( UInt size );
/// Access an array element (zero based index ).
/// If the array contains less than index element, then null value are inserted
/// in the array so that its size is index+1.
/// (You may need to say 'value[0u]' to get your compiler to distinguish
/// this from the operator[] which takes a string.)
Value &operator[]( ArrayIndex index );
/// Access an array element (zero based index ).
/// If the array contains less than index element, then null value are inserted
/// in the array so that its size is index+1.
/// (You may need to say 'value[0u]' to get your compiler to distinguish
/// this from the operator[] which takes a string.)
Value &operator[]( int index );
Value &operator[]( UInt index );
/// Access an array element (zero based index )
/// (You may need to say 'value[0u]' to get your compiler to distinguish
/// this from the operator[] which takes a string.)
const Value &operator[]( ArrayIndex index ) const;
/// Access an array element (zero based index )
/// (You may need to say 'value[0u]' to get your compiler to distinguish
/// this from the operator[] which takes a string.)
const Value &operator[]( int index ) const;
const Value &operator[]( UInt index ) const;
/// If the array contains at least index+1 elements, returns the element value,
/// otherwise returns defaultValue.
Value get( ArrayIndex index,
Value get( UInt index,
const Value &defaultValue ) const;
/// Return true if index < size().
bool isValidIndex( ArrayIndex index ) const;
bool isValidIndex( UInt index ) const;
/// \brief Append value to array at the end.
///
/// Equivalent to jsonvalue[jsonvalue.size()] = value;
@@ -442,13 +376,6 @@ namespace Json {
iterator begin();
iterator end();
// Accessors for the [start, limit) range of bytes within the JSON text from
// which this value was parsed, if any.
void setOffsetStart( size_t start );
void setOffsetLimit( size_t limit );
size_t getOffsetStart() const;
size_t getOffsetLimit() const;
private:
Value &resolveReference( const char *key,
bool isStatic );
@@ -497,8 +424,8 @@ namespace Json {
union ValueHolder
{
LargestInt int_;
LargestUInt uint_;
Int int_;
UInt uint_;
double real_;
bool bool_;
char *string_;
@@ -516,23 +443,18 @@ namespace Json {
int memberNameIsStatic_ : 1; // used by the ValueInternalMap container.
# endif
CommentInfo *comments_;
// [start, limit) byte offsets in the source JSON text from which this Value
// was extracted.
size_t start_;
size_t limit_;
};
/** \brief Experimental and untested: represents an element of the "path" to access a node.
*/
class JSON_API PathArgument
class PathArgument
{
public:
friend class Path;
PathArgument();
PathArgument( ArrayIndex index );
PathArgument( UInt index );
PathArgument( const char *key );
PathArgument( const std::string &key );
@@ -544,7 +466,7 @@ namespace Json {
kindKey
};
std::string key_;
ArrayIndex index_;
UInt index_;
Kind kind_;
};
@@ -559,7 +481,7 @@ namespace Json {
* - ".%" => member name is provided as parameter
* - ".[%]" => index is provied as parameter
*/
class JSON_API Path
class Path
{
public:
Path( const std::string &path,
@@ -591,7 +513,26 @@ namespace Json {
Args args_;
};
/** \brief Experimental do not use: Allocator to customize member name and string value memory management done by Value.
*
* - makeMemberName() and releaseMemberName() are called to respectively duplicate and
* free an Json::objectValue member name.
* - duplicateStringValue() and releaseStringValue() are called similarly to
* duplicate and free a Json::stringValue value.
*/
class ValueAllocator
{
public:
enum { unknown = (unsigned)-1 };
virtual ~ValueAllocator();
virtual char *makeMemberName( const char *memberName ) = 0;
virtual void releaseMemberName( char *memberName ) = 0;
virtual char *duplicateStringValue( const char *value,
unsigned int length = unknown ) = 0;
virtual void releaseStringValue( char *value ) = 0;
};
#ifdef JSON_VALUE_USE_INTERNAL_MAP
/** \brief Allocator to customize Value internal map.
@@ -935,10 +876,9 @@ public: // overridden from ValueArrayAllocator
/** \brief base class for Value iterators.
*
*/
class JSON_API ValueIteratorBase
class ValueIteratorBase
{
public:
typedef std::bidirectional_iterator_tag iterator_category;
typedef unsigned int size_t;
typedef int difference_type;
typedef ValueIteratorBase SelfType;
@@ -1006,11 +946,10 @@ public: // overridden from ValueArrayAllocator
/** \brief const iterator for object and array value.
*
*/
class JSON_API ValueConstIterator : public ValueIteratorBase
class ValueConstIterator : public ValueIteratorBase
{
friend class Value;
public:
typedef const Value value_type;
typedef unsigned int size_t;
typedef int difference_type;
typedef const Value &reference;
@@ -1065,11 +1004,10 @@ public: // overridden from ValueArrayAllocator
/** \brief Iterator for object and array value.
*/
class JSON_API ValueIterator : public ValueIteratorBase
class ValueIterator : public ValueIteratorBase
{
friend class Value;
public:
typedef Value value_type;
typedef unsigned int size_t;
typedef int difference_type;
typedef Value &reference;
@@ -1128,9 +1066,4 @@ public: // overridden from ValueArrayAllocator
} // namespace Json
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
# pragma warning(pop)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#endif // CPPTL_JSON_H_INCLUDED

View File

@@ -1,14 +0,0 @@
// DO NOT EDIT. This file is generated by CMake from "version"
// and "version.h.in" files.
// Run CMake configure step to update it.
#ifndef JSON_VERSION_H_INCLUDED
# define JSON_VERSION_H_INCLUDED
# define JSONCPP_VERSION_STRING "0.6.0-dev"
# define JSONCPP_VERSION_MAJOR 0
# define JSONCPP_VERSION_MINOR 6
# define JSONCPP_VERSION_PATCH 0
# define JSONCPP_VERSION_QUALIFIER -dev
# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
#endif // JSON_VERSION_H_INCLUDED

View File

@@ -1,23 +1,10 @@
// Copyright 2007-2010 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSON_WRITER_H_INCLUDED
# define JSON_WRITER_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION)
# include "value.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
# include <vector>
# include <string>
// Disable warning C4251: <data member>: <type> needs to have dll-interface to be used by...
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
# pragma warning(push)
# pragma warning(disable:4251)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
# include <iostream>
namespace Json {
@@ -47,13 +34,6 @@ namespace Json {
void enableYAMLCompatibility();
/** \brief Drop the "null" string from the writer's output for nullValues.
* Strictly speaking, this is not valid JSON. But when the output is being
* fed to a browser's Javascript, it makes for smaller output and the
* browser can handle the output just fine.
*/
void dropNullPlaceholders();
public: // overridden from Writer
virtual std::string write( const Value &root );
@@ -62,7 +42,6 @@ namespace Json {
std::string document_;
bool yamlCompatiblityEnabled_;
bool dropNullPlaceholders_;
};
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way.
@@ -178,26 +157,18 @@ namespace Json {
bool addChildValues_;
};
# if defined(JSON_HAS_INT64)
std::string JSON_API valueToString( Int value );
std::string JSON_API valueToString( UInt value );
# endif // if defined(JSON_HAS_INT64)
std::string JSON_API valueToString( LargestInt value );
std::string JSON_API valueToString( LargestUInt value );
std::string JSON_API valueToString( double value );
std::string JSON_API valueToString( bool value );
std::string JSON_API valueToQuotedString( const char *value );
/// \brief Output using the StyledStreamWriter.
/// \see Json::operator>>()
JSON_API std::ostream& operator<<( std::ostream&, const Value &root );
std::ostream& operator<<( std::ostream&, const Value &root );
} // namespace Json
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
# pragma warning(pop)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#endif // JSON_WRITER_H_INCLUDED

View File

@@ -3,10 +3,7 @@
Requires Python 2.6
Example of invocation (use to test the script):
python makerelease.py --platform=msvc6,msvc71,msvc80,msvc90,mingw -ublep 0.6.0 0.7.0-dev
When testing this script:
python makerelease.py --force --retag --platform=msvc6,msvc71,msvc80,mingw -ublep test-0.6.0 test-0.6.1-dev
python makerelease.py --force --retag --platform=msvc6,msvc71,msvc80,mingw -ublep 0.5.0 0.6.0-dev
Example of invocation when doing a release:
python makerelease.py 0.5.0 0.6.0-dev
@@ -23,7 +20,6 @@ import tempfile
import os
import time
from devtools import antglob, fixeol, tarball
import amalgamate
SVN_ROOT = 'https://jsoncpp.svn.sourceforge.net/svnroot/jsoncpp/'
SVN_TAG_ROOT = SVN_ROOT + 'tags/jsoncpp'
@@ -323,14 +319,6 @@ Warning: --force should only be used when developping/testing the release script
print 'Generating source tarball to', source_tarball_path
tarball.make_tarball( source_tarball_path, [export_dir], export_dir, prefix_dir=source_dir )
amalgamation_tarball_path = 'dist/%s-amalgamation.tar.gz' % source_dir
print 'Generating amalgamation source tarball to', amalgamation_tarball_path
amalgamation_dir = 'dist/amalgamation'
amalgamate.amalgamate_source( export_dir, '%s/jsoncpp.cpp' % amalgamation_dir, 'json/json.h' )
amalgamation_source_dir = 'jsoncpp-src-amalgamation' + release_version
tarball.make_tarball( amalgamation_tarball_path, [amalgamation_dir],
amalgamation_dir, prefix_dir=amalgamation_source_dir )
# Decompress source tarball, download and install scons-local
distcheck_dir = 'dist/distcheck'
distcheck_top_dir = distcheck_dir + '/' + source_dir

View File

@@ -1,53 +1,53 @@
import fnmatch
import os
def generate( env ):
def Glob( env, includes = None, excludes = None, dir = '.' ):
"""Adds Glob( includes = Split( '*' ), excludes = None, dir = '.')
helper function to environment.
Glob both the file-system files.
includes: list of file name pattern included in the return list when matched.
excludes: list of file name pattern exluced from the return list.
Example:
sources = env.Glob( ("*.cpp", '*.h'), "~*.cpp", "#src" )
"""
def filterFilename(path):
abs_path = os.path.join( dir, path )
if not os.path.isfile(abs_path):
return 0
fn = os.path.basename(path)
match = 0
for include in includes:
if fnmatch.fnmatchcase( fn, include ):
match = 1
break
if match == 1 and not excludes is None:
for exclude in excludes:
if fnmatch.fnmatchcase( fn, exclude ):
match = 0
break
return match
if includes is None:
includes = ('*',)
elif type(includes) in ( type(''), type(u'') ):
includes = (includes,)
if type(excludes) in ( type(''), type(u'') ):
excludes = (excludes,)
dir = env.Dir(dir).abspath
paths = os.listdir( dir )
def makeAbsFileNode( path ):
return env.File( os.path.join( dir, path ) )
nodes = filter( filterFilename, paths )
return map( makeAbsFileNode, nodes )
from SCons.Script import Environment
import fnmatch
import os
def generate( env ):
def Glob( env, includes = None, excludes = None, dir = '.' ):
"""Adds Glob( includes = Split( '*' ), excludes = None, dir = '.')
helper function to environment.
Glob both the file-system files.
includes: list of file name pattern included in the return list when matched.
excludes: list of file name pattern exluced from the return list.
Example:
sources = env.Glob( ("*.cpp", '*.h'), "~*.cpp", "#src" )
"""
def filterFilename(path):
abs_path = os.path.join( dir, path )
if not os.path.isfile(abs_path):
return 0
fn = os.path.basename(path)
match = 0
for include in includes:
if fnmatch.fnmatchcase( fn, include ):
match = 1
break
if match == 1 and not excludes is None:
for exclude in excludes:
if fnmatch.fnmatchcase( fn, exclude ):
match = 0
break
return match
if includes is None:
includes = ('*',)
elif type(includes) in ( type(''), type(u'') ):
includes = (includes,)
if type(excludes) in ( type(''), type(u'') ):
excludes = (excludes,)
dir = env.Dir(dir).abspath
paths = os.listdir( dir )
def makeAbsFileNode( path ):
return env.File( os.path.join( dir, path ) )
nodes = filter( filterFilename, paths )
return map( makeAbsFileNode, nodes )
from SCons.Script import Environment
Environment.Glob = Glob
def exists(env):
"""
Tool always exists.
"""
return True
def exists(env):
"""
Tool always exists.
"""
return True

View File

@@ -1,5 +0,0 @@
ADD_SUBDIRECTORY(lib_json)
IF(JSONCPP_WITH_TESTS)
ADD_SUBDIRECTORY(jsontestrunner)
ADD_SUBDIRECTORY(test_lib_json)
ENDIF(JSONCPP_WITH_TESTS)

View File

@@ -1,23 +0,0 @@
FIND_PACKAGE(PythonInterp 2.6 REQUIRED)
IF(JSONCPP_LIB_BUILD_SHARED)
ADD_DEFINITIONS( -DJSON_DLL )
ENDIF(JSONCPP_LIB_BUILD_SHARED)
ADD_EXECUTABLE(jsontestrunner_exe
main.cpp
)
TARGET_LINK_LIBRARIES(jsontestrunner_exe jsoncpp_lib)
SET_TARGET_PROPERTIES(jsontestrunner_exe PROPERTIES OUTPUT_NAME jsontestrunner_exe)
IF(PYTHONINTERP_FOUND)
# Run end to end parser/writer tests
GET_PROPERTY(JSONTESTRUNNER_EXE_PATH TARGET jsontestrunner_exe PROPERTY LOCATION)
SET(TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../test)
SET(RUNJSONTESTS_PATH ${TEST_DIR}/runjsontests.py)
ADD_CUSTOM_TARGET(jsoncpp_readerwriter_tests ALL
"${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" "${JSONTESTRUNNER_EXE_PATH}" "${TEST_DIR}/data"
DEPENDS jsontestrunner_exe jsoncpp_test
)
ADD_CUSTOM_TARGET(jsoncpp_check DEPENDS jsoncpp_readerwriter_tests)
ENDIF(PYTHONINTERP_FOUND)

View File

@@ -1,12 +1,3 @@
// Copyright 2007-2010 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
/* This executable is used for testing parser/writer using real JSON files.
*/
#include <json/json.h>
#include <algorithm> // sort
#include <stdio.h>
@@ -15,35 +6,6 @@
# pragma warning( disable: 4996 ) // disable fopen deprecation warning
#endif
static std::string
normalizeFloatingPointStr( double value )
{
char buffer[32];
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
sprintf_s( buffer, sizeof(buffer), "%.16g", value );
#else
snprintf( buffer, sizeof(buffer), "%.16g", value );
#endif
buffer[sizeof(buffer)-1] = 0;
std::string s( buffer );
std::string::size_type index = s.find_last_of( "eE" );
if ( index != std::string::npos )
{
std::string::size_type hasSign = (s[index+1] == '+' || s[index+1] == '-') ? 1 : 0;
std::string::size_type exponentStartIndex = index + 1 + hasSign;
std::string normalized = s.substr( 0, exponentStartIndex );
std::string::size_type indexDigit = s.find_first_not_of( '0', exponentStartIndex );
std::string exponent = "0";
if ( indexDigit != std::string::npos ) // There is an exponent different from 0
{
exponent = s.substr( indexDigit );
}
return normalized + exponent;
}
return s;
}
static std::string
readInputTestFile( const char *path )
{
@@ -63,6 +25,7 @@ readInputTestFile( const char *path )
return text;
}
static void
printValueTree( FILE *fout, Json::Value &value, const std::string &path = "." )
{
@@ -72,13 +35,13 @@ printValueTree( FILE *fout, Json::Value &value, const std::string &path = "." )
fprintf( fout, "%s=null\n", path.c_str() );
break;
case Json::intValue:
fprintf( fout, "%s=%s\n", path.c_str(), Json::valueToString( value.asLargestInt() ).c_str() );
fprintf( fout, "%s=%d\n", path.c_str(), value.asInt() );
break;
case Json::uintValue:
fprintf( fout, "%s=%s\n", path.c_str(), Json::valueToString( value.asLargestUInt() ).c_str() );
fprintf( fout, "%s=%u\n", path.c_str(), value.asUInt() );
break;
case Json::realValue:
fprintf( fout, "%s=%s\n", path.c_str(), normalizeFloatingPointStr(value.asDouble()).c_str() );
fprintf( fout, "%s=%.16g\n", path.c_str(), value.asDouble() );
break;
case Json::stringValue:
fprintf( fout, "%s=\"%s\"\n", path.c_str(), value.asString().c_str() );
@@ -93,11 +56,7 @@ printValueTree( FILE *fout, Json::Value &value, const std::string &path = "." )
for ( int index =0; index < size; ++index )
{
static char buffer[16];
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
sprintf_s( buffer, sizeof(buffer), "[%d]", index );
#else
snprintf( buffer, sizeof(buffer), "[%d]", index );
#endif
sprintf( buffer, "[%d]", index );
printValueTree( fout, value[index], path + buffer );
}
}
@@ -137,7 +96,7 @@ parseAndSaveValueTree( const std::string &input,
{
printf( "Failed to parse %s file: \n%s\n",
kind.c_str(),
reader.getFormattedErrorMessages().c_str() );
reader.getFormatedErrorMessages().c_str() );
return 1;
}
@@ -189,19 +148,6 @@ removeSuffix( const std::string &path,
return path.substr( 0, path.length() - extension.length() );
}
static void
printConfig()
{
// Print the configuration used to compile JsonCpp
#if defined(JSON_NO_INT64)
printf( "JSON_NO_INT64=1\n" );
#else
printf( "JSON_NO_INT64=0\n" );
#endif
}
static int
printUsage( const char *argv[] )
{
@@ -229,12 +175,6 @@ parseCommandLine( int argc, const char *argv[],
++index;
}
if ( std::string(argv[1]) == "--json-config" )
{
printConfig();
return 3;
}
if ( index == argc || index + 1 < argc )
{
return printUsage( argv );
@@ -256,46 +196,38 @@ int main( int argc, const char *argv[] )
return exitCode;
}
try
std::string input = readInputTestFile( path.c_str() );
if ( input.empty() )
{
std::string input = readInputTestFile( path.c_str() );
if ( input.empty() )
{
printf( "Failed to read input or empty input: %s\n", path.c_str() );
return 3;
}
std::string basePath = removeSuffix( argv[1], ".json" );
if ( !parseOnly && basePath.empty() )
{
printf( "Bad input path. Path does not end with '.expected':\n%s\n", path.c_str() );
return 3;
}
std::string actualPath = basePath + ".actual";
std::string rewritePath = basePath + ".rewrite";
std::string rewriteActualPath = basePath + ".actual-rewrite";
Json::Value root;
exitCode = parseAndSaveValueTree( input, actualPath, "input", root, features, parseOnly );
if ( exitCode == 0 && !parseOnly )
{
std::string rewrite;
exitCode = rewriteValueTree( rewritePath, root, rewrite );
if ( exitCode == 0 )
{
Json::Value rewriteRoot;
exitCode = parseAndSaveValueTree( rewrite, rewriteActualPath,
"rewrite", rewriteRoot, features, parseOnly );
}
}
printf( "Failed to read input or empty input: %s\n", path.c_str() );
return 3;
}
catch ( const std::exception &e )
std::string basePath = removeSuffix( argv[1], ".json" );
if ( !parseOnly && basePath.empty() )
{
printf( "Unhandled exception:\n%s\n", e.what() );
exitCode = 1;
printf( "Bad input path. Path does not end with '.expected':\n%s\n", path.c_str() );
return 3;
}
std::string actualPath = basePath + ".actual";
std::string rewritePath = basePath + ".rewrite";
std::string rewriteActualPath = basePath + ".actual-rewrite";
Json::Value root;
exitCode = parseAndSaveValueTree( input, actualPath, "input", root, features, parseOnly );
if ( exitCode == 0 && !parseOnly )
{
std::string rewrite;
exitCode = rewriteValueTree( rewritePath, root, rewrite );
if ( exitCode == 0 )
{
Json::Value rewriteRoot;
exitCode = parseAndSaveValueTree( rewrite, rewriteActualPath,
"rewrite", rewriteRoot, features, parseOnly );
}
}
return exitCode;
}
// vim: et ts=4 sts=4 sw=4 tw=0

View File

@@ -1,43 +0,0 @@
OPTION(JSONCPP_LIB_BUILD_SHARED "Build jsoncpp_lib as a shared library." OFF)
IF(JSONCPP_LIB_BUILD_SHARED)
SET(JSONCPP_LIB_TYPE SHARED)
ADD_DEFINITIONS( -DJSON_DLL_BUILD )
ELSE(JSONCPP_LIB_BUILD_SHARED)
SET(JSONCPP_LIB_TYPE STATIC)
ENDIF(JSONCPP_LIB_BUILD_SHARED)
SET( JSONCPP_INCLUDE_DIR ../../include )
SET( PUBLIC_HEADERS
${JSONCPP_INCLUDE_DIR}/json/config.h
${JSONCPP_INCLUDE_DIR}/json/forwards.h
${JSONCPP_INCLUDE_DIR}/json/features.h
${JSONCPP_INCLUDE_DIR}/json/value.h
${JSONCPP_INCLUDE_DIR}/json/reader.h
${JSONCPP_INCLUDE_DIR}/json/writer.h
${JSONCPP_INCLUDE_DIR}/json/assertions.h
${JSONCPP_INCLUDE_DIR}/json/version.h
)
SOURCE_GROUP( "Public API" FILES ${PUBLIC_HEADERS} )
ADD_LIBRARY( jsoncpp_lib ${JSONCPP_LIB_TYPE}
${PUBLIC_HEADERS}
json_tool.h
json_reader.cpp
json_batchallocator.h
json_valueiterator.inl
json_value.cpp
json_writer.cpp
version.h.in
)
SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES OUTPUT_NAME jsoncpp )
SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES VERSION ${JSON_CPP_VERSION} SOVERSION ${JSON_CPP_VERSION} )
# Install instructions for this target
INSTALL( TARGETS jsoncpp_lib
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)

View File

@@ -1,8 +1,3 @@
// Copyright 2007-2010 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
# define JSONCPP_BATCHALLOCATOR_H_INCLUDED
@@ -30,6 +25,8 @@ template<typename AllocatedType
class BatchAllocator
{
public:
typedef AllocatedType Type;
BatchAllocator( unsigned int objectsPerPage = 255 )
: freeHead_( 0 )
, objectsPerPage_( objectsPerPage )
@@ -125,4 +122,4 @@ private:
# endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
// vim: et ts=3 sts=3 sw=3 tw=0

View File

@@ -1,11 +1,5 @@
// Copyright 2007-2010 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
// included by json_value.cpp
namespace Json {
// everything is within Json namespace
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
@@ -53,7 +47,8 @@ public: // overridden from ValueArrayAllocator
if ( minNewIndexCount > newIndexCount )
newIndexCount = minNewIndexCount;
void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
JSON_ASSERT_MESSAGE(newIndexes, "Couldn't realloc.");
if ( !newIndexes )
throw std::bad_alloc();
indexCount = newIndexCount;
indexes = static_cast<Value **>( newIndexes );
}
@@ -116,7 +111,8 @@ public: // overridden from ValueArrayAllocator
if ( minNewIndexCount > newIndexCount )
newIndexCount = minNewIndexCount;
void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
JSON_ASSERT_MESSAGE(newIndexes, "Couldn't realloc.");
if ( !newIndexes )
throw std::bad_alloc();
indexCount = newIndexCount;
indexes = static_cast<Value **>( newIndexes );
}
@@ -256,8 +252,8 @@ ValueInternalArray::ValueInternalArray()
ValueInternalArray::ValueInternalArray( const ValueInternalArray &other )
: pages_( 0 )
, size_( other.size_ )
, pageCount_( 0 )
, size_( other.size_ )
{
PageIndex minNewPages = other.size_ / itemsPerPage;
arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
@@ -450,6 +446,3 @@ ValueInternalArray::compare( const ValueInternalArray &other ) const
}
return 0;
}
} // namespace Json
// vim: et ts=3 sts=3 sw=3 tw=0

View File

@@ -1,11 +1,5 @@
// Copyright 2007-2010 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
// included by json_value.cpp
namespace Json {
// everything is within Json namespace
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
@@ -421,7 +415,7 @@ ValueInternalMap::setNewItem( const char *key,
ValueInternalLink *link,
BucketIndex index )
{
char *duplicatedKey = makeMemberName( key );
char *duplicatedKey = valueAllocator()->makeMemberName( key );
++itemCount_;
link->keys_[index] = duplicatedKey;
link->items_[index].setItemUsed();
@@ -611,6 +605,3 @@ ValueInternalMap::distance( const IteratorState &x, const IteratorState &y )
increment( it );
return offset;
}
} // namespace Json
// vim: et ts=3 sts=3 sw=3 tw=0

View File

@@ -1,21 +1,13 @@
// Copyright 2007-2011 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#if !defined(JSON_IS_AMALGAMATION)
# include <json/assertions.h>
# include <json/reader.h>
# include <json/value.h>
# include "json_tool.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
#include <json/reader.h>
#include <json/value.h>
#include <utility>
#include <cstdio>
#include <cassert>
#include <cstring>
#include <istream>
#include <iostream>
#include <stdexcept>
#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
#if _MSC_VER >= 1400 // VC++ 8.0
#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated.
#endif
@@ -27,8 +19,6 @@ namespace Json {
Features::Features()
: allowComments_( true )
, strictRoot_( false )
, allowDroppedNullPlaceholders_ ( false )
, allowNumericKeys_ ( false )
{
}
@@ -46,8 +36,6 @@ Features::strictMode()
Features features;
features.allowComments_ = false;
features.strictRoot_ = true;
features.allowDroppedNullPlaceholders_ = false;
features.allowNumericKeys_ = false;
return features;
}
@@ -78,36 +66,54 @@ containsNewLine( Reader::Location begin,
return false;
}
static std::string codePointToUTF8(unsigned int cp)
{
std::string result;
// based on description from http://en.wikipedia.org/wiki/UTF-8
if (cp <= 0x7f)
{
result.resize(1);
result[0] = static_cast<char>(cp);
}
else if (cp <= 0x7FF)
{
result.resize(2);
result[1] = static_cast<char>(0x80 | (0x3f & cp));
result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
}
else if (cp <= 0xFFFF)
{
result.resize(3);
result[2] = static_cast<char>(0x80 | (0x3f & cp));
result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6)));
result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12)));
}
else if (cp <= 0x10FFFF)
{
result.resize(4);
result[3] = static_cast<char>(0x80 | (0x3f & cp));
result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
}
return result;
}
// Class Reader
// //////////////////////////////////////////////////////////////////
Reader::Reader()
: errors_(),
document_(),
begin_(),
end_(),
current_(),
lastValueEnd_(),
lastValue_(),
commentsBefore_(),
features_( Features::all() ),
collectComments_()
: features_( Features::all() )
{
}
Reader::Reader( const Features &features )
: errors_(),
document_(),
begin_(),
end_(),
current_(),
lastValueEnd_(),
lastValue_(),
commentsBefore_(),
features_( features ),
collectComments_()
: features_( features )
{
}
@@ -194,17 +200,6 @@ Reader::readValue()
if ( collectComments_ && !commentsBefore_.empty() )
{
// Remove newline characters at the end of the comments
size_t lastNonNewline = commentsBefore_.find_last_not_of("\r\n");
if (lastNonNewline != std::string::npos)
{
commentsBefore_.erase(lastNonNewline+1);
}
else
{
commentsBefore_.clear();
}
currentValue().setComment( commentsBefore_, commentBefore );
commentsBefore_ = "";
}
@@ -214,11 +209,9 @@ Reader::readValue()
{
case tokenObjectBegin:
successful = readObject( token );
currentValue().setOffsetLimit(current_ - begin_);
break;
case tokenArrayBegin:
successful = readArray( token );
currentValue().setOffsetLimit(current_ - begin_);
break;
case tokenNumber:
successful = decodeNumber( token );
@@ -228,34 +221,14 @@ Reader::readValue()
break;
case tokenTrue:
currentValue() = true;
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
break;
case tokenFalse:
currentValue() = false;
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
break;
case tokenNull:
currentValue() = Value();
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
break;
case tokenArraySeparator:
if ( features_.allowDroppedNullPlaceholders_ )
{
// "Un-read" the current token and mark the current value as a null
// token.
current_--;
currentValue() = Value();
currentValue().setOffsetStart(current_ - begin_ - 1);
currentValue().setOffsetLimit(current_ - begin_);
break;
}
// Else, fall through...
default:
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
return addError( "Syntax error: value, object or array expected.", token );
}
@@ -509,7 +482,6 @@ Reader::readObject( Token &tokenStart )
Token tokenName;
std::string name;
currentValue() = Value( objectValue );
currentValue().setOffsetStart(tokenStart.start_ - begin_);
while ( readToken( tokenName ) )
{
bool initialTokenOk = true;
@@ -519,24 +491,12 @@ Reader::readObject( Token &tokenStart )
break;
if ( tokenName.type_ == tokenObjectEnd && name.empty() ) // empty object
return true;
name = "";
if ( tokenName.type_ == tokenString )
{
if ( !decodeString( tokenName, name ) )
return recoverFromError( tokenObjectEnd );
}
else if ( tokenName.type_ == tokenNumber &&
features_.allowNumericKeys_ )
{
Value numberName;
if ( !decodeNumber( tokenName, numberName ) )
return recoverFromError( tokenObjectEnd );
name = numberName.asString();
}
else
{
if ( tokenName.type_ != tokenString )
break;
}
name = "";
if ( !decodeString( tokenName, name ) )
return recoverFromError( tokenObjectEnd );
Token colon;
if ( !readToken( colon ) || colon.type_ != tokenMemberSeparator )
@@ -556,7 +516,7 @@ Reader::readObject( Token &tokenStart )
if ( !readToken( comma )
|| ( comma.type_ != tokenObjectEnd &&
comma.type_ != tokenArraySeparator &&
comma.type_ != tokenComment ) )
comma.type_ != tokenComment ) )
{
return addErrorAndRecover( "Missing ',' or '}' in object declaration",
comma,
@@ -579,7 +539,6 @@ bool
Reader::readArray( Token &tokenStart )
{
currentValue() = Value( arrayValue );
currentValue().setOffsetStart(tokenStart.start_ - begin_);
skipSpaces();
if ( *current_ == ']' ) // empty array
{
@@ -588,7 +547,7 @@ Reader::readArray( Token &tokenStart )
return true;
}
int index = 0;
for (;;)
while ( true )
{
Value &value = currentValue()[ index++ ];
nodes_.push( &value );
@@ -604,8 +563,8 @@ Reader::readArray( Token &tokenStart )
{
ok = readToken( token );
}
bool badTokenType = ( token.type_ != tokenArraySeparator &&
token.type_ != tokenArrayEnd );
bool badTokenType = ( token.type_ == tokenArraySeparator &&
token.type_ == tokenArrayEnd );
if ( !ok || badTokenType )
{
return addErrorAndRecover( "Missing ',' or ']' in array declaration",
@@ -621,19 +580,6 @@ Reader::readArray( Token &tokenStart )
bool
Reader::decodeNumber( Token &token )
{
Value decoded;
if ( !decodeNumber( token, decoded ) )
return false;
currentValue() = decoded;
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
return true;
}
bool
Reader::decodeNumber( Token &token, Value &decoded )
{
bool isDouble = false;
for ( Location inspect = token.start_; inspect != token.end_; ++inspect )
@@ -643,98 +589,56 @@ Reader::decodeNumber( Token &token, Value &decoded )
|| ( *inspect == '-' && inspect != token.start_ );
}
if ( isDouble )
return decodeDouble( token, decoded );
// Attempts to parse the number as an integer. If the number is
// larger than the maximum supported value of an integer then
// we decode the number as a double.
return decodeDouble( token );
Location current = token.start_;
bool isNegative = *current == '-';
if ( isNegative )
++current;
Value::LargestUInt maxIntegerValue = isNegative ? Value::LargestUInt(-Value::minLargestInt)
: Value::maxLargestUInt;
Value::LargestUInt threshold = maxIntegerValue / 10;
Value::LargestUInt value = 0;
Value::UInt threshold = (isNegative ? Value::UInt(-Value::minInt)
: Value::maxUInt) / 10;
Value::UInt value = 0;
while ( current < token.end_ )
{
Char c = *current++;
if ( c < '0' || c > '9' )
return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
Value::UInt digit(c - '0');
if ( value >= threshold )
{
// We've hit or exceeded the max value divided by 10 (rounded down). If
// a) we've only just touched the limit, b) this is the last digit, and
// c) it's small enough to fit in that rounding delta, we're okay.
// Otherwise treat this number as a double to avoid overflow.
if (value > threshold ||
current != token.end_ ||
digit > maxIntegerValue % 10)
{
return decodeDouble( token, decoded );
}
}
value = value * 10 + digit;
return decodeDouble( token );
value = value * 10 + Value::UInt(c - '0');
}
if ( isNegative )
decoded = -Value::LargestInt( value );
else if ( value <= Value::LargestUInt(Value::maxInt) )
decoded = Value::LargestInt( value );
currentValue() = -Value::Int( value );
else if ( value <= Value::UInt(Value::maxInt) )
currentValue() = Value::Int( value );
else
decoded = value;
currentValue() = value;
return true;
}
bool
Reader::decodeDouble( Token &token )
{
Value decoded;
if ( !decodeDouble( token, decoded ) )
return false;
currentValue() = decoded;
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
return true;
}
bool
Reader::decodeDouble( Token &token, Value &decoded )
{
double value = 0;
const int bufferSize = 32;
int count;
int length = int(token.end_ - token.start_);
// Sanity check to avoid buffer overflow exploits.
if (length < 0) {
return addError( "Unable to parse token length", token );
}
// Avoid using a string constant for the format control string given to
// sscanf, as this can cause hard to debug crashes on OS X. See here for more
// info:
//
// http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
char format[] = "%lf";
if ( length <= bufferSize )
{
Char buffer[bufferSize+1];
Char buffer[bufferSize];
memcpy( buffer, token.start_, length );
buffer[length] = 0;
count = sscanf( buffer, format, &value );
count = sscanf( buffer, "%lf", &value );
}
else
{
std::string buffer( token.start_, token.end_ );
count = sscanf( buffer.c_str(), format, &value );
count = sscanf( buffer.c_str(), "%lf", &value );
}
if ( count != 1 )
return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
decoded = value;
currentValue() = value;
return true;
}
@@ -746,8 +650,6 @@ Reader::decodeString( Token &token )
if ( !decodeString( token, decoded ) )
return false;
currentValue() = decoded;
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
return true;
}
@@ -873,7 +775,7 @@ Reader::recoverFromError( TokenType skipUntilToken )
{
int errorCount = int(errors_.size());
Token skip;
for (;;)
while ( true )
{
if ( !readToken(skip) )
errors_.resize( errorCount ); // discard errors caused by recovery
@@ -947,25 +849,13 @@ Reader::getLocationLineAndColumn( Location location ) const
int line, column;
getLocationLineAndColumn( location, line, column );
char buffer[18+16+16+1];
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
sprintf_s(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
#else
snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
#endif
sprintf( buffer, "Line %d, Column %d", line, column );
return buffer;
}
// Deprecated. Preserved for backward compatibility
std::string
Reader::getFormatedErrorMessages() const
{
return getFormattedErrorMessages();
}
std::string
Reader::getFormattedErrorMessages() const
{
std::string formattedMessage;
for ( Errors::const_iterator itError = errors_.begin();
@@ -982,40 +872,14 @@ Reader::getFormattedErrorMessages() const
}
std::vector<Reader::StructuredError>
Reader::getStructuredErrors() const
{
std::vector<Reader::StructuredError> allErrors;
for ( Errors::const_iterator itError = errors_.begin();
itError != errors_.end();
++itError )
{
const ErrorInfo &error = *itError;
Reader::StructuredError structured;
structured.offset_start = error.token_.start_ - begin_;
structured.offset_limit = error.token_.end_ - begin_;
structured.message = error.message_;
allErrors.push_back(structured);
}
return allErrors;
}
std::istream& operator>>( std::istream &sin, Value &root )
{
Json::Reader reader;
bool ok = reader.parse(sin, root, true);
if (!ok) {
fprintf(
stderr,
"Error from reader: %s",
reader.getFormattedErrorMessages().c_str());
JSON_FAIL_MESSAGE("reader error");
}
//JSON_ASSERT( ok );
if (!ok) throw std::runtime_error(reader.getFormatedErrorMessages());
return sin;
}
} // namespace Json
// vim: et ts=3 sts=3 sw=3 tw=0

View File

@@ -1,93 +0,0 @@
// Copyright 2007-2010 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
# define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
/* This header provides common string manipulation support, such as UTF-8,
* portable conversion from/to string...
*
* It is an internal header that must not be exposed.
*/
namespace Json {
/// Converts a unicode code-point to UTF-8.
static inline std::string
codePointToUTF8(unsigned int cp)
{
std::string result;
// based on description from http://en.wikipedia.org/wiki/UTF-8
if (cp <= 0x7f)
{
result.resize(1);
result[0] = static_cast<char>(cp);
}
else if (cp <= 0x7FF)
{
result.resize(2);
result[1] = static_cast<char>(0x80 | (0x3f & cp));
result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
}
else if (cp <= 0xFFFF)
{
result.resize(3);
result[2] = static_cast<char>(0x80 | (0x3f & cp));
result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6)));
result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12)));
}
else if (cp <= 0x10FFFF)
{
result.resize(4);
result[3] = static_cast<char>(0x80 | (0x3f & cp));
result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
}
return result;
}
/// Returns true if ch is a control character (in range [0,32[).
static inline bool
isControlCharacter(char ch)
{
return ch > 0 && ch <= 0x1F;
}
enum {
/// Constant that specify the size of the buffer that must be passed to uintToString.
uintToStringBufferSize = 3*sizeof(LargestUInt)+1
};
// Defines a char buffer for use with uintToString().
typedef char UIntToStringBuffer[uintToStringBufferSize];
/** Converts an unsigned integer to string.
* @param value Unsigned interger to convert to string
* @param current Input/Output string buffer.
* Must have at least uintToStringBufferSize chars free.
*/
static inline void
uintToString( LargestUInt value,
char *&current )
{
*--current = 0;
do
{
*--current = char(value % 10) + '0';
value /= 10;
}
while ( value != 0 );
}
} // namespace Json {
#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,6 @@
// Copyright 2007-2010 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
// included by json_value.cpp
// everything is within Json namespace
namespace Json {
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
@@ -149,7 +144,6 @@ ValueIteratorBase::copy( const SelfType &other )
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP
current_ = other.current_;
isNull_ = other.isNull_;
#else
if ( isArray_ )
iterator_.array_ = other.iterator_.array_;
@@ -296,6 +290,3 @@ ValueIterator::operator =( const SelfType &other )
copy( other );
return *this;
}
} // namespace Json
// vim: et ts=3 sts=3 sw=3 tw=0

View File

@@ -1,25 +1,23 @@
// Copyright 2011 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#if !defined(JSON_IS_AMALGAMATION)
# include <json/writer.h>
# include "json_tool.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
#include <json/writer.h>
#include <utility>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <sstream>
#include <iomanip>
#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
#if _MSC_VER >= 1400 // VC++ 8.0
#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated.
#endif
namespace Json {
static bool isControlCharacter(char ch)
{
return ch > 0 && ch <= 0x1F;
}
static bool containsControlCharacter( const char* str )
{
while ( *str )
@@ -29,16 +27,26 @@ static bool containsControlCharacter( const char* str )
}
return false;
}
std::string valueToString( LargestInt value )
static void uintToString( unsigned int value,
char *&current )
{
UIntToStringBuffer buffer;
*--current = 0;
do
{
*--current = (value % 10) + '0';
value /= 10;
}
while ( value != 0 );
}
std::string valueToString( Int value )
{
char buffer[32];
char *current = buffer + sizeof(buffer);
bool isNegative = value < 0;
if ( isNegative )
value = -value;
uintToString( LargestUInt(value), current );
uintToString( UInt(value), current );
if ( isNegative )
*--current = '-';
assert( current >= buffer );
@@ -46,46 +54,51 @@ std::string valueToString( LargestInt value )
}
std::string valueToString( LargestUInt value )
std::string valueToString( UInt value )
{
UIntToStringBuffer buffer;
char buffer[32];
char *current = buffer + sizeof(buffer);
uintToString( value, current );
assert( current >= buffer );
return current;
}
#if defined(JSON_HAS_INT64)
std::string valueToString( Int value )
{
return valueToString( LargestInt(value) );
}
std::string valueToString( UInt value )
{
return valueToString( LargestUInt(value) );
}
#endif // # if defined(JSON_HAS_INT64)
std::string valueToString( double value )
{
// Allocate a buffer that is more than large enough to store the 16 digits of
// precision requested below.
char buffer[32];
// Print into the buffer. We need not request the alternative representation
// that always has a decimal point because JSON doesn't distingish the
// concepts of reals and integers.
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning.
sprintf_s(buffer, sizeof(buffer), "%.16g", value);
#else
snprintf(buffer, sizeof(buffer), "%.16g", value);
sprintf_s(buffer, sizeof(buffer), "%#.16g", value);
#else
sprintf(buffer, "%#.16g", value);
#endif
char* ch = buffer + strlen(buffer) - 1;
if (*ch != '0') return buffer; // nothing to truncate, so save time
while(ch > buffer && *ch == '0'){
--ch;
}
char* last_nonzero = ch;
while(ch >= buffer){
switch(*ch){
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
--ch;
continue;
case '.':
// Truncate zeroes to save bytes in output, but keep one.
*(last_nonzero+2) = '\0';
return buffer;
default:
return buffer;
}
}
return buffer;
}
@@ -97,15 +110,13 @@ std::string valueToString( bool value )
std::string valueToQuotedString( const char *value )
{
if (value == NULL)
return "";
// Not sure how to handle unicode...
if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && !containsControlCharacter( value ))
return std::string("\"") + value + "\"";
// We have to walk value and escape any special characters.
// Appending to std::string is not efficient, but this should be rare.
// (Note: forward slashes are *not* rare, but I am not escaping them.)
std::string::size_type maxsize = strlen(value)*2 + 3; // allescaped+quotes+NULL
unsigned maxsize = strlen(value)*2 + 3; // allescaped+quotes+NULL
std::string result;
result.reserve(maxsize); // to avoid lots of mallocs
result += "\"";
@@ -171,8 +182,7 @@ Writer::~Writer()
// //////////////////////////////////////////////////////////////////
FastWriter::FastWriter()
: yamlCompatiblityEnabled_( false ),
dropNullPlaceholders_( false )
: yamlCompatiblityEnabled_( false )
{
}
@@ -184,13 +194,6 @@ FastWriter::enableYAMLCompatibility()
}
void
FastWriter::dropNullPlaceholders()
{
dropNullPlaceholders_ = true;
}
std::string
FastWriter::write( const Value &root )
{
@@ -207,13 +210,13 @@ FastWriter::writeValue( const Value &value )
switch ( value.type() )
{
case nullValue:
if (!dropNullPlaceholders_) document_ += "null";
document_ += "null";
break;
case intValue:
document_ += valueToString( value.asLargestInt() );
document_ += valueToString( value.asInt() );
break;
case uintValue:
document_ += valueToString( value.asLargestUInt() );
document_ += valueToString( value.asUInt() );
break;
case realValue:
document_ += valueToString( value.asDouble() );
@@ -266,7 +269,6 @@ FastWriter::writeValue( const Value &value )
StyledWriter::StyledWriter()
: rightMargin_( 74 )
, indentSize_( 3 )
, addChildValues_()
{
}
@@ -294,10 +296,10 @@ StyledWriter::writeValue( const Value &value )
pushValue( "null" );
break;
case intValue:
pushValue( valueToString( value.asLargestInt() ) );
pushValue( valueToString( value.asInt() ) );
break;
case uintValue:
pushValue( valueToString( value.asLargestUInt() ) );
pushValue( valueToString( value.asUInt() ) );
break;
case realValue:
pushValue( valueToString( value.asDouble() ) );
@@ -321,7 +323,7 @@ StyledWriter::writeValue( const Value &value )
writeWithIndent( "{" );
indent();
Value::Members::iterator it = members.begin();
for (;;)
while ( true )
{
const std::string &name = *it;
const Value &childValue = value[name];
@@ -361,7 +363,7 @@ StyledWriter::writeArrayValue( const Value &value )
indent();
bool hasChildValue = !childValues_.empty();
unsigned index =0;
for (;;)
while ( true )
{
const Value &childValue = value[index];
writeCommentBeforeValue( childValue );
@@ -483,20 +485,7 @@ StyledWriter::writeCommentBeforeValue( const Value &root )
{
if ( !root.hasComment( commentBefore ) )
return;
document_ += "\n";
writeIndent();
std::string normalizedComment = normalizeEOL( root.getComment( commentBefore ) );
std::string::const_iterator iter = normalizedComment.begin();
while ( iter != normalizedComment.end() )
{
document_ += *iter;
if ( *iter == '\n' && *(iter+1) == '/' )
writeIndent();
++iter;
}
// Comments are stripped of newlines, so add one here
document_ += normalizeEOL( root.getComment( commentBefore ) );
document_ += "\n";
}
@@ -556,7 +545,6 @@ StyledStreamWriter::StyledStreamWriter( std::string indentation )
: document_(NULL)
, rightMargin_( 74 )
, indentation_( indentation )
, addChildValues_()
{
}
@@ -584,10 +572,10 @@ StyledStreamWriter::writeValue( const Value &value )
pushValue( "null" );
break;
case intValue:
pushValue( valueToString( value.asLargestInt() ) );
pushValue( valueToString( value.asInt() ) );
break;
case uintValue:
pushValue( valueToString( value.asLargestUInt() ) );
pushValue( valueToString( value.asUInt() ) );
break;
case realValue:
pushValue( valueToString( value.asDouble() ) );
@@ -611,7 +599,7 @@ StyledStreamWriter::writeValue( const Value &value )
writeWithIndent( "{" );
indent();
Value::Members::iterator it = members.begin();
for (;;)
while ( true )
{
const std::string &name = *it;
const Value &childValue = value[name];
@@ -651,7 +639,7 @@ StyledStreamWriter::writeArrayValue( const Value &value )
indent();
bool hasChildValue = !childValues_.empty();
unsigned index =0;
for (;;)
while ( true )
{
const Value &childValue = value[index];
writeCommentBeforeValue( childValue );
@@ -659,7 +647,7 @@ StyledStreamWriter::writeArrayValue( const Value &value )
writeWithIndent( childValues_[index] );
else
{
writeIndent();
writeIndent();
writeValue( childValue );
}
if ( ++index == size )
@@ -839,4 +827,3 @@ std::ostream& operator<<( std::ostream &sout, const Value &root )
} // namespace Json
// vim: et ts=3 sts=3 sw=3 tw=0

View File

@@ -1,14 +0,0 @@
// DO NOT EDIT. This file is generated by CMake from "version"
// and "version.h.in" files.
// Run CMake configure step to update it.
#ifndef JSON_VERSION_H_INCLUDED
# define JSON_VERSION_H_INCLUDED
# define JSONCPP_VERSION_STRING "@JSONCPP_VERSION@"
# define JSONCPP_VERSION_MAJOR @JSONCPP_VERSION_MAJOR@
# define JSONCPP_VERSION_MINOR @JSONCPP_VERSION_MINOR@
# define JSONCPP_VERSION_PATCH @JSONCPP_VERSION_PATCH@
# define JSONCPP_VERSION_QUALIFIER @JSONCPP_VERSION_QUALIFIER@
# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
#endif // JSON_VERSION_H_INCLUDED

View File

@@ -1,22 +0,0 @@
IF(JSONCPP_LIB_BUILD_SHARED)
ADD_DEFINITIONS( -DJSON_DLL )
ENDIF(JSONCPP_LIB_BUILD_SHARED)
ADD_EXECUTABLE( jsoncpp_test
jsontest.cpp
jsontest.h
main.cpp
)
TARGET_LINK_LIBRARIES(jsoncpp_test jsoncpp_lib)
# Run unit tests in post-build
# (default cmake workflow hides away the test result into a file, resulting in poor dev workflow?!?)
IF(JSONCPP_WITH_POST_BUILD_UNITTEST)
ADD_CUSTOM_COMMAND( TARGET jsoncpp_test
POST_BUILD
COMMAND jsoncpp_test)
ENDIF(JSONCPP_WITH_POST_BUILD_UNITTEST)
SET_TARGET_PROPERTIES(jsoncpp_test PROPERTIES OUTPUT_NAME jsoncpp_test)

View File

@@ -1,8 +1,3 @@
// Copyright 2007-2010 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#define _CRT_SECURE_NO_WARNINGS 1 // Prevents deprecation warning with MSVC
#include "jsontest.h"
#include <stdio.h>
@@ -249,24 +244,57 @@ TestResult::addToLastFailure( const std::string &message )
return *this;
}
TestResult &
TestResult::operator << ( Json::Int64 value ) {
return addToLastFailure( Json::valueToString(value) );
TestResult::operator << ( bool value )
{
return addToLastFailure( value ? "true" : "false" );
}
TestResult &
TestResult::operator << ( Json::UInt64 value ) {
return addToLastFailure( Json::valueToString(value) );
TestResult::operator << ( int value )
{
char buffer[32];
sprintf( buffer, "%d", value );
return addToLastFailure( buffer );
}
TestResult &
TestResult::operator << ( bool value ) {
return addToLastFailure(value ? "true" : "false");
TestResult::operator << ( unsigned int value )
{
char buffer[32];
sprintf( buffer, "%u", value );
return addToLastFailure( buffer );
}
TestResult &
TestResult::operator << ( double value )
{
char buffer[32];
sprintf( buffer, "%16g", value );
return addToLastFailure( buffer );
}
TestResult &
TestResult::operator << ( const char *value )
{
return addToLastFailure( value ? value
: "<NULL>" );
}
TestResult &
TestResult::operator << ( const std::string &value )
{
return addToLastFailure( value );
}
// class TestCase
// //////////////////////////////////////////////////////////////////
@@ -340,7 +368,7 @@ Runner::runTestAt( unsigned int index, TestResult &result ) const
catch ( const std::exception &e )
{
result.addFailure( __FILE__, __LINE__,
"Unexpected exception caught:" ) << e.what();
"Unexpected exception caugth:" ) << e.what();
}
#endif // if JSON_USE_EXCEPTION
delete test;
@@ -480,10 +508,10 @@ Runner::runCommandLine( int argc, const char *argv[] ) const
}
#if defined(_MSC_VER) && defined(_DEBUG)
#if defined(_MSC_VER)
// Hook MSVCRT assertions to prevent dialog from appearing
static int
msvcrtSilentReportHook( int reportType, char *message, int * /*returnValue*/ )
msvcrtSilentReportHook( int reportType, char *message, int *returnValue )
{
// The default CRT handling of error and assertion is to display
// an error dialog to the user.
@@ -517,11 +545,9 @@ msvcrtSilentReportHook( int reportType, char *message, int * /*returnValue*/ )
void
Runner::preventDialogOnCrash()
{
#if defined(_MSC_VER) && defined(_DEBUG)
#if defined(_MSC_VER)
// Install a hook to prevent MSVCRT error and assertion from
// popping a dialog
// This function a NO-OP in release configuration
// (which cause warning since msvcrtSilentReportHook is not referenced)
// popping a dialog.
_CrtSetReportHook( &msvcrtSilentReportHook );
#endif // if defined(_MSC_VER)
@@ -575,4 +601,3 @@ checkStringEqual( TestResult &result,
} // namespace JsonTest
// vim: et ts=4 sts=4 sw=4 tw=0

View File

@@ -1,17 +1,9 @@
// Copyright 2007-2010 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSONTEST_H_INCLUDED
# define JSONTEST_H_INCLUDED
# include <json/config.h>
# include <json/value.h>
# include <json/writer.h>
# include <stdio.h>
# include <deque>
# include <sstream>
# include <string>
// //////////////////////////////////////////////////////////////////
@@ -87,21 +79,12 @@ namespace JsonTest {
void printFailure( bool printTestName ) const;
// Generic operator that will work with anything ostream can deal with.
template <typename T>
TestResult &operator << ( const T& value ) {
std::ostringstream oss;
oss.precision( 16 );
oss.setf( std::ios_base::floatfield );
oss << value;
return addToLastFailure(oss.str());
}
// Specialized versions.
TestResult &operator << ( bool value );
// std:ostream does not support 64bits integers on all STL implementation
TestResult &operator << ( Json::Int64 value );
TestResult &operator << ( Json::UInt64 value );
TestResult &operator << ( int value );
TestResult &operator << ( unsigned int value );
TestResult &operator << ( double value );
TestResult &operator << ( const char *value );
TestResult &operator << ( const std::string &value );
private:
TestResult &addToLastFailure( const std::string &message );
@@ -185,21 +168,20 @@ namespace JsonTest {
Factories tests_;
};
template<typename T, typename U>
template<typename T>
TestResult &
checkEqual( TestResult &result, const T &expected, const U &actual,
checkEqual( TestResult &result, const T &expected, const T &actual,
const char *file, unsigned int line, const char *expr )
{
if ( static_cast< U >( expected ) != actual )
if ( expected != actual )
{
result.addFailure( file, line, expr );
result << "Expected: " << static_cast< U >( expected ) << "\n";
result << "Expected: " << expected << "\n";
result << "Actual : " << actual;
}
return result;
}
TestResult &
checkStringEqual( TestResult &result,
const std::string &expected, const std::string &actual,
@@ -212,7 +194,7 @@ namespace JsonTest {
/// JSONTEST_ASSERT( x == y ) << "x=" << x << ", y=" << y;
/// JSONTEST_ASSERT( x == y );
#define JSONTEST_ASSERT( expr ) \
if ( expr ) \
if ( condition ) \
{ \
} \
else \
@@ -229,7 +211,8 @@ namespace JsonTest {
result_->predicateStackTail_ = &_minitest_Context; \
(expr); \
result_->popPredicateContext(); \
}
} \
*result_
/// \brief Asserts that two values are equals.
#define JSONTEST_ASSERT_EQUAL( expected, actual ) \
@@ -241,7 +224,6 @@ namespace JsonTest {
#define JSONTEST_ASSERT_STRING_EQUAL( expected, actual ) \
JsonTest::checkStringEqual( *result_, \
std::string(expected), std::string(actual), \
__FILE__, __LINE__, \
#expected " == " #actual )
/// \brief Begin a fixture test case.
@@ -270,4 +252,3 @@ namespace JsonTest {
(runner).add( JSONTEST_FIXTURE_FACTORY( FixtureType, name ) )
#endif // ifndef JSONTEST_H_INCLUDED
// vim: et ts=4 sts=4 sw=4 tw=0

File diff suppressed because it is too large Load Diff

View File

@@ -1 +0,0 @@
[ 1 2 3]

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +1,8 @@
.={}
.test=[]
.test[0]={}
.test[0].a="aaa"
.test[1]={}
.test[1].b="bbb"
.test[2]={}
.test[2].c="ccc"
.={}
.test=[]
.test[0]={}
.test[0].a="aaa"
.test[1]={}
.test[1].b="bbb"
.test[2]={}
.test[2].c="ccc"

View File

@@ -1,8 +1,8 @@
{
"test":
[
{ "a" : "aaa" }, // Comment for a
{ "b" : "bbb" }, // Comment for b
{ "c" : "ccc" } // Comment for c
]
}
{
"test":
[
{ "a" : "aaa" }, // Comment for a
{ "b" : "bbb" }, // Comment for b
{ "c" : "ccc" } // Comment for c
]
}

View File

@@ -1,7 +0,0 @@
.={}
.c-test={}
.c-test.a=1
.c-test.b=2
.cpp-test={}
.cpp-test.c=3
.cpp-test.d=4

View File

@@ -1,16 +0,0 @@
{
/* C-style comment
C-style-2 comment */
"c-test" : {
"a" : 1,
/* Internal comment c-style */
"b" : 2
},
// C++-style comment
"cpp-test" : {
// Internal comment cpp-style
"c" : 3,
"d" : 4
}
}

View File

@@ -1 +0,0 @@
.=9223372036854775808

View File

@@ -1,2 +0,0 @@
9223372036854775808

View File

@@ -1 +0,0 @@
.=-9223372036854775808

View File

@@ -1,2 +0,0 @@
-9223372036854775808

View File

@@ -1 +0,0 @@
.=18446744073709551615

View File

@@ -1,2 +0,0 @@
18446744073709551615

View File

@@ -1 +0,0 @@
.=4300000001

View File

@@ -1,4 +0,0 @@
// Out of 32-bit integer range, switch to double in 32-bit mode. Length the
// same as UINT_MAX in base 10 and digit less than UINT_MAX's last digit in
// order to catch a bug in the parsing code.
4300000001

View File

@@ -1 +0,0 @@
.=1.9e+19

View File

@@ -1,4 +0,0 @@
// Out of 64-bit integer range, switch to double in all modes. Length the same
// as ULONG_MAX in base 10 and digit less than ULONG_MAX's last digit in order
// to catch a bug in the parsing code.
19000000000000000001

View File

@@ -1 +0,0 @@
.=-2200000001

View File

@@ -1,4 +0,0 @@
// Out of 32-bit signed integer range, switch to double in all modes. Length
// the same as INT_MIN in base 10 and digit less than INT_MIN's last digit in
// order to catch a bug in the parsing code.
-2200000001

View File

@@ -1 +0,0 @@
.=-9.3e+18

View File

@@ -1,4 +0,0 @@
// Out of 64-bit signed integer range, switch to double in all modes. Length
// the same as LONG_MIN in base 10 and digit less than LONG_MIN's last digit in
// order to catch a bug in the parsing code.
-9300000000000000001

View File

@@ -1 +0,0 @@
.=1.844674407370955e+19

View File

@@ -1,2 +0,0 @@
// 2^64 -> switch to double.
18446744073709551616

View File

@@ -1 +1 @@
"!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
"!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"

View File

@@ -1 +1 @@
"!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
"!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"

View File

@@ -1 +0,0 @@
.="http://jsoncpp.sourceforge.net/"

View File

@@ -1 +0,0 @@
"http:\/\/jsoncpp.sourceforge.net\/"

View File

@@ -1,2 +0,0 @@
.=""abc\def""

View File

@@ -1,2 +0,0 @@
"\"abc\\def\""

View File

@@ -1,2 +0,0 @@
.="\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"

View File

@@ -1,2 +0,0 @@
"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"

View File

@@ -1 +1 @@
.="a"
.="a"

View File

@@ -1 +1 @@
.="¢"
.="¢"

View File

@@ -1 +1 @@
.="€"
.="€"

View File

@@ -1 +1 @@
.="𝄞"
.="𝄞"

View File

@@ -1,2 +1,2 @@
.="Zażółć gęślą jaźń"
.="Zażółć gęślą jaźń"

View File

@@ -1,3 +1,3 @@
Test suite from http://json.org/JSON_checker/.
If the JSON_checker is working correctly, it must accept all of the pass*.json files and reject all of the fail*.json files.
Test suite from http://json.org/JSON_checker/.
If the JSON_checker is working correctly, it must accept all of the pass*.json files and reject all of the fail*.json files.

View File

@@ -49,8 +49,7 @@ def runAllTests( jsontest_executable_path, input_dir = None,
failed_tests = []
valgrind_path = use_valgrind and VALGRIND_CMD or ''
for input_path in tests + test_jsonchecker:
expect_failure = os.path.basename( input_path ).startswith( 'fail' )
is_json_checker_test = (input_path in test_jsonchecker) or expect_failure
is_json_checker_test = input_path in test_jsonchecker
print 'TESTING:', input_path,
options = is_json_checker_test and '--json-checker' or ''
pipe = os.popen( "%s%s %s %s" % (
@@ -59,6 +58,7 @@ def runAllTests( jsontest_executable_path, input_dir = None,
process_output = pipe.read()
status = pipe.close()
if is_json_checker_test:
expect_failure = os.path.basename( input_path ).startswith( 'fail' )
if expect_failure:
if status is None:
print 'FAILED'

View File

@@ -1,73 +1,73 @@
import sys
import os
import os.path
import subprocess
from glob import glob
import optparse
VALGRIND_CMD = 'valgrind --tool=memcheck --leak-check=yes --undef-value-errors=yes'
class TestProxy(object):
def __init__( self, test_exe_path, use_valgrind=False ):
self.test_exe_path = os.path.normpath( os.path.abspath( test_exe_path ) )
self.use_valgrind = use_valgrind
def run( self, options ):
if self.use_valgrind:
cmd = VALGRIND_CMD.split()
else:
cmd = []
cmd.extend( [self.test_exe_path, '--test-auto'] + options )
process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
stdout = process.communicate()[0]
if process.returncode:
return False, stdout
return True, stdout
def runAllTests( exe_path, use_valgrind=False ):
test_proxy = TestProxy( exe_path, use_valgrind=use_valgrind )
status, test_names = test_proxy.run( ['--list-tests'] )
if not status:
print >> sys.stderr, "Failed to obtain unit tests list:\n" + test_names
return 1
test_names = [name.strip() for name in test_names.strip().split('\n')]
failures = []
for name in test_names:
print 'TESTING %s:' % name,
succeed, result = test_proxy.run( ['--test', name] )
if succeed:
print 'OK'
else:
failures.append( (name, result) )
print 'FAILED'
failed_count = len(failures)
pass_count = len(test_names) - failed_count
if failed_count:
print
for name, result in failures:
print result
print '%d/%d tests passed (%d failure(s))' % (
pass_count, len(test_names), failed_count)
return 1
else:
print 'All %d tests passed' % len(test_names)
return 0
def main():
from optparse import OptionParser
parser = OptionParser( usage="%prog [options] <path to test_lib_json.exe>" )
parser.add_option("--valgrind",
action="store_true", dest="valgrind", default=False,
help="run all the tests using valgrind to detect memory leaks")
parser.enable_interspersed_args()
options, args = parser.parse_args()
if len(args) != 1:
parser.error( 'Must provides at least path to test_lib_json executable.' )
sys.exit( 1 )
exit_code = runAllTests( args[0], use_valgrind=options.valgrind )
sys.exit( exit_code )
if __name__ == '__main__':
main()
import sys
import os
import os.path
import subprocess
from glob import glob
import optparse
VALGRIND_CMD = 'valgrind --tool=memcheck --leak-check=yes --undef-value-errors=yes'
class TestProxy(object):
def __init__( self, test_exe_path, use_valgrind=False ):
self.test_exe_path = os.path.normpath( os.path.abspath( test_exe_path ) )
self.use_valgrind = use_valgrind
def run( self, options ):
if self.use_valgrind:
cmd = VALGRIND_CMD.split()
else:
cmd = []
cmd.extend( [self.test_exe_path, '--test-auto'] + options )
process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
stdout = process.communicate()[0]
if process.returncode:
return False, stdout
return True, stdout
def runAllTests( exe_path, use_valgrind=False ):
test_proxy = TestProxy( exe_path, use_valgrind=use_valgrind )
status, test_names = test_proxy.run( ['--list-tests'] )
if not status:
print >> sys.stderr, "Failed to obtain unit tests list:\n" + test_names
return 1
test_names = [name.strip() for name in test_names.strip().split('\n')]
failures = []
for name in test_names:
print 'TESTING %s:' % name,
succeed, result = test_proxy.run( ['--test', name] )
if succeed:
print 'OK'
else:
failures.append( (name, result) )
print 'FAILED'
failed_count = len(failures)
pass_count = len(test_names) - failed_count
if failed_count:
print
for name, result in failures:
print result
print '%d/%d tests passed (%d failure(s))' % (
pass_count, len(test_names), failed_count)
return 1
else:
print 'All %d tests passed' % len(test_names)
return 0
def main():
from optparse import OptionParser
parser = OptionParser( usage="%prog [options] <path to test_lib_json.exe>" )
parser.add_option("--valgrind",
action="store_true", dest="valgrind", default=False,
help="run all the tests using valgrind to detect memory leaks")
parser.enable_interspersed_args()
options, args = parser.parse_args()
if len(args) != 1:
parser.error( 'Must provides at least path to test_lib_json executable.' )
sys.exit( 1 )
exit_code = runAllTests( args[0], use_valgrind=options.valgrind )
sys.exit( exit_code )
if __name__ == '__main__':
main()

View File

@@ -1 +1 @@
0.6.0-dev
0.5.0