aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordavilla <davilla@svn>2010-02-13 17:53:47 +0000
committerdavilla <davilla@svn>2010-02-13 17:53:47 +0000
commit9ac3aa97a6d139116f0c2ec2d2ae12e35a64d611 (patch)
treec3e6db1c2d126335adefe560fd15740b7ab78031
parent216555f7400cbd9190799b750a512707782d637a (diff)
commit jsoncpp-r91 into trunk
git-svn-id: https://xbmc.svn.sourceforge.net/svnroot/xbmc/trunk@27729 568bbfeb-2a22-0410-94d2-cc84cf5bfa90
-rw-r--r--lib/jsoncpp/jsoncpp/AUTHORS1
-rw-r--r--lib/jsoncpp/jsoncpp/README.txt53
-rw-r--r--lib/jsoncpp/jsoncpp/SConstruct300
-rw-r--r--lib/jsoncpp/jsoncpp/doc/doxyfile.in232
-rw-r--r--lib/jsoncpp/jsoncpp/doc/footer.html23
-rw-r--r--lib/jsoncpp/jsoncpp/doc/header.html24
-rw-r--r--lib/jsoncpp/jsoncpp/doc/jsoncpp.dox97
-rw-r--r--lib/jsoncpp/jsoncpp/doc/readme.txt1
-rw-r--r--lib/jsoncpp/jsoncpp/doc/roadmap.dox35
-rw-r--r--lib/jsoncpp/jsoncpp/doc/sconscript61
-rw-r--r--lib/jsoncpp/jsoncpp/include/json/autolink.h19
-rw-r--r--lib/jsoncpp/jsoncpp/include/json/config.h43
-rw-r--r--lib/jsoncpp/jsoncpp/include/json/features.h42
-rw-r--r--lib/jsoncpp/jsoncpp/include/json/forwards.h34
-rw-r--r--lib/jsoncpp/jsoncpp/include/json/json.h10
-rw-r--r--lib/jsoncpp/jsoncpp/include/json/reader.h196
-rw-r--r--lib/jsoncpp/jsoncpp/include/json/value.h1068
-rw-r--r--lib/jsoncpp/jsoncpp/include/json/writer.h174
-rw-r--r--lib/jsoncpp/jsoncpp/makefiles/vs71/jsoncpp.sln46
-rw-r--r--lib/jsoncpp/jsoncpp/makefiles/vs71/jsontest.vcproj119
-rw-r--r--lib/jsoncpp/jsoncpp/makefiles/vs71/lib_json.vcproj214
-rw-r--r--lib/jsoncpp/jsoncpp/makefiles/vs71/test_lib_json.vcproj130
-rw-r--r--lib/jsoncpp/jsoncpp/scons-tools/doxygen.py116
-rw-r--r--lib/jsoncpp/jsoncpp/scons-tools/globtool.py53
-rw-r--r--lib/jsoncpp/jsoncpp/scons-tools/srcdist.py179
-rw-r--r--lib/jsoncpp/jsoncpp/scons-tools/substinfile.py79
-rw-r--r--lib/jsoncpp/jsoncpp/scons-tools/targz.py82
-rw-r--r--lib/jsoncpp/jsoncpp/src/jsontestrunner/main.cpp233
-rw-r--r--lib/jsoncpp/jsoncpp/src/jsontestrunner/sconscript9
-rw-r--r--lib/jsoncpp/jsoncpp/src/lib_json/json_batchallocator.h125
-rw-r--r--lib/jsoncpp/jsoncpp/src/lib_json/json_internalarray.inl448
-rw-r--r--lib/jsoncpp/jsoncpp/src/lib_json/json_internalmap.inl607
-rw-r--r--lib/jsoncpp/jsoncpp/src/lib_json/json_reader.cpp885
-rw-r--r--lib/jsoncpp/jsoncpp/src/lib_json/json_value.cpp1703
-rw-r--r--lib/jsoncpp/jsoncpp/src/lib_json/json_valueiterator.inl292
-rw-r--r--lib/jsoncpp/jsoncpp/src/lib_json/json_writer.cpp829
-rw-r--r--lib/jsoncpp/jsoncpp/src/lib_json/sconscript8
-rw-r--r--lib/jsoncpp/jsoncpp/src/test_lib_json/jsontest.cpp598
-rw-r--r--lib/jsoncpp/jsoncpp/src/test_lib_json/jsontest.h252
-rw-r--r--lib/jsoncpp/jsoncpp/src/test_lib_json/main.cpp244
-rw-r--r--lib/jsoncpp/jsoncpp/src/test_lib_json/sconscript10
-rw-r--r--lib/jsoncpp/jsoncpp/test/cleantests.py10
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_array_01.expected1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_array_01.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_array_02.expected2
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_array_02.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_array_03.expected6
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_array_03.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_array_04.expected5
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_array_04.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_array_05.expected100
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_array_05.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_array_06.expected5
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_array_06.json4
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_basic_01.expected1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_basic_01.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_basic_02.expected1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_basic_02.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_basic_03.expected3
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_basic_03.json3
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_basic_04.expected2
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_basic_04.json2
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_basic_05.expected2
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_basic_05.json2
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_basic_06.expected2
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_basic_06.json2
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_basic_07.expected2
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_basic_07.json2
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_basic_08.expected2
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_basic_08.json3
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_basic_09.expected2
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_basic_09.json4
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_comment_01.expected8
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_comment_01.json8
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_complex_01.expected20
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_complex_01.json17
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_integer_01.expected1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_integer_01.json2
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_integer_02.expected1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_integer_02.json2
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_integer_03.expected1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_integer_03.json2
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_integer_04.expected2
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_integer_04.json3
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_integer_05.expected2
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_integer_05.json2
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_object_01.expected1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_object_01.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_object_02.expected2
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_object_02.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_object_03.expected4
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_object_03.json5
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_object_04.expected2
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_object_04.json3
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_preserve_comment_01.expected3
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_preserve_comment_01.json14
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_real_01.expected2
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_real_01.json3
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_real_02.expected2
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_real_02.json3
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_real_03.expected2
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_real_03.json3
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_real_04.expected2
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_real_04.json3
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_real_05.expected3
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_real_05.json3
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_real_06.expected3
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_real_06.json3
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_real_07.expected3
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_real_07.json3
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_string_01.expected1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_string_01.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_string_02.expected1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_string_02.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_string_unicode_01.expected1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_string_unicode_01.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_string_unicode_02.expected1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_string_unicode_02.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_string_unicode_03.expected1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_string_unicode_03.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_string_unicode_04.expected1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_string_unicode_04.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_string_unicode_05.expected1
-rw-r--r--lib/jsoncpp/jsoncpp/test/data/test_string_unicode_05.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/generate_expected.py11
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail1.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail10.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail11.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail12.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail13.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail14.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail15.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail16.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail17.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail18.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail19.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail2.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail20.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail21.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail22.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail23.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail24.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail25.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail26.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail27.json2
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail28.json2
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail29.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail3.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail30.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail31.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail32.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail33.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail4.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail5.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail6.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail7.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail8.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/fail9.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/pass1.json58
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/pass2.json1
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/pass3.json6
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsonchecker/readme.txt3
-rw-r--r--lib/jsoncpp/jsoncpp/test/jsontestrunner.py64
-rw-r--r--lib/jsoncpp/jsoncpp/test/runjsontests.py132
-rw-r--r--lib/jsoncpp/jsoncpp/test/rununittests.py73
165 files changed, 10391 insertions, 0 deletions
diff --git a/lib/jsoncpp/jsoncpp/AUTHORS b/lib/jsoncpp/jsoncpp/AUTHORS
new file mode 100644
index 0000000000..c0fbbeec11
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/AUTHORS
@@ -0,0 +1 @@
+Baptiste Lepilleur <blep@users.sourceforge.net>
diff --git a/lib/jsoncpp/jsoncpp/README.txt b/lib/jsoncpp/jsoncpp/README.txt
new file mode 100644
index 0000000000..c1b2c73383
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/README.txt
@@ -0,0 +1,53 @@
+* Introduction:
+
+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 is a simple API to manipulate JSON value, and 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.
+
+* 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/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.
+
+python scons.py platform=PLTFRM [TARGET]
+where PLTFRM may be one of:
+ suncc Sun C++ (Solaris)
+ vacpp Visual Age C++ (AIX)
+ mingw
+ msvc6 Microsoft Visual Studio 6 service pack 5-6
+ msvc70 Microsoft Visual Studio 2002
+ msvc71 Microsoft Visual Studio 2003
+ msvc80 Microsoft Visual Studio 2005
+ linux-gcc Gnu C++ (linux, also reported to work for Mac OS X)
+
+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.
+ doc: build documentation
+ doc-dist: build documentation tarball
+
+To run the test manually:
+cd test
+# This will run the Reader/Writer tests
+python runjsontests.py "path to jsontest.exe"
+# This will run the unit tests (mostly Value)
+python rununittests.py "path to test_lib_json.exe"
+
+You can run the tests using valgrind using:
+python rununittests.py --valgrind "path to test_lib_json.exe"
diff --git a/lib/jsoncpp/jsoncpp/SConstruct b/lib/jsoncpp/jsoncpp/SConstruct
new file mode 100644
index 0000000000..00d37411bd
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/SConstruct
@@ -0,0 +1,300 @@
+"""
+Build system can be clean-up by sticking to a few core production factory, with automatic dependencies resolution.
+4 basic project productions:
+- library
+- binary
+- documentation
+- tests
+
+* Library:
+ Input:
+ - dependencies (other libraries)
+ - headers: include path & files
+ - sources
+ - generated sources
+ - resources
+ - generated resources
+ Production:
+ - Static library
+ - Dynamic library
+ - Naming rule
+ Life-cycle:
+ - Library compilation
+ - Compilation as a dependencies
+ - Run-time
+ - Packaging
+ Identity:
+ - Name
+ - Version
+* Binary:
+ Input:
+ - dependencies (other libraries)
+ - headers: include path & files (usually empty)
+ - sources
+ - generated sources
+ - resources
+ - generated resources
+ - supported variant (optimized/debug, dll/static...)
+ Production:
+ - Binary executable
+ - Manifest [on some platforms]
+ - Debug symbol [on some platforms]
+ Life-cycle:
+ - Compilation
+ - Run-time
+ - Packaging
+ Identity:
+ - Name
+ - Version
+* Documentation:
+ Input:
+ - dependencies (libraries, binaries)
+ - additional sources
+ - generated sources
+ - resources
+ - generated resources
+ - supported variant (public/internal)
+ Production:
+ - HTML documentation
+ - PDF documentation
+ - CHM documentation
+ Life-cycle:
+ - Documentation
+ - Packaging
+ - Test
+ Identity:
+ - Name
+ - Version
+"""
+
+
+
+import os
+import os.path
+import sys
+
+JSONCPP_VERSION = '0.2'
+DIST_DIR = '#dist'
+
+options = Variables()
+options.Add( EnumVariable('platform',
+ 'Platform (compiler/stl) used to build the project',
+ 'msvc71',
+ allowed_values='suncc vacpp mingw msvc6 msvc7 msvc71 msvc80 linux-gcc'.split(),
+ ignorecase=2) )
+
+try:
+ platform = ARGUMENTS['platform']
+ if platform == 'linux-gcc':
+ CXX = 'g++' # not quite right, but env is not yet available.
+ import commands
+ version = commands.getoutput('%s -dumpversion' %CXX)
+ platform = 'linux-gcc-%s' %version
+ print "Using platform '%s'" %platform
+ LD_LIBRARY_PATH = os.environ.get('LD_LIBRARY_PATH', '')
+ LD_LIBRARY_PATH = "%s:libs/%s" %(LD_LIBRARY_PATH, platform)
+ os.environ['LD_LIBRARY_PATH'] = LD_LIBRARY_PATH
+ print "LD_LIBRARY_PATH =", LD_LIBRARY_PATH
+except KeyError:
+ print 'You must specify a "platform"'
+ sys.exit(2)
+
+print "Building using PLATFORM =", platform
+
+rootbuild_dir = Dir('#buildscons')
+build_dir = os.path.join( '#buildscons', platform )
+bin_dir = os.path.join( '#bin', platform )
+lib_dir = os.path.join( '#libs', platform )
+sconsign_dir_path = Dir(build_dir).abspath
+sconsign_path = os.path.join( sconsign_dir_path, '.sconsign.dbm' )
+
+# Ensure build directory exist (SConsignFile fail otherwise!)
+if not os.path.exists( sconsign_dir_path ):
+ os.makedirs( sconsign_dir_path )
+
+# Store all dependencies signature in a database
+SConsignFile( sconsign_path )
+
+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
+ vars = {}
+ for name in ('PATH', 'TEMP', 'TMP'):
+ if name in os.environ:
+ vars[name] = os.environ[name]
+ return vars
+
+
+env = Environment( ENV = make_environ_vars(),
+ toolpath = ['scons-tools'],
+ tools=[] ) #, tools=['default'] )
+
+if platform == 'suncc':
+ env.Tool( 'sunc++' )
+ env.Tool( 'sunlink' )
+ env.Tool( 'sunar' )
+ env.Append( CCFLAGS = ['-mt'] )
+elif platform == 'vacpp':
+ env.Tool( 'default' )
+ env.Tool( 'aixcc' )
+ env['CXX'] = 'xlC_r' #scons does not pick-up the correct one !
+ # using xlC_r ensure multi-threading is enabled:
+ # http://publib.boulder.ibm.com/infocenter/pseries/index.jsp?topic=/com.ibm.vacpp7a.doc/compiler/ref/cuselect.htm
+ env.Append( CCFLAGS = '-qrtti=all',
+ LINKFLAGS='-bh:5' ) # -bh:5 remove duplicate symbol warning
+elif platform == 'msvc6':
+ env['MSVS_VERSION']='6.0'
+ for tool in ['msvc', 'msvs', 'mslink', 'masm', 'mslib']:
+ env.Tool( tool )
+ env['CXXFLAGS']='-GR -GX /nologo /MT'
+elif platform == 'msvc70':
+ env['MSVS_VERSION']='7.0'
+ for tool in ['msvc', 'msvs', 'mslink', 'masm', 'mslib']:
+ env.Tool( tool )
+ env['CXXFLAGS']='-GR -GX /nologo /MT'
+elif platform == 'msvc71':
+ env['MSVS_VERSION']='7.1'
+ for tool in ['msvc', 'msvs', 'mslink', 'masm', 'mslib']:
+ env.Tool( tool )
+ env['CXXFLAGS']='-GR -GX /nologo /MT'
+elif platform == 'msvc80':
+ env['MSVS_VERSION']='8.0'
+ 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" ] )
+elif platform.startswith('linux-gcc'):
+ env.Tool( 'default' )
+ env.Append( LIBS = ['pthread'], CCFLAGS = "-Wall" )
+ env['SHARED_LIB_ENABLED'] = True
+else:
+ print "UNSUPPORTED PLATFORM."
+ env.Exit(1)
+
+env.Tool('doxygen')
+env.Tool('substinfile')
+env.Tool('targz')
+env.Tool('srcdist')
+env.Tool('globtool')
+
+env.Append( CPPPATH = ['#include'],
+ LIBPATH = lib_dir )
+short_platform = platform
+if short_platform.startswith('msvc'):
+ short_platform = short_platform[2:]
+# Notes: on Windows you need to rebuild the source for each variant
+# Build script does not support that yet so we only build static libraries.
+# This also fails on AIX because both dynamic and static library ends with
+# extension .a.
+env['SHARED_LIB_ENABLED'] = env.get('SHARED_LIB_ENABLED', False)
+env['LIB_PLATFORM'] = short_platform
+env['LIB_LINK_TYPE'] = 'lib' # static
+env['LIB_CRUNTIME'] = 'mt'
+env['LIB_NAME_SUFFIX'] = '${LIB_PLATFORM}_${LIB_LINK_TYPE}${LIB_CRUNTIME}' # must match autolink naming convention
+env['JSONCPP_VERSION'] = JSONCPP_VERSION
+env['BUILD_DIR'] = env.Dir(build_dir)
+env['ROOTBUILD_DIR'] = env.Dir(rootbuild_dir)
+env['DIST_DIR'] = DIST_DIR
+if 'TarGz' in env['BUILDERS']:
+ class SrcDistAdder:
+ def __init__( self, env ):
+ self.env = env
+ def __call__( self, *args, **kw ):
+ apply( self.env.SrcDist, (self.env['SRCDIST_TARGET'],) + args, kw )
+ env['SRCDIST_BUILDER'] = env.TarGz
+else: # If tarfile module is missing
+ class SrcDistAdder:
+ def __init__( self, env ):
+ pass
+ def __call__( self, *args, **kw ):
+ pass
+env['SRCDIST_ADD'] = SrcDistAdder( env )
+env['SRCDIST_TARGET'] = os.path.join( DIST_DIR, 'jsoncpp-src-%s.tar.gz' % env['JSONCPP_VERSION'] )
+
+env_testing = env.Clone( )
+env_testing.Append( LIBS = ['json_${LIB_NAME_SUFFIX}'] )
+
+def buildJSONExample( env, target_sources, target_name ):
+ env = env.Clone()
+ env.Append( CPPPATH = ['#'] )
+ exe = env.Program( target=target_name,
+ source=target_sources )
+ env['SRCDIST_ADD']( source=[target_sources] )
+ global bin_dir
+ return env.Install( bin_dir, exe )
+
+def buildJSONTests( env, target_sources, target_name ):
+ jsontests_node = buildJSONExample( env, target_sources, target_name )
+ check_alias_target = env.Alias( 'check', jsontests_node, RunJSONTests( jsontests_node, jsontests_node ) )
+ env.AlwaysBuild( check_alias_target )
+
+def buildUnitTests( env, target_sources, target_name ):
+ jsontests_node = buildJSONExample( env, target_sources, target_name )
+ check_alias_target = env.Alias( 'check', jsontests_node,
+ RunUnitTests( jsontests_node, jsontests_node ) )
+ env.AlwaysBuild( check_alias_target )
+
+def buildLibrary( env, target_sources, target_name ):
+ static_lib = env.StaticLibrary( target=target_name + '_${LIB_NAME_SUFFIX}',
+ source=target_sources )
+ global lib_dir
+ env.Install( lib_dir, static_lib )
+ if env['SHARED_LIB_ENABLED']:
+ shared_lib = env.SharedLibrary( target=target_name + '_${LIB_NAME_SUFFIX}',
+ source=target_sources )
+ env.Install( lib_dir, shared_lib )
+ env['SRCDIST_ADD']( source=[target_sources] )
+
+Export( 'env env_testing buildJSONExample buildLibrary buildJSONTests buildUnitTests' )
+
+def buildProjectInDirectory( target_directory ):
+ global build_dir
+ target_build_dir = os.path.join( build_dir, target_directory )
+ target = os.path.join( target_directory, 'sconscript' )
+ SConscript( target, build_dir=target_build_dir, duplicate=0 )
+ env['SRCDIST_ADD']( source=[target] )
+
+
+def runJSONTests_action( target, source = None, env = None ):
+ # Add test scripts to python path
+ jsontest_path = Dir( '#test' ).abspath
+ sys.path.insert( 0, jsontest_path )
+ data_path = os.path.join( jsontest_path, 'data' )
+ import runjsontests
+ return runjsontests.runAllTests( os.path.abspath(source[0].path), data_path )
+
+def runJSONTests_string( target, source = None, env = None ):
+ return 'RunJSONTests("%s")' % source[0]
+
+import SCons.Action
+ActionFactory = SCons.Action.ActionFactory
+RunJSONTests = ActionFactory(runJSONTests_action, runJSONTests_string )
+
+def runUnitTests_action( target, source = None, env = None ):
+ # Add test scripts to python path
+ jsontest_path = Dir( '#test' ).abspath
+ sys.path.insert( 0, jsontest_path )
+ import rununittests
+ return rununittests.runAllTests( os.path.abspath(source[0].path) )
+
+def runUnitTests_string( target, source = None, env = None ):
+ return 'RunUnitTests("%s")' % source[0]
+
+RunUnitTests = ActionFactory(runUnitTests_action, runUnitTests_string )
+
+env.Alias( 'check' )
+
+srcdist_cmd = env['SRCDIST_ADD']( source = """
+ AUTHORS README.txt SConstruct
+ """.split() )
+env.Alias( 'src-dist', srcdist_cmd )
+
+buildProjectInDirectory( 'src/jsontestrunner' )
+buildProjectInDirectory( 'src/lib_json' )
+buildProjectInDirectory( 'src/test_lib_json' )
+buildProjectInDirectory( 'doc' )
+#print env.Dump()
+
diff --git a/lib/jsoncpp/jsoncpp/doc/doxyfile.in b/lib/jsoncpp/jsoncpp/doc/doxyfile.in
new file mode 100644
index 0000000000..f19f037705
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/doc/doxyfile.in
@@ -0,0 +1,232 @@
+# Doxyfile 1.4.3
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = "JsonCpp"
+PROJECT_NUMBER = %JSONCPP_VERSION%
+OUTPUT_DIRECTORY = %DOC_TOPDIR%
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+USE_WINDOWS_ENCODING = NO
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+ALWAYS_DETAILED_SEC = NO
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH = %TOPDIR%
+STRIP_FROM_INC_PATH = %TOPDIR%/include
+SHORT_NAMES = NO
+JAVADOC_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP = NO
+INHERIT_DOCS = YES
+DISTRIBUTE_GROUP_DOC = NO
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 3
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = NO
+SUBGROUPING = YES
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = YES
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = YES
+EXTRACT_LOCAL_CLASSES = NO
+EXTRACT_LOCAL_METHODS = NO
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = NO
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = YES
+CASE_SENSE_NAMES = NO
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = YES
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+SORT_BRIEF_DOCS = NO
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = YES
+SHOW_DIRECTORIES = YES
+FILE_VERSION_FILTER =
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = NO
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE = jsoncpp-doxygen-warning.log
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = ../include ../src/lib_json .
+FILE_PATTERNS = *.h *.cpp *.dox
+RECURSIVE = YES
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS = *
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = YES
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION = YES
+USE_HTAGS = NO
+VERBATIM_HEADERS = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = NO
+COLS_IN_ALPHA_INDEX = 5
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = json-html-doc-%JSONCPP_VERSION%
+HTML_FILE_EXTENSION = .html
+HTML_HEADER = header.html
+HTML_FOOTER = footer.html
+HTML_STYLESHEET =
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+CHM_FILE = jsoncpp.chm
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = NO
+ENUM_VALUES_PER_LINE = 4
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4wide
+EXTRA_PACKAGES =
+LATEX_HEADER =
+PDF_HYPERLINKS = NO
+USE_PDFLATEX = NO
+LATEX_BATCHMODE = NO
+LATEX_HIDE_INDICES = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
+XML_OUTPUT = xml
+XML_SCHEMA =
+XML_DTD =
+XML_PROGRAMLISTING = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD = NO
+PERLMOD_LATEX = NO
+PERLMOD_PRETTY = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = NO
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = YES
+INCLUDE_PATH = ../include
+INCLUDE_FILE_PATTERNS = *.h
+PREDEFINED = JSONCPP_DOC_EXCLUDE_IMPLEMENTATION JSON_VALUE_USE_INTERNAL_MAP
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+TAGFILES =
+GENERATE_TAGFILE =
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = NO
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = NO
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+GROUP_GRAPHS = YES
+UML_LOOK = NO
+TEMPLATE_RELATIONS = NO
+INCLUDE_GRAPH = YES
+INCLUDED_BY_GRAPH = YES
+CALL_GRAPH = NO
+GRAPHICAL_HIERARCHY = YES
+DIRECTORY_GRAPH = YES
+DOT_IMAGE_FORMAT = png
+DOT_PATH =
+DOTFILE_DIRS =
+MAX_DOT_GRAPH_WIDTH = 1024
+MAX_DOT_GRAPH_HEIGHT = 1024
+MAX_DOT_GRAPH_DEPTH = 1000
+DOT_TRANSPARENT = NO
+DOT_MULTI_TARGETS = NO
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
diff --git a/lib/jsoncpp/jsoncpp/doc/footer.html b/lib/jsoncpp/jsoncpp/doc/footer.html
new file mode 100644
index 0000000000..a61d9528a1
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/doc/footer.html
@@ -0,0 +1,23 @@
+<hr>
+<table width="100%">
+ <tr>
+ <td width="10%" align="left" valign="center">
+ <a href="http://sourceforge.net">
+ <img
+ src="http://sourceforge.net/sflogo.php?group_id=144446"
+ width="88" height="31" border="0" alt="SourceForge Logo"></a>
+ </td>
+ <td width="20%" align="left" valign="center">
+ hosts this site.
+ </td>
+ <td>
+ </td>
+ <td align="right" valign="center">
+ Send comments to:<br>
+ <a href="mailto:jsoncpp-devel@lists.sourceforge.net">Json-cpp Developers</a>
+ </td>
+ </tr>
+</table>
+
+</body>
+</html>
diff --git a/lib/jsoncpp/jsoncpp/doc/header.html b/lib/jsoncpp/jsoncpp/doc/header.html
new file mode 100644
index 0000000000..d56ea59c69
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/doc/header.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<title>
+JsonCpp - JSON data format manipulation library
+</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head>
+
+<body bgcolor="#ffffff">
+<table width="100%">
+ <tr>
+ <td width="40%" align="left" valign="center">
+ <a href="http://sourceforge.net/projects/jsoncpp">
+ JsonCpp project page
+ </a>
+ </td>
+ <td width="40%" align="right" valign="center">
+ <a href="http://jsoncpp.sourceforge.net">JsonCpp home page</a>
+ </td>
+ </tr>
+</table>
+
+<hr>
diff --git a/lib/jsoncpp/jsoncpp/doc/jsoncpp.dox b/lib/jsoncpp/jsoncpp/doc/jsoncpp.dox
new file mode 100644
index 0000000000..fc7b530eba
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/doc/jsoncpp.dox
@@ -0,0 +1,97 @@
+/**
+\mainpage
+\section _intro Introduction
+
+<a HREF="http://www.json.org/">JSON (JavaScript Object Notation)</a>
+ is a lightweight data-interchange format.
+It can represents integer, real number, string, an ordered sequence of value, and
+a collection of name/value pairs.
+
+Here is an example of JSON data:
+\verbatim
+// Configuration options
+{
+ // Default encoding for text
+ "encoding" : "UTF-8",
+
+ // Plug-ins loaded at start-up
+ "plug-ins" : [
+ "python",
+ "c++",
+ "ruby"
+ ],
+
+ // Tab indent size
+ "indent" : { "length" : 3, "use_space" = true }
+}
+\endverbatim
+
+\section _features Features
+- read and write JSON document
+- rewrite JSON document preserving original comments
+
+\code
+Json::Value root; // will contains the root value after parsing.
+Json::Reader reader;
+bool parsingSuccessful = reader.parse( config_doc, root );
+if ( !parsingSuccessful )
+{
+ // report to the user the failure and their locations in the document.
+ std::cout << "Failed to parse configuration\n"
+ << reader.getFormatedErrorMessages();
+ return;
+}
+
+// Get the value of the member of root named 'encoding', return 'UTF-8' if there is no
+// such member.
+std::string encoding = root.get("encoding", "UTF-8" ).asString();
+// Get the value of the member of root named 'encoding', return a 'null' value if
+// there is no such member.
+const Json::Value plugins = root["plug-ins"];
+for ( int index = 0; index < plugins.size(); ++index ) // Iterates over the sequence elements.
+ loadPlugIn( plugins[index].asString() );
+
+setIndentLength( root["indent"].get("length", 3).asInt() );
+setIndentUseSpace( root["indent"].get("use_space", true).asBool() );
+
+// ...
+// At application shutdown to make the new configuration document:
+// Since Json::Value has implicit constructor for all value types, it is not
+// necessary to explicitely construct the Json::Value object:
+root["encoding"] = getCurrentEncoding();
+root["indent"]["length"] = getCurrentIndentLength();
+root["indent"]["use_space"] = getCurrentIndentUseSpace();
+
+Json::StyledWriter writer;
+// Make a new JSON document for the configuration. Preserve original comments.
+std::string outputConfig = writer.write( root );
+
+// You can also use streams. This will put the contents of any JSON
+// stream at a particular sub-value, if you'd like.
+std::cin >> root["subtree"];
+
+// And you can write to a stream, using the StyledWriter automatically.
+std::cout << root;
+\endcode
+
+\section _plinks Build instructions
+The build instruction are located in the file
+<a HREF="README.txt">README.txt</a> in the top-directory of the project.
+
+Permanent link to the lastest revision of the file in subversion:
+<a HREF="http://svn.sourceforge.net/viewcvs.cgi/jsoncpp/README.txt?view=markup">lastest README.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>
+
+\section _rlinks Related links
+- <a HREF="http://www.json.org/">JSON</a> Specification and alternate language implementations.
+- <a HREF="http://www.yaml.org/">YAML</a> A data format designed for human readability.
+- <a HREF="http://www.cl.cam.ac.uk/~mgk25/unicode.html">UTF-8 and Unicode FAQ</a>.
+
+\section _license License
+The json-cpp library and this documentation are in Public Domain.
+
+\author Baptiste Lepilleur <blep@users.sourceforge.net>
+*/
diff --git a/lib/jsoncpp/jsoncpp/doc/readme.txt b/lib/jsoncpp/jsoncpp/doc/readme.txt
new file mode 100644
index 0000000000..0e42cdfb4c
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/doc/readme.txt
@@ -0,0 +1 @@
+The documentation is generated using doxygen (http://www.doxygen.org).
diff --git a/lib/jsoncpp/jsoncpp/doc/roadmap.dox b/lib/jsoncpp/jsoncpp/doc/roadmap.dox
new file mode 100644
index 0000000000..84648b9eed
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/doc/roadmap.dox
@@ -0,0 +1,35 @@
+/*! \page roadmap JsonCpp roadmap
+ \section ms_release Makes JsonCpp ready for release
+ - Build system clean-up:
+ - Fix build on Windows (shared-library build is broken)
+ - Fix doxygen build issue (discard doxygen dependency check, always rebuild)
+ - Add enable/disable flag for static and shared library build
+ - Enhance help
+ - Test with recent Scons checkpoint
+ - Platform portability check:
+ - linux/gcc,
+ - solaris/cc,
+ - windows/msvc678,
+ - 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_unicode Clean-up unicode handling
+ - Ensure reader properly convert \u and \U unicode sequence to UTF8
+ - Ensure writer emit only UTF8 string.
+ - Provides hook to convert string to/from utf8/other encoding.
+ - look into iconv, icu and windows API
+ \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
+ \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.
+ - 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
+ - Static property dictionnary can be provided to JSON reader
+ - Performance scenario & benchmarking
+*/
diff --git a/lib/jsoncpp/jsoncpp/doc/sconscript b/lib/jsoncpp/jsoncpp/doc/sconscript
new file mode 100644
index 0000000000..7b78a21d80
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/doc/sconscript
@@ -0,0 +1,61 @@
+Import( 'env' )
+import os.path
+
+if 'doxygen' in env['TOOLS']:
+ doc_topdir = str(env['ROOTBUILD_DIR'])
+ html_dir = 'jsoncpp-api-doc'
+
+ doxygen_inputs = env.Glob( includes = '*.dox', dir = '#doc' ) \
+ + env.Glob( includes = '*.h', dir = '#include/json/' ) \
+ + env.Glob( includes = ('*.dox','*.h','*.inl','*.cpp'),
+ dir = '#src/lib_json' )
+## for p in doxygen_inputs:
+## print p.abspath
+
+ top_dir = env.Dir('#').abspath
+ include_top_dir = env.Dir('#include').abspath
+ env['DOXYFILE_DICT'] = { 'PROJECT_NAME': 'JsonCpp',
+ 'PROJECT_NUMBER': env['JSONCPP_VERSION'],
+ 'STRIP_FROM_PATH': top_dir,
+ 'STRIP_FROM_INC_PATH': include_top_dir,
+ 'HTML_OUTPUT': html_dir,
+ 'HTML_HEADER': env.File('#doc/header.html').abspath,
+ 'HTML_FOOTER': env.File('#doc/footer.html').abspath,
+ 'INCLUDE_PATH': include_top_dir,
+ 'PREDEFINED': 'JSONCPP_DOC_EXCLUDE_IMPLEMENTATION JSON_VALUE_USE_INTERNAL_MAP'
+ }
+ env['DOXYFILE_FILE'] = 'doxyfile.in'
+ doxfile_nodes = env.Doxyfile( os.path.join( doc_topdir, 'doxyfile' ), doxygen_inputs )
+ html_doc_path = os.path.join( doc_topdir, html_dir )
+ doc_nodes = env.Doxygen( source = doxfile_nodes,
+ target = os.path.join( html_doc_path, 'index.html' ) )
+ alias_doc_cmd = env.Alias('doc', doc_nodes )
+ env.Alias('doc', env.Install( html_doc_path, '#README.txt' ) )
+ if 'TarGz' in env['BUILDERS']:
+ targz_path = os.path.join( env['DIST_DIR'], '%s.tar.gz' % html_dir )
+ zip_doc_cmd = env.TarGz( targz_path, [env.Dir(html_doc_path)],
+ TARGZ_BASEDIR = env['ROOTBUILD_DIR'] )
+ env.Depends( zip_doc_cmd, alias_doc_cmd )
+ env.Alias( 'doc-dist', zip_doc_cmd )
+##
+## doxyfile = env.SubstInFile( '#doc/doxyfile', 'doxyfile.in',
+## SUBST_DICT = {
+## '%JSONCPP_VERSION%' : env['JSONCPP_VERSION'],
+## '%TOPDIR%' : env.Dir('#').abspath,
+## '%DOC_TOPDIR%' : str(doc_topdir) } )
+## doc_cmd = env.Doxygen( doxyfile )
+## alias_doc_cmd = env.Alias('doc', doc_cmd )
+## env.AlwaysBuild(alias_doc_cmd)
+##
+## for dir in doc_cmd:
+## env.Alias('doc', env.Install( '#' + dir.path, '#README.txt' ) )
+## filename = os.path.split(dir.path)[1]
+## targz_path = os.path.join( env['DIST_DIR'], '%s.tar.gz' % filename )
+## zip_doc_cmd = env.TarGz( targz_path, [env.Dir(dir)],
+## TARGZ_BASEDIR = doc_topdir )
+## env.Depends( zip_doc_cmd, alias_doc_cmd )
+## env.Alias( 'doc-dist', zip_doc_cmd )
+##
+## # When doxyfile gets updated, I get errors on the first pass.
+## # I have to run scons twice. Something is wrong with the dependencies
+## # here, but I avoid it by running "scons doc/doxyfile" first.
diff --git a/lib/jsoncpp/jsoncpp/include/json/autolink.h b/lib/jsoncpp/jsoncpp/include/json/autolink.h
new file mode 100644
index 0000000000..37c9258ed5
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/include/json/autolink.h
@@ -0,0 +1,19 @@
+#ifndef JSON_AUTOLINK_H_INCLUDED
+# define JSON_AUTOLINK_H_INCLUDED
+
+# include "config.h"
+
+# ifdef JSON_IN_CPPTL
+# include <cpptl/cpptl_autolink.h>
+# endif
+
+# if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && !defined(JSON_IN_CPPTL)
+# define CPPTL_AUTOLINK_NAME "json"
+# undef CPPTL_AUTOLINK_DLL
+# ifdef JSON_DLL
+# define CPPTL_AUTOLINK_DLL
+# endif
+# include "autolink.h"
+# endif
+
+#endif // JSON_AUTOLINK_H_INCLUDED
diff --git a/lib/jsoncpp/jsoncpp/include/json/config.h b/lib/jsoncpp/jsoncpp/include/json/config.h
new file mode 100644
index 0000000000..5d334cbc5e
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/include/json/config.h
@@ -0,0 +1,43 @@
+#ifndef JSON_CONFIG_H_INCLUDED
+# define JSON_CONFIG_H_INCLUDED
+
+/// If defined, indicates that json library is embedded in CppTL library.
+//# define JSON_IN_CPPTL 1
+
+/// If defined, indicates that json may leverage CppTL library
+//# define JSON_USE_CPPTL 1
+/// If defined, indicates that cpptl vector based map should be used instead of std::map
+/// as Value container.
+//# 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!
+//# 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
+/// as if it was a POD) that may cause some validation tool to report errors.
+/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined.
+//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1
+
+/// If defined, indicates that Json use exception to report invalid type manipulation
+/// instead of C assert macro.
+# define JSON_USE_EXCEPTION 1
+
+# ifdef JSON_IN_CPPTL
+# include <cpptl/config.h>
+# ifndef JSON_USE_CPPTL
+# define JSON_USE_CPPTL 1
+# endif
+# endif
+
+# ifdef JSON_IN_CPPTL
+# define JSON_API CPPTL_API
+# elif defined(JSON_DLL_BUILD)
+# define JSON_API __declspec(dllexport)
+# elif defined(JSON_DLL)
+# define JSON_API __declspec(dllimport)
+# else
+# define JSON_API
+# endif
+
+#endif // JSON_CONFIG_H_INCLUDED
diff --git a/lib/jsoncpp/jsoncpp/include/json/features.h b/lib/jsoncpp/jsoncpp/include/json/features.h
new file mode 100644
index 0000000000..f1404f6204
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/include/json/features.h
@@ -0,0 +1,42 @@
+#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
diff --git a/lib/jsoncpp/jsoncpp/include/json/forwards.h b/lib/jsoncpp/jsoncpp/include/json/forwards.h
new file mode 100644
index 0000000000..ee76071c12
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/include/json/forwards.h
@@ -0,0 +1,34 @@
+#ifndef JSON_FORWARDS_H_INCLUDED
+# define JSON_FORWARDS_H_INCLUDED
+
+# include "config.h"
+
+namespace Json {
+
+ class FastWriter;
+ class Reader;
+ class StyledWriter;
+
+ // features.h
+ class Features;
+
+ // value.h
+ class StaticString;
+ class Path;
+ class PathArgument;
+ class Value;
+ class ValueIteratorBase;
+ class ValueIterator;
+ class ValueConstIterator;
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+ class ValueAllocator;
+ class ValueMapAllocator;
+ class ValueInternalLink;
+ class ValueInternalArray;
+ class ValueInternalMap;
+#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
+
+} // namespace Json
+
+
+#endif // JSON_FORWARDS_H_INCLUDED
diff --git a/lib/jsoncpp/jsoncpp/include/json/json.h b/lib/jsoncpp/jsoncpp/include/json/json.h
new file mode 100644
index 0000000000..c71ed65abf
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/include/json/json.h
@@ -0,0 +1,10 @@
+#ifndef JSON_JSON_H_INCLUDED
+# define JSON_JSON_H_INCLUDED
+
+# include "autolink.h"
+# include "value.h"
+# include "reader.h"
+# include "writer.h"
+# include "features.h"
+
+#endif // JSON_JSON_H_INCLUDED
diff --git a/lib/jsoncpp/jsoncpp/include/json/reader.h b/lib/jsoncpp/jsoncpp/include/json/reader.h
new file mode 100644
index 0000000000..ee1d6a2444
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/include/json/reader.h
@@ -0,0 +1,196 @@
+#ifndef CPPTL_JSON_READER_H_INCLUDED
+# define CPPTL_JSON_READER_H_INCLUDED
+
+# include "features.h"
+# include "value.h"
+# include <deque>
+# include <stack>
+# include <string>
+# include <iostream>
+
+namespace Json {
+
+ /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a Value.
+ *
+ */
+ class JSON_API Reader
+ {
+ public:
+ typedef char Char;
+ typedef const Char *Location;
+
+ /** \brief Constructs a Reader allowing all features
+ * for parsing.
+ */
+ Reader();
+
+ /** \brief Constructs a Reader allowing the specified feature set
+ * for parsing.
+ */
+ Reader( const Features &features );
+
+ /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
+ * \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
+ * serialization, \c false to discard comments.
+ * This parameter is ignored if Features::allowComments_
+ * is \c false.
+ * \return \c true if the document was successfully parsed, \c false if an error occurred.
+ */
+ bool parse( const std::string &document,
+ Value &root,
+ bool collectComments = true );
+
+ /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
+ * \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
+ * serialization, \c false to discard comments.
+ * This parameter is ignored if Features::allowComments_
+ * is \c false.
+ * \return \c true if the document was successfully parsed, \c false if an error occurred.
+ */
+ bool parse( const char *beginDoc, const char *endDoc,
+ Value &root,
+ bool collectComments = true );
+
+ /// \brief Parse from input stream.
+ /// \see Json::operator>>(std::istream&, Json::Value&).
+ bool parse( std::istream &is,
+ Value &root,
+ bool collectComments = true );
+
+ /** \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 getFormatedErrorMessages() const;
+
+ private:
+ enum TokenType
+ {
+ tokenEndOfStream = 0,
+ tokenObjectBegin,
+ tokenObjectEnd,
+ tokenArrayBegin,
+ tokenArrayEnd,
+ tokenString,
+ tokenNumber,
+ tokenTrue,
+ tokenFalse,
+ tokenNull,
+ tokenArraySeparator,
+ tokenMemberSeparator,
+ tokenComment,
+ tokenError
+ };
+
+ class Token
+ {
+ public:
+ TokenType type_;
+ Location start_;
+ Location end_;
+ };
+
+ class ErrorInfo
+ {
+ public:
+ Token token_;
+ std::string message_;
+ Location extra_;
+ };
+
+ typedef std::deque<ErrorInfo> Errors;
+
+ bool expectToken( TokenType type, Token &token, const char *message );
+ bool readToken( Token &token );
+ void skipSpaces();
+ bool match( Location pattern,
+ int patternLength );
+ bool readComment();
+ bool readCStyleComment();
+ bool readCppStyleComment();
+ bool readString();
+ void readNumber();
+ bool readValue();
+ bool readObject( Token &token );
+ bool readArray( Token &token );
+ bool decodeNumber( Token &token );
+ bool decodeString( Token &token );
+ bool decodeString( Token &token, std::string &decoded );
+ bool decodeDouble( Token &token );
+ bool decodeUnicodeCodePoint( Token &token,
+ Location &current,
+ Location end,
+ unsigned int &unicode );
+ bool decodeUnicodeEscapeSequence( Token &token,
+ Location &current,
+ Location end,
+ unsigned int &unicode );
+ bool addError( const std::string &message,
+ Token &token,
+ Location extra = 0 );
+ bool recoverFromError( TokenType skipUntilToken );
+ bool addErrorAndRecover( const std::string &message,
+ Token &token,
+ TokenType skipUntilToken );
+ void skipUntilSpace();
+ Value &currentValue();
+ Char getNextChar();
+ void getLocationLineAndColumn( Location location,
+ int &line,
+ int &column ) const;
+ std::string getLocationLineAndColumn( Location location ) const;
+ void addComment( Location begin,
+ Location end,
+ CommentPlacement placement );
+ void skipCommentTokens( Token &token );
+
+ typedef std::stack<Value *> Nodes;
+ Nodes nodes_;
+ Errors errors_;
+ std::string document_;
+ Location begin_;
+ Location end_;
+ Location current_;
+ Location lastValueEnd_;
+ Value *lastValue_;
+ std::string commentsBefore_;
+ Features features_;
+ bool collectComments_;
+ };
+
+ /** \brief Read from 'sin' into 'root'.
+
+ Always keep comments from the input JSON.
+
+ This can be used to read a file into a particular sub-object.
+ For example:
+ \code
+ Json::Value root;
+ cin >> root["dir"]["file"];
+ cout << root;
+ \endcode
+ Result:
+ \verbatim
+ {
+ "dir": {
+ "file": {
+ // The input stream JSON would be nested here.
+ }
+ }
+ }
+ \endverbatim
+ \throw std::exception on parse error.
+ \see Json::operator<<()
+ */
+ std::istream& operator>>( std::istream&, Value& );
+
+} // namespace Json
+
+#endif // CPPTL_JSON_READER_H_INCLUDED
diff --git a/lib/jsoncpp/jsoncpp/include/json/value.h b/lib/jsoncpp/jsoncpp/include/json/value.h
new file mode 100644
index 0000000000..ce3d3cd0e9
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/include/json/value.h
@@ -0,0 +1,1068 @@
+#ifndef CPPTL_JSON_H_INCLUDED
+# define CPPTL_JSON_H_INCLUDED
+
+# include "forwards.h"
+# include <string>
+# include <vector>
+
+# ifndef JSON_USE_CPPTL_SMALLMAP
+# include <map>
+# else
+# include <cpptl/smallmap.h>
+# endif
+# ifdef JSON_USE_CPPTL
+# include <cpptl/forwards.h>
+# endif
+
+/** \brief JSON (JavaScript Object Notation).
+ */
+namespace Json {
+
+ /** \brief Type of the value held by a Value object.
+ */
+ enum ValueType
+ {
+ nullValue = 0, ///< 'null' value
+ intValue, ///< signed integer value
+ uintValue, ///< unsigned integer value
+ realValue, ///< double value
+ stringValue, ///< UTF-8 string value
+ booleanValue, ///< bool value
+ arrayValue, ///< array value (ordered list)
+ objectValue ///< object value (collection of name/value pairs).
+ };
+
+ enum CommentPlacement
+ {
+ commentBefore = 0, ///< a comment placed on the line before a value
+ commentAfterOnSameLine, ///< a comment just after a value on the same line
+ commentAfter, ///< a comment on the line after a value (only make sense for root value)
+ numberOfCommentPlacement
+ };
+
+//# ifdef JSON_USE_CPPTL
+// typedef CppTL::AnyEnumerator<const char *> EnumMemberNames;
+// typedef CppTL::AnyEnumerator<const Value &> EnumValues;
+//# endif
+
+ /** \brief Lightweight wrapper to tag static string.
+ *
+ * Value constructor and objectValue member assignement takes advantage of the
+ * StaticString and avoid the cost of string duplication when storing the
+ * string or the member name.
+ *
+ * Example of usage:
+ * \code
+ * Json::Value aValue( StaticString("some text") );
+ * Json::Value object;
+ * static const StaticString code("code");
+ * object[code] = 1234;
+ * \endcode
+ */
+ class JSON_API StaticString
+ {
+ public:
+ explicit StaticString( const char *czstring )
+ : str_( czstring )
+ {
+ }
+
+ operator const char *() const
+ {
+ return str_;
+ }
+
+ const char *c_str() const
+ {
+ return str_;
+ }
+
+ private:
+ const char *str_;
+ };
+
+ /** \brief Represents a <a HREF="http://www.json.org">JSON</a> value.
+ *
+ * This class is a discriminated union wrapper that can represents a:
+ * - signed integer [range: Value::minInt - Value::maxInt]
+ * - unsigned integer (range: 0 - Value::maxUInt)
+ * - double
+ * - UTF-8 string
+ * - boolean
+ * - 'null'
+ * - an ordered list of Value
+ * - collection of name/value pairs (javascript object)
+ *
+ * The type of the held value is represented by a #ValueType and
+ * can be obtained using type().
+ *
+ * values of an #objectValue or #arrayValue can be accessed using operator[]() methods.
+ * Non const methods will automatically create the a #nullValue element
+ * if it does not exist.
+ * The sequence of an #arrayValue will be automatically resize and initialized
+ * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue.
+ *
+ * The get() methods can be used to obtanis default value in the case the required element
+ * does not exist.
+ *
+ * It is possible to iterate over the list of a #objectValue values using
+ * the getMemberNames() method.
+ */
+ class JSON_API Value
+ {
+ friend class ValueIteratorBase;
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ friend class ValueInternalLink;
+ friend class ValueInternalMap;
+# endif
+ public:
+ typedef std::vector<std::string> Members;
+ typedef int Int;
+ typedef unsigned int UInt;
+ typedef ValueIterator iterator;
+ typedef ValueConstIterator const_iterator;
+ typedef UInt ArrayIndex;
+
+ static const Value null;
+ static const Int minInt;
+ static const Int maxInt;
+ static const UInt maxUInt;
+
+ private:
+#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+# ifndef JSON_VALUE_USE_INTERNAL_MAP
+ class CZString
+ {
+ public:
+ enum DuplicationPolicy
+ {
+ noDuplication = 0,
+ duplicate,
+ duplicateOnCopy
+ };
+ 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;
+ int index() const;
+ const char *c_str() const;
+ bool isStaticString() const;
+ private:
+ void swap( CZString &other );
+ const char *cstr_;
+ int index_;
+ };
+
+ public:
+# ifndef JSON_USE_CPPTL_SMALLMAP
+ typedef std::map<CZString, Value> ObjectValues;
+# else
+ typedef CppTL::SmallMap<CZString, Value> ObjectValues;
+# endif // ifndef JSON_USE_CPPTL_SMALLMAP
+# endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
+#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+ public:
+ /** \brief Create a default Value of the given type.
+
+ This is a very useful constructor.
+ 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.
+
+ Examples:
+ \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 );
+ Value( double value );
+ Value( const char *value );
+ /** \brief Constructs a value from a static string.
+
+ * Like other value string constructor but do not duplicate the string for
+ * internal storage. The given string must remain alive after the call to this
+ * constructor.
+ * Example of usage:
+ * \code
+ * Json::Value aValue( StaticString("some text") );
+ * \endcode
+ */
+ Value( const StaticString &value );
+ Value( const std::string &value );
+# ifdef JSON_USE_CPPTL
+ Value( const CppTL::ConstString &value );
+# endif
+ Value( bool value );
+ Value( const Value &other );
+ ~Value();
+
+ Value &operator=( const Value &other );
+ /// Swap values.
+ /// \note Currently, comments are intentionally not swapped, for
+ /// both logic and efficiency.
+ void swap( Value &other );
+
+ ValueType type() const;
+
+ bool operator <( const Value &other ) const;
+ bool operator <=( const Value &other ) const;
+ bool operator >=( const Value &other ) const;
+ bool operator >( const Value &other ) const;
+
+ bool operator ==( const Value &other ) const;
+ bool operator !=( const Value &other ) const;
+
+ int compare( const Value &other );
+
+ const char *asCString() const;
+ std::string asString() const;
+# ifdef JSON_USE_CPPTL
+ CppTL::ConstString asConstString() const;
+# endif
+ Int asInt() const;
+ UInt asUInt() const;
+ double asDouble() const;
+ bool asBool() const;
+
+ bool isNull() const;
+ bool isBool() const;
+ bool isInt() const;
+ bool isUInt() const;
+ bool isIntegral() const;
+ bool isDouble() const;
+ bool isNumeric() const;
+ bool isString() const;
+ bool isArray() const;
+ bool isObject() const;
+
+ bool isConvertibleTo( ValueType other ) const;
+
+ /// Number of values in array or object
+ UInt size() const;
+
+ /// \brief Return true if empty array, empty object, or null;
+ /// otherwise, false.
+ bool empty() const;
+
+ /// Return isNull()
+ bool operator!() const;
+
+ /// Remove all object members and array elements.
+ /// \pre type() is arrayValue, objectValue, or nullValue
+ /// \post type() is unchanged
+ void clear();
+
+ /// Resize the array to size elements.
+ /// New elements are initialized to null.
+ /// May only be called on nullValue or arrayValue.
+ /// \pre type() is arrayValue or nullValue
+ /// \post type() is arrayValue
+ 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[]( 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[]( UInt index ) const;
+ /// If the array contains at least index+1 elements, returns the element value,
+ /// otherwise returns defaultValue.
+ Value get( UInt index,
+ const Value &defaultValue ) const;
+ /// Return true if index < size().
+ bool isValidIndex( UInt index ) const;
+ /// \brief Append value to array at the end.
+ ///
+ /// Equivalent to jsonvalue[jsonvalue.size()] = value;
+ Value &append( const Value &value );
+
+ /// Access an object value by name, create a null member if it does not exist.
+ Value &operator[]( const char *key );
+ /// Access an object value by name, returns null if there is no member with that name.
+ const Value &operator[]( const char *key ) const;
+ /// Access an object value by name, create a null member if it does not exist.
+ Value &operator[]( const std::string &key );
+ /// Access an object value by name, returns null if there is no member with that name.
+ const Value &operator[]( const std::string &key ) const;
+ /** \brief Access an object value by name, create a null member if it does not exist.
+
+ * If the object as no entry for that name, then the member name used to store
+ * the new entry is not duplicated.
+ * Example of use:
+ * \code
+ * Json::Value object;
+ * static const StaticString code("code");
+ * object[code] = 1234;
+ * \endcode
+ */
+ Value &operator[]( const StaticString &key );
+# ifdef JSON_USE_CPPTL
+ /// Access an object value by name, create a null member if it does not exist.
+ Value &operator[]( const CppTL::ConstString &key );
+ /// Access an object value by name, returns null if there is no member with that name.
+ const Value &operator[]( const CppTL::ConstString &key ) const;
+# endif
+ /// Return the member named key if it exist, defaultValue otherwise.
+ Value get( const char *key,
+ const Value &defaultValue ) const;
+ /// Return the member named key if it exist, defaultValue otherwise.
+ Value get( const std::string &key,
+ const Value &defaultValue ) const;
+# ifdef JSON_USE_CPPTL
+ /// Return the member named key if it exist, defaultValue otherwise.
+ Value get( const CppTL::ConstString &key,
+ const Value &defaultValue ) const;
+# endif
+ /// \brief Remove and return the named member.
+ ///
+ /// Do nothing if it did not exist.
+ /// \return the removed Value, or null.
+ /// \pre type() is objectValue or nullValue
+ /// \post type() is unchanged
+ Value removeMember( const char* key );
+ /// Same as removeMember(const char*)
+ Value removeMember( const std::string &key );
+
+ /// Return true if the object has a member named key.
+ bool isMember( const char *key ) const;
+ /// Return true if the object has a member named key.
+ bool isMember( const std::string &key ) const;
+# ifdef JSON_USE_CPPTL
+ /// Return true if the object has a member named key.
+ bool isMember( const CppTL::ConstString &key ) const;
+# endif
+
+ /// \brief Return a list of the member names.
+ ///
+ /// If null, return an empty list.
+ /// \pre type() is objectValue or nullValue
+ /// \post if type() was nullValue, it remains nullValue
+ Members getMemberNames() const;
+
+//# ifdef JSON_USE_CPPTL
+// EnumMemberNames enumMemberNames() const;
+// EnumValues enumValues() const;
+//# endif
+
+ /// Comments must be //... or /* ... */
+ void setComment( const char *comment,
+ CommentPlacement placement );
+ /// Comments must be //... or /* ... */
+ void setComment( const std::string &comment,
+ CommentPlacement placement );
+ bool hasComment( CommentPlacement placement ) const;
+ /// Include delimiters and embedded newlines.
+ std::string getComment( CommentPlacement placement ) const;
+
+ std::string toStyledString() const;
+
+ const_iterator begin() const;
+ const_iterator end() const;
+
+ iterator begin();
+ iterator end();
+
+ private:
+ Value &resolveReference( const char *key,
+ bool isStatic );
+
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ inline bool isItemAvailable() const
+ {
+ return itemIsUsed_ == 0;
+ }
+
+ inline void setItemUsed( bool isUsed = true )
+ {
+ itemIsUsed_ = isUsed ? 1 : 0;
+ }
+
+ inline bool isMemberNameStatic() const
+ {
+ return memberNameIsStatic_ == 0;
+ }
+
+ inline void setMemberNameIsStatic( bool isStatic )
+ {
+ memberNameIsStatic_ = isStatic ? 1 : 0;
+ }
+# endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP
+
+ private:
+ struct CommentInfo
+ {
+ CommentInfo();
+ ~CommentInfo();
+
+ void setComment( const char *text );
+
+ char *comment_;
+ };
+
+ //struct MemberNamesTransform
+ //{
+ // typedef const char *result_type;
+ // const char *operator()( const CZString &name ) const
+ // {
+ // return name.c_str();
+ // }
+ //};
+
+ union ValueHolder
+ {
+ Int int_;
+ UInt uint_;
+ double real_;
+ bool bool_;
+ char *string_;
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ ValueInternalArray *array_;
+ ValueInternalMap *map_;
+#else
+ ObjectValues *map_;
+# endif
+ } value_;
+ ValueType type_ : 8;
+ int allocated_ : 1; // Notes: if declared as bool, bitfield is useless.
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ unsigned int itemIsUsed_ : 1; // used by the ValueInternalMap container.
+ int memberNameIsStatic_ : 1; // used by the ValueInternalMap container.
+# endif
+ CommentInfo *comments_;
+ };
+
+
+ /** \brief Experimental and untested: represents an element of the "path" to access a node.
+ */
+ class PathArgument
+ {
+ public:
+ friend class Path;
+
+ PathArgument();
+ PathArgument( Value::UInt index );
+ PathArgument( const char *key );
+ PathArgument( const std::string &key );
+
+ private:
+ enum Kind
+ {
+ kindNone = 0,
+ kindIndex,
+ kindKey
+ };
+ std::string key_;
+ Value::UInt index_;
+ Kind kind_;
+ };
+
+ /** \brief Experimental and untested: represents a "path" to access a node.
+ *
+ * Syntax:
+ * - "." => root node
+ * - ".[n]" => elements at index 'n' of root node (an array value)
+ * - ".name" => member named 'name' of root node (an object value)
+ * - ".name1.name2.name3"
+ * - ".[0][1][2].name1[3]"
+ * - ".%" => member name is provided as parameter
+ * - ".[%]" => index is provied as parameter
+ */
+ class Path
+ {
+ public:
+ Path( const std::string &path,
+ const PathArgument &a1 = PathArgument(),
+ const PathArgument &a2 = PathArgument(),
+ const PathArgument &a3 = PathArgument(),
+ const PathArgument &a4 = PathArgument(),
+ const PathArgument &a5 = PathArgument() );
+
+ const Value &resolve( const Value &root ) const;
+ Value resolve( const Value &root,
+ const Value &defaultValue ) const;
+ /// Creates the "path" to access the specified node and returns a reference on the node.
+ Value &make( Value &root ) const;
+
+ private:
+ typedef std::vector<const PathArgument *> InArgs;
+ typedef std::vector<PathArgument> Args;
+
+ void makePath( const std::string &path,
+ const InArgs &in );
+ void addPathInArg( const std::string &path,
+ const InArgs &in,
+ InArgs::const_iterator &itInArg,
+ PathArgument::Kind kind );
+ void invalidPath( const std::string &path,
+ int location );
+
+ Args args_;
+ };
+
+ /** \brief 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.
+ * Below is an example of a simple implementation (default implementation actually
+ * use memory pool for speed).
+ * \code
+ class DefaultValueMapAllocator : public ValueMapAllocator
+ {
+ public: // overridden from ValueMapAllocator
+ virtual ValueInternalMap *newMap()
+ {
+ return new ValueInternalMap();
+ }
+
+ virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
+ {
+ return new ValueInternalMap( other );
+ }
+
+ virtual void destructMap( ValueInternalMap *map )
+ {
+ delete map;
+ }
+
+ virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
+ {
+ return new ValueInternalLink[size];
+ }
+
+ virtual void releaseMapBuckets( ValueInternalLink *links )
+ {
+ delete [] links;
+ }
+
+ virtual ValueInternalLink *allocateMapLink()
+ {
+ return new ValueInternalLink();
+ }
+
+ virtual void releaseMapLink( ValueInternalLink *link )
+ {
+ delete link;
+ }
+ };
+ * \endcode
+ */
+ class JSON_API ValueMapAllocator
+ {
+ public:
+ virtual ~ValueMapAllocator();
+ virtual ValueInternalMap *newMap() = 0;
+ virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) = 0;
+ virtual void destructMap( ValueInternalMap *map ) = 0;
+ virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) = 0;
+ virtual void releaseMapBuckets( ValueInternalLink *links ) = 0;
+ virtual ValueInternalLink *allocateMapLink() = 0;
+ virtual void releaseMapLink( ValueInternalLink *link ) = 0;
+ };
+
+ /** \brief ValueInternalMap hash-map bucket chain link (for internal use only).
+ * \internal previous_ & next_ allows for bidirectional traversal.
+ */
+ class JSON_API ValueInternalLink
+ {
+ public:
+ enum { itemPerLink = 6 }; // sizeof(ValueInternalLink) = 128 on 32 bits architecture.
+ enum InternalFlags {
+ flagAvailable = 0,
+ flagUsed = 1
+ };
+
+ ValueInternalLink();
+
+ ~ValueInternalLink();
+
+ Value items_[itemPerLink];
+ char *keys_[itemPerLink];
+ ValueInternalLink *previous_;
+ ValueInternalLink *next_;
+ };
+
+
+ /** \brief A linked page based hash-table implementation used internally by Value.
+ * \internal ValueInternalMap is a tradional bucket based hash-table, with a linked
+ * list in each bucket to handle collision. There is an addional twist in that
+ * each node of the collision linked list is a page containing a fixed amount of
+ * value. This provides a better compromise between memory usage and speed.
+ *
+ * Each bucket is made up of a chained list of ValueInternalLink. The last
+ * link of a given bucket can be found in the 'previous_' field of the following bucket.
+ * The last link of the last bucket is stored in tailLink_ as it has no following bucket.
+ * Only the last link of a bucket may contains 'available' item. The last link always
+ * contains at least one element unless is it the bucket one very first link.
+ */
+ class JSON_API ValueInternalMap
+ {
+ friend class ValueIteratorBase;
+ friend class Value;
+ public:
+ typedef unsigned int HashKey;
+ typedef unsigned int BucketIndex;
+
+# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+ struct IteratorState
+ {
+ IteratorState()
+ : map_(0)
+ , link_(0)
+ , itemIndex_(0)
+ , bucketIndex_(0)
+ {
+ }
+ ValueInternalMap *map_;
+ ValueInternalLink *link_;
+ BucketIndex itemIndex_;
+ BucketIndex bucketIndex_;
+ };
+# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+ ValueInternalMap();
+ ValueInternalMap( const ValueInternalMap &other );
+ ValueInternalMap &operator =( const ValueInternalMap &other );
+ ~ValueInternalMap();
+
+ void swap( ValueInternalMap &other );
+
+ BucketIndex size() const;
+
+ void clear();
+
+ bool reserveDelta( BucketIndex growth );
+
+ bool reserve( BucketIndex newItemCount );
+
+ const Value *find( const char *key ) const;
+
+ Value *find( const char *key );
+
+ Value &resolveReference( const char *key,
+ bool isStatic );
+
+ void remove( const char *key );
+
+ void doActualRemove( ValueInternalLink *link,
+ BucketIndex index,
+ BucketIndex bucketIndex );
+
+ ValueInternalLink *&getLastLinkInBucket( BucketIndex bucketIndex );
+
+ Value &setNewItem( const char *key,
+ bool isStatic,
+ ValueInternalLink *link,
+ BucketIndex index );
+
+ Value &unsafeAdd( const char *key,
+ bool isStatic,
+ HashKey hashedKey );
+
+ HashKey hash( const char *key ) const;
+
+ int compare( const ValueInternalMap &other ) const;
+
+ private:
+ void makeBeginIterator( IteratorState &it ) const;
+ void makeEndIterator( IteratorState &it ) const;
+ static bool equals( const IteratorState &x, const IteratorState &other );
+ static void increment( IteratorState &iterator );
+ static void incrementBucket( IteratorState &iterator );
+ static void decrement( IteratorState &iterator );
+ static const char *key( const IteratorState &iterator );
+ static const char *key( const IteratorState &iterator, bool &isStatic );
+ static Value &value( const IteratorState &iterator );
+ static int distance( const IteratorState &x, const IteratorState &y );
+
+ private:
+ ValueInternalLink *buckets_;
+ ValueInternalLink *tailLink_;
+ BucketIndex bucketsSize_;
+ BucketIndex itemCount_;
+ };
+
+ /** \brief A simplified deque implementation used internally by Value.
+ * \internal
+ * It is based on a list of fixed "page", each page contains a fixed number of items.
+ * Instead of using a linked-list, a array of pointer is used for fast item look-up.
+ * Look-up for an element is as follow:
+ * - compute page index: pageIndex = itemIndex / itemsPerPage
+ * - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage]
+ *
+ * Insertion is amortized constant time (only the array containing the index of pointers
+ * need to be reallocated when items are appended).
+ */
+ class JSON_API ValueInternalArray
+ {
+ friend class Value;
+ friend class ValueIteratorBase;
+ public:
+ enum { itemsPerPage = 8 }; // should be a power of 2 for fast divide and modulo.
+ typedef Value::ArrayIndex ArrayIndex;
+ typedef unsigned int PageIndex;
+
+# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+ struct IteratorState // Must be a POD
+ {
+ IteratorState()
+ : array_(0)
+ , currentPageIndex_(0)
+ , currentItemIndex_(0)
+ {
+ }
+ ValueInternalArray *array_;
+ Value **currentPageIndex_;
+ unsigned int currentItemIndex_;
+ };
+# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+ ValueInternalArray();
+ ValueInternalArray( const ValueInternalArray &other );
+ ValueInternalArray &operator =( const ValueInternalArray &other );
+ ~ValueInternalArray();
+ void swap( ValueInternalArray &other );
+
+ void clear();
+ void resize( ArrayIndex newSize );
+
+ Value &resolveReference( ArrayIndex index );
+
+ Value *find( ArrayIndex index ) const;
+
+ ArrayIndex size() const;
+
+ int compare( const ValueInternalArray &other ) const;
+
+ private:
+ static bool equals( const IteratorState &x, const IteratorState &other );
+ static void increment( IteratorState &iterator );
+ static void decrement( IteratorState &iterator );
+ static Value &dereference( const IteratorState &iterator );
+ static Value &unsafeDereference( const IteratorState &iterator );
+ static int distance( const IteratorState &x, const IteratorState &y );
+ static ArrayIndex indexOf( const IteratorState &iterator );
+ void makeBeginIterator( IteratorState &it ) const;
+ void makeEndIterator( IteratorState &it ) const;
+ void makeIterator( IteratorState &it, ArrayIndex index ) const;
+
+ void makeIndexValid( ArrayIndex index );
+
+ Value **pages_;
+ ArrayIndex size_;
+ PageIndex pageCount_;
+ };
+
+ /** \brief Allocator to customize Value internal array.
+ * Below is an example of a simple implementation (actual implementation use
+ * memory pool).
+ \code
+class DefaultValueArrayAllocator : public ValueArrayAllocator
+{
+public: // overridden from ValueArrayAllocator
+ virtual ~DefaultValueArrayAllocator()
+ {
+ }
+
+ virtual ValueInternalArray *newArray()
+ {
+ return new ValueInternalArray();
+ }
+
+ virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
+ {
+ return new ValueInternalArray( other );
+ }
+
+ virtual void destruct( ValueInternalArray *array )
+ {
+ delete array;
+ }
+
+ virtual void reallocateArrayPageIndex( Value **&indexes,
+ ValueInternalArray::PageIndex &indexCount,
+ ValueInternalArray::PageIndex minNewIndexCount )
+ {
+ ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
+ if ( minNewIndexCount > newIndexCount )
+ newIndexCount = minNewIndexCount;
+ void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
+ if ( !newIndexes )
+ throw std::bad_alloc();
+ indexCount = newIndexCount;
+ indexes = static_cast<Value **>( newIndexes );
+ }
+ virtual void releaseArrayPageIndex( Value **indexes,
+ ValueInternalArray::PageIndex indexCount )
+ {
+ if ( indexes )
+ free( indexes );
+ }
+
+ virtual Value *allocateArrayPage()
+ {
+ return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
+ }
+
+ virtual void releaseArrayPage( Value *value )
+ {
+ if ( value )
+ free( value );
+ }
+};
+ \endcode
+ */
+ class JSON_API ValueArrayAllocator
+ {
+ public:
+ virtual ~ValueArrayAllocator();
+ virtual ValueInternalArray *newArray() = 0;
+ virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) = 0;
+ virtual void destructArray( ValueInternalArray *array ) = 0;
+ /** \brief Reallocate array page index.
+ * Reallocates an array of pointer on each page.
+ * \param indexes [input] pointer on the current index. May be \c NULL.
+ * [output] pointer on the new index of at least
+ * \a minNewIndexCount pages.
+ * \param indexCount [input] current number of pages in the index.
+ * [output] number of page the reallocated index can handle.
+ * \b MUST be >= \a minNewIndexCount.
+ * \param minNewIndexCount Minimum number of page the new index must be able to
+ * handle.
+ */
+ virtual void reallocateArrayPageIndex( Value **&indexes,
+ ValueInternalArray::PageIndex &indexCount,
+ ValueInternalArray::PageIndex minNewIndexCount ) = 0;
+ virtual void releaseArrayPageIndex( Value **indexes,
+ ValueInternalArray::PageIndex indexCount ) = 0;
+ virtual Value *allocateArrayPage() = 0;
+ virtual void releaseArrayPage( Value *value ) = 0;
+ };
+#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
+
+
+ /** \brief Experimental and untested: base class for Value iterators.
+ *
+ */
+ class ValueIteratorBase
+ {
+ public:
+ typedef unsigned int size_t;
+ typedef int difference_type;
+ typedef ValueIteratorBase SelfType;
+
+ ValueIteratorBase();
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ explicit ValueIteratorBase( const Value::ObjectValues::iterator &current );
+#else
+ ValueIteratorBase( const ValueInternalArray::IteratorState &state );
+ ValueIteratorBase( const ValueInternalMap::IteratorState &state );
+#endif
+
+ bool operator ==( const SelfType &other ) const
+ {
+ return isEqual( other );
+ }
+
+ bool operator !=( const SelfType &other ) const
+ {
+ return !isEqual( other );
+ }
+
+ difference_type operator -( const SelfType &other ) const
+ {
+ return computeDistance( other );
+ }
+
+ /// Return either the index or the member name of the referenced value as a Value.
+ Value key() const;
+
+ /// Return the index of the referenced Value. -1 if it is not an arrayValue.
+ Value::UInt index() const;
+
+ /// Return the member name of the referenced Value. "" if it is not an objectValue.
+ const char *memberName() const;
+
+ protected:
+ Value &deref() const;
+
+ void increment();
+
+ void decrement();
+
+ difference_type computeDistance( const SelfType &other ) const;
+
+ bool isEqual( const SelfType &other ) const;
+
+ void copy( const SelfType &other );
+
+ private:
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ Value::ObjectValues::iterator current_;
+ // Indicates that iterator is for a null value.
+ bool isNull_;
+#else
+ union
+ {
+ ValueInternalArray::IteratorState array_;
+ ValueInternalMap::IteratorState map_;
+ } iterator_;
+ bool isArray_;
+#endif
+ };
+
+ /** \brief Experimental and untested: const iterator for object and array value.
+ *
+ */
+ class ValueConstIterator : public ValueIteratorBase
+ {
+ friend class Value;
+ public:
+ typedef unsigned int size_t;
+ typedef int difference_type;
+ typedef const Value &reference;
+ typedef const Value *pointer;
+ typedef ValueConstIterator SelfType;
+
+ ValueConstIterator();
+ private:
+ /*! \internal Use by Value to create an iterator.
+ */
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ explicit ValueConstIterator( const Value::ObjectValues::iterator &current );
+#else
+ ValueConstIterator( const ValueInternalArray::IteratorState &state );
+ ValueConstIterator( const ValueInternalMap::IteratorState &state );
+#endif
+ public:
+ SelfType &operator =( const ValueIteratorBase &other );
+
+ SelfType operator++( int )
+ {
+ SelfType temp( *this );
+ ++*this;
+ return temp;
+ }
+
+ SelfType operator--( int )
+ {
+ SelfType temp( *this );
+ --*this;
+ return temp;
+ }
+
+ SelfType &operator--()
+ {
+ decrement();
+ return *this;
+ }
+
+ SelfType &operator++()
+ {
+ increment();
+ return *this;
+ }
+
+ reference operator *() const
+ {
+ return deref();
+ }
+ };
+
+
+ /** \brief Experimental and untested: iterator for object and array value.
+ */
+ class ValueIterator : public ValueIteratorBase
+ {
+ friend class Value;
+ public:
+ typedef unsigned int size_t;
+ typedef int difference_type;
+ typedef Value &reference;
+ typedef Value *pointer;
+ typedef ValueIterator SelfType;
+
+ ValueIterator();
+ ValueIterator( const ValueConstIterator &other );
+ ValueIterator( const ValueIterator &other );
+ private:
+ /*! \internal Use by Value to create an iterator.
+ */
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ explicit ValueIterator( const Value::ObjectValues::iterator &current );
+#else
+ ValueIterator( const ValueInternalArray::IteratorState &state );
+ ValueIterator( const ValueInternalMap::IteratorState &state );
+#endif
+ public:
+
+ SelfType &operator =( const SelfType &other );
+
+ SelfType operator++( int )
+ {
+ SelfType temp( *this );
+ ++*this;
+ return temp;
+ }
+
+ SelfType operator--( int )
+ {
+ SelfType temp( *this );
+ --*this;
+ return temp;
+ }
+
+ SelfType &operator--()
+ {
+ decrement();
+ return *this;
+ }
+
+ SelfType &operator++()
+ {
+ increment();
+ return *this;
+ }
+
+ reference operator *() const
+ {
+ return deref();
+ }
+ };
+
+
+} // namespace Json
+
+
+#endif // CPPTL_JSON_H_INCLUDED
diff --git a/lib/jsoncpp/jsoncpp/include/json/writer.h b/lib/jsoncpp/jsoncpp/include/json/writer.h
new file mode 100644
index 0000000000..cfa92c6ae4
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/include/json/writer.h
@@ -0,0 +1,174 @@
+#ifndef JSON_WRITER_H_INCLUDED
+# define JSON_WRITER_H_INCLUDED
+
+# include "value.h"
+# include <vector>
+# include <string>
+# include <iostream>
+
+namespace Json {
+
+ class Value;
+
+ /** \brief Abstract class for writers.
+ */
+ class JSON_API Writer
+ {
+ public:
+ virtual ~Writer();
+
+ virtual std::string write( const Value &root ) = 0;
+ };
+
+ /** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format without formatting (not human friendly).
+ *
+ * The JSON document is written in a single line. It is not intended for 'human' consumption,
+ * but may be usefull to support feature such as RPC where bandwith is limited.
+ * \sa Reader, Value
+ */
+ class JSON_API FastWriter : public Writer
+ {
+ public:
+ FastWriter();
+ virtual ~FastWriter(){}
+
+ void enableYAMLCompatibility();
+
+ public: // overridden from Writer
+ virtual std::string write( const Value &root );
+
+ private:
+ void writeValue( const Value &value );
+
+ std::string document_;
+ bool yamlCompatiblityEnabled_;
+ };
+
+ /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way.
+ *
+ * The rules for line break and indent are as follow:
+ * - Object value:
+ * - if empty then print {} without indent and line break
+ * - if not empty the print '{', line break & indent, print one value per line
+ * and then unindent and line break and print '}'.
+ * - Array value:
+ * - if empty then print [] without indent and line break
+ * - if the array contains no object value, empty array or some other value types,
+ * and all the values fit on one lines, then print the array on a single line.
+ * - otherwise, it the values do not fit on one line, or the array contains
+ * object or non empty array, then print one value per line.
+ *
+ * If the Value have comments then they are outputed according to their #CommentPlacement.
+ *
+ * \sa Reader, Value, Value::setComment()
+ */
+ class JSON_API StyledWriter: public Writer
+ {
+ public:
+ StyledWriter();
+ virtual ~StyledWriter(){}
+
+ public: // overridden from Writer
+ /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+ * \param root Value to serialize.
+ * \return String containing the JSON document that represents the root value.
+ */
+ virtual std::string write( const Value &root );
+
+ private:
+ void writeValue( const Value &value );
+ void writeArrayValue( const Value &value );
+ bool isMultineArray( const Value &value );
+ void pushValue( const std::string &value );
+ void writeIndent();
+ void writeWithIndent( const std::string &value );
+ void indent();
+ void unindent();
+ void writeCommentBeforeValue( const Value &root );
+ void writeCommentAfterValueOnSameLine( const Value &root );
+ bool hasCommentForValue( const Value &value );
+ static std::string normalizeEOL( const std::string &text );
+
+ typedef std::vector<std::string> ChildValues;
+
+ ChildValues childValues_;
+ std::string document_;
+ std::string indentString_;
+ int rightMargin_;
+ int indentSize_;
+ bool addChildValues_;
+ };
+
+ /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way,
+ to a stream rather than to a string.
+ *
+ * The rules for line break and indent are as follow:
+ * - Object value:
+ * - if empty then print {} without indent and line break
+ * - if not empty the print '{', line break & indent, print one value per line
+ * and then unindent and line break and print '}'.
+ * - Array value:
+ * - if empty then print [] without indent and line break
+ * - if the array contains no object value, empty array or some other value types,
+ * and all the values fit on one lines, then print the array on a single line.
+ * - otherwise, it the values do not fit on one line, or the array contains
+ * object or non empty array, then print one value per line.
+ *
+ * If the Value have comments then they are outputed according to their #CommentPlacement.
+ *
+ * \param indentation Each level will be indented by this amount extra.
+ * \sa Reader, Value, Value::setComment()
+ */
+ class JSON_API StyledStreamWriter
+ {
+ public:
+ StyledStreamWriter( std::string indentation="\t" );
+ ~StyledStreamWriter(){}
+
+ public:
+ /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+ * \param out Stream to write to. (Can be ostringstream, e.g.)
+ * \param root Value to serialize.
+ * \note There is no point in deriving from Writer, since write() should not return a value.
+ */
+ void write( std::ostream &out, const Value &root );
+
+ private:
+ void writeValue( const Value &value );
+ void writeArrayValue( const Value &value );
+ bool isMultineArray( const Value &value );
+ void pushValue( const std::string &value );
+ void writeIndent();
+ void writeWithIndent( const std::string &value );
+ void indent();
+ void unindent();
+ void writeCommentBeforeValue( const Value &root );
+ void writeCommentAfterValueOnSameLine( const Value &root );
+ bool hasCommentForValue( const Value &value );
+ static std::string normalizeEOL( const std::string &text );
+
+ typedef std::vector<std::string> ChildValues;
+
+ ChildValues childValues_;
+ std::ostream* document_;
+ std::string indentString_;
+ int rightMargin_;
+ std::string indentation_;
+ bool addChildValues_;
+ };
+
+ std::string JSON_API valueToString( Value::Int value );
+ std::string JSON_API valueToString( Value::UInt 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>>()
+ std::ostream& operator<<( std::ostream&, const Value &root );
+
+} // namespace Json
+
+
+
+#endif // JSON_WRITER_H_INCLUDED
diff --git a/lib/jsoncpp/jsoncpp/makefiles/vs71/jsoncpp.sln b/lib/jsoncpp/jsoncpp/makefiles/vs71/jsoncpp.sln
new file mode 100644
index 0000000000..5bfa366547
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/makefiles/vs71/jsoncpp.sln
@@ -0,0 +1,46 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lib_json", "lib_json.vcproj", "{B84F7231-16CE-41D8-8C08-7B523FF4225B}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jsontest", "jsontest.vcproj", "{25AF2DD2-D396-4668-B188-488C33B8E620}"
+ ProjectSection(ProjectDependencies) = postProject
+ {B84F7231-16CE-41D8-8C08-7B523FF4225B} = {B84F7231-16CE-41D8-8C08-7B523FF4225B}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_lib_json", "test_lib_json.vcproj", "{B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}"
+ ProjectSection(ProjectDependencies) = postProject
+ {B84F7231-16CE-41D8-8C08-7B523FF4225B} = {B84F7231-16CE-41D8-8C08-7B523FF4225B}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ dummy = dummy
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {B84F7231-16CE-41D8-8C08-7B523FF4225B}.Debug.ActiveCfg = Debug|Win32
+ {B84F7231-16CE-41D8-8C08-7B523FF4225B}.Debug.Build.0 = Debug|Win32
+ {B84F7231-16CE-41D8-8C08-7B523FF4225B}.dummy.ActiveCfg = dummy|Win32
+ {B84F7231-16CE-41D8-8C08-7B523FF4225B}.dummy.Build.0 = dummy|Win32
+ {B84F7231-16CE-41D8-8C08-7B523FF4225B}.Release.ActiveCfg = Release|Win32
+ {B84F7231-16CE-41D8-8C08-7B523FF4225B}.Release.Build.0 = Release|Win32
+ {25AF2DD2-D396-4668-B188-488C33B8E620}.Debug.ActiveCfg = Debug|Win32
+ {25AF2DD2-D396-4668-B188-488C33B8E620}.Debug.Build.0 = Debug|Win32
+ {25AF2DD2-D396-4668-B188-488C33B8E620}.dummy.ActiveCfg = Debug|Win32
+ {25AF2DD2-D396-4668-B188-488C33B8E620}.dummy.Build.0 = Debug|Win32
+ {25AF2DD2-D396-4668-B188-488C33B8E620}.Release.ActiveCfg = Release|Win32
+ {25AF2DD2-D396-4668-B188-488C33B8E620}.Release.Build.0 = Release|Win32
+ {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Debug.ActiveCfg = Debug|Win32
+ {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Debug.Build.0 = Debug|Win32
+ {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.dummy.ActiveCfg = Debug|Win32
+ {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.dummy.Build.0 = Debug|Win32
+ {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Release.ActiveCfg = Release|Win32
+ {B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/lib/jsoncpp/jsoncpp/makefiles/vs71/jsontest.vcproj b/lib/jsoncpp/jsoncpp/makefiles/vs71/jsontest.vcproj
new file mode 100644
index 0000000000..99a4dd6971
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/makefiles/vs71/jsontest.vcproj
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="jsontest"
+ ProjectGUID="{25AF2DD2-D396-4668-B188-488C33B8E620}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="../../build/vs71/debug/jsontest"
+ IntermediateDirectory="../../build/vs71/debug/jsontest"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/jsontest.exe"
+ LinkIncremental="2"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/jsontest.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="../../build/vs71/release/jsontest"
+ IntermediateDirectory="../../build/vs71/release/jsontest"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/jsontest.exe"
+ LinkIncremental="1"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\..\src\jsontestrunner\main.cpp">
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/lib/jsoncpp/jsoncpp/makefiles/vs71/lib_json.vcproj b/lib/jsoncpp/jsoncpp/makefiles/vs71/lib_json.vcproj
new file mode 100644
index 0000000000..1aa5978a1f
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/makefiles/vs71/lib_json.vcproj
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="lib_json"
+ ProjectGUID="{B84F7231-16CE-41D8-8C08-7B523FF4225B}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="../../build/vs71/debug/lib_json"
+ IntermediateDirectory="../../build/vs71/debug/lib_json"
+ ConfigurationType="4"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ StringPooling="TRUE"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="TRUE"
+ ForceConformanceInForLoopScope="FALSE"
+ RuntimeTypeInfo="TRUE"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="$(OutDir)/json_vc71_libmtd.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="../../build/vs71/release/lib_json"
+ IntermediateDirectory="../../build/vs71/release/lib_json"
+ ConfigurationType="4"
+ CharacterSet="2"
+ WholeProgramOptimization="TRUE">
+ <Tool
+ Name="VCCLCompilerTool"
+ GlobalOptimizations="TRUE"
+ EnableIntrinsicFunctions="TRUE"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="TRUE"
+ ForceConformanceInForLoopScope="FALSE"
+ RuntimeTypeInfo="TRUE"
+ UsePrecompiledHeader="0"
+ AssemblerOutput="4"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="$(OutDir)/json_vc71_libmt.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="dummy|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="TRUE">
+ <Tool
+ Name="VCCLCompilerTool"
+ GlobalOptimizations="TRUE"
+ EnableIntrinsicFunctions="TRUE"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="4"
+ EnableFunctionLevelLinking="TRUE"
+ DisableLanguageExtensions="TRUE"
+ ForceConformanceInForLoopScope="FALSE"
+ RuntimeTypeInfo="TRUE"
+ UsePrecompiledHeader="0"
+ AssemblerOutput="4"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ GenerateDebugInformation="TRUE"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\..\include\json\autolink.h">
+ </File>
+ <File
+ RelativePath="..\..\include\json\config.h">
+ </File>
+ <File
+ RelativePath="..\..\include\json\features.h">
+ </File>
+ <File
+ RelativePath="..\..\include\json\forwards.h">
+ </File>
+ <File
+ RelativePath="..\..\include\json\json.h">
+ </File>
+ <File
+ RelativePath="..\..\src\lib_json\json_batchallocator.h">
+ </File>
+ <File
+ RelativePath="..\..\src\lib_json\json_internalarray.inl">
+ </File>
+ <File
+ RelativePath="..\..\src\lib_json\json_internalmap.inl">
+ </File>
+ <File
+ RelativePath="..\..\src\lib_json\json_reader.cpp">
+ </File>
+ <File
+ RelativePath="..\..\src\lib_json\json_value.cpp">
+ </File>
+ <File
+ RelativePath="..\..\src\lib_json\json_valueiterator.inl">
+ </File>
+ <File
+ RelativePath="..\..\src\lib_json\json_writer.cpp">
+ </File>
+ <File
+ RelativePath="..\..\include\json\reader.h">
+ </File>
+ <File
+ RelativePath="..\..\include\json\value.h">
+ </File>
+ <File
+ RelativePath="..\..\include\json\writer.h">
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/lib/jsoncpp/jsoncpp/makefiles/vs71/test_lib_json.vcproj b/lib/jsoncpp/jsoncpp/makefiles/vs71/test_lib_json.vcproj
new file mode 100644
index 0000000000..df36700bdc
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/makefiles/vs71/test_lib_json.vcproj
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="test_lib_json"
+ ProjectGUID="{B7A96B78-2782-40D2-8F37-A2DEF2B9C26D}"
+ RootNamespace="test_lib_json"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="../../build/vs71/debug/test_lib_json"
+ IntermediateDirectory="../../build/vs71/debug/test_lib_json"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/test_lib_json.exe"
+ LinkIncremental="2"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile="$(OutDir)/test_lib_json.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Running all unit tests"
+ CommandLine="$(TargetPath)"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="../../build/vs71/release/test_lib_json"
+ IntermediateDirectory="../../build/vs71/release/test_lib_json"
+ ConfigurationType="1"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../../include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)/test_lib_json.exe"
+ LinkIncremental="1"
+ GenerateDebugInformation="TRUE"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Running all unit tests"
+ CommandLine="$(TargetPath)"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\..\src\test_lib_json\jsontest.cpp">
+ </File>
+ <File
+ RelativePath="..\..\src\test_lib_json\jsontest.h">
+ </File>
+ <File
+ RelativePath="..\..\src\test_lib_json\main.cpp">
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/lib/jsoncpp/jsoncpp/scons-tools/doxygen.py b/lib/jsoncpp/jsoncpp/scons-tools/doxygen.py
new file mode 100644
index 0000000000..5ace420a4c
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/scons-tools/doxygen.py
@@ -0,0 +1,116 @@
+# Big issue:
+# emitter depends on doxyfile which is generated from doxyfile.in.
+# build fails after cleaning and relaunching the build.
+
+# Todo:
+# Add helper function to environment like for glob
+# Easier passage of header/footer
+# Automatic deduction of index.html path based on custom parameters passed to doxyfile
+
+import os
+import os.path
+from fnmatch import fnmatch
+import SCons
+
+def Doxyfile_emitter(target, source, env):
+ """
+ Modify the target and source lists to use the defaults if nothing
+ else has been specified.
+
+ Dependencies on external HTML documentation references are also
+ appended to the source list.
+ """
+ doxyfile_template = env.File(env['DOXYFILE_FILE'])
+ source.insert(0, doxyfile_template)
+
+ return target, source
+
+def Doxyfile_Builder(target, source, env):
+ """Input:
+ DOXYFILE_FILE
+ Path of the template file for the output doxyfile
+
+ DOXYFILE_DICT
+ A dictionnary of parameter to append to the generated doxyfile
+ """
+ subdir = os.path.split(source[0].abspath)[0]
+ doc_top_dir = os.path.split(target[0].abspath)[0]
+ doxyfile_path = source[0].abspath
+ doxy_file = file( target[0].abspath, 'wt' )
+ try:
+ # First, output the template file
+ try:
+ f = file(doxyfile_path, 'rt')
+ doxy_file.write( f.read() )
+ f.close()
+ doxy_file.write( '\n' )
+ doxy_file.write( '# Generated content:\n' )
+ except:
+ raise SCons.Errors.UserError, "Can't read doxygen template file '%s'" % doxyfile_path
+ # Then, the input files
+ doxy_file.write( 'INPUT = \\\n' )
+ for source in source:
+ if source.abspath != doxyfile_path: # skip doxyfile path, which is the first source
+ doxy_file.write( '"%s" \\\n' % source.abspath )
+ doxy_file.write( '\n' )
+ # Dot...
+ values_dict = { 'HAVE_DOT': env.get('DOT') and 'YES' or 'NO',
+ 'DOT_PATH': env.get('DOT') and os.path.split(env['DOT'])[0] or '',
+ 'OUTPUT_DIRECTORY': doc_top_dir,
+ 'WARN_LOGFILE': target[0].abspath + '-warning.log'}
+ values_dict.update( env['DOXYFILE_DICT'] )
+ # Finally, output user dictionary values which override any of the previously set parameters.
+ for key, value in values_dict.iteritems():
+ doxy_file.write ('%s = "%s"\n' % (key, str(value)))
+ finally:
+ doxy_file.close()
+
+def generate(env):
+ """
+ Add builders and construction variables for the
+ Doxygen tool.
+ """
+ ## Doxyfile builder
+ def doxyfile_message (target, source, env):
+ return "creating Doxygen config file '%s'" % target[0]
+
+ doxyfile_variables = [
+ 'DOXYFILE_DICT',
+ 'DOXYFILE_FILE'
+ ]
+
+ #doxyfile_action = SCons.Action.Action( Doxyfile_Builder, doxyfile_message,
+ # doxyfile_variables )
+ doxyfile_action = SCons.Action.Action( Doxyfile_Builder, doxyfile_message)
+
+ doxyfile_builder = SCons.Builder.Builder( action = doxyfile_action,
+ emitter = Doxyfile_emitter )
+
+ env['BUILDERS']['Doxyfile'] = doxyfile_builder
+ env['DOXYFILE_DICT'] = {}
+ env['DOXYFILE_FILE'] = 'doxyfile.in'
+
+ ## Doxygen builder
+ def Doxygen_emitter(target, source, env):
+ output_dir = str( source[0].dir )
+ if str(target[0]) == str(source[0]):
+ target = env.File( os.path.join( output_dir, 'html', 'index.html' ) )
+ return target, source
+
+ doxygen_action = SCons.Action.Action( [ '$DOXYGEN_COM'] )
+ doxygen_builder = SCons.Builder.Builder( action = doxygen_action,
+ emitter = Doxygen_emitter )
+ env['BUILDERS']['Doxygen'] = doxygen_builder
+ env['DOXYGEN_COM'] = '$DOXYGEN $DOXYGEN_FLAGS $SOURCE'
+ env['DOXYGEN_FLAGS'] = ''
+ env['DOXYGEN'] = 'doxygen'
+
+ dot_path = env.WhereIs("dot")
+ if dot_path:
+ env['DOT'] = dot_path
+
+def exists(env):
+ """
+ Make sure doxygen exists.
+ """
+ return env.Detect("doxygen")
diff --git a/lib/jsoncpp/jsoncpp/scons-tools/globtool.py b/lib/jsoncpp/jsoncpp/scons-tools/globtool.py
new file mode 100644
index 0000000000..8ee3cbb0b6
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/scons-tools/globtool.py
@@ -0,0 +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
+ Environment.Glob = Glob
+
+def exists(env):
+ """
+ Tool always exists.
+ """
+ return True
diff --git a/lib/jsoncpp/jsoncpp/scons-tools/srcdist.py b/lib/jsoncpp/jsoncpp/scons-tools/srcdist.py
new file mode 100644
index 0000000000..864ff40815
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/scons-tools/srcdist.py
@@ -0,0 +1,179 @@
+import os
+import os.path
+from fnmatch import fnmatch
+import targz
+
+##def DoxyfileParse(file_contents):
+## """
+## Parse a Doxygen source file and return a dictionary of all the values.
+## Values will be strings and lists of strings.
+## """
+## data = {}
+##
+## import shlex
+## lex = shlex.shlex(instream = file_contents, posix = True)
+## lex.wordchars += "*+./-:"
+## lex.whitespace = lex.whitespace.replace("\n", "")
+## lex.escape = ""
+##
+## lineno = lex.lineno
+## last_backslash_lineno = lineno
+## token = lex.get_token()
+## key = token # the first token should be a key
+## last_token = ""
+## key_token = False
+## next_key = False
+## new_data = True
+##
+## def append_data(data, key, new_data, token):
+## if new_data or len(data[key]) == 0:
+## data[key].append(token)
+## else:
+## data[key][-1] += token
+##
+## while token:
+## if token in ['\n']:
+## if last_token not in ['\\']:
+## key_token = True
+## elif token in ['\\']:
+## pass
+## elif key_token:
+## key = token
+## key_token = False
+## else:
+## if token == "+=":
+## if not data.has_key(key):
+## data[key] = list()
+## elif token == "=":
+## data[key] = list()
+## else:
+## append_data( data, key, new_data, token )
+## new_data = True
+##
+## last_token = token
+## token = lex.get_token()
+##
+## if last_token == '\\' and token != '\n':
+## new_data = False
+## append_data( data, key, new_data, '\\' )
+##
+## # compress lists of len 1 into single strings
+## for (k, v) in data.items():
+## if len(v) == 0:
+## data.pop(k)
+##
+## # items in the following list will be kept as lists and not converted to strings
+## if k in ["INPUT", "FILE_PATTERNS", "EXCLUDE_PATTERNS"]:
+## continue
+##
+## if len(v) == 1:
+## data[k] = v[0]
+##
+## return data
+##
+##def DoxySourceScan(node, env, path):
+## """
+## Doxygen Doxyfile source scanner. This should scan the Doxygen file and add
+## any files used to generate docs to the list of source files.
+## """
+## default_file_patterns = [
+## '*.c', '*.cc', '*.cxx', '*.cpp', '*.c++', '*.java', '*.ii', '*.ixx',
+## '*.ipp', '*.i++', '*.inl', '*.h', '*.hh ', '*.hxx', '*.hpp', '*.h++',
+## '*.idl', '*.odl', '*.cs', '*.php', '*.php3', '*.inc', '*.m', '*.mm',
+## '*.py',
+## ]
+##
+## default_exclude_patterns = [
+## '*~',
+## ]
+##
+## sources = []
+##
+## data = DoxyfileParse(node.get_contents())
+##
+## if data.get("RECURSIVE", "NO") == "YES":
+## recursive = True
+## else:
+## recursive = False
+##
+## file_patterns = data.get("FILE_PATTERNS", default_file_patterns)
+## exclude_patterns = data.get("EXCLUDE_PATTERNS", default_exclude_patterns)
+##
+## for node in data.get("INPUT", []):
+## if os.path.isfile(node):
+## sources.add(node)
+## elif os.path.isdir(node):
+## if recursive:
+## for root, dirs, files in os.walk(node):
+## for f in files:
+## filename = os.path.join(root, f)
+##
+## pattern_check = reduce(lambda x, y: x or bool(fnmatch(filename, y)), file_patterns, False)
+## exclude_check = reduce(lambda x, y: x and fnmatch(filename, y), exclude_patterns, True)
+##
+## if pattern_check and not exclude_check:
+## sources.append(filename)
+## else:
+## for pattern in file_patterns:
+## sources.extend(glob.glob("/".join([node, pattern])))
+## sources = map( lambda path: env.File(path), sources )
+## return sources
+##
+##
+##def DoxySourceScanCheck(node, env):
+## """Check if we should scan this file"""
+## return os.path.isfile(node.path)
+
+def srcDistEmitter(source, target, env):
+## """Doxygen Doxyfile emitter"""
+## # possible output formats and their default values and output locations
+## output_formats = {
+## "HTML": ("YES", "html"),
+## "LATEX": ("YES", "latex"),
+## "RTF": ("NO", "rtf"),
+## "MAN": ("YES", "man"),
+## "XML": ("NO", "xml"),
+## }
+##
+## data = DoxyfileParse(source[0].get_contents())
+##
+## targets = []
+## out_dir = data.get("OUTPUT_DIRECTORY", ".")
+##
+## # add our output locations
+## for (k, v) in output_formats.items():
+## if data.get("GENERATE_" + k, v[0]) == "YES":
+## targets.append(env.Dir( os.path.join(out_dir, data.get(k + "_OUTPUT", v[1]))) )
+##
+## # don't clobber targets
+## for node in targets:
+## env.Precious(node)
+##
+## # set up cleaning stuff
+## for node in targets:
+## env.Clean(node, node)
+##
+## return (targets, source)
+ return (target,source)
+
+def generate(env):
+ """
+ Add builders and construction variables for the
+ SrcDist tool.
+ """
+## doxyfile_scanner = env.Scanner(
+## DoxySourceScan,
+## "DoxySourceScan",
+## scan_check = DoxySourceScanCheck,
+## )
+
+ if targz.exists(env):
+ srcdist_builder = targz.makeBuilder( srcDistEmitter )
+
+ env['BUILDERS']['SrcDist'] = srcdist_builder
+
+def exists(env):
+ """
+ Make sure srcdist exists.
+ """
+ return targz.exists(env)
diff --git a/lib/jsoncpp/jsoncpp/scons-tools/substinfile.py b/lib/jsoncpp/jsoncpp/scons-tools/substinfile.py
new file mode 100644
index 0000000000..4d305851bb
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/scons-tools/substinfile.py
@@ -0,0 +1,79 @@
+import re
+from SCons.Script import * # the usual scons stuff you get in a SConscript
+
+def generate(env):
+ """
+ Add builders and construction variables for the
+ SubstInFile tool.
+
+ Adds SubstInFile builder, which substitutes the keys->values of SUBST_DICT
+ from the source to the target.
+ The values of SUBST_DICT first have any construction variables expanded
+ (its keys are not expanded).
+ If a value of SUBST_DICT is a python callable function, it is called and
+ the result is expanded as the value.
+ If there's more than one source and more than one target, each target gets
+ substituted from the corresponding source.
+ """
+ def do_subst_in_file(targetfile, sourcefile, dict):
+ """Replace all instances of the keys of dict with their values.
+ For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
+ then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
+ """
+ try:
+ f = open(sourcefile, 'rb')
+ contents = f.read()
+ f.close()
+ except:
+ raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
+ for (k,v) in dict.items():
+ contents = re.sub(k, v, contents)
+ try:
+ f = open(targetfile, 'wb')
+ f.write(contents)
+ f.close()
+ except:
+ raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
+ return 0 # success
+
+ def subst_in_file(target, source, env):
+ if not env.has_key('SUBST_DICT'):
+ raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
+ d = dict(env['SUBST_DICT']) # copy it
+ for (k,v) in d.items():
+ if callable(v):
+ d[k] = env.subst(v()).replace('\\','\\\\')
+ elif SCons.Util.is_String(v):
+ d[k] = env.subst(v).replace('\\','\\\\')
+ else:
+ raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
+ for (t,s) in zip(target, source):
+ return do_subst_in_file(str(t), str(s), d)
+
+ def subst_in_file_string(target, source, env):
+ """This is what gets printed on the console."""
+ return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
+ for (t,s) in zip(target, source)])
+
+ def subst_emitter(target, source, env):
+ """Add dependency from substituted SUBST_DICT to target.
+ Returns original target, source tuple unchanged.
+ """
+ d = env['SUBST_DICT'].copy() # copy it
+ for (k,v) in d.items():
+ if callable(v):
+ d[k] = env.subst(v())
+ elif SCons.Util.is_String(v):
+ d[k]=env.subst(v)
+ Depends(target, SCons.Node.Python.Value(d))
+ return target, source
+
+## env.Append(TOOLS = 'substinfile') # this should be automaticaly done by Scons ?!?
+ subst_action = SCons.Action.Action( subst_in_file, subst_in_file_string )
+ env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
+
+def exists(env):
+ """
+ Make sure tool exists.
+ """
+ return True
diff --git a/lib/jsoncpp/jsoncpp/scons-tools/targz.py b/lib/jsoncpp/jsoncpp/scons-tools/targz.py
new file mode 100644
index 0000000000..f5432003df
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/scons-tools/targz.py
@@ -0,0 +1,82 @@
+"""tarball
+
+Tool-specific initialization for tarball.
+
+"""
+
+## Commands to tackle a command based implementation:
+##to unpack on the fly...
+##gunzip < FILE.tar.gz | tar xvf -
+##to pack on the fly...
+##tar cvf - FILE-LIST | gzip -c > FILE.tar.gz
+
+import os.path
+
+import SCons.Builder
+import SCons.Node.FS
+import SCons.Util
+
+try:
+ import gzip
+ import tarfile
+ internal_targz = 1
+except ImportError:
+ internal_targz = 0
+
+TARGZ_DEFAULT_COMPRESSION_LEVEL = 9
+
+if internal_targz:
+ def targz(target, source, env):
+ def archive_name( path ):
+ path = os.path.normpath( os.path.abspath( path ) )
+ common_path = os.path.commonprefix( (base_dir, path) )
+ archive_name = path[len(common_path):]
+ return archive_name
+
+ def visit(tar, dirname, names):
+ for name in names:
+ path = os.path.join(dirname, name)
+ if os.path.isfile(path):
+ tar.add(path, archive_name(path) )
+ compression = env.get('TARGZ_COMPRESSION_LEVEL',TARGZ_DEFAULT_COMPRESSION_LEVEL)
+ base_dir = os.path.normpath( env.get('TARGZ_BASEDIR', env.Dir('.')).abspath )
+ target_path = str(target[0])
+ fileobj = gzip.GzipFile( target_path, 'wb', compression )
+ tar = tarfile.TarFile(os.path.splitext(target_path)[0], 'w', fileobj)
+ for source in source:
+ source_path = str(source)
+ if source.isdir():
+ os.path.walk(source_path, visit, tar)
+ else:
+ tar.add(source_path, archive_name(source_path) ) # filename, arcname
+ tar.close()
+
+ targzAction = SCons.Action.Action(targz, varlist=['TARGZ_COMPRESSION_LEVEL','TARGZ_BASEDIR'])
+
+ def makeBuilder( emitter = None ):
+ return SCons.Builder.Builder(action = SCons.Action.Action('$TARGZ_COM', '$TARGZ_COMSTR'),
+ source_factory = SCons.Node.FS.Entry,
+ source_scanner = SCons.Defaults.DirScanner,
+ suffix = '$TARGZ_SUFFIX',
+ multi = 1)
+ TarGzBuilder = makeBuilder()
+
+ def generate(env):
+ """Add Builders and construction variables for zip to an Environment.
+ The following environnement variables may be set:
+ TARGZ_COMPRESSION_LEVEL: integer, [0-9]. 0: no compression, 9: best compression (same as gzip compression level).
+ TARGZ_BASEDIR: base-directory used to determine archive name (this allow archive name to be relative
+ to something other than top-dir).
+ """
+ env['BUILDERS']['TarGz'] = TarGzBuilder
+ env['TARGZ_COM'] = targzAction
+ env['TARGZ_COMPRESSION_LEVEL'] = TARGZ_DEFAULT_COMPRESSION_LEVEL # range 0-9
+ env['TARGZ_SUFFIX'] = '.tar.gz'
+ env['TARGZ_BASEDIR'] = env.Dir('.') # Sources archive name are made relative to that directory.
+else:
+ def generate(env):
+ pass
+
+
+def exists(env):
+ return internal_targz
diff --git a/lib/jsoncpp/jsoncpp/src/jsontestrunner/main.cpp b/lib/jsoncpp/jsoncpp/src/jsontestrunner/main.cpp
new file mode 100644
index 0000000000..231ee0c44d
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/src/jsontestrunner/main.cpp
@@ -0,0 +1,233 @@
+#include <json/json.h>
+#include <algorithm> // sort
+#include <stdio.h>
+
+#if defined(_MSC_VER) && _MSC_VER >= 1310
+# pragma warning( disable: 4996 ) // disable fopen deprecation warning
+#endif
+
+static std::string
+readInputTestFile( const char *path )
+{
+ FILE *file = fopen( path, "rb" );
+ if ( !file )
+ return std::string("");
+ fseek( file, 0, SEEK_END );
+ long size = ftell( file );
+ fseek( file, 0, SEEK_SET );
+ std::string text;
+ char *buffer = new char[size+1];
+ buffer[size] = 0;
+ if ( fread( buffer, 1, size, file ) == (unsigned long)size )
+ text = buffer;
+ fclose( file );
+ delete[] buffer;
+ return text;
+}
+
+
+static void
+printValueTree( FILE *fout, Json::Value &value, const std::string &path = "." )
+{
+ switch ( value.type() )
+ {
+ case Json::nullValue:
+ fprintf( fout, "%s=null\n", path.c_str() );
+ break;
+ case Json::intValue:
+ fprintf( fout, "%s=%d\n", path.c_str(), value.asInt() );
+ break;
+ case Json::uintValue:
+ fprintf( fout, "%s=%u\n", path.c_str(), value.asUInt() );
+ break;
+ case Json::realValue:
+ 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() );
+ break;
+ case Json::booleanValue:
+ fprintf( fout, "%s=%s\n", path.c_str(), value.asBool() ? "true" : "false" );
+ break;
+ case Json::arrayValue:
+ {
+ fprintf( fout, "%s=[]\n", path.c_str() );
+ int size = value.size();
+ for ( int index =0; index < size; ++index )
+ {
+ static char buffer[16];
+ sprintf( buffer, "[%d]", index );
+ printValueTree( fout, value[index], path + buffer );
+ }
+ }
+ break;
+ case Json::objectValue:
+ {
+ fprintf( fout, "%s={}\n", path.c_str() );
+ Json::Value::Members members( value.getMemberNames() );
+ std::sort( members.begin(), members.end() );
+ std::string suffix = *(path.end()-1) == '.' ? "" : ".";
+ for ( Json::Value::Members::iterator it = members.begin();
+ it != members.end();
+ ++it )
+ {
+ const std::string &name = *it;
+ printValueTree( fout, value[name], path + suffix + name );
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+
+static int
+parseAndSaveValueTree( const std::string &input,
+ const std::string &actual,
+ const std::string &kind,
+ Json::Value &root,
+ const Json::Features &features,
+ bool parseOnly )
+{
+ Json::Reader reader( features );
+ bool parsingSuccessful = reader.parse( input, root );
+ if ( !parsingSuccessful )
+ {
+ printf( "Failed to parse %s file: \n%s\n",
+ kind.c_str(),
+ reader.getFormatedErrorMessages().c_str() );
+ return 1;
+ }
+
+ if ( !parseOnly )
+ {
+ FILE *factual = fopen( actual.c_str(), "wt" );
+ if ( !factual )
+ {
+ printf( "Failed to create %s actual file.\n", kind.c_str() );
+ return 2;
+ }
+ printValueTree( factual, root );
+ fclose( factual );
+ }
+ return 0;
+}
+
+
+static int
+rewriteValueTree( const std::string &rewritePath,
+ const Json::Value &root,
+ std::string &rewrite )
+{
+ //Json::FastWriter writer;
+ //writer.enableYAMLCompatibility();
+ Json::StyledWriter writer;
+ rewrite = writer.write( root );
+ FILE *fout = fopen( rewritePath.c_str(), "wt" );
+ if ( !fout )
+ {
+ printf( "Failed to create rewrite file: %s\n", rewritePath.c_str() );
+ return 2;
+ }
+ fprintf( fout, "%s\n", rewrite.c_str() );
+ fclose( fout );
+ return 0;
+}
+
+
+static std::string
+removeSuffix( const std::string &path,
+ const std::string &extension )
+{
+ if ( extension.length() >= path.length() )
+ return std::string("");
+ std::string suffix = path.substr( path.length() - extension.length() );
+ if ( suffix != extension )
+ return std::string("");
+ return path.substr( 0, path.length() - extension.length() );
+}
+
+static int
+printUsage( const char *argv[] )
+{
+ printf( "Usage: %s [--strict] input-json-file", argv[0] );
+ return 3;
+}
+
+
+int
+parseCommandLine( int argc, const char *argv[],
+ Json::Features &features, std::string &path,
+ bool &parseOnly )
+{
+ parseOnly = false;
+ if ( argc < 2 )
+ {
+ return printUsage( argv );
+ }
+
+ int index = 1;
+ if ( std::string(argv[1]) == "--json-checker" )
+ {
+ features = Json::Features::strictMode();
+ parseOnly = true;
+ ++index;
+ }
+
+ if ( index == argc || index + 1 < argc )
+ {
+ return printUsage( argv );
+ }
+
+ path = argv[index];
+ return 0;
+}
+
+
+int main( int argc, const char *argv[] )
+{
+ std::string path;
+ Json::Features features;
+ bool parseOnly;
+ int exitCode = parseCommandLine( argc, argv, features, path, parseOnly );
+ if ( exitCode != 0 )
+ {
+ return exitCode;
+ }
+
+ 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 );
+ }
+ }
+
+ return exitCode;
+}
+
diff --git a/lib/jsoncpp/jsoncpp/src/jsontestrunner/sconscript b/lib/jsoncpp/jsoncpp/src/jsontestrunner/sconscript
new file mode 100644
index 0000000000..6e68e31533
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/src/jsontestrunner/sconscript
@@ -0,0 +1,9 @@
+Import( 'env_testing buildJSONTests' )
+
+buildJSONTests( env_testing, Split( """
+ main.cpp
+ """ ),
+ 'jsontestrunner' )
+
+# For 'check' to work, 'libs' must be built first.
+env_testing.Depends('jsontestrunner', '#libs')
diff --git a/lib/jsoncpp/jsoncpp/src/lib_json/json_batchallocator.h b/lib/jsoncpp/jsoncpp/src/lib_json/json_batchallocator.h
new file mode 100644
index 0000000000..87ea5ed807
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/src/lib_json/json_batchallocator.h
@@ -0,0 +1,125 @@
+#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
+# define JSONCPP_BATCHALLOCATOR_H_INCLUDED
+
+# include <stdlib.h>
+# include <assert.h>
+
+# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+namespace Json {
+
+/* Fast memory allocator.
+ *
+ * This memory allocator allocates memory for a batch of object (specified by
+ * the page size, the number of object in each page).
+ *
+ * It does not allow the destruction of a single object. All the allocated objects
+ * can be destroyed at once. The memory can be either released or reused for future
+ * allocation.
+ *
+ * The in-place new operator must be used to construct the object using the pointer
+ * returned by allocate.
+ */
+template<typename AllocatedType
+ ,const unsigned int objectPerAllocation>
+class BatchAllocator
+{
+public:
+ typedef AllocatedType Type;
+
+ BatchAllocator( unsigned int objectsPerPage = 255 )
+ : freeHead_( 0 )
+ , objectsPerPage_( objectsPerPage )
+ {
+// printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
+ assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space.
+ assert( objectsPerPage >= 16 );
+ batches_ = allocateBatch( 0 ); // allocated a dummy page
+ currentBatch_ = batches_;
+ }
+
+ ~BatchAllocator()
+ {
+ for ( BatchInfo *batch = batches_; batch; )
+ {
+ BatchInfo *nextBatch = batch->next_;
+ free( batch );
+ batch = nextBatch;
+ }
+ }
+
+ /// allocate space for an array of objectPerAllocation object.
+ /// @warning it is the responsability of the caller to call objects constructors.
+ AllocatedType *allocate()
+ {
+ if ( freeHead_ ) // returns node from free list.
+ {
+ AllocatedType *object = freeHead_;
+ freeHead_ = *(AllocatedType **)object;
+ return object;
+ }
+ if ( currentBatch_->used_ == currentBatch_->end_ )
+ {
+ currentBatch_ = currentBatch_->next_;
+ while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ )
+ currentBatch_ = currentBatch_->next_;
+
+ if ( !currentBatch_ ) // no free batch found, allocate a new one
+ {
+ currentBatch_ = allocateBatch( objectsPerPage_ );
+ currentBatch_->next_ = batches_; // insert at the head of the list
+ batches_ = currentBatch_;
+ }
+ }
+ AllocatedType *allocated = currentBatch_->used_;
+ currentBatch_->used_ += objectPerAllocation;
+ return allocated;
+ }
+
+ /// Release the object.
+ /// @warning it is the responsability of the caller to actually destruct the object.
+ void release( AllocatedType *object )
+ {
+ assert( object != 0 );
+ *(AllocatedType **)object = freeHead_;
+ freeHead_ = object;
+ }
+
+private:
+ struct BatchInfo
+ {
+ BatchInfo *next_;
+ AllocatedType *used_;
+ AllocatedType *end_;
+ AllocatedType buffer_[objectPerAllocation];
+ };
+
+ // disabled copy constructor and assignement operator.
+ BatchAllocator( const BatchAllocator & );
+ void operator =( const BatchAllocator &);
+
+ static BatchInfo *allocateBatch( unsigned int objectsPerPage )
+ {
+ const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation
+ + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
+ BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) );
+ batch->next_ = 0;
+ batch->used_ = batch->buffer_;
+ batch->end_ = batch->buffer_ + objectsPerPage;
+ return batch;
+ }
+
+ BatchInfo *batches_;
+ BatchInfo *currentBatch_;
+ /// Head of a single linked list within the allocated space of freeed object
+ AllocatedType *freeHead_;
+ unsigned int objectsPerPage_;
+};
+
+
+} // namespace Json
+
+# endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
+
+#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
+
diff --git a/lib/jsoncpp/jsoncpp/src/lib_json/json_internalarray.inl b/lib/jsoncpp/jsoncpp/src/lib_json/json_internalarray.inl
new file mode 100644
index 0000000000..9b985d2585
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/src/lib_json/json_internalarray.inl
@@ -0,0 +1,448 @@
+// included by json_value.cpp
+// everything is within Json namespace
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueInternalArray
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueArrayAllocator::~ValueArrayAllocator()
+{
+}
+
+// //////////////////////////////////////////////////////////////////
+// class DefaultValueArrayAllocator
+// //////////////////////////////////////////////////////////////////
+#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+class DefaultValueArrayAllocator : public ValueArrayAllocator
+{
+public: // overridden from ValueArrayAllocator
+ virtual ~DefaultValueArrayAllocator()
+ {
+ }
+
+ virtual ValueInternalArray *newArray()
+ {
+ return new ValueInternalArray();
+ }
+
+ virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
+ {
+ return new ValueInternalArray( other );
+ }
+
+ virtual void destructArray( ValueInternalArray *array )
+ {
+ delete array;
+ }
+
+ virtual void reallocateArrayPageIndex( Value **&indexes,
+ ValueInternalArray::PageIndex &indexCount,
+ ValueInternalArray::PageIndex minNewIndexCount )
+ {
+ ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
+ if ( minNewIndexCount > newIndexCount )
+ newIndexCount = minNewIndexCount;
+ void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
+ if ( !newIndexes )
+ throw std::bad_alloc();
+ indexCount = newIndexCount;
+ indexes = static_cast<Value **>( newIndexes );
+ }
+ virtual void releaseArrayPageIndex( Value **indexes,
+ ValueInternalArray::PageIndex indexCount )
+ {
+ if ( indexes )
+ free( indexes );
+ }
+
+ virtual Value *allocateArrayPage()
+ {
+ return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
+ }
+
+ virtual void releaseArrayPage( Value *value )
+ {
+ if ( value )
+ free( value );
+ }
+};
+
+#else // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+/// @todo make this thread-safe (lock when accessign batch allocator)
+class DefaultValueArrayAllocator : public ValueArrayAllocator
+{
+public: // overridden from ValueArrayAllocator
+ virtual ~DefaultValueArrayAllocator()
+ {
+ }
+
+ virtual ValueInternalArray *newArray()
+ {
+ ValueInternalArray *array = arraysAllocator_.allocate();
+ new (array) ValueInternalArray(); // placement new
+ return array;
+ }
+
+ virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
+ {
+ ValueInternalArray *array = arraysAllocator_.allocate();
+ new (array) ValueInternalArray( other ); // placement new
+ return array;
+ }
+
+ virtual void destructArray( ValueInternalArray *array )
+ {
+ if ( array )
+ {
+ array->~ValueInternalArray();
+ arraysAllocator_.release( array );
+ }
+ }
+
+ virtual void reallocateArrayPageIndex( Value **&indexes,
+ ValueInternalArray::PageIndex &indexCount,
+ ValueInternalArray::PageIndex minNewIndexCount )
+ {
+ ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
+ if ( minNewIndexCount > newIndexCount )
+ newIndexCount = minNewIndexCount;
+ void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
+ if ( !newIndexes )
+ throw std::bad_alloc();
+ indexCount = newIndexCount;
+ indexes = static_cast<Value **>( newIndexes );
+ }
+ virtual void releaseArrayPageIndex( Value **indexes,
+ ValueInternalArray::PageIndex indexCount )
+ {
+ if ( indexes )
+ free( indexes );
+ }
+
+ virtual Value *allocateArrayPage()
+ {
+ return static_cast<Value *>( pagesAllocator_.allocate() );
+ }
+
+ virtual void releaseArrayPage( Value *value )
+ {
+ if ( value )
+ pagesAllocator_.release( value );
+ }
+private:
+ BatchAllocator<ValueInternalArray,1> arraysAllocator_;
+ BatchAllocator<Value,ValueInternalArray::itemsPerPage> pagesAllocator_;
+};
+#endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+
+static ValueArrayAllocator *&arrayAllocator()
+{
+ static DefaultValueArrayAllocator defaultAllocator;
+ static ValueArrayAllocator *arrayAllocator = &defaultAllocator;
+ return arrayAllocator;
+}
+
+static struct DummyArrayAllocatorInitializer {
+ DummyArrayAllocatorInitializer()
+ {
+ arrayAllocator(); // ensure arrayAllocator() statics are initialized before main().
+ }
+} dummyArrayAllocatorInitializer;
+
+// //////////////////////////////////////////////////////////////////
+// class ValueInternalArray
+// //////////////////////////////////////////////////////////////////
+bool
+ValueInternalArray::equals( const IteratorState &x,
+ const IteratorState &other )
+{
+ return x.array_ == other.array_
+ && x.currentItemIndex_ == other.currentItemIndex_
+ && x.currentPageIndex_ == other.currentPageIndex_;
+}
+
+
+void
+ValueInternalArray::increment( IteratorState &it )
+{
+ JSON_ASSERT_MESSAGE( it.array_ &&
+ (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
+ != it.array_->size_,
+ "ValueInternalArray::increment(): moving iterator beyond end" );
+ ++(it.currentItemIndex_);
+ if ( it.currentItemIndex_ == itemsPerPage )
+ {
+ it.currentItemIndex_ = 0;
+ ++(it.currentPageIndex_);
+ }
+}
+
+
+void
+ValueInternalArray::decrement( IteratorState &it )
+{
+ JSON_ASSERT_MESSAGE( it.array_ && it.currentPageIndex_ == it.array_->pages_
+ && it.currentItemIndex_ == 0,
+ "ValueInternalArray::decrement(): moving iterator beyond end" );
+ if ( it.currentItemIndex_ == 0 )
+ {
+ it.currentItemIndex_ = itemsPerPage-1;
+ --(it.currentPageIndex_);
+ }
+ else
+ {
+ --(it.currentItemIndex_);
+ }
+}
+
+
+Value &
+ValueInternalArray::unsafeDereference( const IteratorState &it )
+{
+ return (*(it.currentPageIndex_))[it.currentItemIndex_];
+}
+
+
+Value &
+ValueInternalArray::dereference( const IteratorState &it )
+{
+ JSON_ASSERT_MESSAGE( it.array_ &&
+ (it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
+ < it.array_->size_,
+ "ValueInternalArray::dereference(): dereferencing invalid iterator" );
+ return unsafeDereference( it );
+}
+
+void
+ValueInternalArray::makeBeginIterator( IteratorState &it ) const
+{
+ it.array_ = const_cast<ValueInternalArray *>( this );
+ it.currentItemIndex_ = 0;
+ it.currentPageIndex_ = pages_;
+}
+
+
+void
+ValueInternalArray::makeIterator( IteratorState &it, ArrayIndex index ) const
+{
+ it.array_ = const_cast<ValueInternalArray *>( this );
+ it.currentItemIndex_ = index % itemsPerPage;
+ it.currentPageIndex_ = pages_ + index / itemsPerPage;
+}
+
+
+void
+ValueInternalArray::makeEndIterator( IteratorState &it ) const
+{
+ makeIterator( it, size_ );
+}
+
+
+ValueInternalArray::ValueInternalArray()
+ : pages_( 0 )
+ , size_( 0 )
+ , pageCount_( 0 )
+{
+}
+
+
+ValueInternalArray::ValueInternalArray( const ValueInternalArray &other )
+ : pages_( 0 )
+ , pageCount_( 0 )
+ , size_( other.size_ )
+{
+ PageIndex minNewPages = other.size_ / itemsPerPage;
+ arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
+ JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages,
+ "ValueInternalArray::reserve(): bad reallocation" );
+ IteratorState itOther;
+ other.makeBeginIterator( itOther );
+ Value *value;
+ for ( ArrayIndex index = 0; index < size_; ++index, increment(itOther) )
+ {
+ if ( index % itemsPerPage == 0 )
+ {
+ PageIndex pageIndex = index / itemsPerPage;
+ value = arrayAllocator()->allocateArrayPage();
+ pages_[pageIndex] = value;
+ }
+ new (value) Value( dereference( itOther ) );
+ }
+}
+
+
+ValueInternalArray &
+ValueInternalArray::operator =( const ValueInternalArray &other )
+{
+ ValueInternalArray temp( other );
+ swap( temp );
+ return *this;
+}
+
+
+ValueInternalArray::~ValueInternalArray()
+{
+ // destroy all constructed items
+ IteratorState it;
+ IteratorState itEnd;
+ makeBeginIterator( it);
+ makeEndIterator( itEnd );
+ for ( ; !equals(it,itEnd); increment(it) )
+ {
+ Value *value = &dereference(it);
+ value->~Value();
+ }
+ // release all pages
+ PageIndex lastPageIndex = size_ / itemsPerPage;
+ for ( PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex )
+ arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
+ // release pages index
+ arrayAllocator()->releaseArrayPageIndex( pages_, pageCount_ );
+}
+
+
+void
+ValueInternalArray::swap( ValueInternalArray &other )
+{
+ Value **tempPages = pages_;
+ pages_ = other.pages_;
+ other.pages_ = tempPages;
+ ArrayIndex tempSize = size_;
+ size_ = other.size_;
+ other.size_ = tempSize;
+ PageIndex tempPageCount = pageCount_;
+ pageCount_ = other.pageCount_;
+ other.pageCount_ = tempPageCount;
+}
+
+void
+ValueInternalArray::clear()
+{
+ ValueInternalArray dummy;
+ swap( dummy );
+}
+
+
+void
+ValueInternalArray::resize( ArrayIndex newSize )
+{
+ if ( newSize == 0 )
+ clear();
+ else if ( newSize < size_ )
+ {
+ IteratorState it;
+ IteratorState itEnd;
+ makeIterator( it, newSize );
+ makeIterator( itEnd, size_ );
+ for ( ; !equals(it,itEnd); increment(it) )
+ {
+ Value *value = &dereference(it);
+ value->~Value();
+ }
+ PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage;
+ PageIndex lastPageIndex = size_ / itemsPerPage;
+ for ( ; pageIndex < lastPageIndex; ++pageIndex )
+ arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
+ size_ = newSize;
+ }
+ else if ( newSize > size_ )
+ resolveReference( newSize );
+}
+
+
+void
+ValueInternalArray::makeIndexValid( ArrayIndex index )
+{
+ // Need to enlarge page index ?
+ if ( index >= pageCount_ * itemsPerPage )
+ {
+ PageIndex minNewPages = (index + 1) / itemsPerPage;
+ arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
+ JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, "ValueInternalArray::reserve(): bad reallocation" );
+ }
+
+ // Need to allocate new pages ?
+ ArrayIndex nextPageIndex =
+ (size_ % itemsPerPage) != 0 ? size_ - (size_%itemsPerPage) + itemsPerPage
+ : size_;
+ if ( nextPageIndex <= index )
+ {
+ PageIndex pageIndex = nextPageIndex / itemsPerPage;
+ PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1;
+ for ( ; pageToAllocate-- > 0; ++pageIndex )
+ pages_[pageIndex] = arrayAllocator()->allocateArrayPage();
+ }
+
+ // Initialize all new entries
+ IteratorState it;
+ IteratorState itEnd;
+ makeIterator( it, size_ );
+ size_ = index + 1;
+ makeIterator( itEnd, size_ );
+ for ( ; !equals(it,itEnd); increment(it) )
+ {
+ Value *value = &dereference(it);
+ new (value) Value(); // Construct a default value using placement new
+ }
+}
+
+Value &
+ValueInternalArray::resolveReference( ArrayIndex index )
+{
+ if ( index >= size_ )
+ makeIndexValid( index );
+ return pages_[index/itemsPerPage][index%itemsPerPage];
+}
+
+Value *
+ValueInternalArray::find( ArrayIndex index ) const
+{
+ if ( index >= size_ )
+ return 0;
+ return &(pages_[index/itemsPerPage][index%itemsPerPage]);
+}
+
+ValueInternalArray::ArrayIndex
+ValueInternalArray::size() const
+{
+ return size_;
+}
+
+int
+ValueInternalArray::distance( const IteratorState &x, const IteratorState &y )
+{
+ return indexOf(y) - indexOf(x);
+}
+
+
+ValueInternalArray::ArrayIndex
+ValueInternalArray::indexOf( const IteratorState &iterator )
+{
+ if ( !iterator.array_ )
+ return ArrayIndex(-1);
+ return ArrayIndex(
+ (iterator.currentPageIndex_ - iterator.array_->pages_) * itemsPerPage
+ + iterator.currentItemIndex_ );
+}
+
+
+int
+ValueInternalArray::compare( const ValueInternalArray &other ) const
+{
+ int sizeDiff( size_ - other.size_ );
+ if ( sizeDiff != 0 )
+ return sizeDiff;
+
+ for ( ArrayIndex index =0; index < size_; ++index )
+ {
+ int diff = pages_[index/itemsPerPage][index%itemsPerPage].compare(
+ other.pages_[index/itemsPerPage][index%itemsPerPage] );
+ if ( diff != 0 )
+ return diff;
+ }
+ return 0;
+}
diff --git a/lib/jsoncpp/jsoncpp/src/lib_json/json_internalmap.inl b/lib/jsoncpp/jsoncpp/src/lib_json/json_internalmap.inl
new file mode 100644
index 0000000000..19771488d6
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/src/lib_json/json_internalmap.inl
@@ -0,0 +1,607 @@
+// included by json_value.cpp
+// everything is within Json namespace
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueInternalMap
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+/** \internal MUST be safely initialized using memset( this, 0, sizeof(ValueInternalLink) );
+ * This optimization is used by the fast allocator.
+ */
+ValueInternalLink::ValueInternalLink()
+ : previous_( 0 )
+ , next_( 0 )
+{
+}
+
+ValueInternalLink::~ValueInternalLink()
+{
+ for ( int index =0; index < itemPerLink; ++index )
+ {
+ if ( !items_[index].isItemAvailable() )
+ {
+ if ( !items_[index].isMemberNameStatic() )
+ free( keys_[index] );
+ }
+ else
+ break;
+ }
+}
+
+
+
+ValueMapAllocator::~ValueMapAllocator()
+{
+}
+
+#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+class DefaultValueMapAllocator : public ValueMapAllocator
+{
+public: // overridden from ValueMapAllocator
+ virtual ValueInternalMap *newMap()
+ {
+ return new ValueInternalMap();
+ }
+
+ virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
+ {
+ return new ValueInternalMap( other );
+ }
+
+ virtual void destructMap( ValueInternalMap *map )
+ {
+ delete map;
+ }
+
+ virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
+ {
+ return new ValueInternalLink[size];
+ }
+
+ virtual void releaseMapBuckets( ValueInternalLink *links )
+ {
+ delete [] links;
+ }
+
+ virtual ValueInternalLink *allocateMapLink()
+ {
+ return new ValueInternalLink();
+ }
+
+ virtual void releaseMapLink( ValueInternalLink *link )
+ {
+ delete link;
+ }
+};
+#else
+/// @todo make this thread-safe (lock when accessign batch allocator)
+class DefaultValueMapAllocator : public ValueMapAllocator
+{
+public: // overridden from ValueMapAllocator
+ virtual ValueInternalMap *newMap()
+ {
+ ValueInternalMap *map = mapsAllocator_.allocate();
+ new (map) ValueInternalMap(); // placement new
+ return map;
+ }
+
+ virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
+ {
+ ValueInternalMap *map = mapsAllocator_.allocate();
+ new (map) ValueInternalMap( other ); // placement new
+ return map;
+ }
+
+ virtual void destructMap( ValueInternalMap *map )
+ {
+ if ( map )
+ {
+ map->~ValueInternalMap();
+ mapsAllocator_.release( map );
+ }
+ }
+
+ virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
+ {
+ return new ValueInternalLink[size];
+ }
+
+ virtual void releaseMapBuckets( ValueInternalLink *links )
+ {
+ delete [] links;
+ }
+
+ virtual ValueInternalLink *allocateMapLink()
+ {
+ ValueInternalLink *link = linksAllocator_.allocate();
+ memset( link, 0, sizeof(ValueInternalLink) );
+ return link;
+ }
+
+ virtual void releaseMapLink( ValueInternalLink *link )
+ {
+ link->~ValueInternalLink();
+ linksAllocator_.release( link );
+ }
+private:
+ BatchAllocator<ValueInternalMap,1> mapsAllocator_;
+ BatchAllocator<ValueInternalLink,1> linksAllocator_;
+};
+#endif
+
+static ValueMapAllocator *&mapAllocator()
+{
+ static DefaultValueMapAllocator defaultAllocator;
+ static ValueMapAllocator *mapAllocator = &defaultAllocator;
+ return mapAllocator;
+}
+
+static struct DummyMapAllocatorInitializer {
+ DummyMapAllocatorInitializer()
+ {
+ mapAllocator(); // ensure mapAllocator() statics are initialized before main().
+ }
+} dummyMapAllocatorInitializer;
+
+
+
+// h(K) = value * K >> w ; with w = 32 & K prime w.r.t. 2^32.
+
+/*
+use linked list hash map.
+buckets array is a container.
+linked list element contains 6 key/values. (memory = (16+4) * 6 + 4 = 124)
+value have extra state: valid, available, deleted
+*/
+
+
+ValueInternalMap::ValueInternalMap()
+ : buckets_( 0 )
+ , tailLink_( 0 )
+ , bucketsSize_( 0 )
+ , itemCount_( 0 )
+{
+}
+
+
+ValueInternalMap::ValueInternalMap( const ValueInternalMap &other )
+ : buckets_( 0 )
+ , tailLink_( 0 )
+ , bucketsSize_( 0 )
+ , itemCount_( 0 )
+{
+ reserve( other.itemCount_ );
+ IteratorState it;
+ IteratorState itEnd;
+ other.makeBeginIterator( it );
+ other.makeEndIterator( itEnd );
+ for ( ; !equals(it,itEnd); increment(it) )
+ {
+ bool isStatic;
+ const char *memberName = key( it, isStatic );
+ const Value &aValue = value( it );
+ resolveReference(memberName, isStatic) = aValue;
+ }
+}
+
+
+ValueInternalMap &
+ValueInternalMap::operator =( const ValueInternalMap &other )
+{
+ ValueInternalMap dummy( other );
+ swap( dummy );
+ return *this;
+}
+
+
+ValueInternalMap::~ValueInternalMap()
+{
+ if ( buckets_ )
+ {
+ for ( BucketIndex bucketIndex =0; bucketIndex < bucketsSize_; ++bucketIndex )
+ {
+ ValueInternalLink *link = buckets_[bucketIndex].next_;
+ while ( link )
+ {
+ ValueInternalLink *linkToRelease = link;
+ link = link->next_;
+ mapAllocator()->releaseMapLink( linkToRelease );
+ }
+ }
+ mapAllocator()->releaseMapBuckets( buckets_ );
+ }
+}
+
+
+void
+ValueInternalMap::swap( ValueInternalMap &other )
+{
+ ValueInternalLink *tempBuckets = buckets_;
+ buckets_ = other.buckets_;
+ other.buckets_ = tempBuckets;
+ ValueInternalLink *tempTailLink = tailLink_;
+ tailLink_ = other.tailLink_;
+ other.tailLink_ = tempTailLink;
+ BucketIndex tempBucketsSize = bucketsSize_;
+ bucketsSize_ = other.bucketsSize_;
+ other.bucketsSize_ = tempBucketsSize;
+ BucketIndex tempItemCount = itemCount_;
+ itemCount_ = other.itemCount_;
+ other.itemCount_ = tempItemCount;
+}
+
+
+void
+ValueInternalMap::clear()
+{
+ ValueInternalMap dummy;
+ swap( dummy );
+}
+
+
+ValueInternalMap::BucketIndex
+ValueInternalMap::size() const
+{
+ return itemCount_;
+}
+
+bool
+ValueInternalMap::reserveDelta( BucketIndex growth )
+{
+ return reserve( itemCount_ + growth );
+}
+
+bool
+ValueInternalMap::reserve( BucketIndex newItemCount )
+{
+ if ( !buckets_ && newItemCount > 0 )
+ {
+ buckets_ = mapAllocator()->allocateMapBuckets( 1 );
+ bucketsSize_ = 1;
+ tailLink_ = &buckets_[0];
+ }
+// BucketIndex idealBucketCount = (newItemCount + ValueInternalLink::itemPerLink) / ValueInternalLink::itemPerLink;
+ return true;
+}
+
+
+const Value *
+ValueInternalMap::find( const char *key ) const
+{
+ if ( !bucketsSize_ )
+ return 0;
+ HashKey hashedKey = hash( key );
+ BucketIndex bucketIndex = hashedKey % bucketsSize_;
+ for ( const ValueInternalLink *current = &buckets_[bucketIndex];
+ current != 0;
+ current = current->next_ )
+ {
+ for ( BucketIndex index=0; index < ValueInternalLink::itemPerLink; ++index )
+ {
+ if ( current->items_[index].isItemAvailable() )
+ return 0;
+ if ( strcmp( key, current->keys_[index] ) == 0 )
+ return &current->items_[index];
+ }
+ }
+ return 0;
+}
+
+
+Value *
+ValueInternalMap::find( const char *key )
+{
+ const ValueInternalMap *constThis = this;
+ return const_cast<Value *>( constThis->find( key ) );
+}
+
+
+Value &
+ValueInternalMap::resolveReference( const char *key,
+ bool isStatic )
+{
+ HashKey hashedKey = hash( key );
+ if ( bucketsSize_ )
+ {
+ BucketIndex bucketIndex = hashedKey % bucketsSize_;
+ ValueInternalLink **previous = 0;
+ BucketIndex index;
+ for ( ValueInternalLink *current = &buckets_[bucketIndex];
+ current != 0;
+ previous = &current->next_, current = current->next_ )
+ {
+ for ( index=0; index < ValueInternalLink::itemPerLink; ++index )
+ {
+ if ( current->items_[index].isItemAvailable() )
+ return setNewItem( key, isStatic, current, index );
+ if ( strcmp( key, current->keys_[index] ) == 0 )
+ return current->items_[index];
+ }
+ }
+ }
+
+ reserveDelta( 1 );
+ return unsafeAdd( key, isStatic, hashedKey );
+}
+
+
+void
+ValueInternalMap::remove( const char *key )
+{
+ HashKey hashedKey = hash( key );
+ if ( !bucketsSize_ )
+ return;
+ BucketIndex bucketIndex = hashedKey % bucketsSize_;
+ for ( ValueInternalLink *link = &buckets_[bucketIndex];
+ link != 0;
+ link = link->next_ )
+ {
+ BucketIndex index;
+ for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
+ {
+ if ( link->items_[index].isItemAvailable() )
+ return;
+ if ( strcmp( key, link->keys_[index] ) == 0 )
+ {
+ doActualRemove( link, index, bucketIndex );
+ return;
+ }
+ }
+ }
+}
+
+void
+ValueInternalMap::doActualRemove( ValueInternalLink *link,
+ BucketIndex index,
+ BucketIndex bucketIndex )
+{
+ // find last item of the bucket and swap it with the 'removed' one.
+ // set removed items flags to 'available'.
+ // if last page only contains 'available' items, then desallocate it (it's empty)
+ ValueInternalLink *&lastLink = getLastLinkInBucket( index );
+ BucketIndex lastItemIndex = 1; // a link can never be empty, so start at 1
+ for ( ;
+ lastItemIndex < ValueInternalLink::itemPerLink;
+ ++lastItemIndex ) // may be optimized with dicotomic search
+ {
+ if ( lastLink->items_[lastItemIndex].isItemAvailable() )
+ break;
+ }
+
+ BucketIndex lastUsedIndex = lastItemIndex - 1;
+ Value *valueToDelete = &link->items_[index];
+ Value *valueToPreserve = &lastLink->items_[lastUsedIndex];
+ if ( valueToDelete != valueToPreserve )
+ valueToDelete->swap( *valueToPreserve );
+ if ( lastUsedIndex == 0 ) // page is now empty
+ { // remove it from bucket linked list and delete it.
+ ValueInternalLink *linkPreviousToLast = lastLink->previous_;
+ if ( linkPreviousToLast != 0 ) // can not deleted bucket link.
+ {
+ mapAllocator()->releaseMapLink( lastLink );
+ linkPreviousToLast->next_ = 0;
+ lastLink = linkPreviousToLast;
+ }
+ }
+ else
+ {
+ Value dummy;
+ valueToPreserve->swap( dummy ); // restore deleted to default Value.
+ valueToPreserve->setItemUsed( false );
+ }
+ --itemCount_;
+}
+
+
+ValueInternalLink *&
+ValueInternalMap::getLastLinkInBucket( BucketIndex bucketIndex )
+{
+ if ( bucketIndex == bucketsSize_ - 1 )
+ return tailLink_;
+ ValueInternalLink *&previous = buckets_[bucketIndex+1].previous_;
+ if ( !previous )
+ previous = &buckets_[bucketIndex];
+ return previous;
+}
+
+
+Value &
+ValueInternalMap::setNewItem( const char *key,
+ bool isStatic,
+ ValueInternalLink *link,
+ BucketIndex index )
+{
+ char *duplicatedKey = valueAllocator()->makeMemberName( key );
+ ++itemCount_;
+ link->keys_[index] = duplicatedKey;
+ link->items_[index].setItemUsed();
+ link->items_[index].setMemberNameIsStatic( isStatic );
+ return link->items_[index]; // items already default constructed.
+}
+
+
+Value &
+ValueInternalMap::unsafeAdd( const char *key,
+ bool isStatic,
+ HashKey hashedKey )
+{
+ JSON_ASSERT_MESSAGE( bucketsSize_ > 0, "ValueInternalMap::unsafeAdd(): internal logic error." );
+ BucketIndex bucketIndex = hashedKey % bucketsSize_;
+ ValueInternalLink *&previousLink = getLastLinkInBucket( bucketIndex );
+ ValueInternalLink *link = previousLink;
+ BucketIndex index;
+ for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
+ {
+ if ( link->items_[index].isItemAvailable() )
+ break;
+ }
+ if ( index == ValueInternalLink::itemPerLink ) // need to add a new page
+ {
+ ValueInternalLink *newLink = mapAllocator()->allocateMapLink();
+ index = 0;
+ link->next_ = newLink;
+ previousLink = newLink;
+ link = newLink;
+ }
+ return setNewItem( key, isStatic, link, index );
+}
+
+
+ValueInternalMap::HashKey
+ValueInternalMap::hash( const char *key ) const
+{
+ HashKey hash = 0;
+ while ( *key )
+ hash += *key++ * 37;
+ return hash;
+}
+
+
+int
+ValueInternalMap::compare( const ValueInternalMap &other ) const
+{
+ int sizeDiff( itemCount_ - other.itemCount_ );
+ if ( sizeDiff != 0 )
+ return sizeDiff;
+ // Strict order guaranty is required. Compare all keys FIRST, then compare values.
+ IteratorState it;
+ IteratorState itEnd;
+ makeBeginIterator( it );
+ makeEndIterator( itEnd );
+ for ( ; !equals(it,itEnd); increment(it) )
+ {
+ if ( !other.find( key( it ) ) )
+ return 1;
+ }
+
+ // All keys are equals, let's compare values
+ makeBeginIterator( it );
+ for ( ; !equals(it,itEnd); increment(it) )
+ {
+ const Value *otherValue = other.find( key( it ) );
+ int valueDiff = value(it).compare( *otherValue );
+ if ( valueDiff != 0 )
+ return valueDiff;
+ }
+ return 0;
+}
+
+
+void
+ValueInternalMap::makeBeginIterator( IteratorState &it ) const
+{
+ it.map_ = const_cast<ValueInternalMap *>( this );
+ it.bucketIndex_ = 0;
+ it.itemIndex_ = 0;
+ it.link_ = buckets_;
+}
+
+
+void
+ValueInternalMap::makeEndIterator( IteratorState &it ) const
+{
+ it.map_ = const_cast<ValueInternalMap *>( this );
+ it.bucketIndex_ = bucketsSize_;
+ it.itemIndex_ = 0;
+ it.link_ = 0;
+}
+
+
+bool
+ValueInternalMap::equals( const IteratorState &x, const IteratorState &other )
+{
+ return x.map_ == other.map_
+ && x.bucketIndex_ == other.bucketIndex_
+ && x.link_ == other.link_
+ && x.itemIndex_ == other.itemIndex_;
+}
+
+
+void
+ValueInternalMap::incrementBucket( IteratorState &iterator )
+{
+ ++iterator.bucketIndex_;
+ JSON_ASSERT_MESSAGE( iterator.bucketIndex_ <= iterator.map_->bucketsSize_,
+ "ValueInternalMap::increment(): attempting to iterate beyond end." );
+ if ( iterator.bucketIndex_ == iterator.map_->bucketsSize_ )
+ iterator.link_ = 0;
+ else
+ iterator.link_ = &(iterator.map_->buckets_[iterator.bucketIndex_]);
+ iterator.itemIndex_ = 0;
+}
+
+
+void
+ValueInternalMap::increment( IteratorState &iterator )
+{
+ JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterator using invalid iterator." );
+ ++iterator.itemIndex_;
+ if ( iterator.itemIndex_ == ValueInternalLink::itemPerLink )
+ {
+ JSON_ASSERT_MESSAGE( iterator.link_ != 0,
+ "ValueInternalMap::increment(): attempting to iterate beyond end." );
+ iterator.link_ = iterator.link_->next_;
+ if ( iterator.link_ == 0 )
+ incrementBucket( iterator );
+ }
+ else if ( iterator.link_->items_[iterator.itemIndex_].isItemAvailable() )
+ {
+ incrementBucket( iterator );
+ }
+}
+
+
+void
+ValueInternalMap::decrement( IteratorState &iterator )
+{
+ if ( iterator.itemIndex_ == 0 )
+ {
+ JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterate using invalid iterator." );
+ if ( iterator.link_ == &iterator.map_->buckets_[iterator.bucketIndex_] )
+ {
+ JSON_ASSERT_MESSAGE( iterator.bucketIndex_ > 0, "Attempting to iterate beyond beginning." );
+ --(iterator.bucketIndex_);
+ }
+ iterator.link_ = iterator.link_->previous_;
+ iterator.itemIndex_ = ValueInternalLink::itemPerLink - 1;
+ }
+}
+
+
+const char *
+ValueInternalMap::key( const IteratorState &iterator )
+{
+ JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
+ return iterator.link_->keys_[iterator.itemIndex_];
+}
+
+const char *
+ValueInternalMap::key( const IteratorState &iterator, bool &isStatic )
+{
+ JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
+ isStatic = iterator.link_->items_[iterator.itemIndex_].isMemberNameStatic();
+ return iterator.link_->keys_[iterator.itemIndex_];
+}
+
+
+Value &
+ValueInternalMap::value( const IteratorState &iterator )
+{
+ JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
+ return iterator.link_->items_[iterator.itemIndex_];
+}
+
+
+int
+ValueInternalMap::distance( const IteratorState &x, const IteratorState &y )
+{
+ int offset = 0;
+ IteratorState it = x;
+ while ( !equals( it, y ) )
+ increment( it );
+ return offset;
+}
diff --git a/lib/jsoncpp/jsoncpp/src/lib_json/json_reader.cpp b/lib/jsoncpp/jsoncpp/src/lib_json/json_reader.cpp
new file mode 100644
index 0000000000..4eb2d11fd3
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/src/lib_json/json_reader.cpp
@@ -0,0 +1,885 @@
+#include <json/reader.h>
+#include <json/value.h>
+#include <utility>
+#include <cstdio>
+#include <cassert>
+#include <cstring>
+#include <iostream>
+#include <stdexcept>
+
+#if _MSC_VER >= 1400 // VC++ 8.0
+#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated.
+#endif
+
+namespace Json {
+
+// Implementation of class Features
+// ////////////////////////////////
+
+Features::Features()
+ : allowComments_( true )
+ , strictRoot_( false )
+{
+}
+
+
+Features
+Features::all()
+{
+ return Features();
+}
+
+
+Features
+Features::strictMode()
+{
+ Features features;
+ features.allowComments_ = false;
+ features.strictRoot_ = true;
+ return features;
+}
+
+// Implementation of class Reader
+// ////////////////////////////////
+
+
+static inline bool
+in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4 )
+{
+ return c == c1 || c == c2 || c == c3 || c == c4;
+}
+
+static inline bool
+in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5 )
+{
+ return c == c1 || c == c2 || c == c3 || c == c4 || c == c5;
+}
+
+
+static bool
+containsNewLine( Reader::Location begin,
+ Reader::Location end )
+{
+ for ( ;begin < end; ++begin )
+ if ( *begin == '\n' || *begin == '\r' )
+ return true;
+ 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()
+ : features_( Features::all() )
+{
+}
+
+
+Reader::Reader( const Features &features )
+ : features_( features )
+{
+}
+
+
+bool
+Reader::parse( const std::string &document,
+ Value &root,
+ bool collectComments )
+{
+ document_ = document;
+ const char *begin = document_.c_str();
+ const char *end = begin + document_.length();
+ return parse( begin, end, root, collectComments );
+}
+
+
+bool
+Reader::parse( std::istream& sin,
+ Value &root,
+ bool collectComments )
+{
+ //std::istream_iterator<char> begin(sin);
+ //std::istream_iterator<char> end;
+ // Those would allow streamed input from a file, if parse() were a
+ // template function.
+
+ // Since std::string is reference-counted, this at least does not
+ // create an extra copy.
+ std::string doc;
+ std::getline(sin, doc, (char)EOF);
+ return parse( doc, root, collectComments );
+}
+
+bool
+Reader::parse( const char *beginDoc, const char *endDoc,
+ Value &root,
+ bool collectComments )
+{
+ if ( !features_.allowComments_ )
+ {
+ collectComments = false;
+ }
+
+ begin_ = beginDoc;
+ end_ = endDoc;
+ collectComments_ = collectComments;
+ current_ = begin_;
+ lastValueEnd_ = 0;
+ lastValue_ = 0;
+ commentsBefore_ = "";
+ errors_.clear();
+ while ( !nodes_.empty() )
+ nodes_.pop();
+ nodes_.push( &root );
+
+ bool successful = readValue();
+ Token token;
+ skipCommentTokens( token );
+ if ( collectComments_ && !commentsBefore_.empty() )
+ root.setComment( commentsBefore_, commentAfter );
+ if ( features_.strictRoot_ )
+ {
+ if ( !root.isArray() && !root.isObject() )
+ {
+ // Set error location to start of doc, ideally should be first token found in doc
+ token.type_ = tokenError;
+ token.start_ = beginDoc;
+ token.end_ = endDoc;
+ addError( "A valid JSON document must be either an array or an object value.",
+ token );
+ return false;
+ }
+ }
+ return successful;
+}
+
+
+bool
+Reader::readValue()
+{
+ Token token;
+ skipCommentTokens( token );
+ bool successful = true;
+
+ if ( collectComments_ && !commentsBefore_.empty() )
+ {
+ currentValue().setComment( commentsBefore_, commentBefore );
+ commentsBefore_ = "";
+ }
+
+
+ switch ( token.type_ )
+ {
+ case tokenObjectBegin:
+ successful = readObject( token );
+ break;
+ case tokenArrayBegin:
+ successful = readArray( token );
+ break;
+ case tokenNumber:
+ successful = decodeNumber( token );
+ break;
+ case tokenString:
+ successful = decodeString( token );
+ break;
+ case tokenTrue:
+ currentValue() = true;
+ break;
+ case tokenFalse:
+ currentValue() = false;
+ break;
+ case tokenNull:
+ currentValue() = Value();
+ break;
+ default:
+ return addError( "Syntax error: value, object or array expected.", token );
+ }
+
+ if ( collectComments_ )
+ {
+ lastValueEnd_ = current_;
+ lastValue_ = &currentValue();
+ }
+
+ return successful;
+}
+
+
+void
+Reader::skipCommentTokens( Token &token )
+{
+ if ( features_.allowComments_ )
+ {
+ do
+ {
+ readToken( token );
+ }
+ while ( token.type_ == tokenComment );
+ }
+ else
+ {
+ readToken( token );
+ }
+}
+
+
+bool
+Reader::expectToken( TokenType type, Token &token, const char *message )
+{
+ readToken( token );
+ if ( token.type_ != type )
+ return addError( message, token );
+ return true;
+}
+
+
+bool
+Reader::readToken( Token &token )
+{
+ skipSpaces();
+ token.start_ = current_;
+ Char c = getNextChar();
+ bool ok = true;
+ switch ( c )
+ {
+ case '{':
+ token.type_ = tokenObjectBegin;
+ break;
+ case '}':
+ token.type_ = tokenObjectEnd;
+ break;
+ case '[':
+ token.type_ = tokenArrayBegin;
+ break;
+ case ']':
+ token.type_ = tokenArrayEnd;
+ break;
+ case '"':
+ token.type_ = tokenString;
+ ok = readString();
+ break;
+ case '/':
+ token.type_ = tokenComment;
+ ok = readComment();
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '-':
+ token.type_ = tokenNumber;
+ readNumber();
+ break;
+ case 't':
+ token.type_ = tokenTrue;
+ ok = match( "rue", 3 );
+ break;
+ case 'f':
+ token.type_ = tokenFalse;
+ ok = match( "alse", 4 );
+ break;
+ case 'n':
+ token.type_ = tokenNull;
+ ok = match( "ull", 3 );
+ break;
+ case ',':
+ token.type_ = tokenArraySeparator;
+ break;
+ case ':':
+ token.type_ = tokenMemberSeparator;
+ break;
+ case 0:
+ token.type_ = tokenEndOfStream;
+ break;
+ default:
+ ok = false;
+ break;
+ }
+ if ( !ok )
+ token.type_ = tokenError;
+ token.end_ = current_;
+ return true;
+}
+
+
+void
+Reader::skipSpaces()
+{
+ while ( current_ != end_ )
+ {
+ Char c = *current_;
+ if ( c == ' ' || c == '\t' || c == '\r' || c == '\n' )
+ ++current_;
+ else
+ break;
+ }
+}
+
+
+bool
+Reader::match( Location pattern,
+ int patternLength )
+{
+ if ( end_ - current_ < patternLength )
+ return false;
+ int index = patternLength;
+ while ( index-- )
+ if ( current_[index] != pattern[index] )
+ return false;
+ current_ += patternLength;
+ return true;
+}
+
+
+bool
+Reader::readComment()
+{
+ Location commentBegin = current_ - 1;
+ Char c = getNextChar();
+ bool successful = false;
+ if ( c == '*' )
+ successful = readCStyleComment();
+ else if ( c == '/' )
+ successful = readCppStyleComment();
+ if ( !successful )
+ return false;
+
+ if ( collectComments_ )
+ {
+ CommentPlacement placement = commentBefore;
+ if ( lastValueEnd_ && !containsNewLine( lastValueEnd_, commentBegin ) )
+ {
+ if ( c != '*' || !containsNewLine( commentBegin, current_ ) )
+ placement = commentAfterOnSameLine;
+ }
+
+ addComment( commentBegin, current_, placement );
+ }
+ return true;
+}
+
+
+void
+Reader::addComment( Location begin,
+ Location end,
+ CommentPlacement placement )
+{
+ assert( collectComments_ );
+ if ( placement == commentAfterOnSameLine )
+ {
+ assert( lastValue_ != 0 );
+ lastValue_->setComment( std::string( begin, end ), placement );
+ }
+ else
+ {
+ if ( !commentsBefore_.empty() )
+ commentsBefore_ += "\n";
+ commentsBefore_ += std::string( begin, end );
+ }
+}
+
+
+bool
+Reader::readCStyleComment()
+{
+ while ( current_ != end_ )
+ {
+ Char c = getNextChar();
+ if ( c == '*' && *current_ == '/' )
+ break;
+ }
+ return getNextChar() == '/';
+}
+
+
+bool
+Reader::readCppStyleComment()
+{
+ while ( current_ != end_ )
+ {
+ Char c = getNextChar();
+ if ( c == '\r' || c == '\n' )
+ break;
+ }
+ return true;
+}
+
+
+void
+Reader::readNumber()
+{
+ while ( current_ != end_ )
+ {
+ if ( !(*current_ >= '0' && *current_ <= '9') &&
+ !in( *current_, '.', 'e', 'E', '+', '-' ) )
+ break;
+ ++current_;
+ }
+}
+
+bool
+Reader::readString()
+{
+ Char c = 0;
+ while ( current_ != end_ )
+ {
+ c = getNextChar();
+ if ( c == '\\' )
+ getNextChar();
+ else if ( c == '"' )
+ break;
+ }
+ return c == '"';
+}
+
+
+bool
+Reader::readObject( Token &tokenStart )
+{
+ Token tokenName;
+ std::string name;
+ currentValue() = Value( objectValue );
+ while ( readToken( tokenName ) )
+ {
+ bool initialTokenOk = true;
+ while ( tokenName.type_ == tokenComment && initialTokenOk )
+ initialTokenOk = readToken( tokenName );
+ if ( !initialTokenOk )
+ break;
+ if ( tokenName.type_ == tokenObjectEnd && name.empty() ) // empty object
+ return true;
+ if ( tokenName.type_ != tokenString )
+ break;
+
+ name = "";
+ if ( !decodeString( tokenName, name ) )
+ return recoverFromError( tokenObjectEnd );
+
+ Token colon;
+ if ( !readToken( colon ) || colon.type_ != tokenMemberSeparator )
+ {
+ return addErrorAndRecover( "Missing ':' after object member name",
+ colon,
+ tokenObjectEnd );
+ }
+ Value &value = currentValue()[ name ];
+ nodes_.push( &value );
+ bool ok = readValue();
+ nodes_.pop();
+ if ( !ok ) // error already set
+ return recoverFromError( tokenObjectEnd );
+
+ Token comma;
+ if ( !readToken( comma )
+ || ( comma.type_ != tokenObjectEnd &&
+ comma.type_ != tokenArraySeparator &&
+ comma.type_ != tokenComment ) )
+ {
+ return addErrorAndRecover( "Missing ',' or '}' in object declaration",
+ comma,
+ tokenObjectEnd );
+ }
+ bool finalizeTokenOk = true;
+ while ( comma.type_ == tokenComment &&
+ finalizeTokenOk )
+ finalizeTokenOk = readToken( comma );
+ if ( comma.type_ == tokenObjectEnd )
+ return true;
+ }
+ return addErrorAndRecover( "Missing '}' or object member name",
+ tokenName,
+ tokenObjectEnd );
+}
+
+
+bool
+Reader::readArray( Token &tokenStart )
+{
+ currentValue() = Value( arrayValue );
+ skipSpaces();
+ if ( *current_ == ']' ) // empty array
+ {
+ Token endArray;
+ readToken( endArray );
+ return true;
+ }
+ int index = 0;
+ while ( true )
+ {
+ Value &value = currentValue()[ index++ ];
+ nodes_.push( &value );
+ bool ok = readValue();
+ nodes_.pop();
+ if ( !ok ) // error already set
+ return recoverFromError( tokenArrayEnd );
+
+ Token token;
+ // Accept Comment after last item in the array.
+ ok = readToken( token );
+ while ( token.type_ == tokenComment && ok )
+ {
+ ok = readToken( token );
+ }
+ bool badTokenType = ( token.type_ == tokenArraySeparator &&
+ token.type_ == tokenArrayEnd );
+ if ( !ok || badTokenType )
+ {
+ return addErrorAndRecover( "Missing ',' or ']' in array declaration",
+ token,
+ tokenArrayEnd );
+ }
+ if ( token.type_ == tokenArrayEnd )
+ break;
+ }
+ return true;
+}
+
+
+bool
+Reader::decodeNumber( Token &token )
+{
+ bool isDouble = false;
+ for ( Location inspect = token.start_; inspect != token.end_; ++inspect )
+ {
+ isDouble = isDouble
+ || in( *inspect, '.', 'e', 'E', '+' )
+ || ( *inspect == '-' && inspect != token.start_ );
+ }
+ if ( isDouble )
+ return decodeDouble( token );
+ Location current = token.start_;
+ bool isNegative = *current == '-';
+ if ( isNegative )
+ ++current;
+ 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 );
+ if ( value >= threshold )
+ return decodeDouble( token );
+ value = value * 10 + Value::UInt(c - '0');
+ }
+ if ( isNegative )
+ currentValue() = -Value::Int( value );
+ else if ( value <= Value::UInt(Value::maxInt) )
+ currentValue() = Value::Int( value );
+ else
+ currentValue() = value;
+ return true;
+}
+
+
+bool
+Reader::decodeDouble( Token &token )
+{
+ double value = 0;
+ const int bufferSize = 32;
+ int count;
+ int length = int(token.end_ - token.start_);
+ if ( length <= bufferSize )
+ {
+ Char buffer[bufferSize];
+ memcpy( buffer, token.start_, length );
+ buffer[length] = 0;
+ count = sscanf( buffer, "%lf", &value );
+ }
+ else
+ {
+ std::string buffer( token.start_, token.end_ );
+ count = sscanf( buffer.c_str(), "%lf", &value );
+ }
+
+ if ( count != 1 )
+ return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
+ currentValue() = value;
+ return true;
+}
+
+
+bool
+Reader::decodeString( Token &token )
+{
+ std::string decoded;
+ if ( !decodeString( token, decoded ) )
+ return false;
+ currentValue() = decoded;
+ return true;
+}
+
+
+bool
+Reader::decodeString( Token &token, std::string &decoded )
+{
+ decoded.reserve( token.end_ - token.start_ - 2 );
+ Location current = token.start_ + 1; // skip '"'
+ Location end = token.end_ - 1; // do not include '"'
+ while ( current != end )
+ {
+ Char c = *current++;
+ if ( c == '"' )
+ break;
+ else if ( c == '\\' )
+ {
+ if ( current == end )
+ return addError( "Empty escape sequence in string", token, current );
+ Char escape = *current++;
+ switch ( escape )
+ {
+ case '"': decoded += '"'; break;
+ case '/': decoded += '/'; break;
+ case '\\': decoded += '\\'; break;
+ case 'b': decoded += '\b'; break;
+ case 'f': decoded += '\f'; break;
+ case 'n': decoded += '\n'; break;
+ case 'r': decoded += '\r'; break;
+ case 't': decoded += '\t'; break;
+ case 'u':
+ {
+ unsigned int unicode;
+ if ( !decodeUnicodeCodePoint( token, current, end, unicode ) )
+ return false;
+ decoded += codePointToUTF8(unicode);
+ }
+ break;
+ default:
+ return addError( "Bad escape sequence in string", token, current );
+ }
+ }
+ else
+ {
+ decoded += c;
+ }
+ }
+ return true;
+}
+
+bool
+Reader::decodeUnicodeCodePoint( Token &token,
+ Location &current,
+ Location end,
+ unsigned int &unicode )
+{
+
+ if ( !decodeUnicodeEscapeSequence( token, current, end, unicode ) )
+ return false;
+ if (unicode >= 0xD800 && unicode <= 0xDBFF)
+ {
+ // surrogate pairs
+ if (end - current < 6)
+ return addError( "additional six characters expected to parse unicode surrogate pair.", token, current );
+ unsigned int surrogatePair;
+ if (*(current++) == '\\' && *(current++)== 'u')
+ {
+ if (decodeUnicodeEscapeSequence( token, current, end, surrogatePair ))
+ {
+ unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
+ }
+ else
+ return false;
+ }
+ else
+ return addError( "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current );
+ }
+ return true;
+}
+
+bool
+Reader::decodeUnicodeEscapeSequence( Token &token,
+ Location &current,
+ Location end,
+ unsigned int &unicode )
+{
+ if ( end - current < 4 )
+ return addError( "Bad unicode escape sequence in string: four digits expected.", token, current );
+ unicode = 0;
+ for ( int index =0; index < 4; ++index )
+ {
+ Char c = *current++;
+ unicode *= 16;
+ if ( c >= '0' && c <= '9' )
+ unicode += c - '0';
+ else if ( c >= 'a' && c <= 'f' )
+ unicode += c - 'a' + 10;
+ else if ( c >= 'A' && c <= 'F' )
+ unicode += c - 'A' + 10;
+ else
+ return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", token, current );
+ }
+ return true;
+}
+
+
+bool
+Reader::addError( const std::string &message,
+ Token &token,
+ Location extra )
+{
+ ErrorInfo info;
+ info.token_ = token;
+ info.message_ = message;
+ info.extra_ = extra;
+ errors_.push_back( info );
+ return false;
+}
+
+
+bool
+Reader::recoverFromError( TokenType skipUntilToken )
+{
+ int errorCount = int(errors_.size());
+ Token skip;
+ while ( true )
+ {
+ if ( !readToken(skip) )
+ errors_.resize( errorCount ); // discard errors caused by recovery
+ if ( skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream )
+ break;
+ }
+ errors_.resize( errorCount );
+ return false;
+}
+
+
+bool
+Reader::addErrorAndRecover( const std::string &message,
+ Token &token,
+ TokenType skipUntilToken )
+{
+ addError( message, token );
+ return recoverFromError( skipUntilToken );
+}
+
+
+Value &
+Reader::currentValue()
+{
+ return *(nodes_.top());
+}
+
+
+Reader::Char
+Reader::getNextChar()
+{
+ if ( current_ == end_ )
+ return 0;
+ return *current_++;
+}
+
+
+void
+Reader::getLocationLineAndColumn( Location location,
+ int &line,
+ int &column ) const
+{
+ Location current = begin_;
+ Location lastLineStart = current;
+ line = 0;
+ while ( current < location && current != end_ )
+ {
+ Char c = *current++;
+ if ( c == '\r' )
+ {
+ if ( *current == '\n' )
+ ++current;
+ lastLineStart = current;
+ ++line;
+ }
+ else if ( c == '\n' )
+ {
+ lastLineStart = current;
+ ++line;
+ }
+ }
+ // column & line start at 1
+ column = int(location - lastLineStart) + 1;
+ ++line;
+}
+
+
+std::string
+Reader::getLocationLineAndColumn( Location location ) const
+{
+ int line, column;
+ getLocationLineAndColumn( location, line, column );
+ char buffer[18+16+16+1];
+ sprintf( buffer, "Line %d, Column %d", line, column );
+ return buffer;
+}
+
+
+std::string
+Reader::getFormatedErrorMessages() const
+{
+ std::string formattedMessage;
+ for ( Errors::const_iterator itError = errors_.begin();
+ itError != errors_.end();
+ ++itError )
+ {
+ const ErrorInfo &error = *itError;
+ formattedMessage += "* " + getLocationLineAndColumn( error.token_.start_ ) + "\n";
+ formattedMessage += " " + error.message_ + "\n";
+ if ( error.extra_ )
+ formattedMessage += "See " + getLocationLineAndColumn( error.extra_ ) + " for detail.\n";
+ }
+ return formattedMessage;
+}
+
+
+std::istream& operator>>( std::istream &sin, Value &root )
+{
+ Json::Reader reader;
+ bool ok = reader.parse(sin, root, true);
+ //JSON_ASSERT( ok );
+ if (!ok) throw std::runtime_error(reader.getFormatedErrorMessages());
+ return sin;
+}
+
+
+} // namespace Json
diff --git a/lib/jsoncpp/jsoncpp/src/lib_json/json_value.cpp b/lib/jsoncpp/jsoncpp/src/lib_json/json_value.cpp
new file mode 100644
index 0000000000..734bf16252
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/src/lib_json/json_value.cpp
@@ -0,0 +1,1703 @@
+#include <iostream>
+#include <json/value.h>
+#include <json/writer.h>
+#include <utility>
+#include <stdexcept>
+#include <cstring>
+#include <cassert>
+#ifdef JSON_USE_CPPTL
+# include <cpptl/conststring.h>
+#endif
+#include <cstddef> // size_t
+#ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+# include "json_batchallocator.h"
+#endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+
+#define JSON_ASSERT_UNREACHABLE assert( false )
+#define JSON_ASSERT( condition ) assert( condition ); // @todo <= change this into an exception throw
+#define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) throw std::runtime_error( message );
+
+namespace Json {
+
+const Value Value::null;
+const Value::Int Value::minInt = Value::Int( ~(Value::UInt(-1)/2) );
+const Value::Int Value::maxInt = Value::Int( Value::UInt(-1)/2 );
+const Value::UInt Value::maxUInt = Value::UInt(-1);
+
+// A "safe" implementation of strdup. Allow null pointer to be passed.
+// Also avoid warning on msvc80.
+//
+//inline char *safeStringDup( const char *czstring )
+//{
+// if ( czstring )
+// {
+// const size_t length = (unsigned int)( strlen(czstring) + 1 );
+// char *newString = static_cast<char *>( malloc( length ) );
+// memcpy( newString, czstring, length );
+// return newString;
+// }
+// return 0;
+//}
+//
+//inline char *safeStringDup( const std::string &str )
+//{
+// if ( !str.empty() )
+// {
+// const size_t length = str.length();
+// char *newString = static_cast<char *>( malloc( length + 1 ) );
+// memcpy( newString, str.c_str(), length );
+// newString[length] = 0;
+// return newString;
+// }
+// return 0;
+//}
+
+ValueAllocator::~ValueAllocator()
+{
+}
+
+class DefaultValueAllocator : public ValueAllocator
+{
+public:
+ virtual ~DefaultValueAllocator()
+ {
+ }
+
+ virtual char *makeMemberName( const char *memberName )
+ {
+ return duplicateStringValue( memberName );
+ }
+
+ virtual void releaseMemberName( char *memberName )
+ {
+ releaseStringValue( memberName );
+ }
+
+ virtual char *duplicateStringValue( const char *value,
+ unsigned int length = unknown )
+ {
+ //@todo invesgate this old optimization
+ //if ( !value || value[0] == 0 )
+ // return 0;
+
+ if ( length == unknown )
+ length = (unsigned int)strlen(value);
+ char *newString = static_cast<char *>( malloc( length + 1 ) );
+ memcpy( newString, value, length );
+ newString[length] = 0;
+ return newString;
+ }
+
+ virtual void releaseStringValue( char *value )
+ {
+ if ( value )
+ free( value );
+ }
+};
+
+static ValueAllocator *&valueAllocator()
+{
+ static DefaultValueAllocator defaultAllocator;
+ static ValueAllocator *valueAllocator = &defaultAllocator;
+ return valueAllocator;
+}
+
+static struct DummyValueAllocatorInitializer {
+ DummyValueAllocatorInitializer()
+ {
+ valueAllocator(); // ensure valueAllocator() statics are initialized before main().
+ }
+} dummyValueAllocatorInitializer;
+
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// ValueInternals...
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+# include "json_internalarray.inl"
+# include "json_internalmap.inl"
+#endif // JSON_VALUE_USE_INTERNAL_MAP
+
+# include "json_valueiterator.inl"
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::CommentInfo
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+
+Value::CommentInfo::CommentInfo()
+ : comment_( 0 )
+{
+}
+
+Value::CommentInfo::~CommentInfo()
+{
+ if ( comment_ )
+ valueAllocator()->releaseStringValue( comment_ );
+}
+
+
+void
+Value::CommentInfo::setComment( const char *text )
+{
+ if ( comment_ )
+ valueAllocator()->releaseStringValue( comment_ );
+ JSON_ASSERT( text );
+ JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /");
+ // It seems that /**/ style comments are acceptable as well.
+ comment_ = valueAllocator()->duplicateStringValue( text );
+}
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::CZString
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+# ifndef JSON_VALUE_USE_INTERNAL_MAP
+
+// Notes: index_ indicates if the string was allocated when
+// a string is stored.
+
+Value::CZString::CZString( int index )
+ : cstr_( 0 )
+ , index_( index )
+{
+}
+
+Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate )
+ : cstr_( allocate == duplicate ? valueAllocator()->makeMemberName(cstr)
+ : cstr )
+ , index_( allocate )
+{
+}
+
+Value::CZString::CZString( const CZString &other )
+: cstr_( other.index_ != noDuplication && other.cstr_ != 0
+ ? valueAllocator()->makeMemberName( other.cstr_ )
+ : other.cstr_ )
+ , index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate)
+ : other.index_ )
+{
+}
+
+Value::CZString::~CZString()
+{
+ if ( cstr_ && index_ == duplicate )
+ valueAllocator()->releaseMemberName( const_cast<char *>( cstr_ ) );
+}
+
+void
+Value::CZString::swap( CZString &other )
+{
+ std::swap( cstr_, other.cstr_ );
+ std::swap( index_, other.index_ );
+}
+
+Value::CZString &
+Value::CZString::operator =( const CZString &other )
+{
+ CZString temp( other );
+ swap( temp );
+ return *this;
+}
+
+bool
+Value::CZString::operator<( const CZString &other ) const
+{
+ if ( cstr_ )
+ return strcmp( cstr_, other.cstr_ ) < 0;
+ return index_ < other.index_;
+}
+
+bool
+Value::CZString::operator==( const CZString &other ) const
+{
+ if ( cstr_ )
+ return strcmp( cstr_, other.cstr_ ) == 0;
+ return index_ == other.index_;
+}
+
+
+int
+Value::CZString::index() const
+{
+ return index_;
+}
+
+
+const char *
+Value::CZString::c_str() const
+{
+ return cstr_;
+}
+
+bool
+Value::CZString::isStaticString() const
+{
+ return index_ == noDuplication;
+}
+
+#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::Value
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+/*! \internal Default constructor initialization must be equivalent to:
+ * memset( this, 0, sizeof(Value) )
+ * This optimization is used in ValueInternalMap fast allocator.
+ */
+Value::Value( ValueType type )
+ : type_( type )
+ , allocated_( 0 )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ switch ( type )
+ {
+ case nullValue:
+ break;
+ case intValue:
+ case uintValue:
+ value_.int_ = 0;
+ break;
+ case realValue:
+ value_.real_ = 0.0;
+ break;
+ case stringValue:
+ value_.string_ = 0;
+ break;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ case objectValue:
+ value_.map_ = new ObjectValues();
+ break;
+#else
+ case arrayValue:
+ value_.array_ = arrayAllocator()->newArray();
+ break;
+ case objectValue:
+ value_.map_ = mapAllocator()->newMap();
+ break;
+#endif
+ case booleanValue:
+ value_.bool_ = false;
+ break;
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+}
+
+
+Value::Value( Int value )
+ : type_( intValue )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ value_.int_ = value;
+}
+
+
+Value::Value( UInt value )
+ : type_( uintValue )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ value_.uint_ = value;
+}
+
+Value::Value( double value )
+ : type_( realValue )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ value_.real_ = value;
+}
+
+Value::Value( const char *value )
+ : type_( stringValue )
+ , allocated_( true )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ value_.string_ = valueAllocator()->duplicateStringValue( value );
+}
+
+Value::Value( const std::string &value )
+ : type_( stringValue )
+ , allocated_( true )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ value_.string_ = valueAllocator()->duplicateStringValue( value.c_str(),
+ (unsigned int)value.length() );
+
+}
+
+Value::Value( const StaticString &value )
+ : type_( stringValue )
+ , allocated_( false )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ value_.string_ = const_cast<char *>( value.c_str() );
+}
+
+
+# ifdef JSON_USE_CPPTL
+Value::Value( const CppTL::ConstString &value )
+ : type_( stringValue )
+ , allocated_( true )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ value_.string_ = valueAllocator()->duplicateStringValue( value, value.length() );
+}
+# endif
+
+Value::Value( bool value )
+ : type_( booleanValue )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ value_.bool_ = value;
+}
+
+
+Value::Value( const Value &other )
+ : type_( other.type_ )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ switch ( type_ )
+ {
+ case nullValue:
+ case intValue:
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ value_ = other.value_;
+ break;
+ case stringValue:
+ if ( other.value_.string_ )
+ {
+ value_.string_ = valueAllocator()->duplicateStringValue( other.value_.string_ );
+ allocated_ = true;
+ }
+ else
+ value_.string_ = 0;
+ break;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ case objectValue:
+ value_.map_ = new ObjectValues( *other.value_.map_ );
+ break;
+#else
+ case arrayValue:
+ value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ );
+ break;
+ case objectValue:
+ value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ );
+ break;
+#endif
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ if ( other.comments_ )
+ {
+ comments_ = new CommentInfo[numberOfCommentPlacement];
+ for ( int comment =0; comment < numberOfCommentPlacement; ++comment )
+ {
+ const CommentInfo &otherComment = other.comments_[comment];
+ if ( otherComment.comment_ )
+ comments_[comment].setComment( otherComment.comment_ );
+ }
+ }
+}
+
+
+Value::~Value()
+{
+ switch ( type_ )
+ {
+ case nullValue:
+ case intValue:
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ break;
+ case stringValue:
+ if ( allocated_ )
+ valueAllocator()->releaseStringValue( value_.string_ );
+ break;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ case objectValue:
+ delete value_.map_;
+ break;
+#else
+ case arrayValue:
+ arrayAllocator()->destructArray( value_.array_ );
+ break;
+ case objectValue:
+ mapAllocator()->destructMap( value_.map_ );
+ break;
+#endif
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+
+ if ( comments_ )
+ delete[] comments_;
+}
+
+Value &
+Value::operator=( const Value &other )
+{
+ Value temp( other );
+ swap( temp );
+ return *this;
+}
+
+void
+Value::swap( Value &other )
+{
+ ValueType temp = type_;
+ type_ = other.type_;
+ other.type_ = temp;
+ std::swap( value_, other.value_ );
+ int temp2 = allocated_;
+ allocated_ = other.allocated_;
+ other.allocated_ = temp2;
+}
+
+ValueType
+Value::type() const
+{
+ return type_;
+}
+
+
+int
+Value::compare( const Value &other )
+{
+ /*
+ int typeDelta = other.type_ - type_;
+ switch ( type_ )
+ {
+ case nullValue:
+
+ return other.type_ == type_;
+ case intValue:
+ if ( other.type_.isNumeric()
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ break;
+ case stringValue,
+ break;
+ case arrayValue:
+ delete value_.array_;
+ break;
+ case objectValue:
+ delete value_.map_;
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ */
+ return 0; // unreachable
+}
+
+bool
+Value::operator <( const Value &other ) const
+{
+ int typeDelta = type_ - other.type_;
+ if ( typeDelta )
+ return typeDelta < 0 ? true : false;
+ switch ( type_ )
+ {
+ case nullValue:
+ return false;
+ case intValue:
+ return value_.int_ < other.value_.int_;
+ case uintValue:
+ return value_.uint_ < other.value_.uint_;
+ case realValue:
+ return value_.real_ < other.value_.real_;
+ case booleanValue:
+ return value_.bool_ < other.value_.bool_;
+ case stringValue:
+ return ( value_.string_ == 0 && other.value_.string_ )
+ || ( other.value_.string_
+ && value_.string_
+ && strcmp( value_.string_, other.value_.string_ ) < 0 );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ case objectValue:
+ {
+ int delta = int( value_.map_->size() - other.value_.map_->size() );
+ if ( delta )
+ return delta < 0;
+ return (*value_.map_) < (*other.value_.map_);
+ }
+#else
+ case arrayValue:
+ return value_.array_->compare( *(other.value_.array_) ) < 0;
+ case objectValue:
+ return value_.map_->compare( *(other.value_.map_) ) < 0;
+#endif
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return 0; // unreachable
+}
+
+bool
+Value::operator <=( const Value &other ) const
+{
+ return !(other > *this);
+}
+
+bool
+Value::operator >=( const Value &other ) const
+{
+ return !(*this < other);
+}
+
+bool
+Value::operator >( const Value &other ) const
+{
+ return other < *this;
+}
+
+bool
+Value::operator ==( const Value &other ) const
+{
+ //if ( type_ != other.type_ )
+ // GCC 2.95.3 says:
+ // attempt to take address of bit-field structure member `Json::Value::type_'
+ // Beats me, but a temp solves the problem.
+ int temp = other.type_;
+ if ( type_ != temp )
+ return false;
+ switch ( type_ )
+ {
+ case nullValue:
+ return true;
+ case intValue:
+ return value_.int_ == other.value_.int_;
+ case uintValue:
+ return value_.uint_ == other.value_.uint_;
+ case realValue:
+ return value_.real_ == other.value_.real_;
+ case booleanValue:
+ return value_.bool_ == other.value_.bool_;
+ case stringValue:
+ return ( value_.string_ == other.value_.string_ )
+ || ( other.value_.string_
+ && value_.string_
+ && strcmp( value_.string_, other.value_.string_ ) == 0 );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ case objectValue:
+ return value_.map_->size() == other.value_.map_->size()
+ && (*value_.map_) == (*other.value_.map_);
+#else
+ case arrayValue:
+ return value_.array_->compare( *(other.value_.array_) ) == 0;
+ case objectValue:
+ return value_.map_->compare( *(other.value_.map_) ) == 0;
+#endif
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return 0; // unreachable
+}
+
+bool
+Value::operator !=( const Value &other ) const
+{
+ return !( *this == other );
+}
+
+const char *
+Value::asCString() const
+{
+ JSON_ASSERT( type_ == stringValue );
+ return value_.string_;
+}
+
+
+std::string
+Value::asString() const
+{
+ switch ( type_ )
+ {
+ case nullValue:
+ return "";
+ case stringValue:
+ return value_.string_ ? value_.string_ : "";
+ case booleanValue:
+ return value_.bool_ ? "true" : "false";
+ case intValue:
+ case uintValue:
+ case realValue:
+ case arrayValue:
+ case objectValue:
+ JSON_ASSERT_MESSAGE( false, "Type is not convertible to string" );
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return ""; // unreachable
+}
+
+# ifdef JSON_USE_CPPTL
+CppTL::ConstString
+Value::asConstString() const
+{
+ return CppTL::ConstString( asString().c_str() );
+}
+# endif
+
+Value::Int
+Value::asInt() const
+{
+ switch ( type_ )
+ {
+ case nullValue:
+ return 0;
+ case intValue:
+ return value_.int_;
+ case uintValue:
+ JSON_ASSERT_MESSAGE( value_.uint_ < (unsigned)maxInt, "integer out of signed integer range" );
+ return value_.uint_;
+ case realValue:
+ JSON_ASSERT_MESSAGE( value_.real_ >= minInt && value_.real_ <= maxInt, "Real out of signed integer range" );
+ return Int( value_.real_ );
+ case booleanValue:
+ return value_.bool_ ? 1 : 0;
+ case stringValue:
+ case arrayValue:
+ case objectValue:
+ JSON_ASSERT_MESSAGE( false, "Type is not convertible to int" );
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return 0; // unreachable;
+}
+
+Value::UInt
+Value::asUInt() const
+{
+ switch ( type_ )
+ {
+ case nullValue:
+ return 0;
+ case intValue:
+ JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to unsigned integer" );
+ return value_.int_;
+ case uintValue:
+ return value_.uint_;
+ case realValue:
+ JSON_ASSERT_MESSAGE( value_.real_ >= 0 && value_.real_ <= maxUInt, "Real out of unsigned integer range" );
+ return UInt( value_.real_ );
+ case booleanValue:
+ return value_.bool_ ? 1 : 0;
+ case stringValue:
+ case arrayValue:
+ case objectValue:
+ JSON_ASSERT_MESSAGE( false, "Type is not convertible to uint" );
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return 0; // unreachable;
+}
+
+double
+Value::asDouble() const
+{
+ switch ( type_ )
+ {
+ case nullValue:
+ return 0.0;
+ case intValue:
+ return value_.int_;
+ case uintValue:
+ return value_.uint_;
+ case realValue:
+ return value_.real_;
+ case booleanValue:
+ return value_.bool_ ? 1.0 : 0.0;
+ case stringValue:
+ case arrayValue:
+ case objectValue:
+ JSON_ASSERT_MESSAGE( false, "Type is not convertible to double" );
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return 0; // unreachable;
+}
+
+bool
+Value::asBool() const
+{
+ switch ( type_ )
+ {
+ case nullValue:
+ return false;
+ case intValue:
+ case uintValue:
+ return value_.int_ != 0;
+ case realValue:
+ return value_.real_ != 0.0;
+ case booleanValue:
+ return value_.bool_;
+ case stringValue:
+ return value_.string_ && value_.string_[0] != 0;
+ case arrayValue:
+ case objectValue:
+ return value_.map_->size() != 0;
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return false; // unreachable;
+}
+
+
+bool
+Value::isConvertibleTo( ValueType other ) const
+{
+ switch ( type_ )
+ {
+ case nullValue:
+ return true;
+ case intValue:
+ return ( other == nullValue && value_.int_ == 0 )
+ || other == intValue
+ || ( other == uintValue && value_.int_ >= 0 )
+ || other == realValue
+ || other == stringValue
+ || other == booleanValue;
+ case uintValue:
+ return ( other == nullValue && value_.uint_ == 0 )
+ || ( other == intValue && value_.uint_ <= (unsigned)maxInt )
+ || other == uintValue
+ || other == realValue
+ || other == stringValue
+ || other == booleanValue;
+ case realValue:
+ return ( other == nullValue && value_.real_ == 0.0 )
+ || ( other == intValue && value_.real_ >= minInt && value_.real_ <= maxInt )
+ || ( other == uintValue && value_.real_ >= 0 && value_.real_ <= maxUInt )
+ || other == realValue
+ || other == stringValue
+ || other == booleanValue;
+ case booleanValue:
+ return ( other == nullValue && value_.bool_ == false )
+ || other == intValue
+ || other == uintValue
+ || other == realValue
+ || other == stringValue
+ || other == booleanValue;
+ case stringValue:
+ return other == stringValue
+ || ( other == nullValue && (!value_.string_ || value_.string_[0] == 0) );
+ case arrayValue:
+ return other == arrayValue
+ || ( other == nullValue && value_.map_->size() == 0 );
+ case objectValue:
+ return other == objectValue
+ || ( other == nullValue && value_.map_->size() == 0 );
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return false; // unreachable;
+}
+
+
+/// Number of values in array or object
+Value::UInt
+Value::size() const
+{
+ switch ( type_ )
+ {
+ case nullValue:
+ case intValue:
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ case stringValue:
+ return 0;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue: // size of the array is highest index + 1
+ if ( !value_.map_->empty() )
+ {
+ ObjectValues::const_iterator itLast = value_.map_->end();
+ --itLast;
+ return (*itLast).first.index()+1;
+ }
+ return 0;
+ case objectValue:
+ return Int( value_.map_->size() );
+#else
+ case arrayValue:
+ return Int( value_.array_->size() );
+ case objectValue:
+ return Int( value_.map_->size() );
+#endif
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return 0; // unreachable;
+}
+
+
+bool
+Value::empty() const
+{
+ if ( isNull() || isArray() || isObject() )
+ return size() == 0u;
+ else
+ return false;
+}
+
+
+bool
+Value::operator!() const
+{
+ return isNull();
+}
+
+
+void
+Value::clear()
+{
+ JSON_ASSERT( type_ == nullValue || type_ == arrayValue || type_ == objectValue );
+
+ switch ( type_ )
+ {
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ case objectValue:
+ value_.map_->clear();
+ break;
+#else
+ case arrayValue:
+ value_.array_->clear();
+ break;
+ case objectValue:
+ value_.map_->clear();
+ break;
+#endif
+ default:
+ break;
+ }
+}
+
+void
+Value::resize( UInt newSize )
+{
+ JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
+ if ( type_ == nullValue )
+ *this = Value( arrayValue );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ UInt oldSize = size();
+ if ( newSize == 0 )
+ clear();
+ else if ( newSize > oldSize )
+ (*this)[ newSize - 1 ];
+ else
+ {
+ for ( UInt index = newSize; index < oldSize; ++index )
+ value_.map_->erase( index );
+ assert( size() == newSize );
+ }
+#else
+ value_.array_->resize( newSize );
+#endif
+}
+
+
+Value &
+Value::operator[]( UInt index )
+{
+ JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
+ if ( type_ == nullValue )
+ *this = Value( arrayValue );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ CZString key( index );
+ ObjectValues::iterator it = value_.map_->lower_bound( key );
+ if ( it != value_.map_->end() && (*it).first == key )
+ return (*it).second;
+
+ ObjectValues::value_type defaultValue( key, null );
+ it = value_.map_->insert( it, defaultValue );
+ return (*it).second;
+#else
+ return value_.array_->resolveReference( index );
+#endif
+}
+
+
+const Value &
+Value::operator[]( UInt index ) const
+{
+ JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
+ if ( type_ == nullValue )
+ return null;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ CZString key( index );
+ ObjectValues::const_iterator it = value_.map_->find( key );
+ if ( it == value_.map_->end() )
+ return null;
+ return (*it).second;
+#else
+ Value *value = value_.array_->find( index );
+ return value ? *value : null;
+#endif
+}
+
+
+Value &
+Value::operator[]( const char *key )
+{
+ return resolveReference( key, false );
+}
+
+
+Value &
+Value::resolveReference( const char *key,
+ bool isStatic )
+{
+ JSON_ASSERT( type_ == nullValue || type_ == objectValue );
+ if ( type_ == nullValue )
+ *this = Value( objectValue );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ CZString actualKey( key, isStatic ? CZString::noDuplication
+ : CZString::duplicateOnCopy );
+ ObjectValues::iterator it = value_.map_->lower_bound( actualKey );
+ if ( it != value_.map_->end() && (*it).first == actualKey )
+ return (*it).second;
+
+ ObjectValues::value_type defaultValue( actualKey, null );
+ it = value_.map_->insert( it, defaultValue );
+ Value &value = (*it).second;
+ return value;
+#else
+ return value_.map_->resolveReference( key, isStatic );
+#endif
+}
+
+
+Value
+Value::get( UInt index,
+ const Value &defaultValue ) const
+{
+ const Value *value = &((*this)[index]);
+ return value == &null ? defaultValue : *value;
+}
+
+
+bool
+Value::isValidIndex( UInt index ) const
+{
+ return index < size();
+}
+
+
+
+const Value &
+Value::operator[]( const char *key ) const
+{
+ JSON_ASSERT( type_ == nullValue || type_ == objectValue );
+ if ( type_ == nullValue )
+ return null;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ CZString actualKey( key, CZString::noDuplication );
+ ObjectValues::const_iterator it = value_.map_->find( actualKey );
+ if ( it == value_.map_->end() )
+ return null;
+ return (*it).second;
+#else
+ const Value *value = value_.map_->find( key );
+ return value ? *value : null;
+#endif
+}
+
+
+Value &
+Value::operator[]( const std::string &key )
+{
+ return (*this)[ key.c_str() ];
+}
+
+
+const Value &
+Value::operator[]( const std::string &key ) const
+{
+ return (*this)[ key.c_str() ];
+}
+
+Value &
+Value::operator[]( const StaticString &key )
+{
+ return resolveReference( key, true );
+}
+
+
+# ifdef JSON_USE_CPPTL
+Value &
+Value::operator[]( const CppTL::ConstString &key )
+{
+ return (*this)[ key.c_str() ];
+}
+
+
+const Value &
+Value::operator[]( const CppTL::ConstString &key ) const
+{
+ return (*this)[ key.c_str() ];
+}
+# endif
+
+
+Value &
+Value::append( const Value &value )
+{
+ return (*this)[size()] = value;
+}
+
+
+Value
+Value::get( const char *key,
+ const Value &defaultValue ) const
+{
+ const Value *value = &((*this)[key]);
+ return value == &null ? defaultValue : *value;
+}
+
+
+Value
+Value::get( const std::string &key,
+ const Value &defaultValue ) const
+{
+ return get( key.c_str(), defaultValue );
+}
+
+Value
+Value::removeMember( const char* key )
+{
+ JSON_ASSERT( type_ == nullValue || type_ == objectValue );
+ if ( type_ == nullValue )
+ return null;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ CZString actualKey( key, CZString::noDuplication );
+ ObjectValues::iterator it = value_.map_->find( actualKey );
+ if ( it == value_.map_->end() )
+ return null;
+ Value old(it->second);
+ value_.map_->erase(it);
+ return old;
+#else
+ Value *value = value_.map_->find( key );
+ if (value){
+ Value old(*value);
+ value_.map_.remove( key );
+ return old;
+ } else {
+ return null;
+ }
+#endif
+}
+
+Value
+Value::removeMember( const std::string &key )
+{
+ return removeMember( key.c_str() );
+}
+
+# ifdef JSON_USE_CPPTL
+Value
+Value::get( const CppTL::ConstString &key,
+ const Value &defaultValue ) const
+{
+ return get( key.c_str(), defaultValue );
+}
+# endif
+
+bool
+Value::isMember( const char *key ) const
+{
+ const Value *value = &((*this)[key]);
+ return value != &null;
+}
+
+
+bool
+Value::isMember( const std::string &key ) const
+{
+ return isMember( key.c_str() );
+}
+
+
+# ifdef JSON_USE_CPPTL
+bool
+Value::isMember( const CppTL::ConstString &key ) const
+{
+ return isMember( key.c_str() );
+}
+#endif
+
+Value::Members
+Value::getMemberNames() const
+{
+ JSON_ASSERT( type_ == nullValue || type_ == objectValue );
+ if ( type_ == nullValue )
+ return Value::Members();
+ Members members;
+ members.reserve( value_.map_->size() );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ ObjectValues::const_iterator it = value_.map_->begin();
+ ObjectValues::const_iterator itEnd = value_.map_->end();
+ for ( ; it != itEnd; ++it )
+ members.push_back( std::string( (*it).first.c_str() ) );
+#else
+ ValueInternalMap::IteratorState it;
+ ValueInternalMap::IteratorState itEnd;
+ value_.map_->makeBeginIterator( it );
+ value_.map_->makeEndIterator( itEnd );
+ for ( ; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) )
+ members.push_back( std::string( ValueInternalMap::key( it ) ) );
+#endif
+ return members;
+}
+//
+//# ifdef JSON_USE_CPPTL
+//EnumMemberNames
+//Value::enumMemberNames() const
+//{
+// if ( type_ == objectValue )
+// {
+// return CppTL::Enum::any( CppTL::Enum::transform(
+// CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
+// MemberNamesTransform() ) );
+// }
+// return EnumMemberNames();
+//}
+//
+//
+//EnumValues
+//Value::enumValues() const
+//{
+// if ( type_ == objectValue || type_ == arrayValue )
+// return CppTL::Enum::anyValues( *(value_.map_),
+// CppTL::Type<const Value &>() );
+// return EnumValues();
+//}
+//
+//# endif
+
+
+bool
+Value::isNull() const
+{
+ return type_ == nullValue;
+}
+
+
+bool
+Value::isBool() const
+{
+ return type_ == booleanValue;
+}
+
+
+bool
+Value::isInt() const
+{
+ return type_ == intValue;
+}
+
+
+bool
+Value::isUInt() const
+{
+ return type_ == uintValue;
+}
+
+
+bool
+Value::isIntegral() const
+{
+ return type_ == intValue
+ || type_ == uintValue
+ || type_ == booleanValue;
+}
+
+
+bool
+Value::isDouble() const
+{
+ return type_ == realValue;
+}
+
+
+bool
+Value::isNumeric() const
+{
+ return isIntegral() || isDouble();
+}
+
+
+bool
+Value::isString() const
+{
+ return type_ == stringValue;
+}
+
+
+bool
+Value::isArray() const
+{
+ return type_ == nullValue || type_ == arrayValue;
+}
+
+
+bool
+Value::isObject() const
+{
+ return type_ == nullValue || type_ == objectValue;
+}
+
+
+void
+Value::setComment( const char *comment,
+ CommentPlacement placement )
+{
+ if ( !comments_ )
+ comments_ = new CommentInfo[numberOfCommentPlacement];
+ comments_[placement].setComment( comment );
+}
+
+
+void
+Value::setComment( const std::string &comment,
+ CommentPlacement placement )
+{
+ setComment( comment.c_str(), placement );
+}
+
+
+bool
+Value::hasComment( CommentPlacement placement ) const
+{
+ return comments_ != 0 && comments_[placement].comment_ != 0;
+}
+
+std::string
+Value::getComment( CommentPlacement placement ) const
+{
+ if ( hasComment(placement) )
+ return comments_[placement].comment_;
+ return "";
+}
+
+
+std::string
+Value::toStyledString() const
+{
+ StyledWriter writer;
+ return writer.write( *this );
+}
+
+
+Value::const_iterator
+Value::begin() const
+{
+ switch ( type_ )
+ {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ if ( value_.array_ )
+ {
+ ValueInternalArray::IteratorState it;
+ value_.array_->makeBeginIterator( it );
+ return const_iterator( it );
+ }
+ break;
+ case objectValue:
+ if ( value_.map_ )
+ {
+ ValueInternalMap::IteratorState it;
+ value_.map_->makeBeginIterator( it );
+ return const_iterator( it );
+ }
+ break;
+#else
+ case arrayValue:
+ case objectValue:
+ if ( value_.map_ )
+ return const_iterator( value_.map_->begin() );
+ break;
+#endif
+ default:
+ break;
+ }
+ return const_iterator();
+}
+
+Value::const_iterator
+Value::end() const
+{
+ switch ( type_ )
+ {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ if ( value_.array_ )
+ {
+ ValueInternalArray::IteratorState it;
+ value_.array_->makeEndIterator( it );
+ return const_iterator( it );
+ }
+ break;
+ case objectValue:
+ if ( value_.map_ )
+ {
+ ValueInternalMap::IteratorState it;
+ value_.map_->makeEndIterator( it );
+ return const_iterator( it );
+ }
+ break;
+#else
+ case arrayValue:
+ case objectValue:
+ if ( value_.map_ )
+ return const_iterator( value_.map_->end() );
+ break;
+#endif
+ default:
+ break;
+ }
+ return const_iterator();
+}
+
+
+Value::iterator
+Value::begin()
+{
+ switch ( type_ )
+ {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ if ( value_.array_ )
+ {
+ ValueInternalArray::IteratorState it;
+ value_.array_->makeBeginIterator( it );
+ return iterator( it );
+ }
+ break;
+ case objectValue:
+ if ( value_.map_ )
+ {
+ ValueInternalMap::IteratorState it;
+ value_.map_->makeBeginIterator( it );
+ return iterator( it );
+ }
+ break;
+#else
+ case arrayValue:
+ case objectValue:
+ if ( value_.map_ )
+ return iterator( value_.map_->begin() );
+ break;
+#endif
+ default:
+ break;
+ }
+ return iterator();
+}
+
+Value::iterator
+Value::end()
+{
+ switch ( type_ )
+ {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+ case arrayValue:
+ if ( value_.array_ )
+ {
+ ValueInternalArray::IteratorState it;
+ value_.array_->makeEndIterator( it );
+ return iterator( it );
+ }
+ break;
+ case objectValue:
+ if ( value_.map_ )
+ {
+ ValueInternalMap::IteratorState it;
+ value_.map_->makeEndIterator( it );
+ return iterator( it );
+ }
+ break;
+#else
+ case arrayValue:
+ case objectValue:
+ if ( value_.map_ )
+ return iterator( value_.map_->end() );
+ break;
+#endif
+ default:
+ break;
+ }
+ return iterator();
+}
+
+
+// class PathArgument
+// //////////////////////////////////////////////////////////////////
+
+PathArgument::PathArgument()
+ : kind_( kindNone )
+{
+}
+
+
+PathArgument::PathArgument( Value::UInt index )
+ : index_( index )
+ , kind_( kindIndex )
+{
+}
+
+
+PathArgument::PathArgument( const char *key )
+ : key_( key )
+ , kind_( kindKey )
+{
+}
+
+
+PathArgument::PathArgument( const std::string &key )
+ : key_( key.c_str() )
+ , kind_( kindKey )
+{
+}
+
+// class Path
+// //////////////////////////////////////////////////////////////////
+
+Path::Path( const std::string &path,
+ const PathArgument &a1,
+ const PathArgument &a2,
+ const PathArgument &a3,
+ const PathArgument &a4,
+ const PathArgument &a5 )
+{
+ InArgs in;
+ in.push_back( &a1 );
+ in.push_back( &a2 );
+ in.push_back( &a3 );
+ in.push_back( &a4 );
+ in.push_back( &a5 );
+ makePath( path, in );
+}
+
+
+void
+Path::makePath( const std::string &path,
+ const InArgs &in )
+{
+ const char *current = path.c_str();
+ const char *end = current + path.length();
+ InArgs::const_iterator itInArg = in.begin();
+ while ( current != end )
+ {
+ if ( *current == '[' )
+ {
+ ++current;
+ if ( *current == '%' )
+ addPathInArg( path, in, itInArg, PathArgument::kindIndex );
+ else
+ {
+ Value::UInt index = 0;
+ for ( ; current != end && *current >= '0' && *current <= '9'; ++current )
+ index = index * 10 + Value::UInt(*current - '0');
+ args_.push_back( index );
+ }
+ if ( current == end || *current++ != ']' )
+ invalidPath( path, int(current - path.c_str()) );
+ }
+ else if ( *current == '%' )
+ {
+ addPathInArg( path, in, itInArg, PathArgument::kindKey );
+ ++current;
+ }
+ else if ( *current == '.' )
+ {
+ ++current;
+ }
+ else
+ {
+ const char *beginName = current;
+ while ( current != end && !strchr( "[.", *current ) )
+ ++current;
+ args_.push_back( std::string( beginName, current ) );
+ }
+ }
+}
+
+
+void
+Path::addPathInArg( const std::string &path,
+ const InArgs &in,
+ InArgs::const_iterator &itInArg,
+ PathArgument::Kind kind )
+{
+ if ( itInArg == in.end() )
+ {
+ // Error: missing argument %d
+ }
+ else if ( (*itInArg)->kind_ != kind )
+ {
+ // Error: bad argument type
+ }
+ else
+ {
+ args_.push_back( **itInArg );
+ }
+}
+
+
+void
+Path::invalidPath( const std::string &path,
+ int location )
+{
+ // Error: invalid path.
+}
+
+
+const Value &
+Path::resolve( const Value &root ) const
+{
+ const Value *node = &root;
+ for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
+ {
+ const PathArgument &arg = *it;
+ if ( arg.kind_ == PathArgument::kindIndex )
+ {
+ if ( !node->isArray() || node->isValidIndex( arg.index_ ) )
+ {
+ // Error: unable to resolve path (array value expected at position...
+ }
+ node = &((*node)[arg.index_]);
+ }
+ else if ( arg.kind_ == PathArgument::kindKey )
+ {
+ if ( !node->isObject() )
+ {
+ // Error: unable to resolve path (object value expected at position...)
+ }
+ node = &((*node)[arg.key_]);
+ if ( node == &Value::null )
+ {
+ // Error: unable to resolve path (object has no member named '' at position...)
+ }
+ }
+ }
+ return *node;
+}
+
+
+Value
+Path::resolve( const Value &root,
+ const Value &defaultValue ) const
+{
+ const Value *node = &root;
+ for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
+ {
+ const PathArgument &arg = *it;
+ if ( arg.kind_ == PathArgument::kindIndex )
+ {
+ if ( !node->isArray() || node->isValidIndex( arg.index_ ) )
+ return defaultValue;
+ node = &((*node)[arg.index_]);
+ }
+ else if ( arg.kind_ == PathArgument::kindKey )
+ {
+ if ( !node->isObject() )
+ return defaultValue;
+ node = &((*node)[arg.key_]);
+ if ( node == &Value::null )
+ return defaultValue;
+ }
+ }
+ return *node;
+}
+
+
+Value &
+Path::make( Value &root ) const
+{
+ Value *node = &root;
+ for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
+ {
+ const PathArgument &arg = *it;
+ if ( arg.kind_ == PathArgument::kindIndex )
+ {
+ if ( !node->isArray() )
+ {
+ // Error: node is not an array at position ...
+ }
+ node = &((*node)[arg.index_]);
+ }
+ else if ( arg.kind_ == PathArgument::kindKey )
+ {
+ if ( !node->isObject() )
+ {
+ // Error: node is not an object at position...
+ }
+ node = &((*node)[arg.key_]);
+ }
+ }
+ return *node;
+}
+
+
+} // namespace Json
diff --git a/lib/jsoncpp/jsoncpp/src/lib_json/json_valueiterator.inl b/lib/jsoncpp/jsoncpp/src/lib_json/json_valueiterator.inl
new file mode 100644
index 0000000000..898c35895b
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/src/lib_json/json_valueiterator.inl
@@ -0,0 +1,292 @@
+// included by json_value.cpp
+// everything is within Json namespace
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueIteratorBase
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueIteratorBase::ValueIteratorBase()
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ : current_()
+ , isNull_( true )
+{
+}
+#else
+ : isArray_( true )
+ , isNull_( true )
+{
+ iterator_.array_ = ValueInternalArray::IteratorState();
+}
+#endif
+
+
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator &current )
+ : current_( current )
+ , isNull_( false )
+{
+}
+#else
+ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state )
+ : isArray_( true )
+{
+ iterator_.array_ = state;
+}
+
+
+ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state )
+ : isArray_( false )
+{
+ iterator_.map_ = state;
+}
+#endif
+
+Value &
+ValueIteratorBase::deref() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ return current_->second;
+#else
+ if ( isArray_ )
+ return ValueInternalArray::dereference( iterator_.array_ );
+ return ValueInternalMap::value( iterator_.map_ );
+#endif
+}
+
+
+void
+ValueIteratorBase::increment()
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ ++current_;
+#else
+ if ( isArray_ )
+ ValueInternalArray::increment( iterator_.array_ );
+ ValueInternalMap::increment( iterator_.map_ );
+#endif
+}
+
+
+void
+ValueIteratorBase::decrement()
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ --current_;
+#else
+ if ( isArray_ )
+ ValueInternalArray::decrement( iterator_.array_ );
+ ValueInternalMap::decrement( iterator_.map_ );
+#endif
+}
+
+
+ValueIteratorBase::difference_type
+ValueIteratorBase::computeDistance( const SelfType &other ) const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+# ifdef JSON_USE_CPPTL_SMALLMAP
+ return current_ - other.current_;
+# else
+ // Iterator for null value are initialized using the default
+ // constructor, which initialize current_ to the default
+ // std::map::iterator. As begin() and end() are two instance
+ // of the default std::map::iterator, they can not be compared.
+ // To allow this, we handle this comparison specifically.
+ if ( isNull_ && other.isNull_ )
+ {
+ return 0;
+ }
+
+
+ // Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL,
+ // which is the one used by default).
+ // Using a portable hand-made version for non random iterator instead:
+ // return difference_type( std::distance( current_, other.current_ ) );
+ difference_type myDistance = 0;
+ for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it )
+ {
+ ++myDistance;
+ }
+ return myDistance;
+# endif
+#else
+ if ( isArray_ )
+ return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ );
+ return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ );
+#endif
+}
+
+
+bool
+ValueIteratorBase::isEqual( const SelfType &other ) const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ if ( isNull_ )
+ {
+ return other.isNull_;
+ }
+ return current_ == other.current_;
+#else
+ if ( isArray_ )
+ return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ );
+ return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ );
+#endif
+}
+
+
+void
+ValueIteratorBase::copy( const SelfType &other )
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ current_ = other.current_;
+#else
+ if ( isArray_ )
+ iterator_.array_ = other.iterator_.array_;
+ iterator_.map_ = other.iterator_.map_;
+#endif
+}
+
+
+Value
+ValueIteratorBase::key() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ const Value::CZString czstring = (*current_).first;
+ if ( czstring.c_str() )
+ {
+ if ( czstring.isStaticString() )
+ return Value( StaticString( czstring.c_str() ) );
+ return Value( czstring.c_str() );
+ }
+ return Value( czstring.index() );
+#else
+ if ( isArray_ )
+ return Value( ValueInternalArray::indexOf( iterator_.array_ ) );
+ bool isStatic;
+ const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic );
+ if ( isStatic )
+ return Value( StaticString( memberName ) );
+ return Value( memberName );
+#endif
+}
+
+
+Value::UInt
+ValueIteratorBase::index() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ const Value::CZString czstring = (*current_).first;
+ if ( !czstring.c_str() )
+ return czstring.index();
+ return Value::UInt( -1 );
+#else
+ if ( isArray_ )
+ return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) );
+ return Value::UInt( -1 );
+#endif
+}
+
+
+const char *
+ValueIteratorBase::memberName() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ const char *name = (*current_).first.c_str();
+ return name ? name : "";
+#else
+ if ( !isArray_ )
+ return ValueInternalMap::key( iterator_.map_ );
+ return "";
+#endif
+}
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueConstIterator
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueConstIterator::ValueConstIterator()
+{
+}
+
+
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator &current )
+ : ValueIteratorBase( current )
+{
+}
+#else
+ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state )
+ : ValueIteratorBase( state )
+{
+}
+
+ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state )
+ : ValueIteratorBase( state )
+{
+}
+#endif
+
+ValueConstIterator &
+ValueConstIterator::operator =( const ValueIteratorBase &other )
+{
+ copy( other );
+ return *this;
+}
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueIterator
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueIterator::ValueIterator()
+{
+}
+
+
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ValueIterator::ValueIterator( const Value::ObjectValues::iterator &current )
+ : ValueIteratorBase( current )
+{
+}
+#else
+ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state )
+ : ValueIteratorBase( state )
+{
+}
+
+ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state )
+ : ValueIteratorBase( state )
+{
+}
+#endif
+
+ValueIterator::ValueIterator( const ValueConstIterator &other )
+ : ValueIteratorBase( other )
+{
+}
+
+ValueIterator::ValueIterator( const ValueIterator &other )
+ : ValueIteratorBase( other )
+{
+}
+
+ValueIterator &
+ValueIterator::operator =( const SelfType &other )
+{
+ copy( other );
+ return *this;
+}
diff --git a/lib/jsoncpp/jsoncpp/src/lib_json/json_writer.cpp b/lib/jsoncpp/jsoncpp/src/lib_json/json_writer.cpp
new file mode 100644
index 0000000000..f2f8311514
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/src/lib_json/json_writer.cpp
@@ -0,0 +1,829 @@
+#include <json/writer.h>
+#include <utility>
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+
+#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 )
+ {
+ if ( isControlCharacter( *(str++) ) )
+ return true;
+ }
+ return false;
+}
+static void uintToString( unsigned int value,
+ char *&current )
+{
+ *--current = 0;
+ do
+ {
+ *--current = (value % 10) + '0';
+ value /= 10;
+ }
+ while ( value != 0 );
+}
+
+std::string valueToString( Value::Int value )
+{
+ char buffer[32];
+ char *current = buffer + sizeof(buffer);
+ bool isNegative = value < 0;
+ if ( isNegative )
+ value = -value;
+ uintToString( Value::UInt(value), current );
+ if ( isNegative )
+ *--current = '-';
+ assert( current >= buffer );
+ return current;
+}
+
+
+std::string valueToString( Value::UInt value )
+{
+ char buffer[32];
+ char *current = buffer + sizeof(buffer);
+ uintToString( value, current );
+ assert( current >= buffer );
+ return current;
+}
+
+std::string valueToString( double value )
+{
+ char buffer[32];
+#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
+ 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;
+}
+
+
+std::string valueToString( bool value )
+{
+ return value ? "true" : "false";
+}
+
+std::string valueToQuotedString( const char *value )
+{
+ // 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.)
+ unsigned maxsize = strlen(value)*2 + 3; // allescaped+quotes+NULL
+ std::string result;
+ result.reserve(maxsize); // to avoid lots of mallocs
+ result += "\"";
+ for (const char* c=value; *c != 0; ++c)
+ {
+ switch(*c)
+ {
+ case '\"':
+ result += "\\\"";
+ break;
+ case '\\':
+ result += "\\\\";
+ break;
+ case '\b':
+ result += "\\b";
+ break;
+ case '\f':
+ result += "\\f";
+ break;
+ case '\n':
+ result += "\\n";
+ break;
+ case '\r':
+ result += "\\r";
+ break;
+ case '\t':
+ result += "\\t";
+ break;
+ //case '/':
+ // Even though \/ is considered a legal escape in JSON, a bare
+ // slash is also legal, so I see no reason to escape it.
+ // (I hope I am not misunderstanding something.
+ // blep notes: actually escaping \/ may be useful in javascript to avoid </
+ // sequence.
+ // Should add a flag to allow this compatibility mode and prevent this
+ // sequence from occurring.
+ default:
+ if ( isControlCharacter( *c ) )
+ {
+ std::ostringstream oss;
+ oss << "\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4) << static_cast<int>(*c);
+ result += oss.str();
+ }
+ else
+ {
+ result += *c;
+ }
+ break;
+ }
+ }
+ result += "\"";
+ return result;
+}
+
+// Class Writer
+// //////////////////////////////////////////////////////////////////
+Writer::~Writer()
+{
+}
+
+
+// Class FastWriter
+// //////////////////////////////////////////////////////////////////
+
+FastWriter::FastWriter()
+ : yamlCompatiblityEnabled_( false )
+{
+}
+
+
+void
+FastWriter::enableYAMLCompatibility()
+{
+ yamlCompatiblityEnabled_ = true;
+}
+
+
+std::string
+FastWriter::write( const Value &root )
+{
+ document_ = "";
+ writeValue( root );
+ document_ += "\n";
+ return document_;
+}
+
+
+void
+FastWriter::writeValue( const Value &value )
+{
+ switch ( value.type() )
+ {
+ case nullValue:
+ document_ += "null";
+ break;
+ case intValue:
+ document_ += valueToString( value.asInt() );
+ break;
+ case uintValue:
+ document_ += valueToString( value.asUInt() );
+ break;
+ case realValue:
+ document_ += valueToString( value.asDouble() );
+ break;
+ case stringValue:
+ document_ += valueToQuotedString( value.asCString() );
+ break;
+ case booleanValue:
+ document_ += valueToString( value.asBool() );
+ break;
+ case arrayValue:
+ {
+ document_ += "[";
+ int size = value.size();
+ for ( int index =0; index < size; ++index )
+ {
+ if ( index > 0 )
+ document_ += ",";
+ writeValue( value[index] );
+ }
+ document_ += "]";
+ }
+ break;
+ case objectValue:
+ {
+ Value::Members members( value.getMemberNames() );
+ document_ += "{";
+ for ( Value::Members::iterator it = members.begin();
+ it != members.end();
+ ++it )
+ {
+ const std::string &name = *it;
+ if ( it != members.begin() )
+ document_ += ",";
+ document_ += valueToQuotedString( name.c_str() );
+ document_ += yamlCompatiblityEnabled_ ? ": "
+ : ":";
+ writeValue( value[name] );
+ }
+ document_ += "}";
+ }
+ break;
+ }
+}
+
+
+// Class StyledWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledWriter::StyledWriter()
+ : rightMargin_( 74 )
+ , indentSize_( 3 )
+{
+}
+
+
+std::string
+StyledWriter::write( const Value &root )
+{
+ document_ = "";
+ addChildValues_ = false;
+ indentString_ = "";
+ writeCommentBeforeValue( root );
+ writeValue( root );
+ writeCommentAfterValueOnSameLine( root );
+ document_ += "\n";
+ return document_;
+}
+
+
+void
+StyledWriter::writeValue( const Value &value )
+{
+ switch ( value.type() )
+ {
+ case nullValue:
+ pushValue( "null" );
+ break;
+ case intValue:
+ pushValue( valueToString( value.asInt() ) );
+ break;
+ case uintValue:
+ pushValue( valueToString( value.asUInt() ) );
+ break;
+ case realValue:
+ pushValue( valueToString( value.asDouble() ) );
+ break;
+ case stringValue:
+ pushValue( valueToQuotedString( value.asCString() ) );
+ break;
+ case booleanValue:
+ pushValue( valueToString( value.asBool() ) );
+ break;
+ case arrayValue:
+ writeArrayValue( value);
+ break;
+ case objectValue:
+ {
+ Value::Members members( value.getMemberNames() );
+ if ( members.empty() )
+ pushValue( "{}" );
+ else
+ {
+ writeWithIndent( "{" );
+ indent();
+ Value::Members::iterator it = members.begin();
+ while ( true )
+ {
+ const std::string &name = *it;
+ const Value &childValue = value[name];
+ writeCommentBeforeValue( childValue );
+ writeWithIndent( valueToQuotedString( name.c_str() ) );
+ document_ += " : ";
+ writeValue( childValue );
+ if ( ++it == members.end() )
+ {
+ writeCommentAfterValueOnSameLine( childValue );
+ break;
+ }
+ document_ += ",";
+ writeCommentAfterValueOnSameLine( childValue );
+ }
+ unindent();
+ writeWithIndent( "}" );
+ }
+ }
+ break;
+ }
+}
+
+
+void
+StyledWriter::writeArrayValue( const Value &value )
+{
+ unsigned size = value.size();
+ if ( size == 0 )
+ pushValue( "[]" );
+ else
+ {
+ bool isArrayMultiLine = isMultineArray( value );
+ if ( isArrayMultiLine )
+ {
+ writeWithIndent( "[" );
+ indent();
+ bool hasChildValue = !childValues_.empty();
+ unsigned index =0;
+ while ( true )
+ {
+ const Value &childValue = value[index];
+ writeCommentBeforeValue( childValue );
+ if ( hasChildValue )
+ writeWithIndent( childValues_[index] );
+ else
+ {
+ writeIndent();
+ writeValue( childValue );
+ }
+ if ( ++index == size )
+ {
+ writeCommentAfterValueOnSameLine( childValue );
+ break;
+ }
+ document_ += ",";
+ writeCommentAfterValueOnSameLine( childValue );
+ }
+ unindent();
+ writeWithIndent( "]" );
+ }
+ else // output on a single line
+ {
+ assert( childValues_.size() == size );
+ document_ += "[ ";
+ for ( unsigned index =0; index < size; ++index )
+ {
+ if ( index > 0 )
+ document_ += ", ";
+ document_ += childValues_[index];
+ }
+ document_ += " ]";
+ }
+ }
+}
+
+
+bool
+StyledWriter::isMultineArray( const Value &value )
+{
+ int size = value.size();
+ bool isMultiLine = size*3 >= rightMargin_ ;
+ childValues_.clear();
+ for ( int index =0; index < size && !isMultiLine; ++index )
+ {
+ const Value &childValue = value[index];
+ isMultiLine = isMultiLine ||
+ ( (childValue.isArray() || childValue.isObject()) &&
+ childValue.size() > 0 );
+ }
+ if ( !isMultiLine ) // check if line length > max line length
+ {
+ childValues_.reserve( size );
+ addChildValues_ = true;
+ int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
+ for ( int index =0; index < size && !isMultiLine; ++index )
+ {
+ writeValue( value[index] );
+ lineLength += int( childValues_[index].length() );
+ isMultiLine = isMultiLine && hasCommentForValue( value[index] );
+ }
+ addChildValues_ = false;
+ isMultiLine = isMultiLine || lineLength >= rightMargin_;
+ }
+ return isMultiLine;
+}
+
+
+void
+StyledWriter::pushValue( const std::string &value )
+{
+ if ( addChildValues_ )
+ childValues_.push_back( value );
+ else
+ document_ += value;
+}
+
+
+void
+StyledWriter::writeIndent()
+{
+ if ( !document_.empty() )
+ {
+ char last = document_[document_.length()-1];
+ if ( last == ' ' ) // already indented
+ return;
+ if ( last != '\n' ) // Comments may add new-line
+ document_ += '\n';
+ }
+ document_ += indentString_;
+}
+
+
+void
+StyledWriter::writeWithIndent( const std::string &value )
+{
+ writeIndent();
+ document_ += value;
+}
+
+
+void
+StyledWriter::indent()
+{
+ indentString_ += std::string( indentSize_, ' ' );
+}
+
+
+void
+StyledWriter::unindent()
+{
+ assert( int(indentString_.size()) >= indentSize_ );
+ indentString_.resize( indentString_.size() - indentSize_ );
+}
+
+
+void
+StyledWriter::writeCommentBeforeValue( const Value &root )
+{
+ if ( !root.hasComment( commentBefore ) )
+ return;
+ document_ += normalizeEOL( root.getComment( commentBefore ) );
+ document_ += "\n";
+}
+
+
+void
+StyledWriter::writeCommentAfterValueOnSameLine( const Value &root )
+{
+ if ( root.hasComment( commentAfterOnSameLine ) )
+ document_ += " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
+
+ if ( root.hasComment( commentAfter ) )
+ {
+ document_ += "\n";
+ document_ += normalizeEOL( root.getComment( commentAfter ) );
+ document_ += "\n";
+ }
+}
+
+
+bool
+StyledWriter::hasCommentForValue( const Value &value )
+{
+ return value.hasComment( commentBefore )
+ || value.hasComment( commentAfterOnSameLine )
+ || value.hasComment( commentAfter );
+}
+
+
+std::string
+StyledWriter::normalizeEOL( const std::string &text )
+{
+ std::string normalized;
+ normalized.reserve( text.length() );
+ const char *begin = text.c_str();
+ const char *end = begin + text.length();
+ const char *current = begin;
+ while ( current != end )
+ {
+ char c = *current++;
+ if ( c == '\r' ) // mac or dos EOL
+ {
+ if ( *current == '\n' ) // convert dos EOL
+ ++current;
+ normalized += '\n';
+ }
+ else // handle unix EOL & other char
+ normalized += c;
+ }
+ return normalized;
+}
+
+
+// Class StyledStreamWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledStreamWriter::StyledStreamWriter( std::string indentation )
+ : document_(NULL)
+ , rightMargin_( 74 )
+ , indentation_( indentation )
+{
+}
+
+
+void
+StyledStreamWriter::write( std::ostream &out, const Value &root )
+{
+ document_ = &out;
+ addChildValues_ = false;
+ indentString_ = "";
+ writeCommentBeforeValue( root );
+ writeValue( root );
+ writeCommentAfterValueOnSameLine( root );
+ *document_ << "\n";
+ document_ = NULL; // Forget the stream, for safety.
+}
+
+
+void
+StyledStreamWriter::writeValue( const Value &value )
+{
+ switch ( value.type() )
+ {
+ case nullValue:
+ pushValue( "null" );
+ break;
+ case intValue:
+ pushValue( valueToString( value.asInt() ) );
+ break;
+ case uintValue:
+ pushValue( valueToString( value.asUInt() ) );
+ break;
+ case realValue:
+ pushValue( valueToString( value.asDouble() ) );
+ break;
+ case stringValue:
+ pushValue( valueToQuotedString( value.asCString() ) );
+ break;
+ case booleanValue:
+ pushValue( valueToString( value.asBool() ) );
+ break;
+ case arrayValue:
+ writeArrayValue( value);
+ break;
+ case objectValue:
+ {
+ Value::Members members( value.getMemberNames() );
+ if ( members.empty() )
+ pushValue( "{}" );
+ else
+ {
+ writeWithIndent( "{" );
+ indent();
+ Value::Members::iterator it = members.begin();
+ while ( true )
+ {
+ const std::string &name = *it;
+ const Value &childValue = value[name];
+ writeCommentBeforeValue( childValue );
+ writeWithIndent( valueToQuotedString( name.c_str() ) );
+ *document_ << " : ";
+ writeValue( childValue );
+ if ( ++it == members.end() )
+ {
+ writeCommentAfterValueOnSameLine( childValue );
+ break;
+ }
+ *document_ << ",";
+ writeCommentAfterValueOnSameLine( childValue );
+ }
+ unindent();
+ writeWithIndent( "}" );
+ }
+ }
+ break;
+ }
+}
+
+
+void
+StyledStreamWriter::writeArrayValue( const Value &value )
+{
+ unsigned size = value.size();
+ if ( size == 0 )
+ pushValue( "[]" );
+ else
+ {
+ bool isArrayMultiLine = isMultineArray( value );
+ if ( isArrayMultiLine )
+ {
+ writeWithIndent( "[" );
+ indent();
+ bool hasChildValue = !childValues_.empty();
+ unsigned index =0;
+ while ( true )
+ {
+ const Value &childValue = value[index];
+ writeCommentBeforeValue( childValue );
+ if ( hasChildValue )
+ writeWithIndent( childValues_[index] );
+ else
+ {
+ writeIndent();
+ writeValue( childValue );
+ }
+ if ( ++index == size )
+ {
+ writeCommentAfterValueOnSameLine( childValue );
+ break;
+ }
+ *document_ << ",";
+ writeCommentAfterValueOnSameLine( childValue );
+ }
+ unindent();
+ writeWithIndent( "]" );
+ }
+ else // output on a single line
+ {
+ assert( childValues_.size() == size );
+ *document_ << "[ ";
+ for ( unsigned index =0; index < size; ++index )
+ {
+ if ( index > 0 )
+ *document_ << ", ";
+ *document_ << childValues_[index];
+ }
+ *document_ << " ]";
+ }
+ }
+}
+
+
+bool
+StyledStreamWriter::isMultineArray( const Value &value )
+{
+ int size = value.size();
+ bool isMultiLine = size*3 >= rightMargin_ ;
+ childValues_.clear();
+ for ( int index =0; index < size && !isMultiLine; ++index )
+ {
+ const Value &childValue = value[index];
+ isMultiLine = isMultiLine ||
+ ( (childValue.isArray() || childValue.isObject()) &&
+ childValue.size() > 0 );
+ }
+ if ( !isMultiLine ) // check if line length > max line length
+ {
+ childValues_.reserve( size );
+ addChildValues_ = true;
+ int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
+ for ( int index =0; index < size && !isMultiLine; ++index )
+ {
+ writeValue( value[index] );
+ lineLength += int( childValues_[index].length() );
+ isMultiLine = isMultiLine && hasCommentForValue( value[index] );
+ }
+ addChildValues_ = false;
+ isMultiLine = isMultiLine || lineLength >= rightMargin_;
+ }
+ return isMultiLine;
+}
+
+
+void
+StyledStreamWriter::pushValue( const std::string &value )
+{
+ if ( addChildValues_ )
+ childValues_.push_back( value );
+ else
+ *document_ << value;
+}
+
+
+void
+StyledStreamWriter::writeIndent()
+{
+ /*
+ Some comments in this method would have been nice. ;-)
+
+ if ( !document_.empty() )
+ {
+ char last = document_[document_.length()-1];
+ if ( last == ' ' ) // already indented
+ return;
+ if ( last != '\n' ) // Comments may add new-line
+ *document_ << '\n';
+ }
+ */
+ *document_ << '\n' << indentString_;
+}
+
+
+void
+StyledStreamWriter::writeWithIndent( const std::string &value )
+{
+ writeIndent();
+ *document_ << value;
+}
+
+
+void
+StyledStreamWriter::indent()
+{
+ indentString_ += indentation_;
+}
+
+
+void
+StyledStreamWriter::unindent()
+{
+ assert( indentString_.size() >= indentation_.size() );
+ indentString_.resize( indentString_.size() - indentation_.size() );
+}
+
+
+void
+StyledStreamWriter::writeCommentBeforeValue( const Value &root )
+{
+ if ( !root.hasComment( commentBefore ) )
+ return;
+ *document_ << normalizeEOL( root.getComment( commentBefore ) );
+ *document_ << "\n";
+}
+
+
+void
+StyledStreamWriter::writeCommentAfterValueOnSameLine( const Value &root )
+{
+ if ( root.hasComment( commentAfterOnSameLine ) )
+ *document_ << " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
+
+ if ( root.hasComment( commentAfter ) )
+ {
+ *document_ << "\n";
+ *document_ << normalizeEOL( root.getComment( commentAfter ) );
+ *document_ << "\n";
+ }
+}
+
+
+bool
+StyledStreamWriter::hasCommentForValue( const Value &value )
+{
+ return value.hasComment( commentBefore )
+ || value.hasComment( commentAfterOnSameLine )
+ || value.hasComment( commentAfter );
+}
+
+
+std::string
+StyledStreamWriter::normalizeEOL( const std::string &text )
+{
+ std::string normalized;
+ normalized.reserve( text.length() );
+ const char *begin = text.c_str();
+ const char *end = begin + text.length();
+ const char *current = begin;
+ while ( current != end )
+ {
+ char c = *current++;
+ if ( c == '\r' ) // mac or dos EOL
+ {
+ if ( *current == '\n' ) // convert dos EOL
+ ++current;
+ normalized += '\n';
+ }
+ else // handle unix EOL & other char
+ normalized += c;
+ }
+ return normalized;
+}
+
+
+std::ostream& operator<<( std::ostream &sout, const Value &root )
+{
+ Json::StyledStreamWriter writer;
+ writer.write(sout, root);
+ return sout;
+}
+
+
+} // namespace Json
diff --git a/lib/jsoncpp/jsoncpp/src/lib_json/sconscript b/lib/jsoncpp/jsoncpp/src/lib_json/sconscript
new file mode 100644
index 0000000000..6e7c6c8a07
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/src/lib_json/sconscript
@@ -0,0 +1,8 @@
+Import( 'env buildLibrary' )
+
+buildLibrary( env, Split( """
+ json_reader.cpp
+ json_value.cpp
+ json_writer.cpp
+ """ ),
+ 'json' )
diff --git a/lib/jsoncpp/jsoncpp/src/test_lib_json/jsontest.cpp b/lib/jsoncpp/jsoncpp/src/test_lib_json/jsontest.cpp
new file mode 100644
index 0000000000..dfd2b5c77d
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/src/test_lib_json/jsontest.cpp
@@ -0,0 +1,598 @@
+#define _CRT_SECURE_NO_WARNINGS 1 // Prevents deprecation warning with MSVC
+#include "jsontest.h"
+#include <stdio.h>
+#include <string>
+
+#if defined(_MSC_VER)
+// Used to install a report hook that prevent dialog on assertion and error.
+# include <crtdbg.h>
+#endif // if defined(_MSC_VER)
+
+#if defined(_WIN32)
+// Used to prevent dialog on memory fault.
+// Limits headers included by Windows.h
+# define WIN32_LEAN_AND_MEAN
+# define NOSERVICE
+# define NOMCX
+# define NOIME
+# define NOSOUND
+# define NOCOMM
+# define NORPC
+# define NOGDI
+# define NOUSER
+# define NODRIVERS
+# define NOLOGERROR
+# define NOPROFILER
+# define NOMEMMGR
+# define NOLFILEIO
+# define NOOPENFILE
+# define NORESOURCE
+# define NOATOM
+# define NOLANGUAGE
+# define NOLSTRING
+# define NODBCS
+# define NOKEYBOARDINFO
+# define NOGDICAPMASKS
+# define NOCOLOR
+# define NOGDIOBJ
+# define NODRAWTEXT
+# define NOTEXTMETRIC
+# define NOSCALABLEFONT
+# define NOBITMAP
+# define NORASTEROPS
+# define NOMETAFILE
+# define NOSYSMETRICS
+# define NOSYSTEMPARAMSINFO
+# define NOMSG
+# define NOWINSTYLES
+# define NOWINOFFSETS
+# define NOSHOWWINDOW
+# define NODEFERWINDOWPOS
+# define NOVIRTUALKEYCODES
+# define NOKEYSTATES
+# define NOWH
+# define NOMENUS
+# define NOSCROLL
+# define NOCLIPBOARD
+# define NOICONS
+# define NOMB
+# define NOSYSCOMMANDS
+# define NOMDI
+# define NOCTLMGR
+# define NOWINMESSAGES
+# include <windows.h>
+#endif // if defined(_WIN32)
+
+namespace JsonTest {
+
+
+// class TestResult
+// //////////////////////////////////////////////////////////////////
+
+TestResult::TestResult()
+ : predicateId_( 1 )
+ , lastUsedPredicateId_( 0 )
+ , messageTarget_( 0 )
+{
+ // The root predicate has id 0
+ rootPredicateNode_.id_ = 0;
+ rootPredicateNode_.next_ = 0;
+ predicateStackTail_ = &rootPredicateNode_;
+}
+
+
+void
+TestResult::setTestName( const std::string &name )
+{
+ name_ = name;
+}
+
+TestResult &
+TestResult::addFailure( const char *file, unsigned int line,
+ const char *expr )
+{
+ /// Walks the PredicateContext stack adding them to failures_ if not already added.
+ unsigned int nestingLevel = 0;
+ PredicateContext *lastNode = rootPredicateNode_.next_;
+ for ( ; lastNode != 0; lastNode = lastNode->next_ )
+ {
+ if ( lastNode->id_ > lastUsedPredicateId_ ) // new PredicateContext
+ {
+ lastUsedPredicateId_ = lastNode->id_;
+ addFailureInfo( lastNode->file_, lastNode->line_, lastNode->expr_,
+ nestingLevel );
+ // Link the PredicateContext to the failure for message target when
+ // popping the PredicateContext.
+ lastNode->failure_ = &( failures_.back() );
+ }
+ ++nestingLevel;
+ }
+
+ // Adds the failed assertion
+ addFailureInfo( file, line, expr, nestingLevel );
+ messageTarget_ = &( failures_.back() );
+ return *this;
+}
+
+
+void
+TestResult::addFailureInfo( const char *file, unsigned int line,
+ const char *expr, unsigned int nestingLevel )
+{
+ Failure failure;
+ failure.file_ = file;
+ failure.line_ = line;
+ if ( expr )
+ {
+ failure.expr_ = expr;
+ }
+ failure.nestingLevel_ = nestingLevel;
+ failures_.push_back( failure );
+}
+
+
+TestResult &
+TestResult::popPredicateContext()
+{
+ PredicateContext *lastNode = &rootPredicateNode_;
+ while ( lastNode->next_ != 0 && lastNode->next_->next_ != 0 )
+ {
+ lastNode = lastNode->next_;
+ }
+ // Set message target to popped failure
+ PredicateContext *tail = lastNode->next_;
+ if ( tail != 0 && tail->failure_ != 0 )
+ {
+ messageTarget_ = tail->failure_;
+ }
+ // Remove tail from list
+ predicateStackTail_ = lastNode;
+ lastNode->next_ = 0;
+ return *this;
+}
+
+
+bool
+TestResult::failed() const
+{
+ return !failures_.empty();
+}
+
+
+unsigned int
+TestResult::getAssertionNestingLevel() const
+{
+ unsigned int level = 0;
+ const PredicateContext *lastNode = &rootPredicateNode_;
+ while ( lastNode->next_ != 0 )
+ {
+ lastNode = lastNode->next_;
+ ++level;
+ }
+ return level;
+}
+
+
+void
+TestResult::printFailure( bool printTestName ) const
+{
+ if ( failures_.empty() )
+ {
+ return;
+ }
+
+ if ( printTestName )
+ {
+ printf( "* Detail of %s test failure:\n", name_.c_str() );
+ }
+
+ // Print in reverse to display the callstack in the right order
+ Failures::const_iterator itEnd = failures_.end();
+ for ( Failures::const_iterator it = failures_.begin(); it != itEnd; ++it )
+ {
+ const Failure &failure = *it;
+ std::string indent( failure.nestingLevel_ * 2, ' ' );
+ if ( failure.file_ )
+ {
+ printf( "%s%s(%d): ", indent.c_str(), failure.file_, failure.line_ );
+ }
+ if ( !failure.expr_.empty() )
+ {
+ printf( "%s\n", failure.expr_.c_str() );
+ }
+ else if ( failure.file_ )
+ {
+ printf( "\n" );
+ }
+ if ( !failure.message_.empty() )
+ {
+ std::string reindented = indentText( failure.message_, indent + " " );
+ printf( "%s\n", reindented.c_str() );
+ }
+ }
+}
+
+
+std::string
+TestResult::indentText( const std::string &text,
+ const std::string &indent )
+{
+ std::string reindented;
+ std::string::size_type lastIndex = 0;
+ while ( lastIndex < text.size() )
+ {
+ std::string::size_type nextIndex = text.find( '\n', lastIndex );
+ if ( nextIndex == std::string::npos )
+ {
+ nextIndex = text.size() - 1;
+ }
+ reindented += indent;
+ reindented += text.substr( lastIndex, nextIndex - lastIndex + 1 );
+ lastIndex = nextIndex + 1;
+ }
+ return reindented;
+}
+
+
+TestResult &
+TestResult::addToLastFailure( const std::string &message )
+{
+ if ( messageTarget_ != 0 )
+ {
+ messageTarget_->message_ += message;
+ }
+ return *this;
+}
+
+
+TestResult &
+TestResult::operator << ( bool value )
+{
+ return addToLastFailure( value ? "true" : "false" );
+}
+
+
+TestResult &
+TestResult::operator << ( int value )
+{
+ char buffer[32];
+ sprintf( buffer, "%d", value );
+ return addToLastFailure( buffer );
+}
+
+
+TestResult &
+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
+// //////////////////////////////////////////////////////////////////
+
+TestCase::TestCase()
+ : result_( 0 )
+{
+}
+
+
+void
+TestCase::run( TestResult &result )
+{
+ result_ = &result;
+ runTestCase();
+}
+
+
+
+// class Runner
+// //////////////////////////////////////////////////////////////////
+
+Runner::Runner()
+{
+}
+
+
+Runner &
+Runner::add( TestCaseFactory factory )
+{
+ tests_.push_back( factory );
+ return *this;
+}
+
+
+unsigned int
+Runner::testCount() const
+{
+ return static_cast<unsigned int>( tests_.size() );
+}
+
+
+std::string
+Runner::testNameAt( unsigned int index ) const
+{
+ TestCase *test = tests_[index]();
+ std::string name = test->testName();
+ delete test;
+ return name;
+}
+
+
+void
+Runner::runTestAt( unsigned int index, TestResult &result ) const
+{
+ TestCase *test = tests_[index]();
+ result.setTestName( test->testName() );
+ printf( "Testing %s: ", test->testName() );
+ fflush( stdout );
+#if JSON_USE_EXCEPTION
+ try
+ {
+#endif // if JSON_USE_EXCEPTION
+ test->run( result );
+#if JSON_USE_EXCEPTION
+ }
+ catch ( const std::exception &e )
+ {
+ result.addFailure( __FILE__, __LINE__,
+ "Unexpected exception caugth:" ) << e.what();
+ }
+#endif // if JSON_USE_EXCEPTION
+ delete test;
+ const char *status = result.failed() ? "FAILED"
+ : "OK";
+ printf( "%s\n", status );
+ fflush( stdout );
+}
+
+
+bool
+Runner::runAllTest( bool printSummary ) const
+{
+ unsigned int count = testCount();
+ std::deque<TestResult> failures;
+ for ( unsigned int index = 0; index < count; ++index )
+ {
+ TestResult result;
+ runTestAt( index, result );
+ if ( result.failed() )
+ {
+ failures.push_back( result );
+ }
+ }
+
+ if ( failures.empty() )
+ {
+ if ( printSummary )
+ {
+ printf( "All %d tests passed\n", count );
+ }
+ return true;
+ }
+ else
+ {
+ for ( unsigned int index = 0; index < failures.size(); ++index )
+ {
+ TestResult &result = failures[index];
+ result.printFailure( count > 1 );
+ }
+
+ if ( printSummary )
+ {
+ unsigned int failedCount = static_cast<unsigned int>( failures.size() );
+ unsigned int passedCount = count - failedCount;
+ printf( "%d/%d tests passed (%d failure(s))\n", passedCount, count, failedCount );
+ }
+ return false;
+ }
+}
+
+
+bool
+Runner::testIndex( const std::string &testName,
+ unsigned int &indexOut ) const
+{
+ unsigned int count = testCount();
+ for ( unsigned int index = 0; index < count; ++index )
+ {
+ if ( testNameAt(index) == testName )
+ {
+ indexOut = index;
+ return true;
+ }
+ }
+ return false;
+}
+
+
+void
+Runner::listTests() const
+{
+ unsigned int count = testCount();
+ for ( unsigned int index = 0; index < count; ++index )
+ {
+ printf( "%s\n", testNameAt( index ).c_str() );
+ }
+}
+
+
+int
+Runner::runCommandLine( int argc, const char *argv[] ) const
+{
+ typedef std::deque<std::string> TestNames;
+ Runner subrunner;
+ for ( int index = 1; index < argc; ++index )
+ {
+ std::string opt = argv[index];
+ if ( opt == "--list-tests" )
+ {
+ listTests();
+ return 0;
+ }
+ else if ( opt == "--test-auto" )
+ {
+ preventDialogOnCrash();
+ }
+ else if ( opt == "--test" )
+ {
+ ++index;
+ if ( index < argc )
+ {
+ unsigned int testNameIndex;
+ if ( testIndex( argv[index], testNameIndex ) )
+ {
+ subrunner.add( tests_[testNameIndex] );
+ }
+ else
+ {
+ fprintf( stderr, "Test '%s' does not exist!\n", argv[index] );
+ return 2;
+ }
+ }
+ else
+ {
+ printUsage( argv[0] );
+ return 2;
+ }
+ }
+ else
+ {
+ printUsage( argv[0] );
+ return 2;
+ }
+ }
+ bool succeeded;
+ if ( subrunner.testCount() > 0 )
+ {
+ succeeded = subrunner.runAllTest( subrunner.testCount() > 1 );
+ }
+ else
+ {
+ succeeded = runAllTest( true );
+ }
+ return succeeded ? 0
+ : 1;
+}
+
+
+#if defined(_MSC_VER)
+// Hook MSVCRT assertions to prevent dialog from appearing
+static int
+msvcrtSilentReportHook( int reportType, char *message, int *returnValue )
+{
+ // The default CRT handling of error and assertion is to display
+ // an error dialog to the user.
+ // Instead, when an error or an assertion occurs, we force the
+ // application to terminate using abort() after display
+ // the message on stderr.
+ if ( reportType == _CRT_ERROR ||
+ reportType == _CRT_ASSERT )
+ {
+ // calling abort() cause the ReportHook to be called
+ // The following is used to detect this case and let's the
+ // error handler fallback on its default behaviour (
+ // display a warning message)
+ static volatile bool isAborting = false;
+ if ( isAborting )
+ {
+ return TRUE;
+ }
+ isAborting = true;
+
+ fprintf( stderr, "CRT Error/Assert:\n%s\n", message );
+ fflush( stderr );
+ abort();
+ }
+ // Let's other reportType (_CRT_WARNING) be handled as they would by default
+ return FALSE;
+}
+#endif // if defined(_MSC_VER)
+
+
+void
+Runner::preventDialogOnCrash()
+{
+#if defined(_MSC_VER)
+ // Install a hook to prevent MSVCRT error and assertion from
+ // popping a dialog.
+ _CrtSetReportHook( &msvcrtSilentReportHook );
+#endif // if defined(_MSC_VER)
+
+ // @todo investiguate this handler (for buffer overflow)
+ // _set_security_error_handler
+
+#if defined(_WIN32)
+ // Prevents the system from popping a dialog for debugging if the
+ // application fails due to invalid memory access.
+ SetErrorMode( SEM_FAILCRITICALERRORS
+ | SEM_NOGPFAULTERRORBOX
+ | SEM_NOOPENFILEERRORBOX );
+#endif // if defined(_WIN32)
+}
+
+void
+Runner::printUsage( const char *appName )
+{
+ printf(
+ "Usage: %s [options]\n"
+ "\n"
+ "If --test is not specified, then all the test cases be run.\n"
+ "\n"
+ "Valid options:\n"
+ "--list-tests: print the name of all test cases on the standard\n"
+ " output and exit.\n"
+ "--test TESTNAME: executes the test case with the specified name.\n"
+ " May be repeated.\n"
+ "--test-auto: prevent dialog prompting for debugging on crash.\n"
+ , appName );
+}
+
+
+
+// Assertion functions
+// //////////////////////////////////////////////////////////////////
+
+TestResult &
+checkStringEqual( TestResult &result,
+ const std::string &expected, const std::string &actual,
+ const char *file, unsigned int line, const char *expr )
+{
+ if ( expected != actual )
+ {
+ result.addFailure( file, line, expr );
+ result << "Expected: '" << expected << "'\n";
+ result << "Actual : '" << actual << "'";
+ }
+ return result;
+}
+
+
+} // namespace JsonTest
diff --git a/lib/jsoncpp/jsoncpp/src/test_lib_json/jsontest.h b/lib/jsoncpp/jsoncpp/src/test_lib_json/jsontest.h
new file mode 100644
index 0000000000..7abba56cb4
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/src/test_lib_json/jsontest.h
@@ -0,0 +1,252 @@
+#ifndef JSONTEST_H_INCLUDED
+# define JSONTEST_H_INCLUDED
+
+# include <json/config.h>
+# include <stdio.h>
+# include <deque>
+# include <string>
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// Mini Unit Testing framework
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+
+
+/** \brief Unit testing framework.
+ * \warning: all assertions are non-aborting, test case execution will continue
+ * even if an assertion namespace.
+ * This constraint is for portability: the framework needs to compile
+ * on Visual Studio 6 and must not require exception usage.
+ */
+namespace JsonTest {
+
+
+ class Failure
+ {
+ public:
+ const char *file_;
+ unsigned int line_;
+ std::string expr_;
+ std::string message_;
+ unsigned int nestingLevel_;
+ };
+
+
+ /// Context used to create the assertion callstack on failure.
+ /// Must be a POD to allow inline initialisation without stepping
+ /// into the debugger.
+ struct PredicateContext
+ {
+ typedef unsigned int Id;
+ Id id_;
+ const char *file_;
+ unsigned int line_;
+ const char *expr_;
+ PredicateContext *next_;
+ /// Related Failure, set when the PredicateContext is converted
+ /// into a Failure.
+ Failure *failure_;
+ };
+
+ class TestResult
+ {
+ public:
+ TestResult();
+
+ /// \internal Implementation detail for assertion macros
+ /// Not encapsulated to prevent step into when debugging failed assertions
+ /// Incremented by one on assertion predicate entry, decreased by one
+ /// by addPredicateContext().
+ PredicateContext::Id predicateId_;
+
+ /// \internal Implementation detail for predicate macros
+ PredicateContext *predicateStackTail_;
+
+ void setTestName( const std::string &name );
+
+ /// Adds an assertion failure.
+ TestResult &addFailure( const char *file, unsigned int line,
+ const char *expr = 0 );
+
+ /// Removes the last PredicateContext added to the predicate stack
+ /// chained list.
+ /// Next messages will be targed at the PredicateContext that was removed.
+ TestResult &popPredicateContext();
+
+ bool failed() const;
+
+ void printFailure( bool printTestName ) const;
+
+ TestResult &operator << ( bool 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 );
+ unsigned int getAssertionNestingLevel() const;
+ /// Adds a failure or a predicate context
+ void addFailureInfo( const char *file, unsigned int line,
+ const char *expr, unsigned int nestingLevel );
+ static std::string indentText( const std::string &text,
+ const std::string &indent );
+
+ typedef std::deque<Failure> Failures;
+ Failures failures_;
+ std::string name_;
+ PredicateContext rootPredicateNode_;
+ PredicateContext::Id lastUsedPredicateId_;
+ /// Failure which is the target of the messages added using operator <<
+ Failure *messageTarget_;
+ };
+
+
+ class TestCase
+ {
+ public:
+ TestCase();
+
+ void run( TestResult &result );
+
+ virtual const char *testName() const = 0;
+
+ protected:
+ TestResult *result_;
+
+ private:
+ virtual void runTestCase() = 0;
+ };
+
+ /// Function pointer type for TestCase factory
+ typedef TestCase *(*TestCaseFactory)();
+
+ class Runner
+ {
+ public:
+ Runner();
+
+ /// Adds a test to the suite
+ Runner &add( TestCaseFactory factory );
+
+ /// Runs test as specified on the command-line
+ /// If no command-line arguments are provided, run all tests.
+ /// If --list-tests is provided, then print the list of all test cases
+ /// If --test <testname> is provided, then run test testname.
+ int runCommandLine( int argc, const char *argv[] ) const;
+
+ /// Runs all the test cases
+ bool runAllTest( bool printSummary ) const;
+
+ /// Returns the number of test case in the suite
+ unsigned int testCount() const;
+
+ /// Returns the name of the test case at the specified index
+ std::string testNameAt( unsigned int index ) const;
+
+ /// Runs the test case at the specified index using the specified TestResult
+ void runTestAt( unsigned int index, TestResult &result ) const;
+
+ static void printUsage( const char *appName );
+
+ private: // prevents copy construction and assignment
+ Runner( const Runner &other );
+ Runner &operator =( const Runner &other );
+
+ private:
+ void listTests() const;
+ bool testIndex( const std::string &testName, unsigned int &index ) const;
+ static void preventDialogOnCrash();
+
+ private:
+ typedef std::deque<TestCaseFactory> Factories;
+ Factories tests_;
+ };
+
+ template<typename T>
+ TestResult &
+ checkEqual( TestResult &result, const T &expected, const T &actual,
+ const char *file, unsigned int line, const char *expr )
+ {
+ if ( expected != actual )
+ {
+ result.addFailure( file, line, expr );
+ result << "Expected: " << expected << "\n";
+ result << "Actual : " << actual;
+ }
+ return result;
+ }
+
+ TestResult &
+ checkStringEqual( TestResult &result,
+ const std::string &expected, const std::string &actual,
+ const char *file, unsigned int line, const char *expr );
+
+} // namespace JsonTest
+
+
+/// \brief Asserts that the given expression is true.
+/// JSONTEST_ASSERT( x == y ) << "x=" << x << ", y=" << y;
+/// JSONTEST_ASSERT( x == y );
+#define JSONTEST_ASSERT( expr ) \
+ if ( condition ) \
+ { \
+ } \
+ else \
+ result_->addFailure( __FILE__, __LINE__, #expr )
+
+/// \brief Asserts that the given predicate is true.
+/// The predicate may do other assertions and be a member function of the fixture.
+#define JSONTEST_ASSERT_PRED( expr ) \
+ { \
+ JsonTest::PredicateContext _minitest_Context = { \
+ result_->predicateId_, __FILE__, __LINE__, #expr }; \
+ result_->predicateStackTail_->next_ = &_minitest_Context; \
+ result_->predicateId_ += 1; \
+ result_->predicateStackTail_ = &_minitest_Context; \
+ (expr); \
+ result_->popPredicateContext(); \
+ } \
+ *result_
+
+/// \brief Asserts that two values are equals.
+#define JSONTEST_ASSERT_EQUAL( expected, actual ) \
+ JsonTest::checkEqual( *result_, expected, actual, \
+ __FILE__, __LINE__, \
+ #expected " == " #actual )
+
+/// \brief Asserts that two values are equals.
+#define JSONTEST_ASSERT_STRING_EQUAL( expected, actual ) \
+ JsonTest::checkStringEqual( *result_, \
+ std::string(expected), std::string(actual), \
+ #expected " == " #actual )
+
+/// \brief Begin a fixture test case.
+#define JSONTEST_FIXTURE( FixtureType, name ) \
+ class Test##FixtureType##name : public FixtureType \
+ { \
+ public: \
+ static JsonTest::TestCase *factory() \
+ { \
+ return new Test##FixtureType##name(); \
+ } \
+ public: /* overidden from TestCase */ \
+ virtual const char *testName() const \
+ { \
+ return #FixtureType "/" #name; \
+ } \
+ virtual void runTestCase(); \
+ }; \
+ \
+ void Test##FixtureType##name::runTestCase()
+
+#define JSONTEST_FIXTURE_FACTORY( FixtureType, name ) \
+ &Test##FixtureType##name::factory
+
+#define JSONTEST_REGISTER_FIXTURE( runner, FixtureType, name ) \
+ (runner).add( JSONTEST_FIXTURE_FACTORY( FixtureType, name ) )
+
+#endif // ifndef JSONTEST_H_INCLUDED
diff --git a/lib/jsoncpp/jsoncpp/src/test_lib_json/main.cpp b/lib/jsoncpp/jsoncpp/src/test_lib_json/main.cpp
new file mode 100644
index 0000000000..9864178f66
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/src/test_lib_json/main.cpp
@@ -0,0 +1,244 @@
+#include <json/json.h>
+#include "jsontest.h"
+
+
+// TODO:
+// - boolean value returns that they are integral. Should not be.
+// - unsigned integer in integer range are not considered to be valid integer. Should check range.
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// Json Library test cases
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+
+struct ValueTest : JsonTest::TestCase
+{
+ Json::Value null_;
+ Json::Value emptyArray_;
+ Json::Value emptyObject_;
+ Json::Value integer_;
+ Json::Value unsignedInteger_;
+ Json::Value smallUnsignedInteger_;
+ Json::Value real_;
+ Json::Value array1_;
+ Json::Value object1_;
+ Json::Value emptyString_;
+ Json::Value string1_;
+ Json::Value string_;
+ Json::Value true_;
+ Json::Value false_;
+
+ ValueTest()
+ : emptyArray_( Json::arrayValue )
+ , emptyObject_( Json::objectValue )
+ , integer_( 123456789 )
+ , smallUnsignedInteger_( Json::Value::UInt( Json::Value::maxInt ) )
+ , unsignedInteger_( 34567890u )
+ , real_( 1234.56789 )
+ , emptyString_( "" )
+ , string1_( "a" )
+ , string_( "sometext with space" )
+ , true_( true )
+ , false_( false )
+ {
+ array1_.append( 1234 );
+ object1_["id"] = 1234;
+ }
+
+ struct IsCheck
+ {
+ /// Initialize all checks to \c false by default.
+ IsCheck();
+
+ bool isObject_;
+ bool isArray_;
+ bool isBool_;
+ bool isDouble_;
+ bool isInt_;
+ bool isUInt_;
+ bool isIntegral_;
+ bool isNumeric_;
+ bool isString_;
+ bool isNull_;
+ };
+
+ void checkConstMemberCount( const Json::Value &value, unsigned int expectedCount );
+
+ void checkMemberCount( Json::Value &value, unsigned int expectedCount );
+
+ void checkIs( const Json::Value &value, const IsCheck &check );
+};
+
+
+JSONTEST_FIXTURE( ValueTest, size )
+{
+ JSONTEST_ASSERT_PRED( checkMemberCount(emptyArray_, 0) );
+ JSONTEST_ASSERT_PRED( checkMemberCount(emptyObject_, 0) );
+ JSONTEST_ASSERT_PRED( checkMemberCount(array1_, 1) );
+ JSONTEST_ASSERT_PRED( checkMemberCount(object1_, 1) );
+ JSONTEST_ASSERT_PRED( checkMemberCount(null_, 0) );
+ JSONTEST_ASSERT_PRED( checkMemberCount(integer_, 0) );
+ JSONTEST_ASSERT_PRED( checkMemberCount(real_, 0) );
+ JSONTEST_ASSERT_PRED( checkMemberCount(emptyString_, 0) );
+ JSONTEST_ASSERT_PRED( checkMemberCount(string_, 0) );
+ JSONTEST_ASSERT_PRED( checkMemberCount(true_, 0) );
+}
+
+
+JSONTEST_FIXTURE( ValueTest, isObject )
+{
+ IsCheck checks;
+ checks.isObject_ = true;
+ JSONTEST_ASSERT_PRED( checkIs( emptyObject_, checks ) );
+ JSONTEST_ASSERT_PRED( checkIs( object1_, checks ) );
+}
+
+
+JSONTEST_FIXTURE( ValueTest, isArray )
+{
+ IsCheck checks;
+ checks.isArray_ = true;
+ JSONTEST_ASSERT_PRED( checkIs( emptyArray_, checks ) );
+ JSONTEST_ASSERT_PRED( checkIs( array1_, checks ) );
+}
+
+
+JSONTEST_FIXTURE( ValueTest, isNull )
+{
+ IsCheck checks;
+ checks.isNull_ = true;
+ checks.isObject_ = true;
+ checks.isArray_ = true;
+ JSONTEST_ASSERT_PRED( checkIs( null_, checks ) );
+}
+
+
+JSONTEST_FIXTURE( ValueTest, isString )
+{
+ IsCheck checks;
+ checks.isString_ = true;
+ JSONTEST_ASSERT_PRED( checkIs( emptyString_, checks ) );
+ JSONTEST_ASSERT_PRED( checkIs( string_, checks ) );
+ JSONTEST_ASSERT_PRED( checkIs( string1_, checks ) );
+}
+
+
+JSONTEST_FIXTURE( ValueTest, isBool )
+{
+ IsCheck checks;
+ checks.isBool_ = true;
+ checks.isIntegral_ = true;
+ checks.isNumeric_ = true;
+ JSONTEST_ASSERT_PRED( checkIs( false_, checks ) );
+ JSONTEST_ASSERT_PRED( checkIs( true_, checks ) );
+}
+
+
+JSONTEST_FIXTURE( ValueTest, isDouble )
+{
+ IsCheck checks;
+ checks.isDouble_ = true;
+ checks.isNumeric_ = true;
+ JSONTEST_ASSERT_PRED( checkIs( real_, checks ) );
+}
+
+
+JSONTEST_FIXTURE( ValueTest, isInt )
+{
+ IsCheck checks;
+ checks.isInt_ = true;
+ checks.isNumeric_ = true;
+ checks.isIntegral_ = true;
+ JSONTEST_ASSERT_PRED( checkIs( integer_, checks ) );
+}
+
+
+JSONTEST_FIXTURE( ValueTest, isUInt )
+{
+ IsCheck checks;
+ checks.isUInt_ = true;
+ checks.isNumeric_ = true;
+ checks.isIntegral_ = true;
+ JSONTEST_ASSERT_PRED( checkIs( unsignedInteger_, checks ) );
+ JSONTEST_ASSERT_PRED( checkIs( smallUnsignedInteger_, checks ) );
+}
+
+
+void
+ValueTest::checkConstMemberCount( const Json::Value &value, unsigned int expectedCount )
+{
+ unsigned int count = 0;
+ Json::Value::const_iterator itEnd = value.end();
+ for ( Json::Value::const_iterator it = value.begin(); it != itEnd; ++it )
+ {
+ ++count;
+ }
+ JSONTEST_ASSERT_EQUAL( expectedCount, count ) << "Json::Value::const_iterator";
+}
+
+void
+ValueTest::checkMemberCount( Json::Value &value, unsigned int expectedCount )
+{
+ JSONTEST_ASSERT_EQUAL( expectedCount, value.size() );
+
+ unsigned int count = 0;
+ Json::Value::iterator itEnd = value.end();
+ for ( Json::Value::iterator it = value.begin(); it != itEnd; ++it )
+ {
+ ++count;
+ }
+ JSONTEST_ASSERT_EQUAL( expectedCount, count ) << "Json::Value::iterator";
+
+ JSONTEST_ASSERT_PRED( checkConstMemberCount(value, expectedCount) );
+}
+
+
+ValueTest::IsCheck::IsCheck()
+ : isObject_( false )
+ , isArray_( false )
+ , isBool_( false )
+ , isDouble_( false )
+ , isInt_( false )
+ , isUInt_( false )
+ , isIntegral_( false )
+ , isNumeric_( false )
+ , isString_( false )
+ , isNull_( false )
+{
+}
+
+
+void
+ValueTest::checkIs( const Json::Value &value, const IsCheck &check )
+{
+ JSONTEST_ASSERT_EQUAL( check.isObject_, value.isObject() );
+ JSONTEST_ASSERT_EQUAL( check.isArray_, value.isArray() );
+ JSONTEST_ASSERT_EQUAL( check.isBool_, value.isBool() );
+ JSONTEST_ASSERT_EQUAL( check.isDouble_, value.isDouble() );
+ JSONTEST_ASSERT_EQUAL( check.isInt_, value.isInt() );
+ JSONTEST_ASSERT_EQUAL( check.isUInt_, value.isUInt() );
+ JSONTEST_ASSERT_EQUAL( check.isIntegral_, value.isIntegral() );
+ JSONTEST_ASSERT_EQUAL( check.isNumeric_, value.isNumeric() );
+ JSONTEST_ASSERT_EQUAL( check.isString_, value.isString() );
+ JSONTEST_ASSERT_EQUAL( check.isNull_, value.isNull() );
+}
+
+
+
+int main( int argc, const char *argv[] )
+{
+ JsonTest::Runner runner;
+ JSONTEST_REGISTER_FIXTURE( runner, ValueTest, size );
+ JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isObject );
+ JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isArray );
+ JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isBool );
+ JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isInt );
+ JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isUInt );
+ JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isDouble );
+ JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isString );
+ JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isNull );
+ return runner.runCommandLine( argc, argv );
+}
diff --git a/lib/jsoncpp/jsoncpp/src/test_lib_json/sconscript b/lib/jsoncpp/jsoncpp/src/test_lib_json/sconscript
new file mode 100644
index 0000000000..84f56b6a02
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/src/test_lib_json/sconscript
@@ -0,0 +1,10 @@
+Import( 'env_testing buildUnitTests' )
+
+buildUnitTests( env_testing, Split( """
+ main.cpp
+ jsontest.cpp
+ """ ),
+ 'test_lib_json' )
+
+# For 'check' to work, 'libs' must be built first.
+env_testing.Depends('test_lib_json', '#libs')
diff --git a/lib/jsoncpp/jsoncpp/test/cleantests.py b/lib/jsoncpp/jsoncpp/test/cleantests.py
new file mode 100644
index 0000000000..c38fd8ffdd
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/cleantests.py
@@ -0,0 +1,10 @@
+# removes all files created during testing
+import glob
+import os
+
+paths = []
+for pattern in [ '*.actual', '*.actual-rewrite', '*.rewrite', '*.process-output' ]:
+ paths += glob.glob( 'data/' + pattern )
+
+for path in paths:
+ os.unlink( path )
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_array_01.expected b/lib/jsoncpp/jsoncpp/test/data/test_array_01.expected
new file mode 100644
index 0000000000..a341ff753c
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_array_01.expected
@@ -0,0 +1 @@
+.=[]
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_array_01.json b/lib/jsoncpp/jsoncpp/test/data/test_array_01.json
new file mode 100644
index 0000000000..fe51488c70
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_array_01.json
@@ -0,0 +1 @@
+[]
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_array_02.expected b/lib/jsoncpp/jsoncpp/test/data/test_array_02.expected
new file mode 100644
index 0000000000..ef1f2623de
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_array_02.expected
@@ -0,0 +1,2 @@
+.=[]
+.[0]=1
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_array_02.json b/lib/jsoncpp/jsoncpp/test/data/test_array_02.json
new file mode 100644
index 0000000000..7660873d10
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_array_02.json
@@ -0,0 +1 @@
+[1]
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_array_03.expected b/lib/jsoncpp/jsoncpp/test/data/test_array_03.expected
new file mode 100644
index 0000000000..3d8dc18eb1
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_array_03.expected
@@ -0,0 +1,6 @@
+.=[]
+.[0]=1
+.[1]=2
+.[2]=3
+.[3]=4
+.[4]=5
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_array_03.json b/lib/jsoncpp/jsoncpp/test/data/test_array_03.json
new file mode 100644
index 0000000000..9b3f924755
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_array_03.json
@@ -0,0 +1 @@
+[ 1, 2 , 3,4,5]
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_array_04.expected b/lib/jsoncpp/jsoncpp/test/data/test_array_04.expected
new file mode 100644
index 0000000000..ad4add9794
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_array_04.expected
@@ -0,0 +1,5 @@
+.=[]
+.[0]=1
+.[1]="abc"
+.[2]=12.3
+.[3]=-4
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_array_04.json b/lib/jsoncpp/jsoncpp/test/data/test_array_04.json
new file mode 100644
index 0000000000..ecca546b2c
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_array_04.json
@@ -0,0 +1 @@
+[1, "abc" , 12.3, -4]
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_array_05.expected b/lib/jsoncpp/jsoncpp/test/data/test_array_05.expected
new file mode 100644
index 0000000000..76cff87c2a
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_array_05.expected
@@ -0,0 +1,100 @@
+.=[]
+.[0]=1
+.[1]=2
+.[2]=3
+.[3]=4
+.[4]=5
+.[5]=6
+.[6]=7
+.[7]=8
+.[8]=9
+.[9]=10
+.[10]=11
+.[11]=12
+.[12]=13
+.[13]=14
+.[14]=15
+.[15]=16
+.[16]=17
+.[17]=18
+.[18]=19
+.[19]=20
+.[20]=21
+.[21]=22
+.[22]=23
+.[23]=24
+.[24]=25
+.[25]=26
+.[26]=27
+.[27]=28
+.[28]=29
+.[29]=30
+.[30]=31
+.[31]=32
+.[32]=33
+.[33]=34
+.[34]=35
+.[35]=36
+.[36]=37
+.[37]=38
+.[38]=39
+.[39]=40
+.[40]=41
+.[41]=42
+.[42]=43
+.[43]=44
+.[44]=45
+.[45]=46
+.[46]=47
+.[47]=48
+.[48]=49
+.[49]=50
+.[50]=51
+.[51]=52
+.[52]=53
+.[53]=54
+.[54]=55
+.[55]=56
+.[56]=57
+.[57]=58
+.[58]=59
+.[59]=60
+.[60]=61
+.[61]=62
+.[62]=63
+.[63]=64
+.[64]=65
+.[65]=66
+.[66]=67
+.[67]=68
+.[68]=69
+.[69]=70
+.[70]=71
+.[71]=72
+.[72]=73
+.[73]=74
+.[74]=75
+.[75]=76
+.[76]=77
+.[77]=78
+.[78]=79
+.[79]=80
+.[80]=81
+.[81]=82
+.[82]=83
+.[83]=84
+.[84]=85
+.[85]=86
+.[86]=87
+.[87]=88
+.[88]=89
+.[89]=90
+.[90]=91
+.[91]=92
+.[92]=93
+.[93]=94
+.[94]=95
+.[95]=96
+.[96]=97
+.[97]=98
+.[98]=99
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_array_05.json b/lib/jsoncpp/jsoncpp/test/data/test_array_05.json
new file mode 100644
index 0000000000..7809d6c9a1
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_array_05.json
@@ -0,0 +1 @@
+[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99] \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_array_06.expected b/lib/jsoncpp/jsoncpp/test/data/test_array_06.expected
new file mode 100644
index 0000000000..5c9f48eaac
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_array_06.expected
@@ -0,0 +1,5 @@
+.=[]
+.[0]="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+.[1]="bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
+.[2]="ccccccccccccccccccccccc"
+.[3]="dddddddddddddddddddddddddddddddddddddddddddddddddddd"
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_array_06.json b/lib/jsoncpp/jsoncpp/test/data/test_array_06.json
new file mode 100644
index 0000000000..7f6c516afd
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_array_06.json
@@ -0,0 +1,4 @@
+[ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+ "ccccccccccccccccccccccc",
+ "dddddddddddddddddddddddddddddddddddddddddddddddddddd" ] \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_basic_01.expected b/lib/jsoncpp/jsoncpp/test/data/test_basic_01.expected
new file mode 100644
index 0000000000..d761fce1cc
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_basic_01.expected
@@ -0,0 +1 @@
+.=123456789
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_basic_01.json b/lib/jsoncpp/jsoncpp/test/data/test_basic_01.json
new file mode 100644
index 0000000000..11f11f9be3
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_basic_01.json
@@ -0,0 +1 @@
+0123456789
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_basic_02.expected b/lib/jsoncpp/jsoncpp/test/data/test_basic_02.expected
new file mode 100644
index 0000000000..650e37cbaa
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_basic_02.expected
@@ -0,0 +1 @@
+.=-123456789
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_basic_02.json b/lib/jsoncpp/jsoncpp/test/data/test_basic_02.json
new file mode 100644
index 0000000000..bf11bceac7
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_basic_02.json
@@ -0,0 +1 @@
+-0123456789
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_basic_03.expected b/lib/jsoncpp/jsoncpp/test/data/test_basic_03.expected
new file mode 100644
index 0000000000..1da2d395b8
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_basic_03.expected
@@ -0,0 +1,3 @@
+.=1.2345678
+
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_basic_03.json b/lib/jsoncpp/jsoncpp/test/data/test_basic_03.json
new file mode 100644
index 0000000000..a92b6bd28b
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_basic_03.json
@@ -0,0 +1,3 @@
+1.2345678
+
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_basic_04.expected b/lib/jsoncpp/jsoncpp/test/data/test_basic_04.expected
new file mode 100644
index 0000000000..013f424f93
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_basic_04.expected
@@ -0,0 +1,2 @@
+.="abcdef"
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_basic_04.json b/lib/jsoncpp/jsoncpp/test/data/test_basic_04.json
new file mode 100644
index 0000000000..17eeb99e0b
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_basic_04.json
@@ -0,0 +1,2 @@
+"abcdef"
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_basic_05.expected b/lib/jsoncpp/jsoncpp/test/data/test_basic_05.expected
new file mode 100644
index 0000000000..c8db822e58
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_basic_05.expected
@@ -0,0 +1,2 @@
+.=null
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_basic_05.json b/lib/jsoncpp/jsoncpp/test/data/test_basic_05.json
new file mode 100644
index 0000000000..d0aaea2126
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_basic_05.json
@@ -0,0 +1,2 @@
+null
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_basic_06.expected b/lib/jsoncpp/jsoncpp/test/data/test_basic_06.expected
new file mode 100644
index 0000000000..49be55a965
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_basic_06.expected
@@ -0,0 +1,2 @@
+.=true
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_basic_06.json b/lib/jsoncpp/jsoncpp/test/data/test_basic_06.json
new file mode 100644
index 0000000000..7eead1ee75
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_basic_06.json
@@ -0,0 +1,2 @@
+true
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_basic_07.expected b/lib/jsoncpp/jsoncpp/test/data/test_basic_07.expected
new file mode 100644
index 0000000000..fe55a6a854
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_basic_07.expected
@@ -0,0 +1,2 @@
+.=false
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_basic_07.json b/lib/jsoncpp/jsoncpp/test/data/test_basic_07.json
new file mode 100644
index 0000000000..a864bc487d
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_basic_07.json
@@ -0,0 +1,2 @@
+false
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_basic_08.expected b/lib/jsoncpp/jsoncpp/test/data/test_basic_08.expected
new file mode 100644
index 0000000000..c8db822e58
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_basic_08.expected
@@ -0,0 +1,2 @@
+.=null
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_basic_08.json b/lib/jsoncpp/jsoncpp/test/data/test_basic_08.json
new file mode 100644
index 0000000000..fd78837c0c
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_basic_08.json
@@ -0,0 +1,3 @@
+// C++ style comment
+null
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_basic_09.expected b/lib/jsoncpp/jsoncpp/test/data/test_basic_09.expected
new file mode 100644
index 0000000000..c8db822e58
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_basic_09.expected
@@ -0,0 +1,2 @@
+.=null
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_basic_09.json b/lib/jsoncpp/jsoncpp/test/data/test_basic_09.json
new file mode 100644
index 0000000000..fc95f0f514
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_basic_09.json
@@ -0,0 +1,4 @@
+/* C style comment
+ */
+null
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_comment_01.expected b/lib/jsoncpp/jsoncpp/test/data/test_comment_01.expected
new file mode 100644
index 0000000000..0b8f42d504
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_comment_01.expected
@@ -0,0 +1,8 @@
+.={}
+.test=[]
+.test[0]={}
+.test[0].a="aaa"
+.test[1]={}
+.test[1].b="bbb"
+.test[2]={}
+.test[2].c="ccc"
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_comment_01.json b/lib/jsoncpp/jsoncpp/test/data/test_comment_01.json
new file mode 100644
index 0000000000..0de8f9cf73
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_comment_01.json
@@ -0,0 +1,8 @@
+{
+ "test":
+ [
+ { "a" : "aaa" }, // Comment for a
+ { "b" : "bbb" }, // Comment for b
+ { "c" : "ccc" } // Comment for c
+ ]
+}
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_complex_01.expected b/lib/jsoncpp/jsoncpp/test/data/test_complex_01.expected
new file mode 100644
index 0000000000..7573c8812d
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_complex_01.expected
@@ -0,0 +1,20 @@
+.={}
+.attribute=[]
+.attribute[0]="random"
+.attribute[1]="short"
+.attribute[2]="bold"
+.attribute[3]=12
+.attribute[4]={}
+.attribute[4].height=7
+.attribute[4].width=64
+.count=1234
+.name={}
+.name.aka="T.E.S.T."
+.name.id=123987
+.test={}
+.test.1={}
+.test.1.2={}
+.test.1.2.3={}
+.test.1.2.3.coord=[]
+.test.1.2.3.coord[0]=1
+.test.1.2.3.coord[1]=2
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_complex_01.json b/lib/jsoncpp/jsoncpp/test/data/test_complex_01.json
new file mode 100644
index 0000000000..cc0f30f5c3
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_complex_01.json
@@ -0,0 +1,17 @@
+{
+ "count" : 1234,
+ "name" : { "aka" : "T.E.S.T.", "id" : 123987 },
+ "attribute" : [
+ "random",
+ "short",
+ "bold",
+ 12,
+ { "height" : 7, "width" : 64 }
+ ],
+ "test": { "1" :
+ { "2" :
+ { "3" : { "coord" : [ 1,2] }
+ }
+ }
+ }
+}
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_integer_01.expected b/lib/jsoncpp/jsoncpp/test/data/test_integer_01.expected
new file mode 100644
index 0000000000..593f1db32b
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_integer_01.expected
@@ -0,0 +1 @@
+.=2147483647
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_integer_01.json b/lib/jsoncpp/jsoncpp/test/data/test_integer_01.json
new file mode 100644
index 0000000000..5ab12ffee4
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_integer_01.json
@@ -0,0 +1,2 @@
+// Max signed integer
+2147483647
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_integer_02.expected b/lib/jsoncpp/jsoncpp/test/data/test_integer_02.expected
new file mode 100644
index 0000000000..4b83bd7cae
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_integer_02.expected
@@ -0,0 +1 @@
+.=-2147483648
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_integer_02.json b/lib/jsoncpp/jsoncpp/test/data/test_integer_02.json
new file mode 100644
index 0000000000..056c850065
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_integer_02.json
@@ -0,0 +1,2 @@
+// Min signed integer
+-2147483648
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_integer_03.expected b/lib/jsoncpp/jsoncpp/test/data/test_integer_03.expected
new file mode 100644
index 0000000000..37c1cb146b
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_integer_03.expected
@@ -0,0 +1 @@
+.=4294967295
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_integer_03.json b/lib/jsoncpp/jsoncpp/test/data/test_integer_03.json
new file mode 100644
index 0000000000..12ef3fbb89
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_integer_03.json
@@ -0,0 +1,2 @@
+// Max unsigned integer
+4294967295
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_integer_04.expected b/lib/jsoncpp/jsoncpp/test/data/test_integer_04.expected
new file mode 100644
index 0000000000..b7b548e3d3
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_integer_04.expected
@@ -0,0 +1,2 @@
+.=0
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_integer_04.json b/lib/jsoncpp/jsoncpp/test/data/test_integer_04.json
new file mode 100644
index 0000000000..bf81499453
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_integer_04.json
@@ -0,0 +1,3 @@
+// Min unsigned integer
+0
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_integer_05.expected b/lib/jsoncpp/jsoncpp/test/data/test_integer_05.expected
new file mode 100644
index 0000000000..0caea9d3fd
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_integer_05.expected
@@ -0,0 +1,2 @@
+.=1
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_integer_05.json b/lib/jsoncpp/jsoncpp/test/data/test_integer_05.json
new file mode 100644
index 0000000000..d474e1b4d6
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_integer_05.json
@@ -0,0 +1,2 @@
+1
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_object_01.expected b/lib/jsoncpp/jsoncpp/test/data/test_object_01.expected
new file mode 100644
index 0000000000..67444e5794
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_object_01.expected
@@ -0,0 +1 @@
+.={}
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_object_01.json b/lib/jsoncpp/jsoncpp/test/data/test_object_01.json
new file mode 100644
index 0000000000..0967ef424b
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_object_01.json
@@ -0,0 +1 @@
+{}
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_object_02.expected b/lib/jsoncpp/jsoncpp/test/data/test_object_02.expected
new file mode 100644
index 0000000000..79391c2a6c
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_object_02.expected
@@ -0,0 +1,2 @@
+.={}
+.count=1234
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_object_02.json b/lib/jsoncpp/jsoncpp/test/data/test_object_02.json
new file mode 100644
index 0000000000..d0f2facac3
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_object_02.json
@@ -0,0 +1 @@
+{ "count" : 1234 }
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_object_03.expected b/lib/jsoncpp/jsoncpp/test/data/test_object_03.expected
new file mode 100644
index 0000000000..5e96113792
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_object_03.expected
@@ -0,0 +1,4 @@
+.={}
+.attribute="random"
+.count=1234
+.name="test"
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_object_03.json b/lib/jsoncpp/jsoncpp/test/data/test_object_03.json
new file mode 100644
index 0000000000..4fcd4d821d
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_object_03.json
@@ -0,0 +1,5 @@
+{
+ "count" : 1234,
+ "name" : "test",
+ "attribute" : "random"
+}
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_object_04.expected b/lib/jsoncpp/jsoncpp/test/data/test_object_04.expected
new file mode 100644
index 0000000000..812965b0ca
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_object_04.expected
@@ -0,0 +1,2 @@
+.={}
+.=1234
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_object_04.json b/lib/jsoncpp/jsoncpp/test/data/test_object_04.json
new file mode 100644
index 0000000000..450762d71e
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_object_04.json
@@ -0,0 +1,3 @@
+{
+ "" : 1234
+}
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_preserve_comment_01.expected b/lib/jsoncpp/jsoncpp/test/data/test_preserve_comment_01.expected
new file mode 100644
index 0000000000..8d88041086
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_preserve_comment_01.expected
@@ -0,0 +1,3 @@
+.={}
+.first=1
+.second=2
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_preserve_comment_01.json b/lib/jsoncpp/jsoncpp/test/data/test_preserve_comment_01.json
new file mode 100644
index 0000000000..fabd55dd96
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_preserve_comment_01.json
@@ -0,0 +1,14 @@
+/* A comment
+ at the beginning of the file.
+ */
+{
+ "first" : 1, // comment after 'first' on the same line
+
+/* Comment before 'second'
+ */
+ "second" : 2
+}
+
+/* A comment at
+ the end of the file.
+ */
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_real_01.expected b/lib/jsoncpp/jsoncpp/test/data/test_real_01.expected
new file mode 100644
index 0000000000..ae2357231e
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_real_01.expected
@@ -0,0 +1,2 @@
+.=8589934592
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_real_01.json b/lib/jsoncpp/jsoncpp/test/data/test_real_01.json
new file mode 100644
index 0000000000..358452d387
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_real_01.json
@@ -0,0 +1,3 @@
+// 2^33 => out of integer range, switch to double
+8589934592
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_real_02.expected b/lib/jsoncpp/jsoncpp/test/data/test_real_02.expected
new file mode 100644
index 0000000000..df8de42109
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_real_02.expected
@@ -0,0 +1,2 @@
+.=-4294967295
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_real_02.json b/lib/jsoncpp/jsoncpp/test/data/test_real_02.json
new file mode 100644
index 0000000000..936c706b68
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_real_02.json
@@ -0,0 +1,3 @@
+// -2^32 => out of signed integer range, switch to double
+-4294967295
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_real_03.expected b/lib/jsoncpp/jsoncpp/test/data/test_real_03.expected
new file mode 100644
index 0000000000..df8de42109
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_real_03.expected
@@ -0,0 +1,2 @@
+.=-4294967295
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_real_03.json b/lib/jsoncpp/jsoncpp/test/data/test_real_03.json
new file mode 100644
index 0000000000..936c706b68
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_real_03.json
@@ -0,0 +1,3 @@
+// -2^32 => out of signed integer range, switch to double
+-4294967295
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_real_04.expected b/lib/jsoncpp/jsoncpp/test/data/test_real_04.expected
new file mode 100644
index 0000000000..d726abe40b
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_real_04.expected
@@ -0,0 +1,2 @@
+.=1.2345678
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_real_04.json b/lib/jsoncpp/jsoncpp/test/data/test_real_04.json
new file mode 100644
index 0000000000..a8eb6d0c92
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_real_04.json
@@ -0,0 +1,3 @@
+// 1.2345678
+12345678e-7
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_real_05.expected b/lib/jsoncpp/jsoncpp/test/data/test_real_05.expected
new file mode 100644
index 0000000000..949fd8f55d
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_real_05.expected
@@ -0,0 +1,3 @@
+.=1234567.8
+
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_real_05.json b/lib/jsoncpp/jsoncpp/test/data/test_real_05.json
new file mode 100644
index 0000000000..f7923bab89
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_real_05.json
@@ -0,0 +1,3 @@
+// 1234567.8
+0.12345678e7
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_real_06.expected b/lib/jsoncpp/jsoncpp/test/data/test_real_06.expected
new file mode 100644
index 0000000000..03b7d7f987
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_real_06.expected
@@ -0,0 +1,3 @@
+.=-1.2345678
+
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_real_06.json b/lib/jsoncpp/jsoncpp/test/data/test_real_06.json
new file mode 100644
index 0000000000..485419a276
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_real_06.json
@@ -0,0 +1,3 @@
+// -1.2345678
+-12345678e-7
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_real_07.expected b/lib/jsoncpp/jsoncpp/test/data/test_real_07.expected
new file mode 100644
index 0000000000..12025a404b
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_real_07.expected
@@ -0,0 +1,3 @@
+.=-1234567.8
+
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_real_07.json b/lib/jsoncpp/jsoncpp/test/data/test_real_07.json
new file mode 100644
index 0000000000..8013eb5c9a
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_real_07.json
@@ -0,0 +1,3 @@
+// -1234567.8
+-0.12345678e7
+
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_string_01.expected b/lib/jsoncpp/jsoncpp/test/data/test_string_01.expected
new file mode 100644
index 0000000000..8fd37b1e0e
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_string_01.expected
@@ -0,0 +1 @@
+.="!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~" \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_string_01.json b/lib/jsoncpp/jsoncpp/test/data/test_string_01.json
new file mode 100644
index 0000000000..c8c059ba5e
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_string_01.json
@@ -0,0 +1 @@
+"!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_string_02.expected b/lib/jsoncpp/jsoncpp/test/data/test_string_02.expected
new file mode 100644
index 0000000000..0443bc3649
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_string_02.expected
@@ -0,0 +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{|}~" \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_string_02.json b/lib/jsoncpp/jsoncpp/test/data/test_string_02.json
new file mode 100644
index 0000000000..f0fe56a650
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_string_02.json
@@ -0,0 +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{|}~"
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_01.expected b/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_01.expected
new file mode 100644
index 0000000000..447f85a30f
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_01.expected
@@ -0,0 +1 @@
+.="a"
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_01.json b/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_01.json
new file mode 100644
index 0000000000..024114bc09
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_01.json
@@ -0,0 +1 @@
+"\u0061" \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_02.expected b/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_02.expected
new file mode 100644
index 0000000000..c0b3b43ba3
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_02.expected
@@ -0,0 +1 @@
+.="¢"
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_02.json b/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_02.json
new file mode 100644
index 0000000000..4961024fab
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_02.json
@@ -0,0 +1 @@
+"\u00A2" \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_03.expected b/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_03.expected
new file mode 100644
index 0000000000..7289743ecf
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_03.expected
@@ -0,0 +1 @@
+.="€"
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_03.json b/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_03.json
new file mode 100644
index 0000000000..e7e1a9e138
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_03.json
@@ -0,0 +1 @@
+"\u20AC" \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_04.expected b/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_04.expected
new file mode 100644
index 0000000000..868fbc3309
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_04.expected
@@ -0,0 +1 @@
+.="𝄞"
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_04.json b/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_04.json
new file mode 100644
index 0000000000..dae65c5155
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_04.json
@@ -0,0 +1 @@
+"\uD834\uDD1E" \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_05.expected b/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_05.expected
new file mode 100644
index 0000000000..e78506524c
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_05.expected
@@ -0,0 +1 @@
+.="za\u017c\u00f3\u0142\u0107 g\u0119\u015bl\u0105 ja\u017a\u0144" \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_05.json b/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_05.json
new file mode 100644
index 0000000000..8770410946
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/data/test_string_unicode_05.json
@@ -0,0 +1 @@
+"Zażółć gęślą jaźń" \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/generate_expected.py b/lib/jsoncpp/jsoncpp/test/generate_expected.py
new file mode 100644
index 0000000000..5b215c4670
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/generate_expected.py
@@ -0,0 +1,11 @@
+import glob
+import os.path
+for path in glob.glob( '*.json' ):
+ text = file(path,'rt').read()
+ target = os.path.splitext(path)[0] + '.expected'
+ if os.path.exists( target ):
+ print 'skipping:', target
+ else:
+ print 'creating:', target
+ file(target,'wt').write(text)
+
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail1.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail1.json
new file mode 100644
index 0000000000..6216b865f1
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail1.json
@@ -0,0 +1 @@
+"A JSON payload should be an object or array, not a string." \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail10.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail10.json
new file mode 100644
index 0000000000..5d8c0047bd
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail10.json
@@ -0,0 +1 @@
+{"Extra value after close": true} "misplaced quoted value" \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail11.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail11.json
new file mode 100644
index 0000000000..76eb95b458
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail11.json
@@ -0,0 +1 @@
+{"Illegal expression": 1 + 2} \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail12.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail12.json
new file mode 100644
index 0000000000..77580a4522
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail12.json
@@ -0,0 +1 @@
+{"Illegal invocation": alert()} \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail13.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail13.json
new file mode 100644
index 0000000000..379406b59b
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail13.json
@@ -0,0 +1 @@
+{"Numbers cannot have leading zeroes": 013} \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail14.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail14.json
new file mode 100644
index 0000000000..0ed366b38a
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail14.json
@@ -0,0 +1 @@
+{"Numbers cannot be hex": 0x14} \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail15.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail15.json
new file mode 100644
index 0000000000..fc8376b605
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail15.json
@@ -0,0 +1 @@
+["Illegal backslash escape: \x15"] \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail16.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail16.json
new file mode 100644
index 0000000000..3fe21d4b53
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail16.json
@@ -0,0 +1 @@
+[\naked] \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail17.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail17.json
new file mode 100644
index 0000000000..62b9214aed
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail17.json
@@ -0,0 +1 @@
+["Illegal backslash escape: \017"] \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail18.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail18.json
new file mode 100644
index 0000000000..edac92716f
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail18.json
@@ -0,0 +1 @@
+[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]] \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail19.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail19.json
new file mode 100644
index 0000000000..3b9c46fa9a
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail19.json
@@ -0,0 +1 @@
+{"Missing colon" null} \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail2.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail2.json
new file mode 100644
index 0000000000..6b7c11e5a5
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail2.json
@@ -0,0 +1 @@
+["Unclosed array" \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail20.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail20.json
new file mode 100644
index 0000000000..27c1af3e72
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail20.json
@@ -0,0 +1 @@
+{"Double colon":: null} \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail21.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail21.json
new file mode 100644
index 0000000000..62474573b2
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail21.json
@@ -0,0 +1 @@
+{"Comma instead of colon", null} \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail22.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail22.json
new file mode 100644
index 0000000000..a7752581bc
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail22.json
@@ -0,0 +1 @@
+["Colon instead of comma": false] \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail23.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail23.json
new file mode 100644
index 0000000000..494add1ca1
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail23.json
@@ -0,0 +1 @@
+["Bad value", truth] \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail24.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail24.json
new file mode 100644
index 0000000000..caff239bfc
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail24.json
@@ -0,0 +1 @@
+['single quote'] \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail25.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail25.json
new file mode 100644
index 0000000000..8b7ad23e01
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail25.json
@@ -0,0 +1 @@
+[" tab character in string "] \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail26.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail26.json
new file mode 100644
index 0000000000..845d26a6a5
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail26.json
@@ -0,0 +1 @@
+["tab\ character\ in\ string\ "] \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail27.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail27.json
new file mode 100644
index 0000000000..6b01a2ca4a
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail27.json
@@ -0,0 +1,2 @@
+["line
+break"] \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail28.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail28.json
new file mode 100644
index 0000000000..621a0101c6
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail28.json
@@ -0,0 +1,2 @@
+["line\
+break"] \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail29.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail29.json
new file mode 100644
index 0000000000..47ec421bb6
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail29.json
@@ -0,0 +1 @@
+[0e] \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail3.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail3.json
new file mode 100644
index 0000000000..168c81eb78
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail3.json
@@ -0,0 +1 @@
+{unquoted_key: "keys must be quoted"} \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail30.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail30.json
new file mode 100644
index 0000000000..8ab0bc4b8b
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail30.json
@@ -0,0 +1 @@
+[0e+] \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail31.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail31.json
new file mode 100644
index 0000000000..1cce602b51
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail31.json
@@ -0,0 +1 @@
+[0e+-1] \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail32.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail32.json
new file mode 100644
index 0000000000..45cba7396f
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail32.json
@@ -0,0 +1 @@
+{"Comma instead if closing brace": true, \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail33.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail33.json
new file mode 100644
index 0000000000..ca5eb19dc9
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail33.json
@@ -0,0 +1 @@
+["mismatch"} \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail4.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail4.json
new file mode 100644
index 0000000000..9de168bf34
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail4.json
@@ -0,0 +1 @@
+["extra comma",] \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail5.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail5.json
new file mode 100644
index 0000000000..ddf3ce3d24
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail5.json
@@ -0,0 +1 @@
+["double extra comma",,] \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail6.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail6.json
new file mode 100644
index 0000000000..ed91580e1b
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail6.json
@@ -0,0 +1 @@
+[ , "<-- missing value"] \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail7.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail7.json
new file mode 100644
index 0000000000..8a96af3e4e
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail7.json
@@ -0,0 +1 @@
+["Comma after the close"], \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail8.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail8.json
new file mode 100644
index 0000000000..b28479c6ec
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail8.json
@@ -0,0 +1 @@
+["Extra close"]] \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/fail9.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail9.json
new file mode 100644
index 0000000000..5815574f36
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/fail9.json
@@ -0,0 +1 @@
+{"Extra comma": true,} \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/pass1.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/pass1.json
new file mode 100644
index 0000000000..70e2685436
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/pass1.json
@@ -0,0 +1,58 @@
+[
+ "JSON Test Pattern pass1",
+ {"object with 1 member":["array with 1 element"]},
+ {},
+ [],
+ -42,
+ true,
+ false,
+ null,
+ {
+ "integer": 1234567890,
+ "real": -9876.543210,
+ "e": 0.123456789e-12,
+ "E": 1.234567890E+34,
+ "": 23456789012E66,
+ "zero": 0,
+ "one": 1,
+ "space": " ",
+ "quote": "\"",
+ "backslash": "\\",
+ "controls": "\b\f\n\r\t",
+ "slash": "/ & \/",
+ "alpha": "abcdefghijklmnopqrstuvwyz",
+ "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ",
+ "digit": "0123456789",
+ "0123456789": "digit",
+ "special": "`1~!@#$%^&*()_+-={':[,]}|;.</>?",
+ "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A",
+ "true": true,
+ "false": false,
+ "null": null,
+ "array":[ ],
+ "object":{ },
+ "address": "50 St. James Street",
+ "url": "http://www.JSON.org/",
+ "comment": "// /* <!-- --",
+ "# -- --> */": " ",
+ " s p a c e d " :[1,2 , 3
+
+,
+
+4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7],
+ "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}",
+ "quotes": "&#34; \u0022 %22 0x22 034 &#x22;",
+ "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"
+: "A key can be any string"
+ },
+ 0.5 ,98.6
+,
+99.44
+,
+
+1066,
+1e1,
+0.1e1,
+1e-1,
+1e00,2e+00,2e-00
+,"rosebud"] \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/pass2.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/pass2.json
new file mode 100644
index 0000000000..d3c63c7ad8
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/pass2.json
@@ -0,0 +1 @@
+[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]] \ No newline at end of file
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/pass3.json b/lib/jsoncpp/jsoncpp/test/jsonchecker/pass3.json
new file mode 100644
index 0000000000..4528d51f1a
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/pass3.json
@@ -0,0 +1,6 @@
+{
+ "JSON Test Pattern pass3": {
+ "The outermost value": "must be an object or array.",
+ "In this test": "It is an object."
+ }
+}
diff --git a/lib/jsoncpp/jsoncpp/test/jsonchecker/readme.txt b/lib/jsoncpp/jsoncpp/test/jsonchecker/readme.txt
new file mode 100644
index 0000000000..0efc2a4477
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsonchecker/readme.txt
@@ -0,0 +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.
diff --git a/lib/jsoncpp/jsoncpp/test/jsontestrunner.py b/lib/jsoncpp/jsoncpp/test/jsontestrunner.py
new file mode 100644
index 0000000000..504f3db2e7
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/jsontestrunner.py
@@ -0,0 +1,64 @@
+# Simple implementation of a json test runner to run the test against json-py.
+
+import sys
+import os.path
+import json
+import types
+
+if len(sys.argv) != 2:
+ print "Usage: %s input-json-file", sys.argv[0]
+ sys.exit(3)
+
+input_path = sys.argv[1]
+base_path = os.path.splitext(input_path)[0]
+actual_path = base_path + '.actual'
+rewrite_path = base_path + '.rewrite'
+rewrite_actual_path = base_path + '.actual-rewrite'
+
+def valueTreeToString( fout, value, path = '.' ):
+ ty = type(value)
+ if ty is types.DictType:
+ fout.write( '%s={}\n' % path )
+ suffix = path[-1] != '.' and '.' or ''
+ names = value.keys()
+ names.sort()
+ for name in names:
+ valueTreeToString( fout, value[name], path + suffix + name )
+ elif ty is types.ListType:
+ fout.write( '%s=[]\n' % path )
+ for index, childValue in zip( xrange(0,len(value)), value ):
+ valueTreeToString( fout, childValue, path + '[%d]' % index )
+ elif ty is types.StringType:
+ fout.write( '%s="%s"\n' % (path,value) )
+ elif ty is types.IntType:
+ fout.write( '%s=%d\n' % (path,value) )
+ elif ty is types.FloatType:
+ fout.write( '%s=%.16g\n' % (path,value) )
+ elif value is True:
+ fout.write( '%s=true\n' % path )
+ elif value is False:
+ fout.write( '%s=false\n' % path )
+ elif value is None:
+ fout.write( '%s=null\n' % path )
+ else:
+ assert False and "Unexpected value type"
+
+def parseAndSaveValueTree( input, actual_path ):
+ root = json.loads( input )
+ fout = file( actual_path, 'wt' )
+ valueTreeToString( fout, root )
+ fout.close()
+ return root
+
+def rewriteValueTree( value, rewrite_path ):
+ rewrite = json.dumps( value )
+ #rewrite = rewrite[1:-1] # Somehow the string is quoted ! jsonpy bug ?
+ file( rewrite_path, 'wt').write( rewrite + '\n' )
+ return rewrite
+
+input = file( input_path, 'rt' ).read()
+root = parseAndSaveValueTree( input, actual_path )
+rewrite = rewriteValueTree( json.write( root ), rewrite_path )
+rewrite_root = parseAndSaveValueTree( rewrite, rewrite_actual_path )
+
+sys.exit( 0 )
diff --git a/lib/jsoncpp/jsoncpp/test/runjsontests.py b/lib/jsoncpp/jsoncpp/test/runjsontests.py
new file mode 100644
index 0000000000..e05bd52b48
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/runjsontests.py
@@ -0,0 +1,132 @@
+import sys
+import os
+import os.path
+from glob import glob
+import optparse
+
+RUN_JSONCHECKER = False
+VALGRIND_CMD = 'valgrind --tool=memcheck --leak-check=yes --undef-value-errors=yes '
+
+def compareOutputs( expected, actual, message ):
+ expected = expected.strip().replace('\r','').split('\n')
+ actual = actual.strip().replace('\r','').split('\n')
+ diff_line = 0
+ max_line_to_compare = min( len(expected), len(actual) )
+ for index in xrange(0,max_line_to_compare):
+ if expected[index].strip() != actual[index].strip():
+ diff_line = index + 1
+ break
+ if diff_line == 0 and len(expected) != len(actual):
+ diff_line = max_line_to_compare+1
+ if diff_line == 0:
+ return None
+ def safeGetLine( lines, index ):
+ index += -1
+ if index >= len(lines):
+ return ''
+ return lines[index].strip()
+ return """ Difference in %s at line %d:
+ Expected: '%s'
+ Actual: '%s'
+""" % (message, diff_line,
+ safeGetLine(expected,diff_line),
+ safeGetLine(actual,diff_line) )
+
+def safeReadFile( path ):
+ try:
+ return file( path, 'rt' ).read()
+ except IOError, e:
+ return '<File "%s" is missing: %s>' % (path,e)
+
+def runAllTests( jsontest_executable_path, input_dir = None,
+ use_valgrind=False ):
+ if not input_dir:
+ input_dir = os.path.join( os.getcwd(), 'data' )
+ tests = glob( os.path.join( input_dir, '*.json' ) )
+ if RUN_JSONCHECKER:
+ test_jsonchecker = glob( os.path.join( input_dir, 'jsonchecker', '*.json' ) )
+ else:
+ test_jsonchecker = []
+ failed_tests = []
+ valgrind_path = use_valgrind and VALGRIND_CMD or ''
+ for input_path in tests + test_jsonchecker:
+ 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" % (
+ valgrind_path, jsontest_executable_path, options,
+ input_path) )
+ 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'
+ failed_tests.append( (input_path, 'Parsing should have failed:\n%s' %
+ safeReadFile(input_path)) )
+ else:
+ print 'OK'
+ else:
+ if status is not None:
+ print 'FAILED'
+ failed_tests.append( (input_path, 'Parsing failed:\n' + process_output) )
+ else:
+ print 'OK'
+ else:
+ base_path = os.path.splitext(input_path)[0]
+ actual_output = safeReadFile( base_path + '.actual' )
+ actual_rewrite_output = safeReadFile( base_path + '.actual-rewrite' )
+ file(base_path + '.process-output','wt').write( process_output )
+ if status:
+ print 'parsing failed'
+ failed_tests.append( (input_path, 'Parsing failed:\n' + process_output) )
+ else:
+ expected_output_path = os.path.splitext(input_path)[0] + '.expected'
+ expected_output = file( expected_output_path, 'rt' ).read()
+ detail = ( compareOutputs( expected_output, actual_output, 'input' )
+ or compareOutputs( expected_output, actual_rewrite_output, 'rewrite' ) )
+ if detail:
+ print 'FAILED'
+ failed_tests.append( (input_path, detail) )
+ else:
+ print 'OK'
+
+ if failed_tests:
+ print
+ print 'Failure details:'
+ for failed_test in failed_tests:
+ print '* Test', failed_test[0]
+ print failed_test[1]
+ print
+ print 'Test results: %d passed, %d failed.' % (len(tests)-len(failed_tests),
+ len(failed_tests) )
+ return 1
+ else:
+ print 'All %d tests passed.' % len(tests)
+ return 0
+
+def main():
+ from optparse import OptionParser
+ parser = OptionParser( usage="%prog [options] <path to jsontestrunner.exe> [test case directory]" )
+ 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 or len(args) > 2:
+ parser.error( 'Must provides at least path to jsontestrunner executable.' )
+ sys.exit( 1 )
+
+ jsontest_executable_path = os.path.normpath( os.path.abspath( args[0] ) )
+ if len(args) > 1:
+ input_path = os.path.normpath( os.path.abspath( args[1] ) )
+ else:
+ input_path = None
+ status = runAllTests( jsontest_executable_path, input_path,
+ use_valgrind=options.valgrind )
+ sys.exit( status )
+
+if __name__ == '__main__':
+ main()
diff --git a/lib/jsoncpp/jsoncpp/test/rununittests.py b/lib/jsoncpp/jsoncpp/test/rununittests.py
new file mode 100644
index 0000000000..ccc54e45a3
--- /dev/null
+++ b/lib/jsoncpp/jsoncpp/test/rununittests.py
@@ -0,0 +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()