Compare commits

..

3 Commits
1.3.0 ... 0.7.0

Author SHA1 Message Date
Christopher Dunn
15949af098 0.7.0 2014-11-20 08:48:22 -06:00
Christopher Dunn
8dc52b3cca 0.7.0 2014-11-20 00:18:47 -06:00
Christopher Dunn
add941c1a9 Revert "Switch to copy-and-swap idiom for operator=."
This reverts commit 45cd9490cd.

Ignored ValueInternal* changes, since those did not produce symbols for
Debian build. (They must not have used the INTERNAL stuff.)

  https://github.com/open-source-parsers/jsoncpp/issues/78

Conflicts:
	include/json/value.h
	src/lib_json/json_internalarray.inl
	src/lib_json/json_internalmap.inl
	src/lib_json/json_value.cpp
2014-11-17 00:16:39 -06:00
29 changed files with 701 additions and 776 deletions

2
.gitignore vendored
View File

@@ -10,4 +10,4 @@
/libs/ /libs/
/doc/doxyfile /doc/doxyfile
/dist/ /dist/
#/include/json/version.h /include/json/version.h

View File

@@ -17,20 +17,28 @@ IF(NOT WIN32)
ENDIF(NOT CMAKE_BUILD_TYPE) ENDIF(NOT CMAKE_BUILD_TYPE)
ENDIF(NOT WIN32) ENDIF(NOT WIN32)
SET(LIB_SUFFIX "" CACHE STRING "Optional arch-dependent suffix for the library installation directory")
SET(RUNTIME_INSTALL_DIR bin SET(RUNTIME_INSTALL_DIR bin
CACHE PATH "Install dir for executables and dlls") CACHE PATH "Install dir for executables and dlls")
SET(ARCHIVE_INSTALL_DIR lib${LIB_SUFFIX} SET(ARCHIVE_INSTALL_DIR lib
CACHE PATH "Install dir for static libraries") CACHE PATH "Install dir for static libraries")
SET(LIBRARY_INSTALL_DIR lib${LIB_SUFFIX} SET(LIBRARY_INSTALL_DIR lib
CACHE PATH "Install dir for shared libraries") CACHE PATH "Install dir for shared libraries")
SET(INCLUDE_INSTALL_DIR include SET(INCLUDE_INSTALL_DIR include
CACHE PATH "Install dir for headers") CACHE PATH "Install dir for headers")
SET(PACKAGE_INSTALL_DIR lib${LIB_SUFFIX}/cmake SET(PACKAGE_INSTALL_DIR lib/cmake
CACHE PATH "Install dir for cmake package config files") CACHE PATH "Install dir for cmake package config files")
MARK_AS_ADVANCED( RUNTIME_INSTALL_DIR ARCHIVE_INSTALL_DIR INCLUDE_INSTALL_DIR PACKAGE_INSTALL_DIR ) MARK_AS_ADVANCED( RUNTIME_INSTALL_DIR ARCHIVE_INSTALL_DIR INCLUDE_INSTALL_DIR PACKAGE_INSTALL_DIR )
# This ensures shared DLL are in the same dir as executable on Windows.
# Put all executables / libraries are in a project global directory.
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib
CACHE PATH "Single directory for all static libraries.")
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib
CACHE PATH "Single directory for all dynamic libraries on Unix.")
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin
CACHE PATH "Single directory for all executable and dynamic libraries on Windows.")
MARK_AS_ADVANCED( CMAKE_RUNTIME_OUTPUT_DIRECTORY CMAKE_LIBRARY_OUTPUT_DIRECTORY CMAKE_ARCHIVE_OUTPUT_DIRECTORY )
# Set variable named ${VAR_NAME} to value ${VALUE} # Set variable named ${VAR_NAME} to value ${VALUE}
FUNCTION(set_using_dynamic_name VAR_NAME VALUE) FUNCTION(set_using_dynamic_name VAR_NAME VALUE)
SET( "${VAR_NAME}" "${VALUE}" PARENT_SCOPE) SET( "${VAR_NAME}" "${VALUE}" PARENT_SCOPE)
@@ -83,14 +91,6 @@ if ( MSVC )
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /W4 ") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /W4 ")
endif( MSVC ) endif( MSVC )
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# using regular Clang or AppleClang
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
# using GCC
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++0x")
endif()
IF(JSONCPP_WITH_WARNING_AS_ERROR) IF(JSONCPP_WITH_WARNING_AS_ERROR)
UseCompilationWarningAsError() UseCompilationWarningAsError()
ENDIF(JSONCPP_WITH_WARNING_AS_ERROR) ENDIF(JSONCPP_WITH_WARNING_AS_ERROR)
@@ -101,7 +101,7 @@ IF(JSONCPP_WITH_PKGCONFIG_SUPPORT)
"pkg-config/jsoncpp.pc" "pkg-config/jsoncpp.pc"
@ONLY) @ONLY)
INSTALL(FILES "${CMAKE_BINARY_DIR}/pkg-config/jsoncpp.pc" INSTALL(FILES "${CMAKE_BINARY_DIR}/pkg-config/jsoncpp.pc"
DESTINATION "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/pkgconfig") DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig")
ENDIF(JSONCPP_WITH_PKGCONFIG_SUPPORT) ENDIF(JSONCPP_WITH_PKGCONFIG_SUPPORT)
IF(JSONCPP_WITH_CMAKE_PACKAGE) IF(JSONCPP_WITH_CMAKE_PACKAGE)

View File

@@ -56,7 +56,7 @@ def amalgamate_source( source_top_dir=None,
target_source_path: output .cpp path target_source_path: output .cpp path
header_include_path: generated header path relative to target_source_path. header_include_path: generated header path relative to target_source_path.
""" """
print("Amalgating header...") print ("Amalgating header...")
header = AmalgamationFile( source_top_dir ) header = AmalgamationFile( source_top_dir )
header.add_text( "/// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/)." ) header.add_text( "/// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/)." )
header.add_text( "/// It is intented to be used with #include <%s>" % header_include_path ) header.add_text( "/// It is intented to be used with #include <%s>" % header_include_path )
@@ -77,12 +77,12 @@ def amalgamate_source( source_top_dir=None,
header.add_text( "#endif //ifndef JSON_AMALGATED_H_INCLUDED" ) header.add_text( "#endif //ifndef JSON_AMALGATED_H_INCLUDED" )
target_header_path = os.path.join( os.path.dirname(target_source_path), header_include_path ) target_header_path = os.path.join( os.path.dirname(target_source_path), header_include_path )
print("Writing amalgated header to %r" % target_header_path) print ("Writing amalgated header to %r" % target_header_path)
header.write_to( target_header_path ) header.write_to( target_header_path )
base, ext = os.path.splitext( header_include_path ) base, ext = os.path.splitext( header_include_path )
forward_header_include_path = base + "-forwards" + ext forward_header_include_path = base + "-forwards" + ext
print("Amalgating forward header...") print ("Amalgating forward header...")
header = AmalgamationFile( source_top_dir ) header = AmalgamationFile( source_top_dir )
header.add_text( "/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/)." ) header.add_text( "/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/)." )
header.add_text( "/// It is intented to be used with #include <%s>" % forward_header_include_path ) header.add_text( "/// It is intented to be used with #include <%s>" % forward_header_include_path )
@@ -99,10 +99,10 @@ def amalgamate_source( source_top_dir=None,
target_forward_header_path = os.path.join( os.path.dirname(target_source_path), target_forward_header_path = os.path.join( os.path.dirname(target_source_path),
forward_header_include_path ) forward_header_include_path )
print("Writing amalgated forward header to %r" % target_forward_header_path) print ("Writing amalgated forward header to %r" % target_forward_header_path)
header.write_to( target_forward_header_path ) header.write_to( target_forward_header_path )
print("Amalgating source...") print ("Amalgating source...")
source = AmalgamationFile( source_top_dir ) source = AmalgamationFile( source_top_dir )
source.add_text( "/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/)." ) source.add_text( "/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/)." )
source.add_text( "/// It is intented to be used with #include <%s>" % header_include_path ) source.add_text( "/// It is intented to be used with #include <%s>" % header_include_path )
@@ -118,7 +118,7 @@ def amalgamate_source( source_top_dir=None,
source.add_file( os.path.join(lib_json, "json_value.cpp") ) source.add_file( os.path.join(lib_json, "json_value.cpp") )
source.add_file( os.path.join(lib_json, "json_writer.cpp") ) source.add_file( os.path.join(lib_json, "json_writer.cpp") )
print("Writing amalgated source to %r" % target_source_path) print ("Writing amalgated source to %r" % target_source_path)
source.write_to( target_source_path ) source.write_to( target_source_path )
def main(): def main():
@@ -144,7 +144,7 @@ Generate a single amalgated source and header file from the sources.
sys.stderr.write( msg + "\n" ) sys.stderr.write( msg + "\n" )
sys.exit( 1 ) sys.exit( 1 )
else: else:
print("Source succesfully amalagated") print ("Source succesfully amalagated")
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@@ -2,7 +2,6 @@
# encoding: utf-8 # encoding: utf-8
# Baptiste Lepilleur, 2009 # Baptiste Lepilleur, 2009
from __future__ import print_function
from dircache import listdir from dircache import listdir
import re import re
import fnmatch import fnmatch
@@ -191,12 +190,12 @@ if __name__ == "__main__":
test_cases.append( (ant_pattern, local_path(accepted_matches), local_path( rejected_matches )) ) test_cases.append( (ant_pattern, local_path(accepted_matches), local_path( rejected_matches )) )
for ant_pattern, accepted_matches, rejected_matches in test_cases: for ant_pattern, accepted_matches, rejected_matches in test_cases:
rex = ant_pattern_to_re( ant_pattern ) rex = ant_pattern_to_re( ant_pattern )
print('ant_pattern:', ant_pattern, ' => ', rex.pattern) print 'ant_pattern:', ant_pattern, ' => ', rex.pattern
for accepted_match in accepted_matches: for accepted_match in accepted_matches:
print('Accepted?:', accepted_match) print 'Accepted?:', accepted_match
self.assertTrue( rex.match( accepted_match ) is not None ) self.assert_( rex.match( accepted_match ) is not None )
for rejected_match in rejected_matches: for rejected_match in rejected_matches:
print('Rejected?:', rejected_match) print 'Rejected?:', rejected_match
self.assertTrue( rex.match( rejected_match ) is None ) self.assert_( rex.match( rejected_match ) is None )
unittest.main() unittest.main()

View File

@@ -1,4 +1,3 @@
from __future__ import print_function
import collections import collections
import itertools import itertools
import json import json
@@ -30,7 +29,7 @@ class BuildDesc:
def env( self ): def env( self ):
environ = os.environ.copy() environ = os.environ.copy()
for values_by_name in self.prepend_envs: for values_by_name in self.prepend_envs:
for var, value in list(values_by_name.items()): for var, value in values_by_name.items():
var = var.upper() var = var.upper()
if type(value) is unicode: if type(value) is unicode:
value = value.encode( sys.getdefaultencoding() ) value = value.encode( sys.getdefaultencoding() )
@@ -63,7 +62,7 @@ class BuildData:
self.build_succeeded = False self.build_succeeded = False
def execute_build(self): def execute_build(self):
print('Build %s' % self.desc) print 'Build %s' % self.desc
self._make_new_work_dir( ) self._make_new_work_dir( )
self.cmake_succeeded = self._generate_makefiles( ) self.cmake_succeeded = self._generate_makefiles( )
if self.cmake_succeeded: if self.cmake_succeeded:
@@ -71,19 +70,19 @@ class BuildData:
return self.build_succeeded return self.build_succeeded
def _generate_makefiles(self): def _generate_makefiles(self):
print(' Generating makefiles: ', end=' ') print ' Generating makefiles: ',
cmd = ['cmake'] + self.desc.cmake_args( ) + [os.path.abspath( self.source_dir )] cmd = ['cmake'] + self.desc.cmake_args( ) + [os.path.abspath( self.source_dir )]
succeeded = self._execute_build_subprocess( cmd, self.desc.env(), self.cmake_log_path ) succeeded = self._execute_build_subprocess( cmd, self.desc.env(), self.cmake_log_path )
print('done' if succeeded else 'FAILED') print 'done' if succeeded else 'FAILED'
return succeeded return succeeded
def _build_using_makefiles(self): def _build_using_makefiles(self):
print(' Building:', end=' ') print ' Building:',
cmd = ['cmake', '--build', self.work_dir] cmd = ['cmake', '--build', self.work_dir]
if self.desc.build_type: if self.desc.build_type:
cmd += ['--config', self.desc.build_type] cmd += ['--config', self.desc.build_type]
succeeded = self._execute_build_subprocess( cmd, self.desc.env(), self.build_log_path ) succeeded = self._execute_build_subprocess( cmd, self.desc.env(), self.build_log_path )
print('done' if succeeded else 'FAILED') print 'done' if succeeded else 'FAILED'
return succeeded return succeeded
def _execute_build_subprocess(self, cmd, env, log_path): def _execute_build_subprocess(self, cmd, env, log_path):
@@ -98,7 +97,7 @@ class BuildData:
def _make_new_work_dir(self): def _make_new_work_dir(self):
if os.path.isdir( self.work_dir ): if os.path.isdir( self.work_dir ):
print(' Removing work directory', self.work_dir) print ' Removing work directory', self.work_dir
shutil.rmtree( self.work_dir, ignore_errors=True ) shutil.rmtree( self.work_dir, ignore_errors=True )
if not os.path.isdir( self.work_dir ): if not os.path.isdir( self.work_dir ):
os.makedirs( self.work_dir ) os.makedirs( self.work_dir )
@@ -135,9 +134,9 @@ def load_build_variants_from_config( config_path ):
def generate_build_variants( build_descs_by_axis ): def generate_build_variants( build_descs_by_axis ):
"""Returns a list of BuildDesc generated for the partial BuildDesc for each axis.""" """Returns a list of BuildDesc generated for the partial BuildDesc for each axis."""
axis_names = list(build_descs_by_axis.keys()) axis_names = build_descs_by_axis.keys()
build_descs = [] build_descs = []
for axis_name, axis_build_descs in list(build_descs_by_axis.items()): for axis_name, axis_build_descs in build_descs_by_axis.items():
if len(build_descs): if len(build_descs):
# for each existing build_desc and each axis build desc, create a new build_desc # for each existing build_desc and each axis build desc, create a new build_desc
new_build_descs = [] new_build_descs = []
@@ -228,7 +227,7 @@ def generate_html_report( html_report_path, builds ):
tr_builds='\n'.join( tr_builds ) ) tr_builds='\n'.join( tr_builds ) )
with open( html_report_path, 'wt' ) as fhtml: with open( html_report_path, 'wt' ) as fhtml:
fhtml.write( html ) fhtml.write( html )
print('HTML report generated in:', html_report_path) print 'HTML report generated in:', html_report_path
def main(): def main():
usage = r"""%prog WORK_DIR SOURCE_DIR CONFIG_JSON_PATH [CONFIG2_JSON_PATH...] usage = r"""%prog WORK_DIR SOURCE_DIR CONFIG_JSON_PATH [CONFIG2_JSON_PATH...]
@@ -259,7 +258,7 @@ python devtools\batchbuild.py e:\buildbots\jsoncpp\build . devtools\agent_vmw7.j
for config_path in config_paths: for config_path in config_paths:
build_descs_by_axis = load_build_variants_from_config( config_path ) build_descs_by_axis = load_build_variants_from_config( config_path )
build_descs.extend( generate_build_variants( build_descs_by_axis ) ) build_descs.extend( generate_build_variants( build_descs_by_axis ) )
print('Build variants (%d):' % len(build_descs)) print 'Build variants (%d):' % len(build_descs)
# assign build directory for each variant # assign build directory for each variant
if not os.path.isdir( work_dir ): if not os.path.isdir( work_dir ):
os.makedirs( work_dir ) os.makedirs( work_dir )
@@ -273,7 +272,7 @@ python devtools\batchbuild.py e:\buildbots\jsoncpp\build . devtools\agent_vmw7.j
build.execute_build() build.execute_build()
html_report_path = os.path.join( work_dir, 'batchbuild-report.html' ) html_report_path = os.path.join( work_dir, 'batchbuild-report.html' )
generate_html_report( html_report_path, builds ) generate_html_report( html_report_path, builds )
print('Done') print 'Done'
if __name__ == '__main__': if __name__ == '__main__':

View File

@@ -1,4 +1,3 @@
from __future__ import print_function
import os.path import os.path
def fix_source_eol( path, is_dry_run = True, verbose = True, eol = '\n' ): def fix_source_eol( path, is_dry_run = True, verbose = True, eol = '\n' ):
@@ -7,8 +6,8 @@ def fix_source_eol( path, is_dry_run = True, verbose = True, eol = '\n' ):
raise ValueError( 'Path "%s" is not a file' % path ) raise ValueError( 'Path "%s" is not a file' % path )
try: try:
f = open(path, 'rb') f = open(path, 'rb')
except IOError as msg: except IOError, msg:
print("%s: I/O Error: %s" % (file, str(msg)), file=sys.stderr) print >> sys.stderr, "%s: I/O Error: %s" % (file, str(msg))
return False return False
try: try:
raw_lines = f.readlines() raw_lines = f.readlines()
@@ -16,7 +15,7 @@ def fix_source_eol( path, is_dry_run = True, verbose = True, eol = '\n' ):
f.close() f.close()
fixed_lines = [line.rstrip('\r\n') + eol for line in raw_lines] fixed_lines = [line.rstrip('\r\n') + eol for line in raw_lines]
if raw_lines != fixed_lines: if raw_lines != fixed_lines:
print('%s =>' % path, end=' ') print '%s =>' % path,
if not is_dry_run: if not is_dry_run:
f = open(path, "wb") f = open(path, "wb")
try: try:
@@ -24,7 +23,7 @@ def fix_source_eol( path, is_dry_run = True, verbose = True, eol = '\n' ):
finally: finally:
f.close() f.close()
if verbose: if verbose:
print(is_dry_run and ' NEED FIX' or ' FIXED') print is_dry_run and ' NEED FIX' or ' FIXED'
return True return True
## ##
## ##

View File

@@ -1,6 +1,5 @@
"""Updates the license text in source file. """Updates the license text in source file.
""" """
from __future__ import print_function
# An existing license is found if the file starts with the string below, # An existing license is found if the file starts with the string below,
# and ends with the first blank line. # and ends with the first blank line.
@@ -35,11 +34,11 @@ def update_license( path, dry_run, show_diff ):
if not dry_run: if not dry_run:
with open( path, 'wb' ) as fout: with open( path, 'wb' ) as fout:
fout.write( new_text.replace('\n', newline ) ) fout.write( new_text.replace('\n', newline ) )
print('Updated', path) print 'Updated', path
if show_diff: if show_diff:
import difflib import difflib
print('\n'.join( difflib.unified_diff( original_text.split('\n'), print '\n'.join( difflib.unified_diff( original_text.split('\n'),
new_text.split('\n') ) )) new_text.split('\n') ) )
return True return True
return False return False
@@ -84,7 +83,7 @@ python devtools\licenseupdater.py include src
parser.enable_interspersed_args() parser.enable_interspersed_args()
options, args = parser.parse_args() options, args = parser.parse_args()
update_license_in_source_directories( args, options.dry_run, options.show_diff ) update_license_in_source_directories( args, options.dry_run, options.show_diff )
print('Done') print 'Done'
if __name__ == '__main__': if __name__ == '__main__':
import sys import sys

View File

@@ -1,12 +1,12 @@
"""Script to generate doxygen documentation. """Script to generate doxygen documentation.
""" """
from __future__ import print_function
from devtools import tarball
import re import re
import os import os
import os.path import os.path
import sys import sys
import shutil import shutil
from devtools import tarball
def find_program(*filenames): def find_program(*filenames):
"""find a program in folders path_lst, and sets env[var] """find a program in folders path_lst, and sets env[var]
@@ -33,9 +33,9 @@ def do_subst_in_file(targetfile, sourcefile, dict):
contents = f.read() contents = f.read()
f.close() f.close()
except: except:
print("Can't read source file %s"%sourcefile) print "Can't read source file %s"%sourcefile
raise raise
for (k,v) in list(dict.items()): for (k,v) in dict.items():
v = v.replace('\\','\\\\') v = v.replace('\\','\\\\')
contents = re.sub(k, v, contents) contents = re.sub(k, v, contents)
try: try:
@@ -43,7 +43,7 @@ def do_subst_in_file(targetfile, sourcefile, dict):
f.write(contents) f.write(contents)
f.close() f.close()
except: except:
print("Can't write target file %s"%targetfile) print "Can't write target file %s"%targetfile
raise raise
def run_doxygen(doxygen_path, config_file, working_dir, is_silent): def run_doxygen(doxygen_path, config_file, working_dir, is_silent):
@@ -53,12 +53,12 @@ def run_doxygen(doxygen_path, config_file, working_dir, is_silent):
try: try:
os.chdir( working_dir ) os.chdir( working_dir )
cmd = [doxygen_path, config_file] cmd = [doxygen_path, config_file]
print('Running:', ' '.join( cmd )) print 'Running:', ' '.join( cmd )
try: try:
import subprocess import subprocess
except: except:
if os.system( ' '.join( cmd ) ) != 0: if os.system( ' '.join( cmd ) ) != 0:
print('Documentation generation failed') print 'Documentation generation failed'
return False return False
else: else:
if is_silent: if is_silent:
@@ -67,8 +67,8 @@ def run_doxygen(doxygen_path, config_file, working_dir, is_silent):
process = subprocess.Popen( cmd ) process = subprocess.Popen( cmd )
stdout, _ = process.communicate() stdout, _ = process.communicate()
if process.returncode: if process.returncode:
print('Documentation generation failed:') print 'Documentation generation failed:'
print(stdout) print stdout
return False return False
return True return True
finally: finally:
@@ -107,7 +107,7 @@ def build_doc( options, make_release=False ):
} }
if os.path.isdir( output_dir ): if os.path.isdir( output_dir ):
print('Deleting directory:', output_dir) print 'Deleting directory:', output_dir
shutil.rmtree( output_dir ) shutil.rmtree( output_dir )
if not os.path.isdir( output_dir ): if not os.path.isdir( output_dir ):
os.makedirs( output_dir ) os.makedirs( output_dir )
@@ -115,15 +115,15 @@ def build_doc( options, make_release=False ):
do_subst_in_file( 'doc/doxyfile', 'doc/doxyfile.in', subst_keys ) do_subst_in_file( 'doc/doxyfile', 'doc/doxyfile.in', subst_keys )
ok = run_doxygen( options.doxygen_path, 'doc/doxyfile', 'doc', is_silent=options.silent ) ok = run_doxygen( options.doxygen_path, 'doc/doxyfile', 'doc', is_silent=options.silent )
if not options.silent: if not options.silent:
print(open(warning_log_path, 'rb').read()) print open(warning_log_path, 'rb').read()
index_path = os.path.abspath(os.path.join('doc', subst_keys['%HTML_OUTPUT%'], 'index.html')) index_path = os.path.abspath(os.path.join('doc', subst_keys['%HTML_OUTPUT%'], 'index.html'))
print('Generated documentation can be found in:') print 'Generated documentation can be found in:'
print(index_path) print index_path
if options.open: if options.open:
import webbrowser import webbrowser
webbrowser.open( 'file://' + index_path ) webbrowser.open( 'file://' + index_path )
if options.make_tarball: if options.make_tarball:
print('Generating doc tarball to', tarball_path) print 'Generating doc tarball to', tarball_path
tarball_sources = [ tarball_sources = [
output_dir, output_dir,
'README.txt', 'README.txt',

View File

@@ -7,7 +7,6 @@
#define CPPTL_JSON_ASSERTIONS_H_INCLUDED #define CPPTL_JSON_ASSERTIONS_H_INCLUDED
#include <stdlib.h> #include <stdlib.h>
#include <sstream>
#if !defined(JSON_IS_AMALGAMATION) #if !defined(JSON_IS_AMALGAMATION)
#include "config.h" #include "config.h"
@@ -17,26 +16,26 @@
#include <stdexcept> #include <stdexcept>
#define JSON_ASSERT(condition) \ #define JSON_ASSERT(condition) \
assert(condition); // @todo <= change this into an exception throw assert(condition); // @todo <= change this into an exception throw
#define JSON_FAIL_MESSAGE(message) do{std::ostringstream oss; oss << message; throw std::runtime_error(oss.str());}while(0) #define JSON_FAIL_MESSAGE(message) throw std::runtime_error(message);
//#define JSON_FAIL_MESSAGE(message) throw std::runtime_error(message)
#else // JSON_USE_EXCEPTION #else // JSON_USE_EXCEPTION
#define JSON_ASSERT(condition) assert(condition); #define JSON_ASSERT(condition) assert(condition);
// The call to assert() will show the failure message in debug builds. In // The call to assert() will show the failure message in debug builds. In
// release bugs we abort, for a core-dump or debugger. // release bugs we write to invalid memory in order to crash hard, so that a
// debugger or crash reporter gets the chance to take over. We still call exit()
// afterward in order to tell the compiler that this macro doesn't return.
#define JSON_FAIL_MESSAGE(message) \ #define JSON_FAIL_MESSAGE(message) \
{ \ { \
std::ostringstream oss; oss << message; \ assert(false&& message); \
assert(false && oss.str().c_str()); \ strcpy(reinterpret_cast<char*>(666), message); \
abort(); \ exit(123); \
} }
#endif #endif
#define JSON_ASSERT_MESSAGE(condition, message) \ #define JSON_ASSERT_MESSAGE(condition, message) \
if (!(condition)) { \ if (!(condition)) { \
JSON_FAIL_MESSAGE(message); \ JSON_FAIL_MESSAGE(message) \
} }
#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED #endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED

View File

@@ -187,6 +187,7 @@ private:
typedef std::deque<ErrorInfo> Errors; typedef std::deque<ErrorInfo> Errors;
bool expectToken(TokenType type, Token& token, const char* message);
bool readToken(Token& token); bool readToken(Token& token);
void skipSpaces(); void skipSpaces();
bool match(Location pattern, int patternLength); bool match(Location pattern, int patternLength);

View File

@@ -171,7 +171,7 @@ private:
CZString(const char* cstr, DuplicationPolicy allocate); CZString(const char* cstr, DuplicationPolicy allocate);
CZString(const CZString& other); CZString(const CZString& other);
~CZString(); ~CZString();
CZString& operator=(CZString other); CZString &operator=(const CZString &other);
bool operator<(const CZString& other) const; bool operator<(const CZString& other) const;
bool operator==(const CZString& other) const; bool operator==(const CZString& other) const;
ArrayIndex index() const; ArrayIndex index() const;
@@ -235,26 +235,25 @@ Json::Value obj_value(Json::objectValue); // {}
Value(const CppTL::ConstString& value); Value(const CppTL::ConstString& value);
#endif #endif
Value(bool value); Value(bool value);
/// Deep copy.
Value(const Value& other); Value(const Value& other);
~Value(); ~Value();
// Deep copy, then swap(other). Value &operator=(const Value &other);
Value& operator=(Value other); /// Swap values.
/// Swap everything. /// \note Currently, comments are intentionally not swapped, for
/// both logic and efficiency.
void swap(Value& other); void swap(Value& other);
/// Swap values but leave comments and source offsets in place.
void swapPayload(Value& other);
ValueType type() const; ValueType type() const;
/// Compare payload only, not comments etc.
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;
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; int compare(const Value& other) const;
const char* asCString() const; const char* asCString() const;
@@ -392,24 +391,9 @@ Json::Value obj_value(Json::objectValue); // {}
/// \return the removed Value, or null. /// \return the removed Value, or null.
/// \pre type() is objectValue or nullValue /// \pre type() is objectValue or nullValue
/// \post type() is unchanged /// \post type() is unchanged
/// \deprecated
Value removeMember(const char* key); Value removeMember(const char* key);
/// Same as removeMember(const char*) /// Same as removeMember(const char*)
/// \deprecated
Value removeMember(const std::string& key); Value removeMember(const std::string& key);
/** \brief Remove the named map member.
Update 'removed' iff removed.
\return true iff removed (no exceptions)
*/
bool removeMember(const char* key, Value* removed);
/** \brief Remove the indexed array element.
O(n) expensive operations.
Update 'removed' iff removed.
\return true iff removed (no exceptions)
*/
bool removeIndex(ArrayIndex i, Value* removed);
/// Return true if the object has a member named key. /// Return true if the object has a member named key.
bool isMember(const char* key) const; bool isMember(const char* key) const;
@@ -456,8 +440,6 @@ Json::Value obj_value(Json::objectValue); // {}
size_t getOffsetLimit() const; size_t getOffsetLimit() const;
private: private:
void initBasic(ValueType type, bool allocated = false);
Value& resolveReference(const char* key, bool isStatic); Value& resolveReference(const char* key, bool isStatic);
#ifdef JSON_VALUE_USE_INTERNAL_MAP #ifdef JSON_VALUE_USE_INTERNAL_MAP
@@ -1097,14 +1079,6 @@ public:
} // namespace Json } // namespace Json
namespace std {
/// Specialize std::swap() for Json::Value.
template<>
inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); }
}
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#pragma warning(pop) #pragma warning(pop)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)

View File

@@ -4,9 +4,9 @@
#ifndef JSON_VERSION_H_INCLUDED #ifndef JSON_VERSION_H_INCLUDED
# define JSON_VERSION_H_INCLUDED # define JSON_VERSION_H_INCLUDED
# define JSONCPP_VERSION_STRING "1.3.0" # define JSONCPP_VERSION_STRING "0.7.0"
# define JSONCPP_VERSION_MAJOR 1 # define JSONCPP_VERSION_MAJOR 0
# define JSONCPP_VERSION_MINOR 3 # define JSONCPP_VERSION_MINOR 7
# define JSONCPP_VERSION_PATCH 0 # define JSONCPP_VERSION_PATCH 0
# define JSONCPP_VERSION_QUALIFIER # define JSONCPP_VERSION_QUALIFIER
# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8)) # define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))

View File

@@ -14,7 +14,6 @@ python makerelease.py 0.5.0 0.6.0-dev
Note: This was for Subversion. Now that we are in GitHub, we do not Note: This was for Subversion. Now that we are in GitHub, we do not
need to build versioned tarballs anymore, so makerelease.py is defunct. need to build versioned tarballs anymore, so makerelease.py is defunct.
""" """
from __future__ import print_function
import os.path import os.path
import subprocess import subprocess
import sys import sys
@@ -47,7 +46,7 @@ class SVNError(Exception):
def svn_command( command, *args ): def svn_command( command, *args ):
cmd = ['svn', '--non-interactive', command] + list(args) cmd = ['svn', '--non-interactive', command] + list(args)
print('Running:', ' '.join( cmd )) print 'Running:', ' '.join( cmd )
process = subprocess.Popen( cmd, process = subprocess.Popen( cmd,
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT ) stderr=subprocess.STDOUT )
@@ -85,7 +84,7 @@ def svn_check_if_tag_exist( tag_url ):
""" """
try: try:
list_stdout = svn_command( 'list', tag_url ) list_stdout = svn_command( 'list', tag_url )
except SVNError as e: except SVNError, e:
if e.returncode != 1 or not str(e).find('tag_url'): if e.returncode != 1 or not str(e).find('tag_url'):
raise e raise e
# otherwise ignore error, meaning tag does not exist # otherwise ignore error, meaning tag does not exist
@@ -118,7 +117,7 @@ def svn_export( tag_url, export_dir ):
def fix_sources_eol( dist_dir ): def fix_sources_eol( dist_dir ):
"""Set file EOL for tarball distribution. """Set file EOL for tarball distribution.
""" """
print('Preparing exported source file EOL for distribution...') print 'Preparing exported source file EOL for distribution...'
prune_dirs = antglob.prune_dirs + 'scons-local* ./build* ./libs ./dist' prune_dirs = antglob.prune_dirs + 'scons-local* ./build* ./libs ./dist'
win_sources = antglob.glob( dist_dir, win_sources = antglob.glob( dist_dir,
includes = '**/*.sln **/*.vcproj', includes = '**/*.sln **/*.vcproj',
@@ -149,7 +148,7 @@ def download( url, target_path ):
def check_compile( distcheck_top_dir, platform ): def check_compile( distcheck_top_dir, platform ):
cmd = [sys.executable, 'scons.py', 'platform=%s' % platform, 'check'] cmd = [sys.executable, 'scons.py', 'platform=%s' % platform, 'check']
print('Running:', ' '.join( cmd )) print 'Running:', ' '.join( cmd )
log_path = os.path.join( distcheck_top_dir, 'build-%s.log' % platform ) log_path = os.path.join( distcheck_top_dir, 'build-%s.log' % platform )
flog = open( log_path, 'wb' ) flog = open( log_path, 'wb' )
try: try:
@@ -180,9 +179,9 @@ def run_sftp_batch( userhost, sftp, batch, retry=0 ):
# psftp -agent -C blep,jsoncpp@web.sourceforge.net -batch -b batch.sftp -bc # psftp -agent -C blep,jsoncpp@web.sourceforge.net -batch -b batch.sftp -bc
cmd = [sftp, '-agent', '-C', '-batch', '-b', path, '-bc', userhost] cmd = [sftp, '-agent', '-C', '-batch', '-b', path, '-bc', userhost]
error = None error = None
for retry_index in range(0, max(1,retry)): for retry_index in xrange(0, max(1,retry)):
heading = retry_index == 0 and 'Running:' or 'Retrying:' heading = retry_index == 0 and 'Running:' or 'Retrying:'
print(heading, ' '.join( cmd )) print heading, ' '.join( cmd )
process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT ) process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
stdout = process.communicate()[0] stdout = process.communicate()[0]
if process.returncode != 0: if process.returncode != 0:
@@ -220,21 +219,21 @@ exit
upload_paths = set( [os.path.basename(p) for p in antglob.glob( doc_dir )] ) upload_paths = set( [os.path.basename(p) for p in antglob.glob( doc_dir )] )
paths_to_remove = existing_paths - upload_paths paths_to_remove = existing_paths - upload_paths
if paths_to_remove: if paths_to_remove:
print('Removing the following file from web:') print 'Removing the following file from web:'
print('\n'.join( paths_to_remove )) print '\n'.join( paths_to_remove )
stdout = run_sftp_batch( userhost, sftp, """cd htdocs stdout = run_sftp_batch( userhost, sftp, """cd htdocs
rm %s rm %s
exit""" % ' '.join(paths_to_remove) ) exit""" % ' '.join(paths_to_remove) )
print('Uploading %d files:' % len(upload_paths)) print 'Uploading %d files:' % len(upload_paths)
batch_size = 10 batch_size = 10
upload_paths = list(upload_paths) upload_paths = list(upload_paths)
start_time = time.time() start_time = time.time()
for index in range(0,len(upload_paths),batch_size): for index in xrange(0,len(upload_paths),batch_size):
paths = upload_paths[index:index+batch_size] paths = upload_paths[index:index+batch_size]
file_per_sec = (time.time() - start_time) / (index+1) file_per_sec = (time.time() - start_time) / (index+1)
remaining_files = len(upload_paths) - index remaining_files = len(upload_paths) - index
remaining_sec = file_per_sec * remaining_files remaining_sec = file_per_sec * remaining_files
print('%d/%d, ETA=%.1fs' % (index+1, len(upload_paths), remaining_sec)) print '%d/%d, ETA=%.1fs' % (index+1, len(upload_paths), remaining_sec)
run_sftp_batch( userhost, sftp, """cd htdocs run_sftp_batch( userhost, sftp, """cd htdocs
lcd %s lcd %s
mput %s mput %s
@@ -298,7 +297,7 @@ Warning: --force should only be used when developping/testing the release script
else: else:
msg = check_no_pending_commit() msg = check_no_pending_commit()
if not msg: if not msg:
print('Setting version to', release_version) print 'Setting version to', release_version
set_version( release_version ) set_version( release_version )
svn_commit( 'Release ' + release_version ) svn_commit( 'Release ' + release_version )
tag_url = svn_join_url( SVN_TAG_ROOT, release_version ) tag_url = svn_join_url( SVN_TAG_ROOT, release_version )
@@ -306,11 +305,11 @@ Warning: --force should only be used when developping/testing the release script
if options.retag_release: if options.retag_release:
svn_remove_tag( tag_url, 'Overwriting previous tag' ) svn_remove_tag( tag_url, 'Overwriting previous tag' )
else: else:
print('Aborting, tag %s already exist. Use --retag to overwrite it!' % tag_url) print 'Aborting, tag %s already exist. Use --retag to overwrite it!' % tag_url
sys.exit( 1 ) sys.exit( 1 )
svn_tag_sandbox( tag_url, 'Release ' + release_version ) svn_tag_sandbox( tag_url, 'Release ' + release_version )
print('Generated doxygen document...') print 'Generated doxygen document...'
## doc_dirname = r'jsoncpp-api-html-0.5.0' ## doc_dirname = r'jsoncpp-api-html-0.5.0'
## doc_tarball_path = r'e:\prg\vc\Lib\jsoncpp-trunk\dist\jsoncpp-api-html-0.5.0.tar.gz' ## doc_tarball_path = r'e:\prg\vc\Lib\jsoncpp-trunk\dist\jsoncpp-api-html-0.5.0.tar.gz'
doc_tarball_path, doc_dirname = doxybuild.build_doc( options, make_release=True ) doc_tarball_path, doc_dirname = doxybuild.build_doc( options, make_release=True )
@@ -324,11 +323,11 @@ Warning: --force should only be used when developping/testing the release script
source_dir = 'jsoncpp-src-' + release_version source_dir = 'jsoncpp-src-' + release_version
source_tarball_path = 'dist/%s.tar.gz' % source_dir source_tarball_path = 'dist/%s.tar.gz' % source_dir
print('Generating source tarball to', source_tarball_path) print 'Generating source tarball to', source_tarball_path
tarball.make_tarball( source_tarball_path, [export_dir], export_dir, prefix_dir=source_dir ) tarball.make_tarball( source_tarball_path, [export_dir], export_dir, prefix_dir=source_dir )
amalgamation_tarball_path = 'dist/%s-amalgamation.tar.gz' % source_dir amalgamation_tarball_path = 'dist/%s-amalgamation.tar.gz' % source_dir
print('Generating amalgamation source tarball to', amalgamation_tarball_path) print 'Generating amalgamation source tarball to', amalgamation_tarball_path
amalgamation_dir = 'dist/amalgamation' amalgamation_dir = 'dist/amalgamation'
amalgamate.amalgamate_source( export_dir, '%s/jsoncpp.cpp' % amalgamation_dir, 'json/json.h' ) amalgamate.amalgamate_source( export_dir, '%s/jsoncpp.cpp' % amalgamation_dir, 'json/json.h' )
amalgamation_source_dir = 'jsoncpp-src-amalgamation' + release_version amalgamation_source_dir = 'jsoncpp-src-amalgamation' + release_version
@@ -338,41 +337,41 @@ Warning: --force should only be used when developping/testing the release script
# Decompress source tarball, download and install scons-local # Decompress source tarball, download and install scons-local
distcheck_dir = 'dist/distcheck' distcheck_dir = 'dist/distcheck'
distcheck_top_dir = distcheck_dir + '/' + source_dir distcheck_top_dir = distcheck_dir + '/' + source_dir
print('Decompressing source tarball to', distcheck_dir) print 'Decompressing source tarball to', distcheck_dir
rmdir_if_exist( distcheck_dir ) rmdir_if_exist( distcheck_dir )
tarball.decompress( source_tarball_path, distcheck_dir ) tarball.decompress( source_tarball_path, distcheck_dir )
scons_local_path = 'dist/scons-local.tar.gz' scons_local_path = 'dist/scons-local.tar.gz'
print('Downloading scons-local to', scons_local_path) print 'Downloading scons-local to', scons_local_path
download( SCONS_LOCAL_URL, scons_local_path ) download( SCONS_LOCAL_URL, scons_local_path )
print('Decompressing scons-local to', distcheck_top_dir) print 'Decompressing scons-local to', distcheck_top_dir
tarball.decompress( scons_local_path, distcheck_top_dir ) tarball.decompress( scons_local_path, distcheck_top_dir )
# Run compilation # Run compilation
print('Compiling decompressed tarball') print 'Compiling decompressed tarball'
all_build_status = True all_build_status = True
for platform in options.platforms.split(','): for platform in options.platforms.split(','):
print('Testing platform:', platform) print 'Testing platform:', platform
build_status, log_path = check_compile( distcheck_top_dir, platform ) build_status, log_path = check_compile( distcheck_top_dir, platform )
print('see build log:', log_path) print 'see build log:', log_path
print(build_status and '=> ok' or '=> FAILED') print build_status and '=> ok' or '=> FAILED'
all_build_status = all_build_status and build_status all_build_status = all_build_status and build_status
if not build_status: if not build_status:
print('Testing failed on at least one platform, aborting...') print 'Testing failed on at least one platform, aborting...'
svn_remove_tag( tag_url, 'Removing tag due to failed testing' ) svn_remove_tag( tag_url, 'Removing tag due to failed testing' )
sys.exit(1) sys.exit(1)
if options.user: if options.user:
if not options.no_web: if not options.no_web:
print('Uploading documentation using user', options.user) print 'Uploading documentation using user', options.user
sourceforge_web_synchro( SOURCEFORGE_PROJECT, doc_distcheck_top_dir, user=options.user, sftp=options.sftp ) sourceforge_web_synchro( SOURCEFORGE_PROJECT, doc_distcheck_top_dir, user=options.user, sftp=options.sftp )
print('Completed documentation upload') print 'Completed documentation upload'
print('Uploading source and documentation tarballs for release using user', options.user) print 'Uploading source and documentation tarballs for release using user', options.user
sourceforge_release_tarball( SOURCEFORGE_PROJECT, sourceforge_release_tarball( SOURCEFORGE_PROJECT,
[source_tarball_path, doc_tarball_path], [source_tarball_path, doc_tarball_path],
user=options.user, sftp=options.sftp ) user=options.user, sftp=options.sftp )
print('Source and doc release tarballs uploaded') print 'Source and doc release tarballs uploaded'
else: else:
print('No upload user specified. Web site and download tarbal were not uploaded.') print 'No upload user specified. Web site and download tarbal were not uploaded.'
print('Tarball can be found at:', doc_tarball_path) print 'Tarball can be found at:', doc_tarball_path
# Set next version number and commit # Set next version number and commit
set_version( next_version ) set_version( next_version )

View File

@@ -1,7 +1,7 @@
prefix=@CMAKE_INSTALL_PREFIX@ prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix} exec_prefix=${prefix}
libdir=${exec_prefix}/@LIBRARY_INSTALL_DIR@ libdir=${exec_prefix}/lib
includedir=${prefix}/@INCLUDE_INSTALL_DIR@ includedir=${prefix}/include
Name: jsoncpp Name: jsoncpp
Description: A C++ library for interacting with JSON Description: A C++ library for interacting with JSON

View File

@@ -1,6 +1,5 @@
import re import re
from SCons.Script import * # the usual scons stuff you get in a SConscript from SCons.Script import * # the usual scons stuff you get in a SConscript
import collections
def generate(env): def generate(env):
""" """
@@ -26,28 +25,28 @@ def generate(env):
contents = f.read() contents = f.read()
f.close() f.close()
except: except:
raise SCons.Errors.UserError("Can't read source file %s"%sourcefile) raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile
for (k,v) in list(dict.items()): for (k,v) in dict.items():
contents = re.sub(k, v, contents) contents = re.sub(k, v, contents)
try: try:
f = open(targetfile, 'wb') f = open(targetfile, 'wb')
f.write(contents) f.write(contents)
f.close() f.close()
except: except:
raise SCons.Errors.UserError("Can't write target file %s"%targetfile) raise SCons.Errors.UserError, "Can't write target file %s"%targetfile
return 0 # success return 0 # success
def subst_in_file(target, source, env): def subst_in_file(target, source, env):
if 'SUBST_DICT' not in env: if not env.has_key('SUBST_DICT'):
raise SCons.Errors.UserError("SubstInFile requires SUBST_DICT to be set.") raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set."
d = dict(env['SUBST_DICT']) # copy it d = dict(env['SUBST_DICT']) # copy it
for (k,v) in list(d.items()): for (k,v) in d.items():
if isinstance(v, collections.Callable): if callable(v):
d[k] = env.subst(v()).replace('\\','\\\\') d[k] = env.subst(v()).replace('\\','\\\\')
elif SCons.Util.is_String(v): elif SCons.Util.is_String(v):
d[k] = env.subst(v).replace('\\','\\\\') d[k] = env.subst(v).replace('\\','\\\\')
else: else:
raise SCons.Errors.UserError("SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))) raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v))
for (t,s) in zip(target, source): for (t,s) in zip(target, source):
return do_subst_in_file(str(t), str(s), d) return do_subst_in_file(str(t), str(s), d)
@@ -61,8 +60,8 @@ def generate(env):
Returns original target, source tuple unchanged. Returns original target, source tuple unchanged.
""" """
d = env['SUBST_DICT'].copy() # copy it d = env['SUBST_DICT'].copy() # copy it
for (k,v) in list(d.items()): for (k,v) in d.items():
if isinstance(v, collections.Callable): if callable(v):
d[k] = env.subst(v()) d[k] = env.subst(v())
elif SCons.Util.is_String(v): elif SCons.Util.is_String(v):
d[k]=env.subst(v) d[k]=env.subst(v)

View File

@@ -1,8 +1,4 @@
OPTION(JSONCPP_LIB_BUILD_SHARED "Build jsoncpp_lib as a shared library." OFF) OPTION(JSONCPP_LIB_BUILD_SHARED "Build jsoncpp_lib as a shared library." OFF)
IF(BUILD_SHARED_LIBS)
SET(JSONCPP_LIB_BUILD_SHARED ON)
ENDIF(BUILD_SHARED_LIBS)
IF(JSONCPP_LIB_BUILD_SHARED) IF(JSONCPP_LIB_BUILD_SHARED)
SET(JSONCPP_LIB_TYPE SHARED) SET(JSONCPP_LIB_TYPE SHARED)
ADD_DEFINITIONS( -DJSON_DLL_BUILD ) ADD_DEFINITIONS( -DJSON_DLL_BUILD )
@@ -10,15 +6,9 @@ ELSE(JSONCPP_LIB_BUILD_SHARED)
SET(JSONCPP_LIB_TYPE STATIC) SET(JSONCPP_LIB_TYPE STATIC)
ENDIF(JSONCPP_LIB_BUILD_SHARED) ENDIF(JSONCPP_LIB_BUILD_SHARED)
if( CMAKE_COMPILER_IS_GNUCXX )
#Get compiler version.
execute_process( COMMAND ${CMAKE_CXX_COMPILER} -dumpversion
OUTPUT_VARIABLE GNUCXX_VERSION )
#-Werror=* was introduced -after- GCC 4.1.2 if( CMAKE_COMPILER_IS_GNUCXX )
if( GNUCXX_VERSION VERSION_GREATER 4.1.2 ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=strict-aliasing")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=strict-aliasing")
endif()
endif( CMAKE_COMPILER_IS_GNUCXX ) endif( CMAKE_COMPILER_IS_GNUCXX )
SET( JSONCPP_INCLUDE_DIR ../../include ) SET( JSONCPP_INCLUDE_DIR ../../include )
@@ -49,15 +39,12 @@ ADD_LIBRARY( jsoncpp_lib ${JSONCPP_LIB_TYPE}
SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES OUTPUT_NAME jsoncpp ) SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES OUTPUT_NAME jsoncpp )
SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES VERSION ${JSONCPP_VERSION} SOVERSION ${JSONCPP_VERSION_MAJOR} ) SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES VERSION ${JSONCPP_VERSION} SOVERSION ${JSONCPP_VERSION_MAJOR} )
IF(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
TARGET_INCLUDE_DIRECTORIES( jsoncpp_lib PUBLIC
$<INSTALL_INTERFACE:${INCLUDE_INSTALL_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
)
ENDIF(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
# Install instructions for this target # Install instructions for this target
IF(JSONCPP_WITH_CMAKE_PACKAGE) IF(JSONCPP_WITH_CMAKE_PACKAGE)
TARGET_INCLUDE_DIRECTORIES( jsoncpp_lib
PUBLIC $<INSTALL_INTERFACE:${INCLUDE_INSTALL_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSON_INCLUDE_DIR}>
)
SET(INSTALL_EXPORT EXPORT jsoncpp) SET(INSTALL_EXPORT EXPORT jsoncpp)
ELSE(JSONCPP_WITH_CMAKE_PACKAGE) ELSE(JSONCPP_WITH_CMAKE_PACKAGE)
SET(INSTALL_EXPORT) SET(INSTALL_EXPORT)

View File

@@ -47,6 +47,23 @@ Features Features::strictMode() {
// Implementation of class Reader // 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) { static bool containsNewLine(Reader::Location begin, Reader::Location end) {
for (; begin < end; ++begin) for (; begin < end; ++begin)
if (*begin == '\n' || *begin == '\r') if (*begin == '\n' || *begin == '\r')
@@ -135,9 +152,14 @@ bool Reader::readValue() {
bool successful = true; bool successful = true;
if (collectComments_ && !commentsBefore_.empty()) { if (collectComments_ && !commentsBefore_.empty()) {
// Remove newline at the end of the comment // Remove newline characters at the end of the comments
if (commentsBefore_[commentsBefore_.size() - 1] == '\n') size_t lastNonNewline = commentsBefore_.find_last_not_of("\r\n");
commentsBefore_.resize(commentsBefore_.size() - 1); if (lastNonNewline != std::string::npos) {
commentsBefore_.erase(lastNonNewline + 1);
} else {
commentsBefore_.clear();
}
currentValue().setComment(commentsBefore_, commentBefore); currentValue().setComment(commentsBefore_, commentBefore);
commentsBefore_ = ""; commentsBefore_ = "";
} }
@@ -158,36 +180,26 @@ bool Reader::readValue() {
successful = decodeString(token); successful = decodeString(token);
break; break;
case tokenTrue: case tokenTrue:
{ currentValue() = true;
Value v(true);
currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_);
}
break; break;
case tokenFalse: case tokenFalse:
{ currentValue() = false;
Value v(false);
currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_);
}
break; break;
case tokenNull: case tokenNull:
{ currentValue() = Value();
Value v;
currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_);
}
break; break;
case tokenArraySeparator: case tokenArraySeparator:
if (features_.allowDroppedNullPlaceholders_) { if (features_.allowDroppedNullPlaceholders_) {
// "Un-read" the current token and mark the current value as a null // "Un-read" the current token and mark the current value as a null
// token. // token.
current_--; current_--;
Value v; currentValue() = Value();
currentValue().swapPayload(v);
currentValue().setOffsetStart(current_ - begin_ - 1); currentValue().setOffsetStart(current_ - begin_ - 1);
currentValue().setOffsetLimit(current_ - begin_); currentValue().setOffsetLimit(current_ - begin_);
break; break;
@@ -217,6 +229,13 @@ void Reader::skipCommentTokens(Token& 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) { bool Reader::readToken(Token& token) {
skipSpaces(); skipSpaces();
token.start_ = current_; token.start_ = current_;
@@ -332,34 +351,14 @@ bool Reader::readComment() {
return true; return true;
} }
static std::string normalizeEOL(Reader::Location begin, Reader::Location end) {
std::string normalized;
normalized.reserve(end - begin);
Reader::Location current = begin;
while (current != end) {
char c = *current++;
if (c == '\r') {
if (current != end && *current == '\n')
// convert dos EOL
++current;
// convert Mac EOL
normalized += '\n';
} else {
normalized += c;
}
}
return normalized;
}
void void
Reader::addComment(Location begin, Location end, CommentPlacement placement) { Reader::addComment(Location begin, Location end, CommentPlacement placement) {
assert(collectComments_); assert(collectComments_);
const std::string& normalized = normalizeEOL(begin, end);
if (placement == commentAfterOnSameLine) { if (placement == commentAfterOnSameLine) {
assert(lastValue_ != 0); assert(lastValue_ != 0);
lastValue_->setComment(normalized, placement); lastValue_->setComment(std::string(begin, end), placement);
} else { } else {
commentsBefore_ += normalized; commentsBefore_ += std::string(begin, end);
} }
} }
@@ -375,38 +374,18 @@ bool Reader::readCStyleComment() {
bool Reader::readCppStyleComment() { bool Reader::readCppStyleComment() {
while (current_ != end_) { while (current_ != end_) {
Char c = getNextChar(); Char c = getNextChar();
if (c == '\n') if (c == '\r' || c == '\n')
break; break;
if (c == '\r') {
// Consume DOS EOL. It will be normalized in addComment.
if (current_ != end_ && *current_ == '\n')
getNextChar();
// Break on Moc OS 9 EOL.
break;
}
} }
return true; return true;
} }
void Reader::readNumber() { void Reader::readNumber() {
const char *p = current_; while (current_ != end_) {
char c = '0'; // stopgap for already consumed character if (!(*current_ >= '0' && *current_ <= '9') &&
// integral part !in(*current_, '.', 'e', 'E', '+', '-'))
while (c >= '0' && c <= '9') break;
c = (current_ = p) < end_ ? *p++ : 0; ++current_;
// fractional part
if (c == '.') {
c = (current_ = p) < end_ ? *p++ : 0;
while (c >= '0' && c <= '9')
c = (current_ = p) < end_ ? *p++ : 0;
}
// exponential part
if (c == 'e' || c == 'E') {
c = (current_ = p) < end_ ? *p++ : 0;
if (c == '+' || c == '-')
c = (current_ = p) < end_ ? *p++ : 0;
while (c >= '0' && c <= '9')
c = (current_ = p) < end_ ? *p++ : 0;
} }
} }
@@ -425,8 +404,7 @@ bool Reader::readString() {
bool Reader::readObject(Token& tokenStart) { bool Reader::readObject(Token& tokenStart) {
Token tokenName; Token tokenName;
std::string name; std::string name;
Value init(objectValue); currentValue() = Value(objectValue);
currentValue().swapPayload(init);
currentValue().setOffsetStart(tokenStart.start_ - begin_); currentValue().setOffsetStart(tokenStart.start_ - begin_);
while (readToken(tokenName)) { while (readToken(tokenName)) {
bool initialTokenOk = true; bool initialTokenOk = true;
@@ -479,8 +457,7 @@ bool Reader::readObject(Token& tokenStart) {
} }
bool Reader::readArray(Token& tokenStart) { bool Reader::readArray(Token& tokenStart) {
Value init(arrayValue); currentValue() = Value(arrayValue);
currentValue().swapPayload(init);
currentValue().setOffsetStart(tokenStart.start_ - begin_); currentValue().setOffsetStart(tokenStart.start_ - begin_);
skipSpaces(); skipSpaces();
if (*current_ == ']') // empty array if (*current_ == ']') // empty array
@@ -520,13 +497,20 @@ bool Reader::decodeNumber(Token& token) {
Value decoded; Value decoded;
if (!decodeNumber(token, decoded)) if (!decodeNumber(token, decoded))
return false; return false;
currentValue().swapPayload(decoded); currentValue() = decoded;
currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_);
return true; return true;
} }
bool Reader::decodeNumber(Token& token, Value& decoded) { bool Reader::decodeNumber(Token& token, Value& decoded) {
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, decoded);
// Attempts to parse the number as an integer. If the number is // Attempts to parse the number as an integer. If the number is
// larger than the maximum supported value of an integer then // larger than the maximum supported value of an integer then
// we decode the number as a double. // we decode the number as a double.
@@ -534,7 +518,6 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
bool isNegative = *current == '-'; bool isNegative = *current == '-';
if (isNegative) if (isNegative)
++current; ++current;
// TODO: Help the compiler do the div and mod at compile time or get rid of them.
Value::LargestUInt maxIntegerValue = Value::LargestUInt maxIntegerValue =
isNegative ? Value::LargestUInt(-Value::minLargestInt) isNegative ? Value::LargestUInt(-Value::minLargestInt)
: Value::maxLargestUInt; : Value::maxLargestUInt;
@@ -543,7 +526,9 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
while (current < token.end_) { while (current < token.end_) {
Char c = *current++; Char c = *current++;
if (c < '0' || c > '9') if (c < '0' || c > '9')
return decodeDouble(token, decoded); return addError("'" + std::string(token.start_, token.end_) +
"' is not a number.",
token);
Value::UInt digit(c - '0'); Value::UInt digit(c - '0');
if (value >= threshold) { if (value >= threshold) {
// We've hit or exceeded the max value divided by 10 (rounded down). If // We've hit or exceeded the max value divided by 10 (rounded down). If
@@ -570,7 +555,7 @@ bool Reader::decodeDouble(Token& token) {
Value decoded; Value decoded;
if (!decodeDouble(token, decoded)) if (!decodeDouble(token, decoded))
return false; return false;
currentValue().swapPayload(decoded); currentValue() = decoded;
currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_);
return true; return true;
@@ -613,11 +598,10 @@ bool Reader::decodeDouble(Token& token, Value& decoded) {
} }
bool Reader::decodeString(Token& token) { bool Reader::decodeString(Token& token) {
std::string decoded_string; std::string decoded;
if (!decodeString(token, decoded_string)) if (!decodeString(token, decoded))
return false; return false;
Value decoded(decoded_string); currentValue() = decoded;
currentValue().swapPayload(decoded);
currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_);
return true; return true;
@@ -847,9 +831,8 @@ std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
} }
bool Reader::pushError(const Value& value, const std::string& message) { bool Reader::pushError(const Value& value, const std::string& message) {
size_t length = end_ - begin_; if(value.getOffsetStart() > end_ - begin_
if(value.getOffsetStart() > length || value.getOffsetLimit() > end_ - begin_)
|| value.getOffsetLimit() > length)
return false; return false;
Token token; Token token;
token.type_ = tokenError; token.type_ = tokenError;
@@ -864,10 +847,9 @@ bool Reader::pushError(const Value& value, const std::string& message) {
} }
bool Reader::pushError(const Value& value, const std::string& message, const Value& extra) { bool Reader::pushError(const Value& value, const std::string& message, const Value& extra) {
size_t length = end_ - begin_; if(value.getOffsetStart() > end_ - begin_
if(value.getOffsetStart() > length || value.getOffsetLimit() > end_ - begin_
|| value.getOffsetLimit() > length || extra.getOffsetLimit() > end_ - begin_)
|| extra.getOffsetLimit() > length)
return false; return false;
Token token; Token token;
token.type_ = tokenError; token.type_ = tokenError;

View File

@@ -175,8 +175,7 @@ Value::CZString::CZString(const CZString& other)
? duplicateStringValue(other.cstr_) ? duplicateStringValue(other.cstr_)
: other.cstr_), : other.cstr_),
index_(other.cstr_ index_(other.cstr_
? static_cast<ArrayIndex>(other.index_ == noDuplication ? (other.index_ == noDuplication ? noDuplication : duplicate)
? noDuplication : duplicate)
: other.index_) {} : other.index_) {}
Value::CZString::~CZString() { Value::CZString::~CZString() {
@@ -189,8 +188,9 @@ void Value::CZString::swap(CZString& other) {
std::swap(index_, other.index_); std::swap(index_, other.index_);
} }
Value::CZString& Value::CZString::operator=(CZString other) { Value::CZString &Value::CZString::operator=(const CZString &other) {
swap(other); CZString temp(other);
swap(temp);
return *this; return *this;
} }
@@ -226,8 +226,14 @@ bool Value::CZString::isStaticString() const { return index_ == noDuplication; }
* memset( this, 0, sizeof(Value) ) * memset( this, 0, sizeof(Value) )
* This optimization is used in ValueInternalMap fast allocator. * This optimization is used in ValueInternalMap fast allocator.
*/ */
Value::Value(ValueType type) { Value::Value(ValueType type)
initBasic(type); : type_(type), allocated_(false)
#ifdef JSON_VALUE_USE_INTERNAL_MAP
,
itemIsUsed_(0)
#endif
,
comments_(0), start_(0), limit_(0) {
switch (type) { switch (type) {
case nullValue: case nullValue:
break; break;
@@ -262,62 +268,130 @@ Value::Value(ValueType type) {
} }
} }
Value::Value(Int value) { Value::Value(UInt value)
initBasic(intValue); : type_(uintValue), allocated_(false)
#ifdef JSON_VALUE_USE_INTERNAL_MAP
,
itemIsUsed_(0)
#endif
,
comments_(0), start_(0), limit_(0) {
value_.uint_ = value;
}
Value::Value(Int value)
: type_(intValue), allocated_(false)
#ifdef JSON_VALUE_USE_INTERNAL_MAP
,
itemIsUsed_(0)
#endif
,
comments_(0), start_(0), limit_(0) {
value_.int_ = value; value_.int_ = value;
} }
Value::Value(UInt value) {
initBasic(uintValue);
value_.uint_ = value;
}
#if defined(JSON_HAS_INT64) #if defined(JSON_HAS_INT64)
Value::Value(Int64 value) { Value::Value(Int64 value)
initBasic(intValue); : type_(intValue), allocated_(false)
#ifdef JSON_VALUE_USE_INTERNAL_MAP
,
itemIsUsed_(0)
#endif
,
comments_(0), start_(0), limit_(0) {
value_.int_ = value; value_.int_ = value;
} }
Value::Value(UInt64 value) {
initBasic(uintValue); Value::Value(UInt64 value)
: type_(uintValue), allocated_(false)
#ifdef JSON_VALUE_USE_INTERNAL_MAP
,
itemIsUsed_(0)
#endif
,
comments_(0), start_(0), limit_(0) {
value_.uint_ = value; value_.uint_ = value;
} }
#endif // defined(JSON_HAS_INT64) #endif // defined(JSON_HAS_INT64)
Value::Value(double value) { Value::Value(double value)
initBasic(realValue); : type_(realValue), allocated_(false)
#ifdef JSON_VALUE_USE_INTERNAL_MAP
,
itemIsUsed_(0)
#endif
,
comments_(0), start_(0), limit_(0) {
value_.real_ = value; value_.real_ = value;
} }
Value::Value(const char* value) { Value::Value(const char* value)
initBasic(stringValue, true); : type_(stringValue), allocated_(true)
#ifdef JSON_VALUE_USE_INTERNAL_MAP
,
itemIsUsed_(0)
#endif
,
comments_(0), start_(0), limit_(0) {
value_.string_ = duplicateStringValue(value); value_.string_ = duplicateStringValue(value);
} }
Value::Value(const char* beginValue, const char* endValue) { Value::Value(const char* beginValue, const char* endValue)
initBasic(stringValue, true); : type_(stringValue), allocated_(true)
#ifdef JSON_VALUE_USE_INTERNAL_MAP
,
itemIsUsed_(0)
#endif
,
comments_(0), start_(0), limit_(0) {
value_.string_ = value_.string_ =
duplicateStringValue(beginValue, (unsigned int)(endValue - beginValue)); duplicateStringValue(beginValue, (unsigned int)(endValue - beginValue));
} }
Value::Value(const std::string& value) { Value::Value(const std::string& value)
initBasic(stringValue, true); : type_(stringValue), allocated_(true)
#ifdef JSON_VALUE_USE_INTERNAL_MAP
,
itemIsUsed_(0)
#endif
,
comments_(0), start_(0), limit_(0) {
value_.string_ = value_.string_ =
duplicateStringValue(value.c_str(), (unsigned int)value.length()); duplicateStringValue(value.c_str(), (unsigned int)value.length());
} }
Value::Value(const StaticString& value) { Value::Value(const StaticString& value)
initBasic(stringValue); : type_(stringValue), allocated_(false)
#ifdef JSON_VALUE_USE_INTERNAL_MAP
,
itemIsUsed_(0)
#endif
,
comments_(0), start_(0), limit_(0) {
value_.string_ = const_cast<char*>(value.c_str()); value_.string_ = const_cast<char*>(value.c_str());
} }
#ifdef JSON_USE_CPPTL #ifdef JSON_USE_CPPTL
Value::Value(const CppTL::ConstString& value) { Value::Value(const CppTL::ConstString& value)
initBasic(stringValue, true); : type_(stringValue), allocated_(true)
#ifdef JSON_VALUE_USE_INTERNAL_MAP
,
itemIsUsed_(0)
#endif
,
comments_(0), start_(0), limit_(0) {
value_.string_ = duplicateStringValue(value, value.length()); value_.string_ = duplicateStringValue(value, value.length());
} }
#endif #endif
Value::Value(bool value) { Value::Value(bool value)
initBasic(booleanValue); : type_(booleanValue), allocated_(false)
#ifdef JSON_VALUE_USE_INTERNAL_MAP
,
itemIsUsed_(0)
#endif
,
comments_(0), start_(0), limit_(0) {
value_.bool_ = value; value_.bool_ = value;
} }
@@ -340,7 +414,7 @@ Value::Value(const Value& other)
case stringValue: case stringValue:
if (other.value_.string_) { if (other.value_.string_) {
value_.string_ = duplicateStringValue(other.value_.string_); value_.string_ = duplicateStringValue(other.value_.string_);
allocated_ |= true; allocated_ = true;
} else { } else {
value_.string_ = 0; value_.string_ = 0;
allocated_ = false; allocated_ = false;
@@ -405,12 +479,13 @@ Value::~Value() {
delete[] comments_; delete[] comments_;
} }
Value& Value::operator=(Value other) { Value &Value::operator=(const Value &other) {
swap(other); Value temp(other);
swap(temp);
return *this; return *this;
} }
void Value::swapPayload(Value& other) { void Value::swap(Value& other) {
ValueType temp = type_; ValueType temp = type_;
type_ = other.type_; type_ = other.type_;
other.type_ = temp; other.type_ = temp;
@@ -418,11 +493,6 @@ void Value::swapPayload(Value& other) {
int temp2 = allocated_; int temp2 = allocated_;
allocated_ = other.allocated_; allocated_ = other.allocated_;
other.allocated_ = temp2; other.allocated_ = temp2;
}
void Value::swap(Value& other) {
swapPayload(other);
std::swap(comments_, other.comments_);
std::swap(start_, other.start_); std::swap(start_, other.start_);
std::swap(limit_, other.limit_); std::swap(limit_, other.limit_);
} }
@@ -898,17 +968,6 @@ Value& Value::operator[](const char* key) {
return resolveReference(key, false); return resolveReference(key, false);
} }
void Value::initBasic(ValueType type, bool allocated) {
type_ = type;
allocated_ = allocated;
#ifdef JSON_VALUE_USE_INTERNAL_MAP
itemIsUsed_ = 0;
#endif
comments_ = 0;
start_ = 0;
limit_ = 0;
}
Value& Value::resolveReference(const char* key, bool isStatic) { Value& Value::resolveReference(const char* key, bool isStatic) {
JSON_ASSERT_MESSAGE( JSON_ASSERT_MESSAGE(
type_ == nullValue || type_ == objectValue, type_ == nullValue || type_ == objectValue,
@@ -989,74 +1048,35 @@ Value Value::get(const std::string& key, const Value& defaultValue) const {
return get(key.c_str(), defaultValue); return get(key.c_str(), defaultValue);
} }
bool Value::removeMember(const char* key, Value* removed) {
if (type_ != objectValue) {
return false;
}
#ifndef JSON_VALUE_USE_INTERNAL_MAP
CZString actualKey(key, CZString::noDuplication);
ObjectValues::iterator it = value_.map_->find(actualKey);
if (it == value_.map_->end())
return false;
*removed = it->second;
value_.map_->erase(it);
return true;
#else
Value* value = value_.map_->find(key);
if (value) {
*removed = *value;
value_.map_.remove(key);
return true;
} else {
return false;
}
#endif
}
Value Value::removeMember(const char* key) { Value Value::removeMember(const char* key) {
JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue, JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
"in Json::Value::removeMember(): requires objectValue"); "in Json::Value::removeMember(): requires objectValue");
if (type_ == nullValue) if (type_ == nullValue)
return null; return null;
#ifndef JSON_VALUE_USE_INTERNAL_MAP
Value removed; // null CZString actualKey(key, CZString::noDuplication);
removeMember(key, &removed); ObjectValues::iterator it = value_.map_->find(actualKey);
return removed; // still null if removeMember() did nothing 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) { Value Value::removeMember(const std::string& key) {
return removeMember(key.c_str()); return removeMember(key.c_str());
} }
bool Value::removeIndex(ArrayIndex index, Value* removed) {
if (type_ != arrayValue) {
return false;
}
#ifdef JSON_VALUE_USE_INTERNAL_MAP
JSON_FAIL_MESSAGE("removeIndex is not implemented for ValueInternalArray.");
return false;
#else
CZString key(index);
ObjectValues::iterator it = value_.map_->find(key);
if (it == value_.map_->end()) {
return false;
}
*removed = it->second;
ArrayIndex oldSize = size();
// shift left all items left, into the place of the "removed"
for (ArrayIndex i = index; i < (oldSize - 1); ++i){
CZString key(i);
(*value_.map_)[key] = (*this)[i + 1];
}
// erase the last one ("leftover")
CZString keyLast(oldSize - 1);
ObjectValues::iterator itLast = value_.map_->find(keyLast);
value_.map_->erase(itLast);
return true;
#endif
}
#ifdef JSON_USE_CPPTL #ifdef JSON_USE_CPPTL
Value Value::get(const CppTL::ConstString& key, Value Value::get(const CppTL::ConstString& key,
const Value& defaultValue) const { const Value& defaultValue) const {

View File

@@ -26,11 +26,6 @@
#pragma warning(disable : 4996) #pragma warning(disable : 4996)
#endif #endif
#if defined(__sun) && defined(__SVR4) //Solaris
#include <ieeefp.h>
#define isfinite finite
#endif
namespace Json { namespace Json {
static bool containsControlCharacter(const char* str) { static bool containsControlCharacter(const char* str) {
@@ -87,13 +82,13 @@ std::string valueToString(double value) {
// visual studio 2005 to // visual studio 2005 to
// avoid warning. // avoid warning.
#if defined(WINCE) #if defined(WINCE)
len = _snprintf(buffer, sizeof(buffer), "%.17g", value); len = _snprintf(buffer, sizeof(buffer), "%.16g", value);
#else #else
len = sprintf_s(buffer, sizeof(buffer), "%.17g", value); len = sprintf_s(buffer, sizeof(buffer), "%.16g", value);
#endif #endif
#else #else
if (isfinite(value)) { if (isfinite(value)) {
len = snprintf(buffer, sizeof(buffer), "%.17g", value); len = snprintf(buffer, sizeof(buffer), "%.16g", value);
} else { } else {
// IEEE standard states that NaN values will not compare to themselves // IEEE standard states that NaN values will not compare to themselves
if (value != value) { if (value != value) {
@@ -222,28 +217,28 @@ void FastWriter::writeValue(const Value& value) {
document_ += valueToString(value.asBool()); document_ += valueToString(value.asBool());
break; break;
case arrayValue: { case arrayValue: {
document_ += '['; document_ += "[";
int size = value.size(); int size = value.size();
for (int index = 0; index < size; ++index) { for (int index = 0; index < size; ++index) {
if (index > 0) if (index > 0)
document_ += ','; document_ += ",";
writeValue(value[index]); writeValue(value[index]);
} }
document_ += ']'; document_ += "]";
} break; } break;
case objectValue: { case objectValue: {
Value::Members members(value.getMemberNames()); Value::Members members(value.getMemberNames());
document_ += '{'; document_ += "{";
for (Value::Members::iterator it = members.begin(); it != members.end(); for (Value::Members::iterator it = members.begin(); it != members.end();
++it) { ++it) {
const std::string& name = *it; const std::string& name = *it;
if (it != members.begin()) if (it != members.begin())
document_ += ','; document_ += ",";
document_ += valueToQuotedString(name.c_str()); document_ += valueToQuotedString(name.c_str());
document_ += yamlCompatiblityEnabled_ ? ": " : ":"; document_ += yamlCompatiblityEnabled_ ? ": " : ":";
writeValue(value[name]); writeValue(value[name]);
} }
document_ += '}'; document_ += "}";
} break; } break;
} }
} }
@@ -307,7 +302,7 @@ void StyledWriter::writeValue(const Value& value) {
writeCommentAfterValueOnSameLine(childValue); writeCommentAfterValueOnSameLine(childValue);
break; break;
} }
document_ += ','; document_ += ",";
writeCommentAfterValueOnSameLine(childValue); writeCommentAfterValueOnSameLine(childValue);
} }
unindent(); unindent();
@@ -341,7 +336,7 @@ void StyledWriter::writeArrayValue(const Value& value) {
writeCommentAfterValueOnSameLine(childValue); writeCommentAfterValueOnSameLine(childValue);
break; break;
} }
document_ += ','; document_ += ",";
writeCommentAfterValueOnSameLine(childValue); writeCommentAfterValueOnSameLine(childValue);
} }
unindent(); unindent();
@@ -421,27 +416,26 @@ void StyledWriter::writeCommentBeforeValue(const Value& root) {
document_ += "\n"; document_ += "\n";
writeIndent(); writeIndent();
const std::string& comment = root.getComment(commentBefore); std::string normalizedComment = normalizeEOL(root.getComment(commentBefore));
std::string::const_iterator iter = comment.begin(); std::string::const_iterator iter = normalizedComment.begin();
while (iter != comment.end()) { while (iter != normalizedComment.end()) {
document_ += *iter; document_ += *iter;
if (*iter == '\n' && if (*iter == '\n' && *(iter + 1) == '/')
(iter != comment.end() && *(iter + 1) == '/'))
writeIndent(); writeIndent();
++iter; ++iter;
} }
// Comments are stripped of trailing newlines, so add one here // Comments are stripped of newlines, so add one here
document_ += "\n"; document_ += "\n";
} }
void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) { void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) {
if (root.hasComment(commentAfterOnSameLine)) if (root.hasComment(commentAfterOnSameLine))
document_ += " " + root.getComment(commentAfterOnSameLine); document_ += " " + normalizeEOL(root.getComment(commentAfterOnSameLine));
if (root.hasComment(commentAfter)) { if (root.hasComment(commentAfter)) {
document_ += "\n"; document_ += "\n";
document_ += root.getComment(commentAfter); document_ += normalizeEOL(root.getComment(commentAfter));
document_ += "\n"; document_ += "\n";
} }
} }
@@ -452,6 +446,25 @@ bool StyledWriter::hasCommentForValue(const Value& value) {
value.hasComment(commentAfter); 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 // Class StyledStreamWriter
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
@@ -628,17 +641,17 @@ void StyledStreamWriter::unindent() {
void StyledStreamWriter::writeCommentBeforeValue(const Value& root) { void StyledStreamWriter::writeCommentBeforeValue(const Value& root) {
if (!root.hasComment(commentBefore)) if (!root.hasComment(commentBefore))
return; return;
*document_ << root.getComment(commentBefore); *document_ << normalizeEOL(root.getComment(commentBefore));
*document_ << "\n"; *document_ << "\n";
} }
void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) { void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) {
if (root.hasComment(commentAfterOnSameLine)) if (root.hasComment(commentAfterOnSameLine))
*document_ << " " + root.getComment(commentAfterOnSameLine); *document_ << " " + normalizeEOL(root.getComment(commentAfterOnSameLine));
if (root.hasComment(commentAfter)) { if (root.hasComment(commentAfter)) {
*document_ << "\n"; *document_ << "\n";
*document_ << root.getComment(commentAfter); *document_ << normalizeEOL(root.getComment(commentAfter));
*document_ << "\n"; *document_ << "\n";
} }
} }
@@ -649,6 +662,25 @@ bool StyledStreamWriter::hasCommentForValue(const Value& value) {
value.hasComment(commentAfter); 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) { std::ostream& operator<<(std::ostream& sout, const Value& root) {
Json::StyledStreamWriter writer; Json::StyledStreamWriter writer;
writer.write(sout, root); writer.write(sout, root);

View File

@@ -17,8 +17,8 @@
#define kint64min Json::Value::minInt64 #define kint64min Json::Value::minInt64
#define kuint64max Json::Value::maxUInt64 #define kuint64max Json::Value::maxUInt64
//static const double kdint64max = double(kint64max); static const double kdint64max = double(kint64max);
//static const float kfint64max = float(kint64max); static const float kfint64max = float(kint64max);
static const float kfint32max = float(kint32max); static const float kfint32max = float(kint32max);
static const float kfuint32max = float(kuint32max); static const float kfuint32max = float(kuint32max);
@@ -198,18 +198,6 @@ JSONTEST_FIXTURE(ValueTest, objects) {
object1_["some other id"] = "foo"; object1_["some other id"] = "foo";
JSONTEST_ASSERT_EQUAL(Json::Value("foo"), object1_["some other id"]); JSONTEST_ASSERT_EQUAL(Json::Value("foo"), object1_["some other id"]);
JSONTEST_ASSERT_EQUAL(Json::Value("foo"), object1_["some other id"]);
// Remove.
Json::Value got;
bool did;
did = object1_.removeMember("some other id", &got);
JSONTEST_ASSERT_EQUAL(Json::Value("foo"), got);
JSONTEST_ASSERT_EQUAL(true, did);
got = Json::Value("bar");
did = object1_.removeMember("some other id", &got);
JSONTEST_ASSERT_EQUAL(Json::Value("bar"), got);
JSONTEST_ASSERT_EQUAL(false, did);
} }
JSONTEST_FIXTURE(ValueTest, arrays) { JSONTEST_FIXTURE(ValueTest, arrays) {
@@ -252,10 +240,6 @@ JSONTEST_FIXTURE(ValueTest, arrays) {
array1_[2] = Json::Value(17); array1_[2] = Json::Value(17);
JSONTEST_ASSERT_EQUAL(Json::Value(), array1_[1]); JSONTEST_ASSERT_EQUAL(Json::Value(), array1_[1]);
JSONTEST_ASSERT_EQUAL(Json::Value(17), array1_[2]); JSONTEST_ASSERT_EQUAL(Json::Value(17), array1_[2]);
Json::Value got;
JSONTEST_ASSERT_EQUAL(true, array1_.removeIndex(2, &got));
JSONTEST_ASSERT_EQUAL(Json::Value(17), got);
JSONTEST_ASSERT_EQUAL(false, array1_.removeIndex(2, &got)); // gone now
} }
JSONTEST_FIXTURE(ValueTest, null) { JSONTEST_FIXTURE(ValueTest, null) {
@@ -942,7 +926,7 @@ JSONTEST_FIXTURE(ValueTest, integers) {
JSONTEST_ASSERT_EQUAL(float(uint64ToDouble(Json::UInt64(1) << 63)), JSONTEST_ASSERT_EQUAL(float(uint64ToDouble(Json::UInt64(1) << 63)),
val.asFloat()); val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool()); JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("9.2233720368547758e+18", JSONTEST_ASSERT_STRING_EQUAL("9.223372036854776e+18",
normalizeFloatingPointStr(val.asString())); normalizeFloatingPointStr(val.asString()));
// int64 min // int64 min
@@ -990,7 +974,7 @@ JSONTEST_FIXTURE(ValueTest, integers) {
JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asDouble()); JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asFloat()); JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool()); JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("-9.2233720368547758e+18", JSONTEST_ASSERT_STRING_EQUAL("-9.223372036854776e+18",
normalizeFloatingPointStr(val.asString())); normalizeFloatingPointStr(val.asString()));
// 10^19 // 10^19
@@ -1081,7 +1065,7 @@ JSONTEST_FIXTURE(ValueTest, integers) {
JSONTEST_ASSERT_EQUAL(18446744073709551616.0, val.asDouble()); JSONTEST_ASSERT_EQUAL(18446744073709551616.0, val.asDouble());
JSONTEST_ASSERT_EQUAL(18446744073709551616.0, val.asFloat()); JSONTEST_ASSERT_EQUAL(18446744073709551616.0, val.asFloat());
JSONTEST_ASSERT_EQUAL(true, val.asBool()); JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_STRING_EQUAL("1.8446744073709552e+19", JSONTEST_ASSERT_STRING_EQUAL("1.844674407370955e+19",
normalizeFloatingPointStr(val.asString())); normalizeFloatingPointStr(val.asString()));
#endif #endif
} }
@@ -1233,7 +1217,7 @@ JSONTEST_FIXTURE(ValueTest, nonIntegers) {
normalizeFloatingPointStr(val.asString())); normalizeFloatingPointStr(val.asString()));
val = Json::Value(1.2345678901234); val = Json::Value(1.2345678901234);
JSONTEST_ASSERT_STRING_EQUAL("1.2345678901234001", JSONTEST_ASSERT_STRING_EQUAL("1.2345678901234",
normalizeFloatingPointStr(val.asString())); normalizeFloatingPointStr(val.asString()));
// A 16-digit floating point number. // A 16-digit floating point number.

View File

@@ -1,7 +1,5 @@
.={} .={}
// Comment for array
.test=[] .test=[]
// Comment within array
.test[0]={} .test[0]={}
.test[0].a="aaa" .test[0].a="aaa"
.test[1]={} .test[1]={}

View File

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

View File

@@ -11,13 +11,4 @@
// Multiline comment cpp-style // Multiline comment cpp-style
// Second line // Second line
.cpp-test.c=3 .cpp-test.c=3
// Comment before double .cpp-test.d=4
.cpp-test.d=4.1
// Comment before string
.cpp-test.e="e-string"
// Comment before true
.cpp-test.f=true
// Comment before false
.cpp-test.g=false
// Comment before null
.cpp-test.h=null

View File

@@ -12,15 +12,6 @@
// Multiline comment cpp-style // Multiline comment cpp-style
// Second line // Second line
"c" : 3, "c" : 3,
// Comment before double "d" : 4
"d" : 4.1,
// Comment before string
"e" : "e-string",
// Comment before true
"f" : true,
// Comment before false
"g" : false,
// Comment before null
"h" : null
} }
} }

View File

@@ -1,12 +1,11 @@
from __future__ import print_function
import glob import glob
import os.path import os.path
for path in glob.glob( '*.json' ): for path in glob.glob( '*.json' ):
text = file(path,'rt').read() text = file(path,'rt').read()
target = os.path.splitext(path)[0] + '.expected' target = os.path.splitext(path)[0] + '.expected'
if os.path.exists( target ): if os.path.exists( target ):
print('skipping:', target) print 'skipping:', target
else: else:
print('creating:', target) print 'creating:', target
file(target,'wt').write(text) file(target,'wt').write(text)

View File

@@ -1,12 +1,12 @@
# Simple implementation of a json test runner to run the test against json-py. # Simple implementation of a json test runner to run the test against json-py.
from __future__ import print_function
import sys import sys
import os.path import os.path
import json import json
import types import types
if len(sys.argv) != 2: if len(sys.argv) != 2:
print("Usage: %s input-json-file", sys.argv[0]) print "Usage: %s input-json-file", sys.argv[0]
sys.exit(3) sys.exit(3)
input_path = sys.argv[1] input_path = sys.argv[1]

View File

@@ -1,36 +1,17 @@
from __future__ import print_function
from __future__ import unicode_literals
from io import open
from glob import glob
import sys import sys
import os import os
import os.path import os.path
from glob import glob
import optparse import optparse
VALGRIND_CMD = 'valgrind --tool=memcheck --leak-check=yes --undef-value-errors=yes ' VALGRIND_CMD = 'valgrind --tool=memcheck --leak-check=yes --undef-value-errors=yes '
def getStatusOutput(cmd):
"""
Return int, unicode (for both Python 2 and 3).
Note: os.popen().close() would return None for 0.
"""
pipe = os.popen(cmd)
process_output = pipe.read()
try:
# We have been using os.popen(). When we read() the result
# we get 'str' (bytes) in py2, and 'str' (unicode) in py3.
# Ugh! There must be a better way to handle this.
process_output = process_output.decode('utf-8')
except AttributeError:
pass # python3
status = pipe.close()
return status, process_output
def compareOutputs( expected, actual, message ): def compareOutputs( expected, actual, message ):
expected = expected.strip().replace('\r','').split('\n') expected = expected.strip().replace('\r','').split('\n')
actual = actual.strip().replace('\r','').split('\n') actual = actual.strip().replace('\r','').split('\n')
diff_line = 0 diff_line = 0
max_line_to_compare = min( len(expected), len(actual) ) max_line_to_compare = min( len(expected), len(actual) )
for index in range(0,max_line_to_compare): for index in xrange(0,max_line_to_compare):
if expected[index].strip() != actual[index].strip(): if expected[index].strip() != actual[index].strip():
diff_line = index + 1 diff_line = index + 1
break break
@@ -52,8 +33,8 @@ def compareOutputs( expected, actual, message ):
def safeReadFile( path ): def safeReadFile( path ):
try: try:
return open( path, 'rt', encoding = 'utf-8' ).read() return file( path, 'rt' ).read()
except IOError as e: except IOError, e:
return '<File "%s" is missing: %s>' % (path,e) return '<File "%s" is missing: %s>' % (path,e)
def runAllTests( jsontest_executable_path, input_dir = None, def runAllTests( jsontest_executable_path, input_dir = None,
@@ -70,57 +51,58 @@ def runAllTests( jsontest_executable_path, input_dir = None,
for input_path in tests + test_jsonchecker: for input_path in tests + test_jsonchecker:
expect_failure = os.path.basename( input_path ).startswith( 'fail' ) expect_failure = os.path.basename( input_path ).startswith( 'fail' )
is_json_checker_test = (input_path in test_jsonchecker) or expect_failure is_json_checker_test = (input_path in test_jsonchecker) or expect_failure
print('TESTING:', input_path, end=' ') print 'TESTING:', input_path,
options = is_json_checker_test and '--json-checker' or '' options = is_json_checker_test and '--json-checker' or ''
cmd = '%s%s %s "%s"' % ( pipe = os.popen( "%s%s %s %s" % (
valgrind_path, jsontest_executable_path, options, valgrind_path, jsontest_executable_path, options,
input_path) input_path) )
status, process_output = getStatusOutput(cmd) process_output = pipe.read()
status = pipe.close()
if is_json_checker_test: if is_json_checker_test:
if expect_failure: if expect_failure:
if not status: if status is None:
print('FAILED') print 'FAILED'
failed_tests.append( (input_path, 'Parsing should have failed:\n%s' % failed_tests.append( (input_path, 'Parsing should have failed:\n%s' %
safeReadFile(input_path)) ) safeReadFile(input_path)) )
else: else:
print('OK') print 'OK'
else: else:
if status: if status is not None:
print('FAILED') print 'FAILED'
failed_tests.append( (input_path, 'Parsing failed:\n' + process_output) ) failed_tests.append( (input_path, 'Parsing failed:\n' + process_output) )
else: else:
print('OK') print 'OK'
else: else:
base_path = os.path.splitext(input_path)[0] base_path = os.path.splitext(input_path)[0]
actual_output = safeReadFile( base_path + '.actual' ) actual_output = safeReadFile( base_path + '.actual' )
actual_rewrite_output = safeReadFile( base_path + '.actual-rewrite' ) actual_rewrite_output = safeReadFile( base_path + '.actual-rewrite' )
open(base_path + '.process-output', 'wt', encoding = 'utf-8').write( process_output ) file(base_path + '.process-output','wt').write( process_output )
if status: if status:
print('parsing failed') print 'parsing failed'
failed_tests.append( (input_path, 'Parsing failed:\n' + process_output) ) failed_tests.append( (input_path, 'Parsing failed:\n' + process_output) )
else: else:
expected_output_path = os.path.splitext(input_path)[0] + '.expected' expected_output_path = os.path.splitext(input_path)[0] + '.expected'
expected_output = open( expected_output_path, 'rt', encoding = 'utf-8' ).read() expected_output = file( expected_output_path, 'rt' ).read()
detail = ( compareOutputs( expected_output, actual_output, 'input' ) detail = ( compareOutputs( expected_output, actual_output, 'input' )
or compareOutputs( expected_output, actual_rewrite_output, 'rewrite' ) ) or compareOutputs( expected_output, actual_rewrite_output, 'rewrite' ) )
if detail: if detail:
print('FAILED') print 'FAILED'
failed_tests.append( (input_path, detail) ) failed_tests.append( (input_path, detail) )
else: else:
print('OK') print 'OK'
if failed_tests: if failed_tests:
print() print
print('Failure details:') print 'Failure details:'
for failed_test in failed_tests: for failed_test in failed_tests:
print('* Test', failed_test[0]) print '* Test', failed_test[0]
print(failed_test[1]) print failed_test[1]
print() print
print('Test results: %d passed, %d failed.' % (len(tests)-len(failed_tests), print 'Test results: %d passed, %d failed.' % (len(tests)-len(failed_tests),
len(failed_tests) )) len(failed_tests) )
return 1 return 1
else: else:
print('All %d tests passed.' % len(tests)) print 'All %d tests passed.' % len(tests)
return 0 return 0
def main(): def main():

View File

@@ -1,11 +1,8 @@
from __future__ import print_function
from __future__ import unicode_literals
from io import open
from glob import glob
import sys import sys
import os import os
import os.path import os.path
import subprocess import subprocess
from glob import glob
import optparse import optparse
VALGRIND_CMD = 'valgrind --tool=memcheck --leak-check=yes --undef-value-errors=yes' VALGRIND_CMD = 'valgrind --tool=memcheck --leak-check=yes --undef-value-errors=yes'
@@ -21,11 +18,7 @@ class TestProxy(object):
else: else:
cmd = [] cmd = []
cmd.extend( [self.test_exe_path, '--test-auto'] + options ) cmd.extend( [self.test_exe_path, '--test-auto'] + options )
try: process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
except:
print(cmd)
raise
stdout = process.communicate()[0] stdout = process.communicate()[0]
if process.returncode: if process.returncode:
return False, stdout return False, stdout
@@ -35,29 +28,29 @@ def runAllTests( exe_path, use_valgrind=False ):
test_proxy = TestProxy( exe_path, use_valgrind=use_valgrind ) test_proxy = TestProxy( exe_path, use_valgrind=use_valgrind )
status, test_names = test_proxy.run( ['--list-tests'] ) status, test_names = test_proxy.run( ['--list-tests'] )
if not status: if not status:
print("Failed to obtain unit tests list:\n" + test_names, file=sys.stderr) print >> sys.stderr, "Failed to obtain unit tests list:\n" + test_names
return 1 return 1
test_names = [name.strip() for name in test_names.decode('utf-8').strip().split('\n')] test_names = [name.strip() for name in test_names.strip().split('\n')]
failures = [] failures = []
for name in test_names: for name in test_names:
print('TESTING %s:' % name, end=' ') print 'TESTING %s:' % name,
succeed, result = test_proxy.run( ['--test', name] ) succeed, result = test_proxy.run( ['--test', name] )
if succeed: if succeed:
print('OK') print 'OK'
else: else:
failures.append( (name, result) ) failures.append( (name, result) )
print('FAILED') print 'FAILED'
failed_count = len(failures) failed_count = len(failures)
pass_count = len(test_names) - failed_count pass_count = len(test_names) - failed_count
if failed_count: if failed_count:
print() print
for name, result in failures: for name, result in failures:
print(result) print result
print('%d/%d tests passed (%d failure(s))' % ( print '%d/%d tests passed (%d failure(s))' % (
pass_count, len(test_names), failed_count)) pass_count, len(test_names), failed_count)
return 1 return 1
else: else:
print('All %d tests passed' % len(test_names)) print 'All %d tests passed' % len(test_names)
return 0 return 0
def main(): def main():

View File

@@ -1 +1 @@
1.3.0 0.7.0